diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 5325a3ae78b1a13b59382d7d2c7bbbe969e86fee..f3c0d05d85d37b1074eb43ff3c99a8f54a111732 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -2,6 +2,7 @@ add_subdirectory(bnet_plugin) add_subdirectory(net_plugin) add_subdirectory(net_api_plugin) add_subdirectory(http_plugin) +add_subdirectory(http_client_plugin) add_subdirectory(chain_plugin) add_subdirectory(chain_api_plugin) add_subdirectory(producer_plugin) diff --git a/plugins/http_client_plugin/CMakeLists.txt b/plugins/http_client_plugin/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..48ae140fca6186cbed6355139032c899fc0f80b6 --- /dev/null +++ b/plugins/http_client_plugin/CMakeLists.txt @@ -0,0 +1,7 @@ +file(GLOB HEADERS "include/eosio/http_client_plugin/*.hpp") +add_library( http_client_plugin + http_client_plugin.cpp + ${HEADERS} ) + +target_link_libraries( http_client_plugin appbase fc ) +target_include_directories( http_client_plugin PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) diff --git a/plugins/http_client_plugin/http_client_plugin.cpp b/plugins/http_client_plugin/http_client_plugin.cpp new file mode 100644 index 0000000000000000000000000000000000000000..886c5f13ebf23cc9a18a26d3bf0fe3283150da4e --- /dev/null +++ b/plugins/http_client_plugin/http_client_plugin.cpp @@ -0,0 +1,60 @@ +/** + * @file + * @copyright defined in eos/LICENSE.txt + */ +#include +#include +#include + +namespace eosio { + +http_client_plugin::http_client_plugin():my(new http_client()){} +http_client_plugin::~http_client_plugin(){} + +void http_client_plugin::set_program_options(options_description&, options_description& cfg) { + cfg.add_options() + ("https-client-root-cert", boost::program_options::value>()->composing()->multitoken(), + "PEM encoded trusted root certificate (or path to file containing one) used to validate any TLS connections made. (may specify multiple times)\n") + ("https-client-validate-peers", boost::program_options::value()->default_value(true), + "true: validate that the peer certificates are valid and trusted, false: ignore cert errors") + ; + +} + +void http_client_plugin::plugin_initialize(const variables_map& options) { + if ( options.count("https-client-root-cert") ) { + const std::vector root_pems = options["https-client-root-cert"].as>(); + for (const auto& root_pem : root_pems) { + std::string pem_str = root_pem; + if (!boost::algorithm::starts_with(pem_str, "-----BEGIN CERTIFICATE-----\n")) { + try { + auto infile = std::ifstream(pem_str); + std::stringstream sstr; + sstr << infile.rdbuf(); + pem_str = sstr.str(); + FC_ASSERT(boost::algorithm::starts_with(pem_str, "-----BEGIN CERTIFICATE-----\n"), "File does not appear to be a PEM encoded certificate"); + } catch (const fc::exception& e) { + elog("Failed to read PEM ${f} : ${e}", ("f", root_pem)("e",e.to_detail_string())); + } + } + + try { + my->add_cert(pem_str); + } catch (const fc::exception& e) { + elog("Failed to read PEM : ${e} \n${pem}\n", ("pem", pem_str)("e",e.to_detail_string())); + } + } + } + + my->set_verify_peers(options.at("https-client-validate-peers").as()); +} + +void http_client_plugin::plugin_startup() { + +} + +void http_client_plugin::plugin_shutdown() { + +} + +} diff --git a/plugins/http_client_plugin/include/eosio/http_client_plugin/http_client_plugin.hpp b/plugins/http_client_plugin/include/eosio/http_client_plugin/http_client_plugin.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b4bb8a5740e7e028cae0ef499c79b85b4a3c0d65 --- /dev/null +++ b/plugins/http_client_plugin/include/eosio/http_client_plugin/http_client_plugin.hpp @@ -0,0 +1,34 @@ +/** + * @file + * @copyright defined in eos/LICENSE.txt + */ +#pragma once +#include +#include + +namespace eosio { + using namespace appbase; + using fc::http_client; + + class http_client_plugin : public appbase::plugin + { + public: + http_client_plugin(); + virtual ~http_client_plugin(); + + APPBASE_PLUGIN_REQUIRES() + virtual void set_program_options(options_description&, options_description& cfg) override; + + void plugin_initialize(const variables_map& options); + void plugin_startup(); + void plugin_shutdown(); + + http_client& get_client() { + return *my; + } + + private: + std::unique_ptr my; + }; + +} diff --git a/plugins/producer_plugin/CMakeLists.txt b/plugins/producer_plugin/CMakeLists.txt index c9fb7ec01e31a5a77d255ae27ddbdafd53f5359c..d7f9188d5bbb14fbfe42ee4a633a23b8c6dc9eb7 100644 --- a/plugins/producer_plugin/CMakeLists.txt +++ b/plugins/producer_plugin/CMakeLists.txt @@ -5,6 +5,6 @@ add_library( producer_plugin ${HEADERS} ) -target_link_libraries( producer_plugin chain_plugin appbase eosio_chain eos_utilities ) +target_link_libraries( producer_plugin chain_plugin http_client_plugin appbase eosio_chain eos_utilities ) target_include_directories( producer_plugin PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/../chain_interface/include" ) diff --git a/plugins/producer_plugin/include/eosio/producer_plugin/producer_plugin.hpp b/plugins/producer_plugin/include/eosio/producer_plugin/producer_plugin.hpp index be6efe7917143d91437ec9180977b079314bed9f..33a10f9c22169d93dccb77ca8a7156696419914d 100644 --- a/plugins/producer_plugin/include/eosio/producer_plugin/producer_plugin.hpp +++ b/plugins/producer_plugin/include/eosio/producer_plugin/producer_plugin.hpp @@ -6,6 +6,7 @@ #pragma once #include +#include #include @@ -15,7 +16,7 @@ using boost::signals2::signal; class producer_plugin : public appbase::plugin { public: - APPBASE_PLUGIN_REQUIRES((chain_plugin)) + APPBASE_PLUGIN_REQUIRES((chain_plugin)(http_client_plugin)) struct runtime_options { fc::optional max_transaction_time; diff --git a/plugins/producer_plugin/producer_plugin.cpp b/plugins/producer_plugin/producer_plugin.cpp index f68440bf797e81fcda5328d6cd3a4c4b4f091df4..d7a70b12144d2aa7f9406f107f77b3d88abffb07 100644 --- a/plugins/producer_plugin/producer_plugin.cpp +++ b/plugins/producer_plugin/producer_plugin.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include @@ -25,7 +24,6 @@ #include #include #include -#include namespace bmi = boost::multi_index; using bmi::indexed_by; @@ -155,8 +153,6 @@ class producer_plugin_impl : public std::enable_shared_from_this _accepted_block_connection; fc::optional _irreversible_block_connection; - fc::http_client _http_client; - /* * HACK ALERT * Boost timers can be in a state where a handler has not yet executed but is not abortable. @@ -434,8 +430,6 @@ void producer_plugin::set_program_options( " KEOSD: \tis the URL where keosd is available and the approptiate wallet(s) are unlocked") ("keosd-provider-timeout", boost::program_options::value()->default_value(5), "Limits the maximum time (in milliseconds) that is allowd for sending blocks to a keosd provider for signing") - ("trusted-root-cert", boost::program_options::value>()->composing()->multitoken(), - "PEM encoded trusted root certificate (or path to file containing one) used to validate any TLS connections made. (may specify multiple times)\n") ; config_file_options.add(producer_options); } @@ -490,7 +484,7 @@ make_keosd_signature_provider(const std::shared_ptr& impl, fc::variant params; fc::to_variant(std::make_pair(digest, pubkey), params); auto deadline = impl->_keosd_provider_timeout_us.count() >= 0 ? fc::time_point::now() + impl->_keosd_provider_timeout_us : fc::time_point::maximum(); - return impl->_http_client.post_sync(keosd_url, params, deadline).as(); + return app().get_plugin().get_client().post_sync(keosd_url, params, deadline).as(); } else { return signature_type(); } @@ -545,28 +539,6 @@ void producer_plugin::plugin_initialize(const boost::program_options::variables_ } } - if ( options.count("trusted-root-cert") ) { - const std::vector root_pems = options["trusted-root-cert"].as>(); - for (const auto& root_pem : root_pems) { - if (boost::algorithm::starts_with(root_pem, "-----BEGIN CERTIFICATE-----\n")) { - try { - my->_http_client.add_cert(root_pem); - } catch (const fc::exception& e) { - elog("Failed add PEM literal\n${p} : ${e}", ("p", root_pem)("e",e.to_detail_string())); - } - } else { - try { - auto infile = std::ifstream(root_pem); - std::stringstream sstr; - sstr << infile.rdbuf(); - my->_http_client.add_cert(sstr.str()); - } catch (const fc::exception& e) { - elog("Failed to read PEM ${f} : ${e}", ("f", root_pem)("e",e.to_detail_string())); - } - } - } - } - my->_keosd_provider_timeout_us = fc::milliseconds(options.at("keosd-provider-timeout").as()); my->_max_transaction_time_ms = options.at("max-transaction-time").as(); diff --git a/programs/nodeos/CMakeLists.txt b/programs/nodeos/CMakeLists.txt index 9dd8fcba69e0d6ed462acdf64dfde9dd38d2d9b3..2fbe7565f3c05fe20ace55e7f43a3853782060b6 100644 --- a/programs/nodeos/CMakeLists.txt +++ b/programs/nodeos/CMakeLists.txt @@ -56,7 +56,7 @@ target_link_libraries( nodeos PRIVATE -Wl,${whole_archive_flag} txn_test_gen_plugin -Wl,${no_whole_archive_flag} PRIVATE -Wl,${whole_archive_flag} db_size_api_plugin -Wl,${no_whole_archive_flag} PRIVATE -Wl,${whole_archive_flag} producer_api_plugin -Wl,${no_whole_archive_flag} - PRIVATE chain_plugin http_plugin producer_plugin + PRIVATE chain_plugin http_plugin producer_plugin http_client_plugin PRIVATE eosio_chain fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} ) if(TARGET sql_db_plugin)