diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/common/dns_utils.cpp | 66 | ||||
-rw-r--r-- | src/common/http_connection.h | 42 | ||||
-rw-r--r-- | src/common/rpc_client.h | 132 | ||||
-rw-r--r-- | src/common/scoped_message_writer.h | 95 | ||||
-rw-r--r-- | src/common/util.cpp | 2 | ||||
-rw-r--r-- | src/common/util.h | 12 |
7 files changed, 351 insertions, 1 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/dns_utils.cpp b/src/common/dns_utils.cpp index 3e50b6af8..4ab93cce8 100644 --- a/src/common/dns_utils.cpp +++ b/src/common/dns_utils.cpp @@ -34,7 +34,65 @@ #include <stdlib.h> #include "include_base_utils.h" +#include <boost/filesystem/fstream.hpp> using namespace epee; +namespace bf = boost::filesystem; + +namespace +{ + +/* + * The following two functions were taken from unbound-anchor.c, from + * the unbound library packaged with this source. The license and source + * can be found in $PROJECT_ROOT/external/unbound + */ + +/* Cert builtin commented out until it's used, as the compiler complains + +// return the built in root update certificate +static const char* +get_builtin_cert(void) +{ + return +// The ICANN CA fetched at 24 Sep 2010. Valid to 2028 +"-----BEGIN CERTIFICATE-----\n" +"MIIDdzCCAl+gAwIBAgIBATANBgkqhkiG9w0BAQsFADBdMQ4wDAYDVQQKEwVJQ0FO\n" +"TjEmMCQGA1UECxMdSUNBTk4gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxFjAUBgNV\n" +"BAMTDUlDQU5OIFJvb3QgQ0ExCzAJBgNVBAYTAlVTMB4XDTA5MTIyMzA0MTkxMloX\n" +"DTI5MTIxODA0MTkxMlowXTEOMAwGA1UEChMFSUNBTk4xJjAkBgNVBAsTHUlDQU5O\n" +"IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRYwFAYDVQQDEw1JQ0FOTiBSb290IENB\n" +"MQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKDb\n" +"cLhPNNqc1NB+u+oVvOnJESofYS9qub0/PXagmgr37pNublVThIzyLPGCJ8gPms9S\n" +"G1TaKNIsMI7d+5IgMy3WyPEOECGIcfqEIktdR1YWfJufXcMReZwU4v/AdKzdOdfg\n" +"ONiwc6r70duEr1IiqPbVm5T05l1e6D+HkAvHGnf1LtOPGs4CHQdpIUcy2kauAEy2\n" +"paKcOcHASvbTHK7TbbvHGPB+7faAztABLoneErruEcumetcNfPMIjXKdv1V1E3C7\n" +"MSJKy+jAqqQJqjZoQGB0necZgUMiUv7JK1IPQRM2CXJllcyJrm9WFxY0c1KjBO29\n" +"iIKK69fcglKcBuFShUECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B\n" +"Af8EBAMCAf4wHQYDVR0OBBYEFLpS6UmDJIZSL8eZzfyNa2kITcBQMA0GCSqGSIb3\n" +"DQEBCwUAA4IBAQAP8emCogqHny2UYFqywEuhLys7R9UKmYY4suzGO4nkbgfPFMfH\n" +"6M+Zj6owwxlwueZt1j/IaCayoKU3QsrYYoDRolpILh+FPwx7wseUEV8ZKpWsoDoD\n" +"2JFbLg2cfB8u/OlE4RYmcxxFSmXBg0yQ8/IoQt/bxOcEEhhiQ168H2yE5rxJMt9h\n" +"15nu5JBSewrCkYqYYmaxyOC3WrVGfHZxVI7MpIFcGdvSb2a1uyuua8l0BKgk3ujF\n" +"0/wsHNeP22qNyVO+XVBzrM8fk8BSUFuiT/6tZTYXRtEt5aKQZgXbKU5dUF3jT9qg\n" +"j/Br5BZw3X/zd325TvnswzMC1+ljLzHnQGGk\n" +"-----END CERTIFICATE-----\n" + ; +} +*/ + +/** return the built in root DS trust anchor */ +static const char* +get_builtin_ds(void) +{ + return +". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5\n"; +} + +/************************************************************ + ************************************************************ + ***********************************************************/ + +} // anonymous namespace namespace tools { @@ -109,6 +167,8 @@ DNSResolver::DNSResolver() : m_data(new DNSResolverData()) // look for "/etc/resolv.conf" and "/etc/hosts" or platform equivalent ub_ctx_resolvconf(m_data->m_ub_context, &empty_string); ub_ctx_hosts(m_data->m_ub_context, &empty_string); + + ub_ctx_add_ta(m_data->m_ub_context, ::get_builtin_ds()); } DNSResolver::~DNSResolver() @@ -143,6 +203,8 @@ std::vector<std::string> DNSResolver::get_ipv4(const std::string& url, bool& dns // call DNS resolver, blocking. if return value not zero, something went wrong if (!ub_resolve(m_data->m_ub_context, urlC, DNS_TYPE_A, DNS_CLASS_IN, &(result.ptr))) { + dnssec_available = (result.ptr->secure || (!result.ptr->secure && result.ptr->bogus)); + dnssec_valid = !result.ptr->bogus; if (result.ptr->havedata) { for (size_t i=0; result.ptr->data[i] != NULL; i++) @@ -175,6 +237,8 @@ std::vector<std::string> DNSResolver::get_ipv6(const std::string& url, bool& dns // call DNS resolver, blocking. if return value not zero, something went wrong if (!ub_resolve(m_data->m_ub_context, urlC, DNS_TYPE_AAAA, DNS_CLASS_IN, &(result.ptr))) { + dnssec_available = (result.ptr->secure || (!result.ptr->secure && result.ptr->bogus)); + dnssec_valid = !result.ptr->bogus; if (result.ptr->havedata) { for (size_t i=0; result.ptr->data[i] != NULL; i++) @@ -207,6 +271,8 @@ std::vector<std::string> DNSResolver::get_txt_record(const std::string& url, boo // call DNS resolver, blocking. if return value not zero, something went wrong if (!ub_resolve(m_data->m_ub_context, urlC, DNS_TYPE_TXT, DNS_CLASS_IN, &(result.ptr))) { + dnssec_available = (result.ptr->secure || (!result.ptr->secure && result.ptr->bogus)); + dnssec_valid = !result.ptr->bogus; if (result.ptr->havedata) { for (size_t i=0; result.ptr->data[i] != NULL; i++) 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 diff --git a/src/common/util.cpp b/src/common/util.cpp index 94c1e042e..7d39bc4f4 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -326,7 +326,7 @@ std::string get_nix_version_display_string() std::string config_folder; #ifdef WIN32 - config_folder = get_special_folder_path(CSIDL_APPDATA, true) + "\\" + CRYPTONOTE_NAME; + config_folder = get_special_folder_path(CSIDL_COMMON_APPDATA, true) + "\\" + CRYPTONOTE_NAME; #else std::string pathRet; char* pszHome = getenv("HOME"); diff --git a/src/common/util.h b/src/common/util.h index 0d23135b0..883fe1e0f 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -58,6 +58,18 @@ namespace tools */ std::string get_default_data_dir(); +#ifdef WIN32 + /** + * @brief + * + * @param nfolder + * @param iscreate + * + * @return + */ + std::string get_special_folder_path(int nfolder, bool iscreate); +#endif + /*! \brief Returns the OS version string * * \details This is a wrapper around the primitives |