blob: 4d36bcdfc91917a64563fd31a71bc5ed9db7a296 [file]
#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_