From 0a468b0a63769ee838536c75b065ea45ec1006ed Mon Sep 17 00:00:00 2001 From: luminousmining Date: Fri, 29 Mar 2024 11:46:22 +0100 Subject: [PATCH 1/2] endpoint hiveos --- miner/sources/CMakeLists.txt | 1 + miner/sources/algo/CMakeLists.txt | 1 - miner/sources/api/CMakeLists.txt | 17 +++ miner/sources/api/api.cpp | 181 ++++++++++++++++++++++++ miner/sources/api/api.hpp | 59 ++++++++ miner/sources/common/app.hpp | 2 +- miner/sources/common/cast.hpp | 2 + miner/sources/common/log/log.cpp | 27 ++++ miner/sources/common/log/log.hpp | 6 + miner/sources/device/device_manager.cpp | 6 + miner/sources/device/device_manager.hpp | 2 + miner/sources/miner.cpp | 10 ++ 12 files changed, 312 insertions(+), 2 deletions(-) create mode 100644 miner/sources/api/CMakeLists.txt create mode 100644 miner/sources/api/api.cpp create mode 100644 miner/sources/api/api.hpp diff --git a/miner/sources/CMakeLists.txt b/miner/sources/CMakeLists.txt index ee3f16c..c7f4b30 100644 --- a/miner/sources/CMakeLists.txt +++ b/miner/sources/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(algo) +add_subdirectory(api) add_subdirectory(common) add_subdirectory(device) add_subdirectory(network) diff --git a/miner/sources/algo/CMakeLists.txt b/miner/sources/algo/CMakeLists.txt index c7da7d3..7bd538b 100644 --- a/miner/sources/algo/CMakeLists.txt +++ b/miner/sources/algo/CMakeLists.txt @@ -1,4 +1,3 @@ - set(ALGO_HEADERS algo_type.hpp bitwise.hpp diff --git a/miner/sources/api/CMakeLists.txt b/miner/sources/api/CMakeLists.txt new file mode 100644 index 0000000..6db6a1f --- /dev/null +++ b/miner/sources/api/CMakeLists.txt @@ -0,0 +1,17 @@ +set(API_HEADERS +api.hpp +) + +set(API_SOURCES +api.cpp +) + +target_sources(${MINER_EXE} PUBLIC +${API_HEADERS} +${API_SOURCES} +) + +target_sources(${UNIT_TEST_EXE} PUBLIC +${API_HEADERS} +${API_SOURCES} +) diff --git a/miner/sources/api/api.cpp b/miner/sources/api/api.cpp new file mode 100644 index 0000000..165cd4e --- /dev/null +++ b/miner/sources/api/api.cpp @@ -0,0 +1,181 @@ +#include + +#include +#include + +#include +#include +#include +#include +#include + + +void api::ServerAPI::setDeviceManager(device::DeviceManager* _deviceManager) +{ + deviceManager = _deviceManager; +} + + +void api::ServerAPI::setPort( + uint32_t const _port) +{ + port = _port; +} + + +bool api::ServerAPI::bind() +{ + alive.store(true, boost::memory_order::seq_cst); + + threadDoAccept.interrupt(); + threadDoAccept = boost_thread{ boost::bind(&api::ServerAPI::loopAccept, this) }; + + return true; +} + + +void api::ServerAPI::loopAccept() +{ + namespace boost_http = boost::beast::http; + + boost_io_context ioContext{}; + boost_acceptor acceptor{ ioContext, { boost_tcp::v4(), 8080 } }; + + while (true == alive.load(boost::memory_order::relaxed)) + { + //////////////////////////////////////////////////////////////////////// + boost_socket socket{ ioContext }; + acceptor.accept(socket); + + //////////////////////////////////////////////////////////////////////// + boost::beast::flat_buffer buffer{}; + boost_http::request request{}; + boost_http::read(socket, buffer, request); + + //////////////////////////////////////////////////////////////////////// + onMessage(socket, request); + + //////////////////////////////////////////////////////////////////////// + socket.shutdown(boost_tcp::socket::shutdown_send); + } +} + + +void api::ServerAPI::onMessage( + boost_socket& socket, + boost::beast::http::request const& request) +{ + namespace boost_http = boost::beast::http; + + //////////////////////////////////////////////////////////////////////// + boost_string_view target{ request.base().target() }; + + //////////////////////////////////////////////////////////////////////// + boost_http::response response{}; + response.version(request.version()); + response.result(boost_http::status::ok); + response.set(boost_http::field::server, "LuminousMiner API"); + response.set(boost_http::field::content_type, "application/json"); + + //////////////////////////////////////////////////////////////////////// + if ("/hiveos/getStats" == target) + { + onHiveOSGetStats(socket, request, response); + } + else if ("/hiveos/getTotalHashrate" == target) + { + onHiveOSGetTotalHashrate(socket, request, response); + } +} + + +void api::ServerAPI::onHiveOSGetStats( + boost_socket& socket, + boost_request const& request, + boost_response& response) +{ + //////////////////////////////////////////////////////////////////////////// + std::string version + { + std::to_string(common::VERSION_MAJOR) + + "." + + std::to_string(common::VERSION_MINOR) + }; + + //////////////////////////////////////////////////////////////////////////// + boost::json::object root + { + { "hs", boost::json::array{} }, // array of hashes + { "hs_units", "khs" }, // Optional: units that are uses for hashes array, "hs", "khs", "mhs", ... Default "khs". + { "temp", boost::json::array{} }, // array of miner temps + { "fan", boost::json::array{} }, // array of miner fans + { "uptime", 0 }, // seconds elapsed from miner stats + { "ver", version }, // miner version currently run, parsed from it's api or manifest + { "ar", boost::json::array{} }, // Optional: acceped, rejected shares + { "algo", "" }, // Optional: algo used by miner, should one of the exiting in Hive + { "bus_numbers", boost::json::array{} } // Pci buses array in decimal format. E.g. 0a:00.0 is 10 + }; + boost::json::array hs{}; + boost::json::array temp{}; + boost::json::array fan{}; + boost::json::array ar{}; + boost::json::array busNumbers{}; + + //////////////////////////////////////////////////////////////////////////// + std::vector devices{ deviceManager->getDevices() }; + for (device::Device* device : devices) + { + if (nullptr == device) + { + hs.push_back(0); + continue; + } + else + { + hs.push_back(device->getHashrate()); + } + temp.push_back(0); + fan.push_back(0); + ar.push_back(0); + busNumbers.push_back(device->id); + } + root["hs"] = hs; + root["temp"] = temp; + root["fan"] = fan; + root["ar"] = ar; + root["bus_numbers"] = busNumbers; + + //////////////////////////////////////////////////////////////////////////// + response.body() = boost::json::serialize(root); + response.prepare_payload(); + + //////////////////////////////////////////////////////////////////////////// + boost::beast::http::write(socket, response); +} + + +void api::ServerAPI::onHiveOSGetTotalHashrate( + boost_socket& socket, + boost_request const& request, + boost_response& response) +{ + double totalHashrate{ 0.0 }; + boost::json::object root{}; + std::vector devices{ deviceManager->getDevices() }; + + for (device::Device* device : devices) + { + if (nullptr == device) + { + continue; + } + totalHashrate += device->getHashrate(); + } + + root["total_hash_rate"] = totalHashrate; + + response.body() = boost::json::serialize(root); + response.prepare_payload(); + + boost::beast::http::write(socket, response); +} diff --git a/miner/sources/api/api.hpp b/miner/sources/api/api.hpp new file mode 100644 index 0000000..76e196a --- /dev/null +++ b/miner/sources/api/api.hpp @@ -0,0 +1,59 @@ +#pragma once + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + + +namespace api +{ + struct ServerAPI + { + public: + using boost_error_code = boost::beast::error_code; + using boost_address = boost::asio::ip::address; + using boost_io_context = boost::asio::io_context; + using boost_tcp = boost::asio::ip::tcp; + using boost_acceptor = boost::asio::ip::tcp::acceptor; + using boost_socket = boost::asio::ip::tcp::socket; + using boost_endpoint = boost::asio::ip::tcp::endpoint; + using boost_thread = boost::thread; + using boost_mutex = boost::mutex; + using boost_atomic_bool = boost::atomic_bool; + using boost_string_view = boost::beast::string_view; + using boost_request = boost::beast::http::request; + using boost_response = boost::beast::http::response; + + uint32_t port{ 0u }; + boost_address address{}; + boost_acceptor* acceptor{ nullptr }; + + boost_thread threadDoAccept{}; + boost_mutex mtx{}; + boost_atomic_bool alive { false }; + + void setDeviceManager(device::DeviceManager* _deviceManager); + void setPort(uint32_t const _port); + bool bind(); + void loopAccept(); + + private: + device::DeviceManager* deviceManager{ nullptr }; + void onMessage(boost_socket& socket, + boost_request const& request); + void onHiveOSGetStats(boost_socket& socket, + boost_request const& request, + boost_response& response); + void onHiveOSGetTotalHashrate(boost_socket& socket, + boost_request const& request, + boost_response& response); + }; +} diff --git a/miner/sources/common/app.hpp b/miner/sources/common/app.hpp index 6485e0c..2a66883 100644 --- a/miner/sources/common/app.hpp +++ b/miner/sources/common/app.hpp @@ -6,5 +6,5 @@ namespace common { constexpr uint8_t VERSION_MAJOR{ 0 }; - constexpr uint8_t VERSION_MINOR{ 1 }; + constexpr uint8_t VERSION_MINOR{ 2 }; } diff --git a/miner/sources/common/cast.hpp b/miner/sources/common/cast.hpp index 7d34eb0..cf20ade 100644 --- a/miner/sources/common/cast.hpp +++ b/miner/sources/common/cast.hpp @@ -8,11 +8,13 @@ #endif // !__LIB_CUDA //////////////////////////////////////////////////////////////////////////////// +#define castU2(value) static_cast(value) #define castU8(value) static_cast(value) #define castU16(value) static_cast(value) #define castU32(value) static_cast(value) #define castU64(value) static_cast(value) //////////////////////////////////////////////////////////////////////////////// +#define cast2(value) static_cast(value) #define cast8(value) static_cast(value) #define cast16(value) static_cast(value) #define cast32(value) static_cast(value) diff --git a/miner/sources/common/log/log.cpp b/miner/sources/common/log/log.cpp index 482402f..e669ceb 100644 --- a/miner/sources/common/log/log.cpp +++ b/miner/sources/common/log/log.cpp @@ -149,6 +149,7 @@ common::Logger& common::Logger::operator<<( return *this; } + common::Logger& common::Logger::operator<<( std::string const& str) { @@ -162,6 +163,32 @@ common::Logger& common::Logger::operator<<( } +common::Logger& common::Logger::operator<<( + std::string_view const& str) +{ + if (typeLog > LOGGER_LEVEL) + { + return *this; + } + + ss << std::string(str); + return *this; +} + + +common::Logger& common::Logger::operator<<( + boost::beast::string_view const& str) +{ + if (typeLog > LOGGER_LEVEL) + { + return *this; + } + + ss << std::string_view(str.data(), str.size()); + return *this; +} + + common::Logger& common::Logger::operator<<( stratum::StratumJobInfo const& jobInfo) { diff --git a/miner/sources/common/log/log.hpp b/miner/sources/common/log/log.hpp index c785d0e..645d77c 100644 --- a/miner/sources/common/log/log.hpp +++ b/miner/sources/common/log/log.hpp @@ -1,6 +1,10 @@ #pragma once #include +#include +#include + +#include #include #include @@ -29,6 +33,8 @@ namespace common Logger& operator<<(algo::hash1024 const& hash); Logger& operator<<(algo::hash2048 const& hash); Logger& operator<<(std::string const& str); + Logger& operator<<(std::string_view const& str); + Logger& operator<<(boost::beast::string_view const& str); Logger& operator<<(stratum::StratumJobInfo const& jobInfo); template diff --git a/miner/sources/device/device_manager.cpp b/miner/sources/device/device_manager.cpp index 507fc1d..436de69 100644 --- a/miner/sources/device/device_manager.cpp +++ b/miner/sources/device/device_manager.cpp @@ -330,6 +330,12 @@ void device::DeviceManager::connectToSmartMining() } +std::vector& device::DeviceManager::getDevices() +{ + return devices; +} + + void device::DeviceManager::loopStatistical() { std::string host{}; diff --git a/miner/sources/device/device_manager.hpp b/miner/sources/device/device_manager.hpp index ec6dfd7..e27ec35 100644 --- a/miner/sources/device/device_manager.hpp +++ b/miner/sources/device/device_manager.hpp @@ -30,6 +30,8 @@ namespace device void run(); void connectToPools(); void connectToSmartMining(); + std::vector& getDevices(); + void onUpdateJob(uint32_t const stratumUUID, stratum::StratumJobInfo const& newJobInfo); void onShareStatus(bool const isValid, diff --git a/miner/sources/miner.cpp b/miner/sources/miner.cpp index 2ee5241..a505f66 100644 --- a/miner/sources/miner.cpp +++ b/miner/sources/miner.cpp @@ -1,5 +1,6 @@ #include +#include #include #include #include @@ -27,6 +28,7 @@ int main( //////////////////////////////////////////////////////////////////////// device::DeviceManager deviceManager{}; common::Config& config { common::Config::instance() }; + api::ServerAPI serverAPI{}; //////////////////////////////////////////////////////////////////////// welcome(); @@ -42,11 +44,19 @@ int main( return 0; } + //////////////////////////////////////////////////////////////////////// + serverAPI.setPort(8080); + if (false == serverAPI.bind()) + { + return 1; + } + //////////////////////////////////////////////////////////////////////// if (false == deviceManager.initialize()) { return 1; } + serverAPI.setDeviceManager(&deviceManager); if (common::PROFILE::STANDARD == config.profile) { deviceManager.run(); From 31500384cf62d3cb8733977390ce4041144af125 Mon Sep 17 00:00:00 2001 From: luminousmining Date: Fri, 29 Mar 2024 11:49:53 +0100 Subject: [PATCH 2/2] remove continue --- miner/sources/api/api.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/miner/sources/api/api.cpp b/miner/sources/api/api.cpp index 165cd4e..cd2a695 100644 --- a/miner/sources/api/api.cpp +++ b/miner/sources/api/api.cpp @@ -128,7 +128,6 @@ void api::ServerAPI::onHiveOSGetStats( if (nullptr == device) { hs.push_back(0); - continue; } else {