Advertisement
Guest User

Untitled

a guest
Oct 21st, 2018
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.93 KB | None | 0 0
  1. HttpDownloader::HttpDownloader(boost::asio::io_context& io_context)
  2.     : resolver_(io_context),
  3.       ssl_context_(boost::asio::ssl::context::tlsv12_client),
  4.       stream_(io_context, ssl_context_)
  5. {
  6.     // Nothing
  7. }
  8.  
  9. HttpDownloader::~HttpDownloader() = default;
  10.  
  11. // static
  12. std::shared_ptr<HttpDownloader> HttpDownloader::create(boost::asio::io_context& io_context)
  13. {
  14.     return std::shared_ptr<HttpDownloader>(new HttpDownloader(io_context));
  15. }
  16.  
  17. void HttpDownloader::start(const std::string& file_url,
  18.                            const std::filesystem::path& file_path,
  19.                            Delegate* delegate)
  20. {
  21.     DCHECK(delegate);
  22.  
  23.     file_path_ = file_path;
  24.     delegate_ = delegate;
  25.  
  26.     //network::uri url(file_url);
  27.     const char host[] = "update.aspia.org";
  28.     const char path[] = "/version.xml";
  29.     const char port[] = "443";
  30.  
  31.     // Set SNI Hostname (many hosts need this to handshake successfully).
  32.     if (!SSL_set_tlsext_host_name(stream_.native_handle(), host))
  33.     {
  34.         LOG(LS_WARNING) << "SSL_set_tlsext_host_name failed";
  35.         return;
  36.     }
  37.  
  38.     stream_.set_verify_mode(boost::asio::ssl::verify_none);
  39.  
  40.     // Set up an HTTP GET request message.
  41.     request_.version(11); // Using HTTP/1.1.
  42.     request_.method(boost::beast::http::verb::get);
  43.     request_.target(path);
  44.     request_.set(boost::beast::http::field::host, host);
  45.     request_.set(boost::beast::http::field::user_agent, BOOST_BEAST_VERSION_STRING);
  46.  
  47.     // Look up the domain name.
  48.     resolver_.async_resolve(
  49.         host,
  50.         port,
  51.         std::bind(&HttpDownloader::onResolve,
  52.                   shared_from_this(),
  53.                   std::placeholders::_1,
  54.                   std::placeholders::_2));
  55. }
  56.  
  57. void HttpDownloader::onResolve(const boost::system::error_code& error_code,
  58.                                boost::asio::ip::tcp::resolver::results_type results)
  59. {
  60.     if (error_code)
  61.     {
  62.         delegate_->onErrorOccurred(ErrorCode::URL_OPEN_ERROR);
  63.         return;
  64.     }
  65.  
  66.     // Make the connection on the IP address we get from a lookup.
  67.     boost::asio::async_connect(
  68.         stream_.next_layer(),
  69.         results.begin(),
  70.         results.end(),
  71.         std::bind(&HttpDownloader::onConnect,
  72.                   shared_from_this(),
  73.                   std::placeholders::_1));
  74. }
  75.  
  76. void HttpDownloader::onConnect(const boost::system::error_code& error_code)
  77. {
  78.     if (error_code)
  79.     {
  80.         delegate_->onErrorOccurred(ErrorCode::URL_OPEN_ERROR);
  81.         return;
  82.     }
  83.  
  84.     // Perform the SSL handshake.
  85.     stream_.async_handshake(
  86.         boost::asio::ssl::stream_base::client,
  87.         std::bind(&HttpDownloader::onHandshake,
  88.                   shared_from_this(),
  89.                   std::placeholders::_1));
  90. }
  91.  
  92. void HttpDownloader::onHandshake(const boost::system::error_code& error_code)
  93. {
  94.     if (error_code)
  95.     {
  96.         delegate_->onErrorOccurred(ErrorCode::URL_OPEN_ERROR);
  97.         return;
  98.     }
  99.  
  100.     // Send the HTTP request to the remote host.
  101.     boost::beast::http::async_write(
  102.         stream_,
  103.         request_,
  104.         std::bind(&HttpDownloader::onWrite,
  105.                   shared_from_this(),
  106.                   std::placeholders::_1,
  107.                   std::placeholders::_2));
  108. }
  109.  
  110. void HttpDownloader::onWrite(const boost::system::error_code& error_code,
  111.                              size_t /* bytes_transferred */)
  112. {
  113.     if (error_code)
  114.     {
  115.         delegate_->onErrorOccurred(ErrorCode::URL_READ_ERROR);
  116.         return;
  117.     }
  118.  
  119.     boost::beast::http::file_body::value_type file;
  120.     boost::beast::error_code ec;
  121.  
  122.     file.open(file_path_.string().c_str(), boost::beast::file_mode::write, ec);
  123.     if (!file.is_open())
  124.     {
  125.         delegate_->onErrorOccurred(ErrorCode::FILE_OPEN_ERROR);
  126.         return;
  127.     }
  128.  
  129.     response_.body() = std::move(file);
  130.  
  131.     // Receive the HTTP response
  132.     boost::beast::http::async_read(
  133.         stream_,
  134.         buffer_,
  135.         response_,
  136.         std::bind(&HttpDownloader::onRead,
  137.                   shared_from_this(),
  138.                   std::placeholders::_1,
  139.                   std::placeholders::_2));
  140. }
  141.  
  142. void HttpDownloader::onRead(const boost::system::error_code& error_code,
  143.                             size_t /* bytes_transferred */)
  144. {
  145.     if (error_code)
  146.     {
  147.         delegate_->onErrorOccurred(ErrorCode::URL_READ_ERROR);
  148.         return;
  149.     }
  150.  
  151.     // Gracefully close the stream.
  152.     stream_.async_shutdown(std::bind(&HttpDownloader::onShutdown,
  153.                                      shared_from_this(),
  154.                                      std::placeholders::_1));
  155. }
  156.  
  157. void HttpDownloader::onShutdown(const boost::system::error_code& error_code)
  158. {
  159.     if (error_code && (error_code != boost::asio::ssl::error::stream_truncated &&
  160.                        error_code != boost::asio::error::eof))
  161.     {
  162.         delegate_->onErrorOccurred(ErrorCode::URL_READ_ERROR);
  163.         return;
  164.     }
  165.  
  166.     delegate_->onFinished();
  167. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement