20 #include <ripple/net/HTTPDownloader.h>
21 #include <boost/asio/ssl.hpp>
26 boost::asio::io_service& io_service,
33 , sessionActive_(false)
43 boost::filesystem::path
const& dstPath,
58 if (!
strand_.running_in_this_thread())
82 std::placeholders::_1));
92 boost::filesystem::path dstPath,
95 boost::asio::yield_context yield)
98 using namespace boost::beast;
100 boost::system::error_code ec;
106 auto close = [&](
auto p) {
110 stream_->getStream().shutdown(socket_base::shutdown_both, ec);
111 if (ec == boost::asio::error::eof)
112 ec.assign(0, ec.category());
117 JLOG(
j_.
trace()) <<
"shutdown: " << ec.message();
128 auto exit = [
this, &dstPath, complete] {
130 complete(std::move(dstPath));
137 auto failAndExit = [&exit, &dstPath, complete, &ec,
this](
139 fail(dstPath, ec, errMsg, p);
148 auto p = this->
getParser(dstPath, complete, ec);
150 return failAndExit(
"getParser", p);
161 if (!
stream_->connect(error, host, port, yield))
162 return failAndExit(error, p);
165 http::request<http::empty_body> req{http::verb::head, target, version};
166 req.set(http::field::host, host);
167 req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
176 (boost::format(
"bytes=%llu-") % rangeStart).str());
179 stream_->asyncWrite(req, yield, ec);
181 return failAndExit(
"async_write", p);
185 http::response_parser<http::empty_body> connectParser;
186 connectParser.skip(
true);
189 return failAndExit(
"async_read", p);
192 if (connectParser.get().result() == http::status::range_not_satisfiable)
194 req.erase(http::field::range);
196 stream_->asyncWrite(req, yield, ec);
198 return failAndExit(
"async_write_range_verify", p);
200 http::response_parser<http::empty_body> rangeParser;
201 rangeParser.skip(
true);
205 return failAndExit(
"async_read_range_verify", p);
208 if (rangeParser.content_length() == rangeStart)
211 return failAndExit(
"range_not_satisfiable", p);
215 connectParser.get().result() != http::status::partial_content)
218 boost::system::errc::not_supported,
219 boost::system::generic_category());
221 return failAndExit(
"Range request ignored", p);
223 else if (
auto len = connectParser.content_length())
228 if (*len > space(dstPath.parent_path()).available)
231 "Insufficient disk space for download", p);
244 req.method(http::verb::get);
250 (boost::format(
"bytes=%llu-") % rangeStart).str());
254 stream_->asyncWrite(req, yield, ec);
256 return failAndExit(
"async_write", p);
265 while (!p->is_done())
276 JLOG(
j_.
trace()) <<
"download completed: " << dstPath.string();
297 boost::filesystem::path dstPath,
298 boost::system::error_code
const& ec,
306 else if (ec != boost::asio::error::operation_aborted)
308 JLOG(
j_.
error()) << errMsg <<
": " << ec.message();
321 <<
" in function: " << __func__;