diff --git a/include/libtorrent/Makefile.am b/include/libtorrent/Makefile.am index 3e0aa0147..83a0174d2 100644 --- a/include/libtorrent/Makefile.am +++ b/include/libtorrent/Makefile.am @@ -80,6 +80,7 @@ nobase_include_HEADERS = \ natpmp.hpp \ netlink.hpp \ operations.hpp \ + optional.hpp \ packet_buffer.hpp \ packet_pool.hpp \ parse_url.hpp \ diff --git a/include/libtorrent/http_parser.hpp b/include/libtorrent/http_parser.hpp index ee251a1fb..f1710a874 100644 --- a/include/libtorrent/http_parser.hpp +++ b/include/libtorrent/http_parser.hpp @@ -43,6 +43,8 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/config.hpp" #include "libtorrent/span.hpp" #include "libtorrent/string_view.hpp" +#include "libtorrent/time.hpp" // for seconds32 +#include "libtorrent/optional.hpp" namespace libtorrent { @@ -62,7 +64,7 @@ namespace libtorrent { explicit http_parser(int flags = 0); ~http_parser(); std::string const& header(string_view key) const; - std::int64_t header_int(string_view key, std::int64_t def_value) const; + boost::optional header_duration(string_view key) const; std::string const& protocol() const { return m_protocol; } int status_code() const { return m_status_code; } std::string const& method() const { return m_method; } diff --git a/include/libtorrent/optional.hpp b/include/libtorrent/optional.hpp new file mode 100644 index 000000000..143e14193 --- /dev/null +++ b/include/libtorrent/optional.hpp @@ -0,0 +1,51 @@ +/* + +Copyright (c) 2017, Arvid Norberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + + +#ifndef TORRENT_OPTIONAL_HPP_INCLUDED +#define TORRENT_OPTIONAL_HPP_INCLUDED + +#include "libtorrent/aux_/disable_warnings_push.hpp" +#include +#include "libtorrent/aux_/disable_warnings_pop.hpp" + +namespace libtorrent { + + template + T value_or(boost::optional opt, U def) + { + return opt ? *opt : T(def); + } +} + +#endif + diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index eee85e25d..7bedc8b99 100644 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -41,6 +41,7 @@ POSSIBILITY OF SUCH DAMAGE. #include // for numeric_limits #include // for unique_ptr +#include "libtorrent/optional.hpp" #include "libtorrent/torrent_handle.hpp" #include "libtorrent/entry.hpp" #include "libtorrent/torrent_info.hpp" @@ -629,7 +630,7 @@ namespace libtorrent { void remove_web_seed(std::string const& url, web_seed_t::type_t type); void disconnect_web_seed(peer_connection* p); - void retry_web_seed(peer_connection* p, int retry = 0); + void retry_web_seed(peer_connection* p, boost::optional retry = boost::none); void remove_web_seed_conn(peer_connection* p, error_code const& ec , operation_t op, int error = 0); diff --git a/src/http_parser.cpp b/src/http_parser.cpp index 0cd899c2f..694decf72 100644 --- a/src/http_parser.cpp +++ b/src/http_parser.cpp @@ -43,6 +43,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/parse_url.hpp" // for parse_url_components #include "libtorrent/string_util.hpp" // for ensure_trailing_slash, to_lower #include "libtorrent/aux_/escape_string.hpp" // for read_until +#include "libtorrent/time.hpp" // for seconds32 namespace libtorrent { @@ -139,14 +140,14 @@ namespace libtorrent { return i->second; } - std::int64_t http_parser::header_int(string_view const key, std::int64_t const def_value) const + boost::optional http_parser::header_duration(string_view const key) const { // TODO: remove to_string() if we're in C++14 auto const i = m_header.find(key.to_string()); - if (i == m_header.end()) return def_value; - auto const val = std::atoll(i->second.c_str()); - if (val <= 0) return def_value; - return val; + if (i == m_header.end()) return boost::none; + auto const val = std::atol(i->second.c_str()); + if (val <= 0) return boost::none; + return seconds32(val); } http_parser::~http_parser() = default; diff --git a/src/http_seed_connection.cpp b/src/http_seed_connection.cpp index 3081814d0..4f3d11351 100644 --- a/src/http_seed_connection.cpp +++ b/src/http_seed_connection.cpp @@ -38,6 +38,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/aux_/session_impl.hpp" #include "libtorrent/peer_info.hpp" #include "libtorrent/hex.hpp" // for is_hex +#include "libtorrent/optional.hpp" namespace libtorrent { @@ -274,7 +275,9 @@ namespace libtorrent { // if the status code is not one of the accepted ones, abort if (!is_ok_status(m_parser.status_code())) { - int const retry_time = aux::numeric_cast(m_parser.header_int("retry-after", 5 * 60)); + auto const retry_time = value_or(m_parser.header_duration("retry-after") + , minutes32(5)); + // temporarily unavailable, retry later t->retry_web_seed(this, retry_time); @@ -420,7 +423,7 @@ namespace libtorrent { received_bytes(0, int(bytes_transferred)); // temporarily unavailable, retry later - t->retry_web_seed(this, retry_time); + t->retry_web_seed(this, seconds32(retry_time)); disconnect(error_code(m_parser.status_code(), http_category()), operation_t::bittorrent, 1); return; } diff --git a/src/torrent.cpp b/src/torrent.cpp index 8a8658ebc..96fd7dbe7 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -9972,7 +9972,7 @@ namespace libtorrent { remove_web_seed_iter(i); } - void torrent::retry_web_seed(peer_connection* p, int retry) + void torrent::retry_web_seed(peer_connection* p, boost::optional const retry) { TORRENT_ASSERT(is_single_thread()); auto const i = std::find_if(m_web_seeds.begin(), m_web_seeds.end() @@ -9981,8 +9981,8 @@ namespace libtorrent { TORRENT_ASSERT(i != m_web_seeds.end()); if (i == m_web_seeds.end()) return; if (i->removed) return; - if (retry == 0) retry = settings().get_int(settings_pack::urlseed_wait_retry); - i->retry = aux::time_now32() + seconds32(retry); + i->retry = aux::time_now32() + value_or(retry, seconds32( + settings().get_int(settings_pack::urlseed_wait_retry))); } torrent_state torrent::get_peer_list_state() diff --git a/src/web_peer_connection.cpp b/src/web_peer_connection.cpp index e648f613c..1658c5542 100644 --- a/src/web_peer_connection.cpp +++ b/src/web_peer_connection.cpp @@ -578,7 +578,8 @@ void web_peer_connection::handle_error(int const bytes_left) // associated with the file we just requested. Only // when it doesn't have any of the file do the following // pad files will make it complicated - int const retry_time = aux::numeric_cast(m_parser.header_int("retry-after", m_settings.get_int(settings_pack::urlseed_wait_retry))); + auto const retry_time = value_or(m_parser.header_duration("retry-after") + , seconds32(m_settings.get_int(settings_pack::urlseed_wait_retry))); // temporarily unavailable, retry later t->retry_web_seed(this, retry_time); if (t->alerts().should_post()) diff --git a/test/test_http_parser.cpp b/test/test_http_parser.cpp index b84c85ce7..a3c1504b0 100644 --- a/test/test_http_parser.cpp +++ b/test/test_http_parser.cpp @@ -91,8 +91,8 @@ TORRENT_TEST(http_parser) TEST_CHECK(std::equal(body.begin(), body.end(), "test")); TEST_CHECK(parser.header("content-type") == "text/plain"); TEST_CHECK(atoi(parser.header("content-length").c_str()) == 4); - TEST_CHECK(atoi(parser.header("content-length").c_str()) == parser.header_int("content-length",-1)); - TEST_CHECK(parser.header_int("content-length-x",-123) == -123); + TEST_CHECK(*parser.header_duration("content-length") == lt::seconds32(4)); + TEST_CHECK(parser.header_duration("content-length-x") == boost::none); parser.reset();