diff --git a/ChangeLog b/ChangeLog index b973b697f..6a50d1b7e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -20,6 +20,7 @@ * fix uTP edge case where udp socket buffer fills up * fix nagle implementation in uTP + * add a number of missing functions to the python binding * fix typo in Jamfile for building shared libraries * prevent tracker exchange for magnet links before metadata is received * fix crash in make_magnet_uri when generating links longer than 1024 characters diff --git a/bindings/python/src/create_torrent.cpp b/bindings/python/src/create_torrent.cpp index 4fbb70848..3b70d6bdf 100644 --- a/bindings/python/src/create_torrent.cpp +++ b/bindings/python/src/create_torrent.cpp @@ -17,6 +17,11 @@ namespace c.set_hash(p, sha1_hash(hash)); } + void set_file_hash(create_torrent& c, int f, char const* hash) + { + c.set_file_hash(f, sha1_hash(hash)); + } + void call_python_object(boost::python::object const& obj, int i) { obj(i); @@ -120,7 +125,9 @@ void bind_create_torrent() .def("set_comment", &create_torrent::set_comment) .def("set_creator", &create_torrent::set_creator) .def("set_hash", &set_hash) + .def("set_file_hash", &set_file_hash) .def("add_url_seed", &create_torrent::add_url_seed) + .def("add_http_seed", &create_torrent::add_http_seed) .def("add_node", &add_node) .def("add_tracker", &create_torrent::add_tracker, (arg("announce_url"), arg("tier") = 0)) .def("set_priv", &create_torrent::set_priv) diff --git a/bindings/python/src/peer_info.cpp b/bindings/python/src/peer_info.cpp index 2d677d3df..377087a14 100644 --- a/bindings/python/src/peer_info.cpp +++ b/bindings/python/src/peer_info.cpp @@ -20,6 +20,11 @@ int get_last_request(peer_info const& pi) return total_seconds(pi.last_request); } +int get_download_queue_time(peer_info const& pi) +{ + return total_seconds(pi.download_queue_time); +} + #ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES str get_country(peer_info const& pi) { @@ -27,6 +32,11 @@ str get_country(peer_info const& pi) } #endif +tuple get_local_endpoint(peer_info const& pi) +{ + return make_tuple(pi.local_endpoint.address().to_string(), pi.local_endpoint.port()); +} + tuple get_ip(peer_info const& pi) { return make_tuple(pi.ip.address().to_string(), pi.ip.port()); @@ -64,8 +74,13 @@ void bind_peer_info() .def_readonly("download_limit", &peer_info::download_limit) .add_property("last_request", get_last_request) .add_property("last_active", get_last_active) + .add_property("download_queue_time", get_download_queue_time) + .def_readonly("queue_bytes", &peer_info::queue_bytes) + .def_readonly("request_timeout", &peer_info::request_timeout) .def_readonly("send_buffer_size", &peer_info::send_buffer_size) .def_readonly("used_send_buffer", &peer_info::used_send_buffer) + .def_readonly("receive_buffer_size", &peer_info::receive_buffer_size) + .def_readonly("used_receive_buffer", &peer_info::used_receive_buffer) .def_readonly("num_hashfails", &peer_info::num_hashfails) #ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES .add_property("country", get_country) @@ -89,7 +104,13 @@ void bind_peer_info() .def_readonly("send_quota", &peer_info::send_quota) .def_readonly("receive_quota", &peer_info::receive_quota) .def_readonly("rtt", &peer_info::rtt) + .def_readonly("num_pieces", &peer_info::num_pieces) + .def_readonly("download_rate_peak", &peer_info::download_rate_peak) + .def_readonly("upload_rate_peak", &peer_info::upload_rate_peak) .def_readonly("progress", &peer_info::progress) + .def_readonly("progress_ppm", &peer_info::progress_ppm) + .def_readonly("estimated_reciprocation_rate", &peer_info::estimated_reciprocation_rate) + .add_property("local_endpoint", get_local_endpoint) ; // flags @@ -104,6 +125,11 @@ void bind_peer_info() pi.attr("queued") = (int)peer_info::queued; pi.attr("on_parole") = (int)peer_info::on_parole; pi.attr("seed") = (int)peer_info::seed; + pi.attr("optimistic_unchoke") = (int)peer_info::optimistic_unchoke; + pi.attr("snubbed") = (int)peer_info::snubbed; + pi.attr("upload_only") = (int)peer_info::upload_only; + pi.attr("endgame_mode") = (int)peer_info::endgame_mode; + pi.attr("holepunched") = (int)peer_info::holepunched; #ifndef TORRENT_DISABLE_ENCRYPTION pi.attr("rc4_encrypted") = (int)peer_info::rc4_encrypted; pi.attr("plaintext_encrypted") = (int)peer_info::plaintext_encrypted; @@ -126,6 +152,8 @@ void bind_peer_info() pi.attr("bw_torrent") = (int)peer_info::bw_torrent; pi.attr("bw_global") = (int)peer_info::bw_global; #endif + pi.attr("bw_limit") = (int)peer_info::bw_limit; pi.attr("bw_network") = (int)peer_info::bw_network; + pi.attr("bw_disk") = (int)peer_info::bw_disk; } diff --git a/bindings/python/src/session.cpp b/bindings/python/src/session.cpp index 4373c629d..2164f1b10 100644 --- a/bindings/python/src/session.cpp +++ b/bindings/python/src/session.cpp @@ -43,6 +43,13 @@ namespace return; } #ifndef TORRENT_DISABLE_DHT + void add_dht_node(session& s, tuple n) + { + std::string ip = extract(n[0]); + int port = extract(n[1]); + s.add_dht_node(std::make_pair(ip, port)); + } + void add_dht_router(session& s, std::string router_, int port_) { allow_threading_guard guard; @@ -396,6 +403,17 @@ namespace return ret; } + dict get_utp_stats(session_status const& st) + { + dict ret; + ret["num_idle"] = st.utp_stats.num_idle; + ret["num_syn_sent"] = st.utp_stats.num_syn_sent; + ret["num_connected"] = st.utp_stats.num_connected; + ret["num_fin_sent"] = st.utp_stats.num_fin_sent; + ret["num_close_wait"] = st.utp_stats.num_close_wait; + return ret; + } + #ifndef TORRENT_DISABLE_GEO_IP void load_asnum_db(session& s, std::string file) { @@ -503,7 +521,9 @@ void bind_session() .def_readonly("dht_torrents", &session_status::dht_torrents) .def_readonly("dht_global_nodes", &session_status::dht_global_nodes) .def_readonly("active_requests", &session_status::active_requests) + .def_readonly("dht_total_allocations", &session_status::dht_total_allocations) #endif + .add_property("utp_stats", &get_utp_stats) ; #ifndef TORRENT_DISABLE_DHT @@ -573,10 +593,12 @@ void bind_session() .def("listen_port", allow_threads(&session::listen_port)) .def("status", allow_threads(&session::status)) #ifndef TORRENT_DISABLE_DHT + .def("add_dht_node", add_dht_node) .def( "add_dht_router", &add_dht_router , (arg("router"), "port") ) + .def("is_dht_running", allow_threads(&session::is_dht_running)) .def("set_dht_settings", allow_threads(&session::set_dht_settings)) .def("start_dht", allow_threads(start_dht0)) .def("stop_dht", allow_threads(&session::stop_dht)) @@ -657,6 +679,10 @@ void bind_session() .def("peer_proxy", allow_threads(&session::peer_proxy)) .def("tracker_proxy", allow_threads(&session::tracker_proxy)) .def("web_seed_proxy", allow_threads(&session::web_seed_proxy)) +#endif +#if TORRENT_USE_I2P + .def("set_i2p_proxy", allow_threads(&session::set_i2p_proxy)) + .def("i2p_proxy", allow_threads(&session::i2p_proxy)) #endif .def("set_proxy", allow_threads(&session::set_proxy)) .def("proxy", allow_threads(&session::proxy)) diff --git a/bindings/python/src/torrent_handle.cpp b/bindings/python/src/torrent_handle.cpp index d6a04ae14..638a564c6 100644 --- a/bindings/python/src/torrent_handle.cpp +++ b/bindings/python/src/torrent_handle.cpp @@ -30,6 +30,21 @@ namespace return ret; } + list http_seeds(torrent_handle& handle) + { + list ret; + std::set urls; + { + allow_threading_guard guard; + urls = handle.http_seeds(); + } + + for (std::set::iterator i(urls.begin()) + , end(urls.end()); i != end; ++i) + ret.append(*i); + return ret; + } + list piece_availability(torrent_handle& handle) { list ret; @@ -158,6 +173,21 @@ void file_prioritity1(torrent_handle& h, int index, int prio) return h.file_priority(index, prio); } +void dict_to_announce_entry(dict d, announce_entry& ae) +{ + ae.url = extract(d["url"]); + if (d.has_key("tier")) + ae.tier = extract(d["tier"]); + if (d.has_key("fail_limit")) + ae.fail_limit = extract(d["fail_limit"]); + if (d.has_key("source")) + ae.source = extract(d["source"]); + if (d.has_key("verified")) + ae.verified = extract(d["verified"]); + if (d.has_key("send_stats")) + ae.send_stats = extract(d["send_stats"]); +} + void replace_trackers(torrent_handle& h, object trackers) { object iter(trackers.attr("__iter__")()); @@ -179,18 +209,9 @@ void replace_trackers(torrent_handle& h, object trackers) { dict d; d = extract(object(entry)); - std::string url = extract(d["url"]); - announce_entry ae(url); - if (d.has_key("tier")) - ae.tier = extract(d["tier"]); - if (d.has_key("fail_limit")) - ae.fail_limit = extract(d["fail_limit"]); - if (d.has_key("source")) - ae.source = extract(d["source"]); - if (d.has_key("verified")) - ae.verified = extract(d["verified"]); - if (d.has_key("send_stats")) - ae.send_stats = extract(d["send_stats"]); + announce_entry ae; + dict_to_announce_entry(d, ae); + result.push_back(ae); } } @@ -198,7 +219,14 @@ void replace_trackers(torrent_handle& h, object trackers) h.replace_trackers(result); } -list trackers(torrent_handle &h) +void add_tracker(torrent_handle& h, dict d) +{ + announce_entry ae; + dict_to_announce_entry(d, ae); + h.add_tracker(ae); +} + +list trackers(torrent_handle& h) { list ret; std::vector const trackers = h.trackers(); @@ -259,6 +287,11 @@ list get_download_queue(torrent_handle& handle) return ret; } +void set_metadata(torrent_handle& handle, std::string const& buf) +{ + handle.set_metadata(buf.c_str(), buf.size()); +} + namespace { tcp::endpoint tuple_to_endpoint(tuple const& t) @@ -331,10 +364,15 @@ void bind_torrent_handle() .def("file_progress", file_progress) .def("trackers", trackers) .def("replace_trackers", replace_trackers) + .def("add_tracker", add_tracker) .def("add_url_seed", _(&torrent_handle::add_url_seed)) .def("remove_url_seed", _(&torrent_handle::remove_url_seed)) .def("url_seeds", url_seeds) + .def("add_http_seed", _(&torrent_handle::add_http_seed)) + .def("remove_http_seed", _(&torrent_handle::remove_http_seed)) + .def("http_seeds", http_seeds) .def("get_torrent_info", _(&torrent_handle::get_torrent_info), return_internal_reference<>()) + .def("set_metadata", set_metadata) .def("is_valid", _(&torrent_handle::is_valid)) .def("pause", _(&torrent_handle::pause), arg("flags") = 0) .def("resume", _(&torrent_handle::resume)) @@ -393,6 +431,7 @@ void bind_torrent_handle() .def("set_upload_mode", _(&torrent_handle::set_upload_mode)) .def("set_share_mode", _(&torrent_handle::set_share_mode)) .def("flush_cache", &torrent_handle::flush_cache) + .def("apply_ip_filter", &torrent_handle::apply_ip_filter) .def("set_upload_limit", _(&torrent_handle::set_upload_limit)) .def("upload_limit", _(&torrent_handle::upload_limit)) .def("set_download_limit", _(&torrent_handle::set_download_limit)) @@ -406,7 +445,9 @@ void bind_torrent_handle() .def("connect_peer", &connect_peer) .def("save_path", _(&torrent_handle::save_path)) .def("set_max_uploads", _(&torrent_handle::set_max_uploads)) + .def("max_uploads", _(&torrent_handle::max_uploads)) .def("set_max_connections", _(&torrent_handle::set_max_connections)) + .def("max_connections", _(&torrent_handle::max_connections)) .def("set_tracker_login", _(&torrent_handle::set_tracker_login)) .def("move_storage", _(move_storage0)) .def("info_hash", _(&torrent_handle::info_hash)) diff --git a/bindings/python/src/torrent_info.cpp b/bindings/python/src/torrent_info.cpp index d96a0b1c3..749476377 100644 --- a/bindings/python/src/torrent_info.cpp +++ b/bindings/python/src/torrent_info.cpp @@ -42,6 +42,50 @@ namespace return result; } + list get_web_seeds(torrent_info const& ti) + { + std::vector const& ws = ti.web_seeds(); + list ret; + for (std::vector::const_iterator i = ws.begin() + , end(ws.end()); i != end; ++i) + { + dict d; + d["url"] = i->url; + d["type"] = i->type; + d["auth"] = i->auth; + d["extra_headers"] = i->extra_headers; + d["retry"] = total_seconds(i->retry - min_time()); + d["resolving"] = i->resolving; + d["removed"] = i->removed; + d["endpoint"] = make_tuple( + boost::lexical_cast(i->endpoint.address()), i->endpoint.port()); + ret.append(d); + } + + return ret; + } + + list get_merkle_tree(torrent_info const& ti) + { + std::vector const& mt = ti.merkle_tree(); + list ret; + for (std::vector::const_iterator i = mt.begin() + , end(mt.end()); i != end; ++i) + { + ret.append(i->to_string()); + } + return ret; + } + + void set_merkle_tree(torrent_info& ti, list hashes) + { + std::vector h; + for (int i = 0, e = len(hashes); i < e; ++i) + h.push_back(sha1_hash(extract(hashes[i]))); + + ti.set_merkle_tree(h); + } + file_storage::iterator begin_files(torrent_info& i) { return i.begin_files(); @@ -161,6 +205,8 @@ void bind_torrent_info() .def("remap_files", &remap_files) .def("add_tracker", &torrent_info::add_tracker, arg("url")) .def("add_url_seed", &torrent_info::add_url_seed) + .def("add_http_seed", &torrent_info::add_http_seed) + .def("web_seeds", get_web_seeds) .def("name", &torrent_info::name, copy) .def("comment", &torrent_info::comment, copy) @@ -172,6 +218,8 @@ void bind_torrent_info() .def("info_hash", &torrent_info::info_hash, copy) #endif .def("hash_for_piece", &hash_for_piece) + .def("merkle_tree", get_merkle_tree) + .def("set_merkle_tree", set_merkle_tree) .def("piece_size", &torrent_info::piece_size) .def("num_files", &torrent_info::num_files, (arg("storage")=false)) diff --git a/bindings/python/src/torrent_status.cpp b/bindings/python/src/torrent_status.cpp index 5346b26a6..a891ea475 100644 --- a/bindings/python/src/torrent_status.cpp +++ b/bindings/python/src/torrent_status.cpp @@ -63,6 +63,7 @@ void bind_torrent_status() .def_readonly("num_incomplete", &torrent_status::num_incomplete) .def_readonly("list_seeds", &torrent_status::list_seeds) .def_readonly("list_peers", &torrent_status::list_peers) + .def_readonly("connect_candidates", &torrent_status::connect_candidates) .add_property("pieces", &pieces) .add_property("verified_pieces", &verified_pieces) .def_readonly("num_pieces", &torrent_status::num_pieces) @@ -92,6 +93,7 @@ void bind_torrent_status() .def_readonly("seed_mode", &torrent_status::seed_mode) .def_readonly("upload_mode", &torrent_status::upload_mode) .def_readonly("share_mode", &torrent_status::share_mode) + .def_readonly("super_seeding", &torrent_status::super_seeding) .def_readonly("error", &torrent_status::error) .def_readonly("priority", &torrent_status::priority) .def_readonly("added_time", &torrent_status::added_time) @@ -101,6 +103,7 @@ void bind_torrent_status() .def_readonly("time_since_download", &torrent_status::time_since_download) .def_readonly("queue_position", &torrent_status::queue_position) .def_readonly("need_save_resume", &torrent_status::need_save_resume) + .def_readonly("ip_filter_applies", &torrent_status::ip_filter_applies) ; enum_("states") diff --git a/include/libtorrent/torrent_info.hpp b/include/libtorrent/torrent_info.hpp index 9ee774065..44415099c 100644 --- a/include/libtorrent/torrent_info.hpp +++ b/include/libtorrent/torrent_info.hpp @@ -83,6 +83,7 @@ namespace libtorrent struct TORRENT_EXPORT announce_entry { announce_entry(std::string const& u); + announce_entry(); ~announce_entry(); // tracker URL as it appeared in the torrent file diff --git a/src/torrent_info.cpp b/src/torrent_info.cpp index b8ec0ca7a..d01928f82 100644 --- a/src/torrent_info.cpp +++ b/src/torrent_info.cpp @@ -496,6 +496,20 @@ namespace libtorrent , send_stats(true) {} + announce_entry::announce_entry() + : next_announce(min_time()) + , min_announce(min_time()) + , tier(0) + , fail_limit(0) + , fails(0) + , updating(false) + , source(0) + , verified(false) + , start_sent(false) + , complete_sent(false) + , send_stats(true) + {} + announce_entry::~announce_entry() {} int announce_entry::next_announce_in() const