diff --git a/.gitignore b/.gitignore index 5a228cc04..eea090af1 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ *.exe *.out *.app +libtool *.m4 *.in @@ -60,3 +61,8 @@ bindings/python/*flags # Logs libtorrent_logs* *.log + +# Python related files and dirs +*.pyc +dist +*.egg-info diff --git a/ChangeLog b/ChangeLog index 4d6e01233..e04d7a4e4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -55,6 +55,8 @@ * resume data no longer has timestamps of files * require C++11 to build libtorrent + * add web_seed_name_lookup_retry to session_settings + * slightly improve proxy settings backwards compatibility * add function to get default settings * updating super seeding would include the torrent in state_update_alert * fix issue where num_seeds could be greater than num_peers in torrent_status diff --git a/bindings/python/src/datetime.cpp b/bindings/python/src/datetime.cpp index 35dcc488c..10d85cf6f 100644 --- a/bindings/python/src/datetime.cpp +++ b/bindings/python/src/datetime.cpp @@ -58,25 +58,42 @@ struct time_duration_to_python } }; +template struct tag {}; + +lt::time_point now(tag) +{ return lt::clock_type::now(); } + +lt::time_point32 now(tag) +{ return lt::time_point_cast(lt::clock_type::now()); } + +template struct time_point_to_python { - static PyObject* convert(lt::time_point const pt) + static PyObject* convert(T const pt) { using std::chrono::system_clock; using std::chrono::duration_cast; - time_t const tm = system_clock::to_time_t(system_clock::now() - + duration_cast(pt - lt::clock_type::now())); + object result; + if (pt > T()) + { + time_t const tm = system_clock::to_time_t(system_clock::now() + + duration_cast(pt - now(tag()))); - std::tm* date = std::localtime(&tm); - object result = datetime_datetime( - (int)1900 + date->tm_year - // tm use 0-11 and we need 1-12 - , (int)date->tm_mon + 1 - , (int)date->tm_mday - , date->tm_hour - , date->tm_min - , date->tm_sec - ); + std::tm* date = std::localtime(&tm); + result = datetime_datetime( + (int)1900 + date->tm_year + // tm use 0-11 and we need 1-12 + , (int)date->tm_mon + 1 + , (int)date->tm_mday + , date->tm_hour + , date->tm_min + , date->tm_sec + ); + } + else + { + result = object(); + } return incref(result.ptr()); } }; @@ -115,11 +132,17 @@ void bind_datetime() , ptime_to_python>(); to_python_converter(); + , time_point_to_python>(); + + to_python_converter>(); to_python_converter>(); + to_python_converter>(); + to_python_converter>(); diff --git a/bindings/python/src/torrent_handle.cpp b/bindings/python/src/torrent_handle.cpp index a64f0641b..10f90cb79 100644 --- a/bindings/python/src/torrent_handle.cpp +++ b/bindings/python/src/torrent_handle.cpp @@ -197,14 +197,6 @@ void dict_to_announce_entry(dict d, announce_entry& ae) 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"]); -#ifndef TORRENT_NO_DEPRECATE - if (d.has_key("send_stats")) - ae.send_stats = extract(d["send_stats"]); -#endif } void replace_trackers(torrent_handle& h, object trackers) @@ -253,6 +245,14 @@ list trackers(torrent_handle& h) { dict d; d["url"] = i->url; + d["trackerid"] = i->trackerid; + d["message"] = i->message; + d["last_error"] = i->last_error; + d["next_announce"] = i->next_announce; + d["min_announce"] = i->min_announce; + d["scrape_incomplete"] = i->scrape_incomplete; + d["scrape_complete"] = i->scrape_complete; + d["scrape_downloaded"] = i->scrape_downloaded; d["tier"] = i->tier; d["fail_limit"] = i->fail_limit; d["fails"] = i->fails; diff --git a/bindings/python/src/torrent_info.cpp b/bindings/python/src/torrent_info.cpp index 4cfb62c40..e12eaad4e 100644 --- a/bindings/python/src/torrent_info.cpp +++ b/bindings/python/src/torrent_info.cpp @@ -20,6 +20,7 @@ using namespace boost::python; using namespace libtorrent; +namespace lt = libtorrent; namespace { @@ -124,16 +125,21 @@ namespace return result; } - int get_tier(announce_entry const& ae) { return ae.tier; } - void set_tier(announce_entry& ae, int v) { ae.tier = v; } - int get_fail_limit(announce_entry const& ae) { return ae.fail_limit; } - void set_fail_limit(announce_entry& ae, int l) { ae.fail_limit = l; } + // Create getters for announce_entry data members with non-trivial types which need converting. + lt::time_point get_next_announce(announce_entry const& ae) { return ae.next_announce; } + lt::time_point get_min_announce(announce_entry const& ae) { return ae.min_announce; } + // announce_entry data member bit-fields. int get_fails(announce_entry const& ae) { return ae.fails; } int get_source(announce_entry const& ae) { return ae.source; } bool get_verified(announce_entry const& ae) { return ae.verified; } bool get_updating(announce_entry const& ae) { return ae.updating; } bool get_start_sent(announce_entry const& ae) { return ae.start_sent; } bool get_complete_sent(announce_entry const& ae) { return ae.complete_sent; } + // announce_entry method requires lt::time_point. + bool can_announce(announce_entry const& ae, bool is_seed) { + lt::time_point now = lt::clock_type::now(); + return ae.can_announce(now, is_seed); + } #ifndef TORRENT_NO_DEPRECATE bool get_send_stats(announce_entry const& ae) { return ae.send_stats; } @@ -306,8 +312,16 @@ void bind_torrent_info() class_("announce_entry", init()) .def_readwrite("url", &announce_entry::url) - .add_property("tier", &get_tier, &set_tier) - .add_property("fail_limit", &get_fail_limit, &set_fail_limit) + .def_readonly("trackerid", &announce_entry::trackerid) + .def_readonly("message", &announce_entry::message) + .def_readonly("last_error", &announce_entry::last_error) + .add_property("next_announce", &get_next_announce) + .add_property("min_announce", &get_min_announce) + .def_readonly("scrape_incomplete", &announce_entry::scrape_incomplete) + .def_readonly("scrape_complete", &announce_entry::scrape_complete) + .def_readonly("scrape_downloaded", &announce_entry::scrape_downloaded) + .def_readwrite("tier", &announce_entry::tier) + .def_readwrite("fail_limit", &announce_entry::fail_limit) .add_property("fails", &get_fails) .add_property("source", &get_source) .add_property("verified", &get_verified) @@ -318,8 +332,10 @@ void bind_torrent_info() .add_property("send_stats", &get_send_stats) #endif + .def("next_announce_in", &announce_entry::next_announce_in) + .def("min_announce_in", &announce_entry::min_announce_in) .def("reset", &announce_entry::reset) - .def("can_announce", &announce_entry::can_announce) + .def("can_announce", can_announce) .def("is_working", &announce_entry::is_working) .def("trim", &announce_entry::trim) ; diff --git a/bindings/python/test.py b/bindings/python/test.py index b6077537b..533ca4b70 100644 --- a/bindings/python/test.py +++ b/bindings/python/test.py @@ -74,6 +74,20 @@ class test_torrent_handle(unittest.TestCase): self.h.prioritize_pieces([(0, 1)]) self.assertEqual(self.h.piece_priorities(), [1]) + def test_replace_trackers(self): + self.setup() + trackers = [] + for idx, tracker_url in enumerate(('udp://tracker1.com', 'udp://tracker2.com')): + tracker = lt.announce_entry(tracker_url) + tracker.tier = idx + tracker.fail_limit = 2 + trackers.append(tracker) + self.h.replace_trackers(trackers) + new_trackers = self.h.trackers() + self.assertEqual(new_trackers[0]['url'], 'udp://tracker1.com') + self.assertEqual(new_trackers[1]['tier'], 1) + self.assertEqual(new_trackers[1]['fail_limit'], 2) + def test_file_status(self): self.setup() l = self.h.file_status() @@ -238,6 +252,12 @@ class test_torrent_info(unittest.TestCase): idx += 1 + def test_announce_entry(self): + ae = lt.announce_entry('test') + self.assertEquals(ae.can_announce(False), True) + self.assertEquals(ae.scrape_incomplete, -1) + self.assertEquals(ae.next_announce, None) + class test_alerts(unittest.TestCase): def test_alert(self): diff --git a/include/libtorrent/settings_pack.hpp b/include/libtorrent/settings_pack.hpp index 7aa450f97..617ec3675 100644 --- a/include/libtorrent/settings_pack.hpp +++ b/include/libtorrent/settings_pack.hpp @@ -810,7 +810,10 @@ namespace libtorrent // time to wait until a new retry of a web seed takes place urlseed_wait_retry, - + + // time to wait until a new retry of a web seed name lookup + web_seed_name_lookup_retry, + // sets the upper limit on the total number of files this session will // keep open. The reason why files are left open at all is that some // anti virus software hooks on every file close, and scans the file diff --git a/src/enum_net.cpp b/src/enum_net.cpp index 1663fb292..a01eb0c7d 100644 --- a/src/enum_net.cpp +++ b/src/enum_net.cpp @@ -614,15 +614,13 @@ namespace libtorrent strncpy(r.name, adapter->AdapterName, sizeof(r.name)); r.name[sizeof(r.name)-1] = 0; r.mtu = adapter->Mtu; - IP_ADAPTER_UNICAST_ADDRESS* unicast = adapter->FirstUnicastAddress; - while (unicast) + for (IP_ADAPTER_UNICAST_ADDRESS* unicast = adapter->FirstUnicastAddress; + unicast; unicast = unicast->Next) { - if (valid_addr_family(unicast->Address.lpSockaddr->sa_family)) - { - r.interface_address = sockaddr_to_address(unicast->Address.lpSockaddr); - ret.push_back(r); - } - unicast = unicast->Next; + if (!valid_addr_family(unicast->Address.lpSockaddr->sa_family)) + continue; + r.interface_address = sockaddr_to_address(unicast->Address.lpSockaddr); + ret.push_back(r); } } diff --git a/src/session_handle.cpp b/src/session_handle.cpp index 291cb64b7..a2a034f64 100644 --- a/src/session_handle.cpp +++ b/src/session_handle.cpp @@ -930,14 +930,19 @@ namespace libtorrent set_proxy(s); } - void session_handle::set_web_seed_proxy(proxy_settings const& s) + void session_handle::set_web_seed_proxy(proxy_settings const&) { - set_proxy(s); + // NO-OP } void session_handle::set_tracker_proxy(proxy_settings const& s) { - set_proxy(s); + // if the tracker proxy is enabled, set the "proxy_tracker_connections" + // setting + settings_pack pack; + pack.set_bool(settings_pack::proxy_tracker_connections + , s.type != aux::proxy_settings::none); + apply_settings(pack); } proxy_settings session_handle::peer_proxy() const @@ -952,12 +957,14 @@ namespace libtorrent proxy_settings session_handle::tracker_proxy() const { - return proxy(); + settings_pack const sett = get_settings(); + return sett.get_bool(settings_pack::proxy_tracker_connections) + ? proxy_settings(sett) : proxy_settings(); } - void session_handle::set_dht_proxy(proxy_settings const& s) + void session_handle::set_dht_proxy(proxy_settings const&) { - set_proxy(s); + // NO-OP } proxy_settings session_handle::dht_proxy() const diff --git a/src/settings_pack.cpp b/src/settings_pack.cpp index 69b844bc6..cbc0b91cc 100644 --- a/src/settings_pack.cpp +++ b/src/settings_pack.cpp @@ -213,6 +213,7 @@ namespace libtorrent SET(urlseed_pipeline_size, 5, nullptr), SET(urlseed_max_request_bytes, 16 * 1024 * 1024, 0), SET(urlseed_wait_retry, 30, nullptr), + SET(web_seed_name_lookup_retry, 1800, nullptr), SET(file_pool_size, 40, nullptr), SET(max_failcount, 3, &session_impl::update_max_failcount), SET(min_reconnect_time, 60, nullptr), diff --git a/src/torrent.cpp b/src/torrent.cpp index 363a29e55..2be64a8a8 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -5727,8 +5727,9 @@ namespace libtorrent } #endif - // unavailable, retry in 30 minutes - web->retry = aux::time_now32() + minutes32(30); + // unavailable, retry in `settings_pack::web_seed_name_lookup_retry` seconds + web->retry = aux::time_now32() + + seconds32(settings().get_int(settings_pack::web_seed_name_lookup_retry)); return; }