diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/common/base58.cpp | 2 | ||||
-rw-r--r-- | src/common/base58.h | 2 | ||||
-rw-r--r-- | src/common/boost_serialization_helper.h | 2 | ||||
-rw-r--r-- | src/common/command_line.cpp | 2 | ||||
-rw-r--r-- | src/common/command_line.h | 4 | ||||
-rw-r--r-- | src/common/dns_utils.cpp | 10 | ||||
-rw-r--r-- | src/common/dns_utils.h | 4 | ||||
-rw-r--r-- | src/common/download.cpp | 182 | ||||
-rw-r--r-- | src/common/download.h | 10 | ||||
-rw-r--r-- | src/common/http_connection.h | 2 | ||||
-rw-r--r-- | src/common/i18n.cpp | 2 | ||||
-rw-r--r-- | src/common/i18n.h | 2 | ||||
-rw-r--r-- | src/common/int-util.h | 2 | ||||
-rw-r--r-- | src/common/pod-class.h | 2 | ||||
-rw-r--r-- | src/common/rpc_client.h | 2 | ||||
-rw-r--r-- | src/common/scoped_message_writer.h | 2 | ||||
-rw-r--r-- | src/common/task_region.cpp | 2 | ||||
-rw-r--r-- | src/common/task_region.h | 2 | ||||
-rw-r--r-- | src/common/thread_group.cpp | 2 | ||||
-rw-r--r-- | src/common/thread_group.h | 2 | ||||
-rw-r--r-- | src/common/unordered_containers_boost_serialization.h | 2 | ||||
-rw-r--r-- | src/common/updates.cpp | 15 | ||||
-rw-r--r-- | src/common/updates.h | 4 | ||||
-rw-r--r-- | src/common/util.cpp | 14 | ||||
-rw-r--r-- | src/common/util.h | 3 | ||||
-rw-r--r-- | src/common/varint.h | 2 |
27 files changed, 219 insertions, 63 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 6f64cfbf2..0a3e8cd19 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2016, The Monero Project +# Copyright (c) 2014-2017, The Monero Project # # All rights reserved. # diff --git a/src/common/base58.cpp b/src/common/base58.cpp index 355d1e209..64cb7c0de 100644 --- a/src/common/base58.cpp +++ b/src/common/base58.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016, The Monero Project +// Copyright (c) 2014-2017, The Monero Project // // All rights reserved. // diff --git a/src/common/base58.h b/src/common/base58.h index df2ac2e9b..6dd850c03 100644 --- a/src/common/base58.h +++ b/src/common/base58.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016, The Monero Project +// Copyright (c) 2014-2017, The Monero Project // // All rights reserved. // diff --git a/src/common/boost_serialization_helper.h b/src/common/boost_serialization_helper.h index 88dccbde7..4a503d830 100644 --- a/src/common/boost_serialization_helper.h +++ b/src/common/boost_serialization_helper.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016, The Monero Project +// Copyright (c) 2014-2017, The Monero Project // // All rights reserved. // diff --git a/src/common/command_line.cpp b/src/common/command_line.cpp index 8739a93cd..f71b3e576 100644 --- a/src/common/command_line.cpp +++ b/src/common/command_line.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016, The Monero Project +// Copyright (c) 2014-2017, The Monero Project // // All rights reserved. // diff --git a/src/common/command_line.h b/src/common/command_line.h index f10e68e13..2110b8849 100644 --- a/src/common/command_line.h +++ b/src/common/command_line.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016, The Monero Project +// Copyright (c) 2014-2017, The Monero Project // // All rights reserved. // @@ -168,7 +168,7 @@ namespace command_line { return parser(); } - catch (std::exception& e) + catch (const std::exception& e) { std::cerr << "Failed to parse arguments: " << e.what() << std::endl; std::cerr << desc << std::endl; diff --git a/src/common/dns_utils.cpp b/src/common/dns_utils.cpp index 19aae93da..ab38cbbae 100644 --- a/src/common/dns_utils.cpp +++ b/src/common/dns_utils.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016, The Monero Project +// Copyright (c) 2014-2017, The Monero Project // // All rights reserved. // @@ -405,21 +405,23 @@ std::vector<std::string> addresses_from_url(const std::string& url, bool& dnssec return addresses; } -std::string get_account_address_as_str_from_url(const std::string& url, bool& dnssec_valid) +std::string get_account_address_as_str_from_url(const std::string& url, bool& dnssec_valid, bool cli_confirm) { // attempt to get address from dns query auto addresses = addresses_from_url(url, dnssec_valid); if (addresses.empty()) { - std::cout << tr("wrong address: ") << url; + LOG_ERROR("wrong address: " << url); return {}; } // for now, move on only if one address found if (addresses.size() > 1) { - std::cout << tr("not yet supported: Multiple Monero addresses found for given URL: ") << url; + LOG_ERROR("not yet supported: Multiple Monero addresses found for given URL: " << url); return {}; } + if (!cli_confirm) + return addresses[0]; // prompt user for confirmation. // inform user of DNSSEC validation status as well. std::string dnssec_str; diff --git a/src/common/dns_utils.h b/src/common/dns_utils.h index 2e881f0e0..53c0c1c7b 100644 --- a/src/common/dns_utils.h +++ b/src/common/dns_utils.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016, The Monero Project +// Copyright (c) 2014-2017, The Monero Project // // All rights reserved. // @@ -163,7 +163,7 @@ namespace dns_utils std::string address_from_txt_record(const std::string& s); std::vector<std::string> addresses_from_url(const std::string& url, bool& dnssec_valid); -std::string get_account_address_as_str_from_url(const std::string& url, bool& dnssec_valid); +std::string get_account_address_as_str_from_url(const std::string& url, bool& dnssec_valid, bool cli_confirm = true); bool load_txt_records_from_dns(std::vector<std::string> &records, const std::vector<std::string> &dns_urls); diff --git a/src/common/download.cpp b/src/common/download.cpp index c5ee797d0..28aac5a59 100644 --- a/src/common/download.cpp +++ b/src/common/download.cpp @@ -27,6 +27,7 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <string> +#include <atomic> #include <boost/filesystem.hpp> #include <boost/asio.hpp> #include <boost/thread/thread.hpp> @@ -40,27 +41,82 @@ namespace tools { - static bool download_thread(const std::string &path, const std::string &url) + struct download_thread_control { + const std::string path; + const std::string uri; + std::function<void(const std::string&, const std::string&, bool)> result_cb; + std::function<bool(const std::string&, const std::string&, size_t, ssize_t)> progress_cb; + bool stop; + bool stopped; + bool success; + boost::thread thread; + boost::mutex mutex; + + download_thread_control(const std::string &path, const std::string &uri, std::function<void(const std::string&, const std::string&, bool)> result_cb, std::function<bool(const std::string&, const std::string&, size_t, ssize_t)> progress_cb): + path(path), uri(uri), result_cb(result_cb), progress_cb(progress_cb), stop(false), stopped(false), success(false) {} + ~download_thread_control() { if (thread.joinable()) thread.detach(); } + }; + + static void download_thread(download_async_handle control) + { + static std::atomic<unsigned int> thread_id(0); + + MLOG_SET_THREAD_NAME("DL" + std::to_string(thread_id++)); + + struct stopped_setter + { + stopped_setter(const download_async_handle &control): control(control) {} + ~stopped_setter() { control->stopped = true; } + download_async_handle control; + } stopped_setter(control); + try { - MINFO("Downloading " << url << " to " << path); + boost::unique_lock<boost::mutex> lock(control->mutex); + MINFO("Downloading " << control->uri << " to " << control->path); std::ofstream f; - f.open(path, std::ios_base::binary | std::ios_base::out | std::ios_base::trunc); + f.open(control->path, std::ios_base::binary | std::ios_base::out | std::ios_base::trunc); if (!f.good()) { - MERROR("Failed to open file " << path); - return false; + MERROR("Failed to open file " << control->path); + control->result_cb(control->path, control->uri, control->success); + return; } class download_client: public epee::net_utils::http::http_simple_client { public: - download_client(std::ofstream &f): f(f) {} + download_client(download_async_handle control, std::ofstream &f): + control(control), f(f), content_length(-1), total(0) {} virtual ~download_client() { f.close(); } + virtual bool on_header(const epee::net_utils::http::http_response_info &headers) + { + ssize_t length; + if (epee::string_tools::get_xtype_from_string(length, headers.m_header_info.m_content_length) && length >= 0) + { + MINFO("Content-Length: " << length); + content_length = length; + boost::filesystem::path path(control->path); + boost::filesystem::space_info si = boost::filesystem::space(path); + if (si.available < (size_t)content_length) + { + const uint64_t avail = (si.available + 1023) / 1024, needed = (content_length + 1023) / 1024; + MERROR("Not enough space to download " << needed << " kB to " << path << " (" << avail << " kB available)"); + return false; + } + } + return true; + } virtual bool handle_target_data(std::string &piece_of_transfer) { try { + boost::lock_guard<boost::mutex> lock(control->mutex); + if (control->stop) + return false; f << piece_of_transfer; + total += piece_of_transfer.size(); + if (control->progress_cb && !control->progress_cb(control->path, control->uri, total, content_length)) + return false; return f.good(); } catch (const std::exception &e) @@ -70,69 +126,145 @@ namespace tools } } private: + download_async_handle control; std::ofstream &f; - } client(f); + ssize_t content_length; + size_t total; + } client(control, f); epee::net_utils::http::url_content u_c; - if (!epee::net_utils::parse_url(url, u_c)) + if (!epee::net_utils::parse_url(control->uri, u_c)) { - MWARNING("Failed to parse URL " << url); - return false; + MERROR("Failed to parse URL " << control->uri); + control->result_cb(control->path, control->uri, control->success); + return; } if (u_c.host.empty()) { - MWARNING("Failed to determine address from URL " << url); - return false; + MERROR("Failed to determine address from URL " << control->uri); + control->result_cb(control->path, control->uri, control->success); + return; } + + lock.unlock(); + uint16_t port = u_c.port ? u_c.port : 80; MDEBUG("Connecting to " << u_c.host << ":" << port); client.set_server(u_c.host, std::to_string(port), boost::none); if (!client.connect(std::chrono::seconds(30))) { - MERROR("Failed to connect to " << url); - return false; + boost::lock_guard<boost::mutex> lock(control->mutex); + MERROR("Failed to connect to " << control->uri); + control->result_cb(control->path, control->uri, control->success); + return; } MDEBUG("GETting " << u_c.uri); const epee::net_utils::http::http_response_info *info = NULL; if (!client.invoke_get(u_c.uri, std::chrono::seconds(30), "", &info)) { - MERROR("Failed to connect to " << url); + boost::lock_guard<boost::mutex> lock(control->mutex); + MERROR("Failed to connect to " << control->uri); client.disconnect(); - return false; + control->result_cb(control->path, control->uri, control->success); + return; + } + if (control->stop) + { + boost::lock_guard<boost::mutex> lock(control->mutex); + MDEBUG("Download cancelled"); + client.disconnect(); + control->result_cb(control->path, control->uri, control->success); + return; } if (!info) { - MERROR("Failed invoking GET command to " << url << ", no status info returned"); + boost::lock_guard<boost::mutex> lock(control->mutex); + MERROR("Failed invoking GET command to " << control->uri << ", no status info returned"); client.disconnect(); - return false; + control->result_cb(control->path, control->uri, control->success); + return; } MDEBUG("response code: " << info->m_response_code); + MDEBUG("response length: " << info->m_header_info.m_content_length); MDEBUG("response comment: " << info->m_response_comment); MDEBUG("response body: " << info->m_body); for (const auto &f: info->m_additional_fields) MDEBUG("additional field: " << f.first << ": " << f.second); if (info->m_response_code != 200) { + boost::lock_guard<boost::mutex> lock(control->mutex); MERROR("Status code " << info->m_response_code); client.disconnect(); - return false; + control->result_cb(control->path, control->uri, control->success); + return; } client.disconnect(); f.close(); MDEBUG("Download complete"); - return true; + lock.lock(); + control->success = true; + control->result_cb(control->path, control->uri, control->success); + return; } catch (const std::exception &e) { MERROR("Exception in download thread: " << e.what()); - return false; + // fall through and call result_cb not from the catch block to avoid another exception } + boost::lock_guard<boost::mutex> lock(control->mutex); + control->result_cb(control->path, control->uri, control->success); } - bool download(const std::string &path, const std::string &url) + bool download(const std::string &path, const std::string &url, std::function<bool(const std::string&, const std::string&, size_t, ssize_t)> cb) { - bool success; - std::unique_ptr<boost::thread> thread(new boost::thread([&](){ success = download_thread(path, url); })); - thread->join(); + bool success = false; + download_async_handle handle = download_async(path, url, [&success](const std::string&, const std::string&, bool result) {success = result;}, cb); + download_wait(handle); return success; } + + download_async_handle download_async(const std::string &path, const std::string &url, std::function<void(const std::string&, const std::string&, bool)> result, std::function<bool(const std::string&, const std::string&, size_t, ssize_t)> progress) + { + download_async_handle control = std::make_shared<download_thread_control>(path, url, result, progress); + control->thread = boost::thread([control](){ download_thread(control); }); + return control; + } + + bool download_finished(const download_async_handle &control) + { + CHECK_AND_ASSERT_MES(control != 0, false, "NULL async download handle"); + boost::lock_guard<boost::mutex> lock(control->mutex); + return control->stopped; + } + + bool download_error(const download_async_handle &control) + { + CHECK_AND_ASSERT_MES(control != 0, false, "NULL async download handle"); + boost::lock_guard<boost::mutex> lock(control->mutex); + return !control->success; + } + + bool download_wait(const download_async_handle &control) + { + CHECK_AND_ASSERT_MES(control != 0, false, "NULL async download handle"); + { + boost::lock_guard<boost::mutex> lock(control->mutex); + if (control->stopped) + return true; + } + control->thread.join(); + return true; + } + + bool download_cancel(const download_async_handle &control) + { + CHECK_AND_ASSERT_MES(control != 0, false, "NULL async download handle"); + { + boost::lock_guard<boost::mutex> lock(control->mutex); + if (control->stopped) + return true; + control->stop = true; + } + control->thread.join(); + return true; + } } diff --git a/src/common/download.h b/src/common/download.h index ab7644689..917cb2278 100644 --- a/src/common/download.h +++ b/src/common/download.h @@ -32,5 +32,13 @@ namespace tools { - bool download(const std::string &path, const std::string &url); + struct download_thread_control; + typedef std::shared_ptr<download_thread_control> download_async_handle; + + bool download(const std::string &path, const std::string &url, std::function<bool(const std::string&, const std::string&, size_t, ssize_t)> progress = NULL); + download_async_handle download_async(const std::string &path, const std::string &url, std::function<void(const std::string&, const std::string&, bool)> result, std::function<bool(const std::string&, const std::string&, size_t, ssize_t)> progress = NULL); + bool download_error(const download_async_handle &h); + bool download_finished(const download_async_handle &h); + bool download_wait(const download_async_handle &h); + bool download_cancel(const download_async_handle &h); } diff --git a/src/common/http_connection.h b/src/common/http_connection.h index 8a786361a..0357a90a0 100644 --- a/src/common/http_connection.h +++ b/src/common/http_connection.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016, The Monero Project +// Copyright (c) 2014-2017, The Monero Project // // All rights reserved. // diff --git a/src/common/i18n.cpp b/src/common/i18n.cpp index 05eea3b66..4a76e76fc 100644 --- a/src/common/i18n.cpp +++ b/src/common/i18n.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016, The Monero Project +// Copyright (c) 2014-2017, The Monero Project // // All rights reserved. // diff --git a/src/common/i18n.h b/src/common/i18n.h index 332602185..5169cf9f7 100644 --- a/src/common/i18n.h +++ b/src/common/i18n.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016, The Monero Project +// Copyright (c) 2014-2017, The Monero Project // // All rights reserved. // diff --git a/src/common/int-util.h b/src/common/int-util.h index 9ac20e582..34288805a 100644 --- a/src/common/int-util.h +++ b/src/common/int-util.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016, The Monero Project +// Copyright (c) 2014-2017, The Monero Project // // All rights reserved. // diff --git a/src/common/pod-class.h b/src/common/pod-class.h index f3f241552..3896d5c29 100644 --- a/src/common/pod-class.h +++ b/src/common/pod-class.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016, The Monero Project +// Copyright (c) 2014-2017, The Monero Project // // All rights reserved. // diff --git a/src/common/rpc_client.h b/src/common/rpc_client.h index 40c103bf3..8494b4a60 100644 --- a/src/common/rpc_client.h +++ b/src/common/rpc_client.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016, The Monero Project +// Copyright (c) 2014-2017, The Monero Project // // All rights reserved. // diff --git a/src/common/scoped_message_writer.h b/src/common/scoped_message_writer.h index f82181926..7ee4f1379 100644 --- a/src/common/scoped_message_writer.h +++ b/src/common/scoped_message_writer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016, The Monero Project +// Copyright (c) 2014-2017, The Monero Project // // All rights reserved. // diff --git a/src/common/task_region.cpp b/src/common/task_region.cpp index b53a8376a..9b4620c6e 100644 --- a/src/common/task_region.cpp +++ b/src/common/task_region.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016, The Monero Project +// Copyright (c) 2014-2017, The Monero Project // // All rights reserved. // diff --git a/src/common/task_region.h b/src/common/task_region.h index e4d210661..30972cce3 100644 --- a/src/common/task_region.h +++ b/src/common/task_region.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016, The Monero Project +// Copyright (c) 2014-2017, The Monero Project // // All rights reserved. // diff --git a/src/common/thread_group.cpp b/src/common/thread_group.cpp index 4e1cc8964..860d0b732 100644 --- a/src/common/thread_group.cpp +++ b/src/common/thread_group.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016, The Monero Project +// Copyright (c) 2014-2017, The Monero Project // // All rights reserved. // diff --git a/src/common/thread_group.h b/src/common/thread_group.h index 10add89e0..48fd4cd56 100644 --- a/src/common/thread_group.h +++ b/src/common/thread_group.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016, The Monero Project +// Copyright (c) 2014-2017, The Monero Project // // All rights reserved. // diff --git a/src/common/unordered_containers_boost_serialization.h b/src/common/unordered_containers_boost_serialization.h index b2d5b27a6..4d82a1364 100644 --- a/src/common/unordered_containers_boost_serialization.h +++ b/src/common/unordered_containers_boost_serialization.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016, The Monero Project +// Copyright (c) 2014-2017, The Monero Project // // All rights reserved. // diff --git a/src/common/updates.cpp b/src/common/updates.cpp index 936106881..5b1acf5fa 100644 --- a/src/common/updates.cpp +++ b/src/common/updates.cpp @@ -35,7 +35,7 @@ namespace tools { - bool check_updates(const std::string &software, const std::string &buildtag, bool testnet, std::string &version, std::string &hash) + bool check_updates(const std::string &software, const std::string &buildtag, std::string &version, std::string &hash) { std::vector<std::string> records; bool found = false; @@ -44,12 +44,13 @@ namespace tools // All four MoneroPulse domains have DNSSEC on and valid static const std::vector<std::string> dns_urls = { + "updates.moneropulse.org", + "updates.moneropulse.net", + "updates.moneropulse.co", + "updates.moneropulse.se" }; - static const std::vector<std::string> testnet_dns_urls = { "testver.moneropulse.net" - }; - - if (!tools::dns_utils::load_txt_records_from_dns(records, testnet ? testnet_dns_urls : dns_urls)) + if (!tools::dns_utils::load_txt_records_from_dns(records, dns_urls)) return false; for (const auto& record : records) @@ -94,9 +95,9 @@ namespace tools return found; } - std::string get_update_url(const std::string &software, const std::string &subdir, const std::string &buildtag, const std::string &version) + std::string get_update_url(const std::string &software, const std::string &subdir, const std::string &buildtag, const std::string &version, bool user) { - static const char base[] = "https://downloads.getmonero.org/"; + const char *base = user ? "https://downloads.getmonero.org/" : "http://updates.getmonero.org/"; #ifdef _WIN32 static const char extension[] = ".zip"; #else diff --git a/src/common/updates.h b/src/common/updates.h index 1a70e06fd..e494ed7ac 100644 --- a/src/common/updates.h +++ b/src/common/updates.h @@ -32,6 +32,6 @@ namespace tools { - bool check_updates(const std::string &software, const std::string &buildtag, bool bestnet, std::string &version, std::string &hash); - std::string get_update_url(const std::string &software, const std::string &subdir, const std::string &buildtag, const std::string &version); + bool check_updates(const std::string &software, const std::string &buildtag, std::string &version, std::string &hash); + std::string get_update_url(const std::string &software, const std::string &subdir, const std::string &buildtag, const std::string &version, bool user); } diff --git a/src/common/util.cpp b/src/common/util.cpp index 90748ddb1..046961b06 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016, The Monero Project +// Copyright (c) 2014-2017, The Monero Project // // All rights reserved. // @@ -587,6 +587,18 @@ std::string get_nix_version_display_string() return 0; } + bool sha256sum(const uint8_t *data, size_t len, crypto::hash &hash) + { + SHA256_CTX ctx; + if (!SHA256_Init(&ctx)) + return false; + if (!SHA256_Update(&ctx, data, len)) + return false; + if (!SHA256_Final((unsigned char*)hash.data, &ctx)) + return false; + return true; + } + bool sha256sum(const std::string &filename, crypto::hash &hash) { if (!epee::file_io_utils::is_file_exist(filename)) diff --git a/src/common/util.h b/src/common/util.h index 8ab469129..4291d7e18 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016, The Monero Project +// Copyright (c) 2014-2017, The Monero Project // // All rights reserved. // @@ -185,5 +185,6 @@ namespace tools bool is_local_address(const std::string &address); int vercmp(const char *v0, const char *v1); // returns < 0, 0, > 0, similar to strcmp, but more human friendly than lexical - does not attempt to validate + bool sha256sum(const uint8_t *data, size_t len, crypto::hash &hash); bool sha256sum(const std::string &filename, crypto::hash &hash); } diff --git a/src/common/varint.h b/src/common/varint.h index ffaa682c5..cb785e61a 100644 --- a/src/common/varint.h +++ b/src/common/varint.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016, The Monero Project +// Copyright (c) 2014-2017, The Monero Project // // All rights reserved. // |