20 #include <ripple/net/SSLHTTPDownloader.h>
21 #include <boost/asio/ssl.hpp>
26 boost::asio::io_service& io_service,
31 , ssl_ctx_(config, j,
boost::asio::ssl::context::tlsv12_client)
34 , sessionActive_(false)
44 boost::filesystem::path
const& dstPath,
50 if (!
strand_.running_in_this_thread())
72 std::placeholders::_1));
96 boost::filesystem::path dstPath,
98 boost::asio::yield_context yield)
101 using namespace boost::beast;
103 boost::system::error_code ec;
112 ip::tcp::resolver resolver{
strand_.context()};
113 auto const results = resolver.async_resolve(host, port, yield[ec]);
115 return fail(dstPath, complete, ec,
"async_resolve",
parser);
133 return fail(dstPath, complete, ec,
"preConnectVerify",
parser);
135 boost::asio::async_connect(
136 stream_->next_layer(), results.begin(), results.end(), yield[ec]);
138 return fail(dstPath, complete, ec,
"async_connect",
parser);
142 return fail(dstPath, complete, ec,
"postConnectVerify",
parser);
144 stream_->async_handshake(ssl::stream_base::client, yield[ec]);
146 return fail(dstPath, complete, ec,
"async_handshake",
parser);
149 http::request<http::empty_body> req{http::verb::head, target, version};
150 req.set(http::field::host, host);
151 req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
158 (boost::format(
"bytes=%llu-") % rangeStart).str());
161 http::async_write(*
stream_, req, yield[ec]);
163 return fail(dstPath, complete, ec,
"async_write",
parser);
167 http::response_parser<http::empty_body> p;
171 return fail(dstPath, complete, ec,
"async_read",
parser);
174 if (p.get().result() == http::status::range_not_satisfiable)
176 req.erase(http::field::range);
178 http::async_write(*
stream_, req, yield[ec]);
184 "async_write_range_verify",
187 http::response_parser<http::empty_body> p;
196 "async_read_range_verify",
200 if (p.content_length() == rangeStart)
204 dstPath, complete, ec,
"range_not_satisfiable",
parser);
207 rangeStart && p.get().result() != http::status::partial_content)
210 boost::system::errc::not_supported,
211 boost::system::generic_category());
214 dstPath, complete, ec,
"Range request ignored",
parser);
216 else if (
auto len = p.content_length())
220 if (*len > space(dstPath.parent_path()).available)
226 "Insufficient disk space for download",
245 req.method(http::verb::get);
251 (boost::format(
"bytes=%llu-") % rangeStart).str());
255 http::async_write(*
stream_, req, yield[ec]);
257 return fail(dstPath, complete, ec,
"async_write",
parser);
262 auto close = [&](
auto p) {
266 stream_->async_shutdown(yield[ec]);
267 if (ec == boost::asio::error::eof)
268 ec.assign(0, ec.category());
273 JLOG(
j_.
trace()) <<
"async_shutdown: " << ec.message();
280 auto p = this->
getParser(dstPath, complete, ec);
282 fail(dstPath, complete, ec,
"getParser", p);
291 auto exit = [
this]() {
312 if (!connect(p) || ec)
319 while (!p->is_done())
330 JLOG(
j_.
trace()) <<
"download completed: " << dstPath.string();
336 complete(std::move(dstPath));
341 boost::filesystem::path dstPath,
342 std::function<
void(boost::filesystem::path)>
const& complete,
343 boost::system::error_code
const& ec,
351 else if (ec != boost::asio::error::operation_aborted)
353 JLOG(
j_.
error()) << errMsg <<
": " << ec.message();
366 <<
" in function: " << __func__;
368 complete(std::move(dstPath));