aboutsummaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/CMakeLists.txt3
-rw-r--r--src/common/http_connection.h42
-rw-r--r--src/common/rpc_client.h132
-rw-r--r--src/common/scoped_message_writer.h95
4 files changed, 272 insertions, 0 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 16c4b0ae3..620e1add9 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -39,8 +39,11 @@ set(common_private_headers
boost_serialization_helper.h
command_line.h
dns_utils.h
+ http_connection.h
int-util.h
pod-class.h
+ rpc_client.h
+ scoped_message_writer.h
unordered_containers_boost_serialization.h
util.h
varint.h)
diff --git a/src/common/http_connection.h b/src/common/http_connection.h
new file mode 100644
index 000000000..759145009
--- /dev/null
+++ b/src/common/http_connection.h
@@ -0,0 +1,42 @@
+#pragma once
+
+#include "string_tools.h"
+#include "net/http_client.h"
+
+namespace tools {
+
+class t_http_connection {
+private:
+ epee::net_utils::http::http_simple_client * mp_http_client;
+ bool m_ok;
+public:
+ static unsigned int const TIMEOUT = 200000;
+
+ t_http_connection(
+ epee::net_utils::http::http_simple_client * p_http_client
+ , uint32_t ip
+ , uint16_t port
+ )
+ : mp_http_client(p_http_client)
+ {
+ // TODO fix http client so that it accepts properly typed arguments
+ std::string ip_str = epee::string_tools::get_ip_string_from_int32(ip);
+ std::string port_str = boost::lexical_cast<std::string>(port);
+ m_ok = mp_http_client->connect(ip_str, port_str, TIMEOUT);
+ }
+
+ ~t_http_connection()
+ {
+ if (m_ok)
+ {
+ mp_http_client->disconnect();
+ }
+ }
+
+ bool is_open()
+ {
+ return m_ok;
+ }
+}; // class t_http_connection
+
+} // namespace tools
diff --git a/src/common/rpc_client.h b/src/common/rpc_client.h
new file mode 100644
index 000000000..a6d4b6cc1
--- /dev/null
+++ b/src/common/rpc_client.h
@@ -0,0 +1,132 @@
+#pragma once
+
+#include "common/http_connection.h"
+#include "common/scoped_message_writer.h"
+#include "rpc/core_rpc_server_commands_defs.h"
+#include "storages/http_abstract_invoke.h"
+#include "net/http_client.h"
+#include "string_tools.h"
+#include <boost/lexical_cast.hpp>
+
+namespace tools
+{
+ class t_rpc_client final
+ {
+ private:
+ epee::net_utils::http::http_simple_client m_http_client;
+ uint32_t m_ip;
+ uint16_t m_port;
+ public:
+ t_rpc_client(
+ uint32_t ip
+ , uint16_t port
+ )
+ : m_http_client{}
+ , m_ip{ip}
+ , m_port{port}
+ {}
+
+ std::string build_url(std::string const & relative_url)
+ {
+ std::string result =
+ "http://"
+ + epee::string_tools::get_ip_string_from_int32(m_ip)
+ + ":"
+ + boost::lexical_cast<std::string>(m_port)
+ + relative_url;
+ return result;
+ }
+
+ template <typename T_req, typename T_res>
+ bool basic_json_rpc_request(
+ T_req & req
+ , T_res & res
+ , std::string const & method_name
+ )
+ {
+ std::string rpc_url = build_url("/json_rpc");
+ t_http_connection connection(&m_http_client, m_ip, m_port);
+
+ bool ok = connection.is_open();
+ if (!ok)
+ {
+ fail_msg_writer() << "Couldn't connect to daemon";
+ return false;
+ }
+ ok = ok && epee::net_utils::invoke_http_json_rpc(rpc_url, method_name, req, res, m_http_client);
+ if (!ok)
+ {
+ fail_msg_writer() << "Daemon request failed";
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ template <typename T_req, typename T_res>
+ bool json_rpc_request(
+ T_req & req
+ , T_res & res
+ , std::string const & method_name
+ , std::string const & fail_msg
+ )
+ {
+ std::string rpc_url = build_url("/json_rpc");
+ t_http_connection connection(&m_http_client, m_ip, m_port);
+
+ bool ok = connection.is_open();
+ ok = ok && epee::net_utils::invoke_http_json_rpc(rpc_url, method_name, req, res, m_http_client);
+ if (!ok)
+ {
+ fail_msg_writer() << "Couldn't connect to daemon";
+ return false;
+ }
+ else if (res.status != CORE_RPC_STATUS_OK) // TODO - handle CORE_RPC_STATUS_BUSY ?
+ {
+ fail_msg_writer() << fail_msg << " -- " << res.status;
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ template <typename T_req, typename T_res>
+ bool rpc_request(
+ T_req & req
+ , T_res & res
+ , std::string const & relative_url
+ , std::string const & fail_msg
+ )
+ {
+ std::string rpc_url = build_url(relative_url);
+ t_http_connection connection(&m_http_client, m_ip, m_port);
+
+ bool ok = connection.is_open();
+ ok = ok && epee::net_utils::invoke_http_json_remote_command2(rpc_url, req, res, m_http_client);
+ if (!ok)
+ {
+ fail_msg_writer() << "Couldn't connect to daemon";
+ return false;
+ }
+ else if (res.status != CORE_RPC_STATUS_OK) // TODO - handle CORE_RPC_STATUS_BUSY ?
+ {
+ fail_msg_writer() << fail_msg << " -- " << res.status;
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ bool check_connection()
+ {
+ t_http_connection connection(&m_http_client, m_ip, m_port);
+ return connection.is_open();
+ }
+ };
+}
diff --git a/src/common/scoped_message_writer.h b/src/common/scoped_message_writer.h
new file mode 100644
index 000000000..70db54eae
--- /dev/null
+++ b/src/common/scoped_message_writer.h
@@ -0,0 +1,95 @@
+#pragma once
+
+#include "misc_log_ex.h"
+#include <iostream>
+
+namespace tools
+{
+
+class scoped_message_writer
+{
+private:
+ bool m_flush;
+ std::stringstream m_oss;
+ epee::log_space::console_colors m_color;
+ bool m_bright;
+ int m_log_level;
+public:
+ scoped_message_writer(
+ epee::log_space::console_colors color = epee::log_space::console_color_default
+ , bool bright = false
+ , std::string&& prefix = std::string()
+ , int log_level = LOG_LEVEL_2
+ )
+ : m_flush(true)
+ , m_color(color)
+ , m_bright(bright)
+ , m_log_level(log_level)
+ {
+ m_oss << prefix;
+ }
+
+ scoped_message_writer(scoped_message_writer&& rhs)
+ : m_flush(std::move(rhs.m_flush))
+#if defined(_MSC_VER)
+ , m_oss(std::move(rhs.m_oss))
+#else
+ // GCC bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54316
+ , m_oss(rhs.m_oss.str(), std::ios_base::out | std::ios_base::ate)
+#endif
+ , m_color(std::move(rhs.m_color))
+ , m_log_level(std::move(rhs.m_log_level))
+ {
+ rhs.m_flush = false;
+ }
+
+ scoped_message_writer(scoped_message_writer& rhs) = delete;
+ scoped_message_writer& operator=(scoped_message_writer& rhs) = delete;
+ scoped_message_writer& operator=(scoped_message_writer&& rhs) = delete;
+
+ template<typename T>
+ std::ostream& operator<<(const T& val)
+ {
+ m_oss << val;
+ return m_oss;
+ }
+
+ ~scoped_message_writer()
+ {
+ if (m_flush)
+ {
+ m_flush = false;
+
+ LOG_PRINT(m_oss.str(), m_log_level)
+
+ if (epee::log_space::console_color_default == m_color)
+ {
+ std::cout << m_oss.str();
+ }
+ else
+ {
+ epee::log_space::set_console_color(m_color, m_bright);
+ std::cout << m_oss.str();
+ epee::log_space::reset_console_color();
+ }
+ std::cout << std::endl;
+ }
+ }
+};
+
+inline scoped_message_writer success_msg_writer()
+{
+ return scoped_message_writer(epee::log_space::console_color_green, false, std::string(), LOG_LEVEL_2);
+}
+
+inline scoped_message_writer msg_writer(epee::log_space::console_colors color = epee::log_space::console_color_default)
+{
+ return scoped_message_writer(color, false, std::string(), LOG_LEVEL_2);
+}
+
+inline scoped_message_writer fail_msg_writer()
+{
+ return scoped_message_writer(epee::log_space::console_color_red, true, "Error: ", LOG_LEVEL_0);
+}
+
+} // namespace tools