| #ifndef THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_HTTP_HTTP_CLIENT_H_ |
| #define THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_HTTP_HTTP_CLIENT_H_ |
| |
| #include <atomic> |
| #include <chrono> // NOLINT: BMC code base can use chrono |
| #include <cstddef> |
| #include <memory> |
| #include <string> |
| #include <string_view> |
| |
| #include "absl/functional/any_invocable.h" |
| #include "absl/status/status.h" |
| #include "boost/asio.hpp" //NOLINT: boost::asio is commonly used in BMC |
| #include "boost/asio/error.hpp" // NOLINT |
| #include "boost/asio/random_access_file.hpp" // NOLINT: boost::asio is commonly used in BMC |
| #include "boost/asio/ssl.hpp" // NOLINT: boost::asio is commonly used in BMC |
| #include "boost/beast/core.hpp" // NOLINT: boost::beast is commonly used in BMC |
| #include "boost/beast/http.hpp" // NOLINT: boost::beast is commonly used in BMC |
| #include "boost/beast/http/buffer_body.hpp" // NOLINT: boost::beast is commonly used in BMC |
| #include "boost/beast/ssl.hpp" // NOLINT: boost::beast is commonly used in BMC |
| #include "boost/beast/version.hpp" // NOLINT: boost::beast is commonly used in BMC |
| #include "boost/filesystem.hpp" // NOLINT: boost::filesystem is commonly used in BMC |
| #include "boost/filesystem/operations.hpp" // NOLINT |
| #include "boost/system/detail/error_code.hpp" // NOLINT: boost::asio is commonly used in BMC |
| #include "tlbmc/http/http_client_interface.h" |
| |
| namespace milotic_tlbmc { |
| |
| // A simple HTTP/HTTPS client for TLBMC. Only allows one active job at a time. |
| class HttpClient : public HttpClientInterface, |
| public std::enable_shared_from_this<HttpClient> { |
| public: |
| struct Options { |
| std::string ca_cert_path; |
| bool verify_hostname = true; |
| bool verify_purpose = true; |
| std::chrono::seconds resolve_timeout = std::chrono::seconds(10); |
| std::chrono::seconds connect_timeout = std::chrono::seconds(10); |
| std::chrono::seconds handshake_timeout = std::chrono::seconds(10); |
| std::chrono::seconds read_write_timeout = std::chrono::seconds(10); |
| }; |
| |
| HttpClient(boost::asio::io_context& io_context, const Options& options); |
| ~HttpClient() override = default; |
| |
| bool IsActive() override; |
| void SendRequest( |
| std::string_view host, std::string_view port, std::string_view target, |
| bool use_tls, |
| absl::AnyInvocable< |
| void(boost::beast::error_code, |
| boost::beast::http::response<boost::beast::http::string_body>)> |
| callback) override; |
| |
| // Downloads the file from the given host, port, target, use_tls to the |
| // destination_path. If progress_callback is provided, it will be called |
| // with the number of bytes downloaded and the total content length. |
| // If callback is provided, it will be called with the error code and the |
| // response. |
| // TODO(nanzhou): today this does a big read and small writes. This can be |
| // optimized to read and write in chunks. |
| void DownloadFile( |
| std::string_view host, std::string_view port, std::string_view target, |
| bool use_tls, std::string_view destination_path, |
| absl::AnyInvocable< |
| void(boost::beast::error_code, |
| boost::beast::http::response<boost::beast::http::empty_body>)> |
| callback, |
| absl::AnyInvocable<void(std::size_t bytes_downloaded, |
| std::size_t bytes_written, |
| std::size_t content_length)> |
| progress_callback) override; |
| |
| void OnResolve(boost::beast::error_code ec, |
| boost::asio::ip::tcp::resolver::results_type results) override; |
| void OnConnect(boost::beast::error_code ec, |
| boost::asio::ip::tcp::resolver::results_type::endpoint_type |
| endpoint) override; |
| void OnHandshake(boost::beast::error_code ec); |
| void OnWrite(boost::beast::error_code ec, |
| std::size_t bytes_transferred) override; |
| void OnRead(boost::beast::error_code ec, |
| std::size_t bytes_transferred) override; |
| |
| static std::unique_ptr<HttpClient> CreateWithOption( |
| boost::asio::io_context& io_context, const Options& options) { |
| return std::make_unique<HttpClient>(io_context, options); |
| } |
| |
| static std::unique_ptr<HttpClient> Create( |
| boost::asio::io_context& io_context) { |
| return std::make_unique<HttpClient>(io_context, Options()); |
| } |
| |
| protected: |
| void InitStream(); |
| boost::asio::strand<boost::asio::io_context::executor_type> executor_; |
| // Networking objects |
| boost::asio::ip::tcp::resolver resolver_; |
| boost::asio::ssl::context ssl_ctx_; |
| std::unique_ptr<boost::beast::ssl_stream<boost::beast::tcp_stream>> stream_; |
| boost::beast::flat_buffer buffer_; |
| |
| std::string host_; |
| std::string port_; |
| bool use_tls_ = false; |
| |
| std::atomic<bool> is_active_ = false; |
| bool connection_established_ = false; |
| std::shared_ptr<ScanJob> job_; |
| |
| boost::system::error_code ca_load_ec_; |
| Options options_; |
| }; |
| } // namespace milotic_tlbmc |
| |
| #endif // THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_HTTP_HTTP_CLIENT_H_ |