diff options
Diffstat (limited to 'contrib/epee/src')
-rw-r--r-- | contrib/epee/src/CMakeLists.txt | 4 | ||||
-rw-r--r-- | contrib/epee/src/connection_basic.cpp | 48 | ||||
-rw-r--r-- | contrib/epee/src/hex.cpp | 65 | ||||
-rw-r--r-- | contrib/epee/src/http_auth.cpp | 2 | ||||
-rw-r--r-- | contrib/epee/src/memwipe.c | 2 | ||||
-rw-r--r-- | contrib/epee/src/net_ssl.cpp | 324 | ||||
-rw-r--r-- | contrib/epee/src/network_throttle-detail.cpp | 8 | ||||
-rw-r--r-- | contrib/epee/src/network_throttle.cpp | 2 | ||||
-rw-r--r-- | contrib/epee/src/wipeable_string.cpp | 2 |
9 files changed, 436 insertions, 21 deletions
diff --git a/contrib/epee/src/CMakeLists.txt b/contrib/epee/src/CMakeLists.txt index cea50c9dd..0787a9d08 100644 --- a/contrib/epee/src/CMakeLists.txt +++ b/contrib/epee/src/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2018, The Monero Project +# Copyright (c) 2014-2019, The Monero Project # # All rights reserved. # @@ -27,7 +27,7 @@ # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. add_library(epee STATIC hex.cpp http_auth.cpp mlog.cpp net_utils_base.cpp string_tools.cpp wipeable_string.cpp memwipe.c - connection_basic.cpp network_throttle.cpp network_throttle-detail.cpp mlocker.cpp buffer.cpp) + connection_basic.cpp network_throttle.cpp network_throttle-detail.cpp mlocker.cpp buffer.cpp net_ssl.cpp) if (USE_READLINE AND GNU_READLINE_FOUND) add_library(epee_readline STATIC readline_buffer.cpp) endif() diff --git a/contrib/epee/src/connection_basic.cpp b/contrib/epee/src/connection_basic.cpp index f5f9b59fe..83db171d8 100644 --- a/contrib/epee/src/connection_basic.cpp +++ b/contrib/epee/src/connection_basic.cpp @@ -2,7 +2,7 @@ /// @author rfree (current maintainer in monero.cc project) /// @brief base for connection, contains e.g. the ratelimit hooks -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // @@ -48,7 +48,7 @@ #include "net/network_throttle-detail.hpp" #undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "net.p2p" +#define MONERO_DEFAULT_LOG_CATEGORY "net.conn" // ################################################################################################ // local (TU local) headers @@ -113,14 +113,41 @@ connection_basic_pimpl::connection_basic_pimpl(const std::string &name) : m_thro int connection_basic_pimpl::m_default_tos; // methods: -connection_basic::connection_basic(boost::asio::ip::tcp::socket&& socket, boost::shared_ptr<socket_stats> stats) +connection_basic::connection_basic(boost::asio::ip::tcp::socket&& sock, boost::shared_ptr<socket_stats> stats, ssl_support_t ssl_support, ssl_context_t &ssl_context) : m_stats(std::move(stats)), mI( new connection_basic_pimpl("peer") ), - strand_(socket.get_io_service()), - socket_(std::move(socket)), + strand_(sock.get_io_service()), + socket_(sock.get_io_service(), ssl_context.context), + m_want_close_connection(false), + m_was_shutdown(false), + m_ssl_support(ssl_support), + m_ssl_context(ssl_context) +{ + // add nullptr checks if removed + CHECK_AND_ASSERT_THROW_MES(bool(m_stats), "stats shared_ptr cannot be null"); + + socket_.next_layer() = std::move(sock); + + ++(m_stats->sock_count); // increase the global counter + mI->m_peer_number = m_stats->sock_number.fetch_add(1); // use, and increase the generated number + + std::string remote_addr_str = "?"; + try { boost::system::error_code e; remote_addr_str = socket().remote_endpoint(e).address().to_string(); } catch(...){} ; + + _note("Spawned connection #"<<mI->m_peer_number<<" to " << remote_addr_str << " currently we have sockets count:" << m_stats->sock_count); +} + +connection_basic::connection_basic(boost::asio::io_service &io_service, boost::shared_ptr<socket_stats> stats, ssl_support_t ssl_support, ssl_context_t &ssl_context) + : + m_stats(std::move(stats)), + mI( new connection_basic_pimpl("peer") ), + strand_(io_service), + socket_(io_service, ssl_context.context), m_want_close_connection(false), - m_was_shutdown(false) + m_was_shutdown(false), + m_ssl_support(ssl_support), + m_ssl_context(ssl_context) { // add nullptr checks if removed CHECK_AND_ASSERT_THROW_MES(bool(m_stats), "stats shared_ptr cannot be null"); @@ -129,17 +156,18 @@ connection_basic::connection_basic(boost::asio::ip::tcp::socket&& socket, boost: mI->m_peer_number = m_stats->sock_number.fetch_add(1); // use, and increase the generated number std::string remote_addr_str = "?"; - try { boost::system::error_code e; remote_addr_str = socket_.remote_endpoint(e).address().to_string(); } catch(...){} ; + try { boost::system::error_code e; remote_addr_str = socket().remote_endpoint(e).address().to_string(); } catch(...){} ; - _note("Spawned connection p2p#"<<mI->m_peer_number<<" to " << remote_addr_str << " currently we have sockets count:" << m_stats->sock_count); + _note("Spawned connection #"<<mI->m_peer_number<<" to " << remote_addr_str << " currently we have sockets count:" << m_stats->sock_count); } connection_basic::~connection_basic() noexcept(false) { --(m_stats->sock_count); std::string remote_addr_str = "?"; - try { boost::system::error_code e; remote_addr_str = socket_.remote_endpoint(e).address().to_string(); } catch(...){} ; - _note("Destructing connection p2p#"<<mI->m_peer_number << " to " << remote_addr_str); + try { boost::system::error_code e; remote_addr_str = socket().remote_endpoint(e).address().to_string(); } catch(...){} ; + _note("Destructing connection #"<<mI->m_peer_number << " to " << remote_addr_str); +try { throw 0; } catch(...){} } void connection_basic::set_rate_up_limit(uint64_t limit) { diff --git a/contrib/epee/src/hex.cpp b/contrib/epee/src/hex.cpp index 5c8acc8be..558983f7e 100644 --- a/contrib/epee/src/hex.cpp +++ b/contrib/epee/src/hex.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2018, The Monero Project +// Copyright (c) 2017-2019, The Monero Project // // All rights reserved. // @@ -83,4 +83,67 @@ namespace epee { return write_hex(out, src); } + + std::vector<uint8_t> from_hex::vector(boost::string_ref src) + { + // should we include a specific character + auto include = [](char input) { + // we ignore spaces and colons + return !std::isspace(input) && input != ':'; + }; + + // the number of relevant characters to decode + auto count = std::count_if(src.begin(), src.end(), include); + + // this must be a multiple of two, otherwise we have a truncated input + if (count % 2) { + throw std::length_error{ "Invalid hexadecimal input length" }; + } + + std::vector<uint8_t> result; + result.reserve(count / 2); + + // the data to work with (std::string is always null-terminated) + auto data = src.data(); + + // convert a single hex character to an unsigned integer + auto char_to_int = [](const char *input) { + switch (std::tolower(*input)) { + case '0': return 0; + case '1': return 1; + case '2': return 2; + case '3': return 3; + case '4': return 4; + case '5': return 5; + case '6': return 6; + case '7': return 7; + case '8': return 8; + case '9': return 9; + case 'a': return 10; + case 'b': return 11; + case 'c': return 12; + case 'd': return 13; + case 'e': return 14; + case 'f': return 15; + default: throw std::range_error{ "Invalid hexadecimal input" }; + } + }; + + // keep going until we reach the end + while (data[0] != '\0') { + // skip unwanted characters + if (!include(data[0])) { + ++data; + continue; + } + + // convert two matching characters to int + auto high = char_to_int(data++); + auto low = char_to_int(data++); + + result.push_back(high << 4 | low); + } + + return result; + } } diff --git a/contrib/epee/src/http_auth.cpp b/contrib/epee/src/http_auth.cpp index dc968d971..289069daa 100644 --- a/contrib/epee/src/http_auth.cpp +++ b/contrib/epee/src/http_auth.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/src/memwipe.c b/contrib/epee/src/memwipe.c index c2a26c392..ad1ef510d 100644 --- a/contrib/epee/src/memwipe.c +++ b/contrib/epee/src/memwipe.c @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2018, The Monero Project +// Copyright (c) 2017-2019, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/src/net_ssl.cpp b/contrib/epee/src/net_ssl.cpp new file mode 100644 index 000000000..eb0b0ad65 --- /dev/null +++ b/contrib/epee/src/net_ssl.cpp @@ -0,0 +1,324 @@ +// Copyright (c) 2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <string.h> +#include <boost/asio/ssl.hpp> +#include <openssl/ssl.h> +#include <openssl/pem.h> +#include "misc_log_ex.h" +#include "net/net_ssl.h" + +#undef MONERO_DEFAULT_LOG_CATEGORY +#define MONERO_DEFAULT_LOG_CATEGORY "net.ssl" + +// openssl genrsa -out /tmp/KEY 4096 +// openssl req -new -key /tmp/KEY -out /tmp/REQ +// openssl x509 -req -days 999999 -sha256 -in /tmp/REQ -signkey /tmp/KEY -out /tmp/CERT + +namespace +{ + struct openssl_bio_free + { + void operator()(BIO* ptr) const noexcept + { + if (ptr) + BIO_free(ptr); + } + }; + using openssl_bio = std::unique_ptr<BIO, openssl_bio_free>; + + struct openssl_pkey_free + { + void operator()(EVP_PKEY* ptr) const noexcept + { + if (ptr) + EVP_PKEY_free(ptr); + } + }; + using openssl_pkey = std::unique_ptr<EVP_PKEY, openssl_pkey_free>; + +} + +namespace epee +{ +namespace net_utils +{ + +// https://stackoverflow.com/questions/256405/programmatically-create-x509-certificate-using-openssl +bool create_ssl_certificate(EVP_PKEY *&pkey, X509 *&cert) +{ + MGINFO("Generating SSL certificate"); + pkey = EVP_PKEY_new(); + if (!pkey) + { + MERROR("Failed to create new private key"); + return false; + } + + openssl_pkey pkey_deleter{pkey}; + RSA *rsa = RSA_generate_key(4096, RSA_F4, NULL, NULL); + if (!rsa) + { + MERROR("Error generating RSA private key"); + return false; + } + if (EVP_PKEY_assign_RSA(pkey, rsa) <= 0) // The RSA will be automatically freed when the EVP_PKEY structure is freed. + { + MERROR("Error assigning RSA private key"); + RSA_free(rsa); + return false; + } + + cert = X509_new(); + if (!cert) + { + MERROR("Failed to create new X509 certificate"); + return false; + } + ASN1_INTEGER_set(X509_get_serialNumber(cert), 1); + X509_gmtime_adj(X509_get_notBefore(cert), 0); + X509_gmtime_adj(X509_get_notAfter(cert), 3600 * 24 * 182); // half a year + if (!X509_set_pubkey(cert, pkey)) + { + MERROR("Error setting pubkey on certificate"); + X509_free(cert); + return false; + } + X509_NAME *name = X509_get_subject_name(cert); + X509_set_issuer_name(cert, name); + + if (X509_sign(cert, pkey, EVP_sha256()) == 0) + { + MERROR("Error signing certificate"); + X509_free(cert); + return false; + } + (void)pkey_deleter.release(); + return true; +} + +ssl_context_t create_ssl_context(const std::pair<std::string, std::string> &private_key_and_certificate_path, std::list<std::string> allowed_certificates, std::vector<std::vector<uint8_t>> allowed_fingerprints, bool allow_any_cert) +{ + ssl_context_t ssl_context{boost::asio::ssl::context(boost::asio::ssl::context::tlsv12), std::move(allowed_certificates), std::move(allowed_fingerprints)}; + + // only allow tls v1.2 and up + ssl_context.context.set_options(boost::asio::ssl::context::default_workarounds); + ssl_context.context.set_options(boost::asio::ssl::context::no_sslv2); + ssl_context.context.set_options(boost::asio::ssl::context::no_sslv3); + ssl_context.context.set_options(boost::asio::ssl::context::no_tlsv1); + ssl_context.context.set_options(boost::asio::ssl::context::no_tlsv1_1); + + // only allow a select handful of tls v1.3 and v1.2 ciphers to be used + SSL_CTX_set_cipher_list(ssl_context.context.native_handle(), "ECDHE-ECDSA-CHACHA20-POLY1305-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-CHACHA20-POLY1305"); + + // set options on the SSL context for added security + SSL_CTX *ctx = ssl_context.context.native_handle(); + CHECK_AND_ASSERT_THROW_MES(ctx, "Failed to get SSL context"); + SSL_CTX_clear_options(ctx, SSL_OP_LEGACY_SERVER_CONNECT); // SSL_CTX_SET_OPTIONS(3) + SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); // https://stackoverflow.com/questions/22378442 +#ifdef SSL_OP_NO_TICKET + SSL_CTX_set_options(ctx, SSL_OP_NO_TICKET); // https://stackoverflow.com/questions/22378442 +#endif +#ifdef SSL_OP_NO_RENEGOTIATION + SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION); +#endif +#ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION + SSL_CTX_set_options(ctx, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); +#endif +#ifdef SSL_OP_NO_COMPRESSION + SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION); +#endif + ssl_context.context.set_default_verify_paths(); + + CHECK_AND_ASSERT_THROW_MES(private_key_and_certificate_path.first.empty() == private_key_and_certificate_path.second.empty(), "private key and certificate must be either both given or both empty"); + if (private_key_and_certificate_path.second.empty()) + { + EVP_PKEY *pkey; + X509 *cert; + CHECK_AND_ASSERT_THROW_MES(create_ssl_certificate(pkey, cert), "Failed to create certificate"); + CHECK_AND_ASSERT_THROW_MES(SSL_CTX_use_certificate(ctx, cert), "Failed to use generated certificate"); + // don't free the cert, the CTX owns it now + CHECK_AND_ASSERT_THROW_MES(SSL_CTX_use_PrivateKey(ctx, pkey), "Failed to use generated private key"); + EVP_PKEY_free(pkey); + } + else + { + ssl_context.context.use_private_key_file(private_key_and_certificate_path.first, boost::asio::ssl::context::pem); + ssl_context.context.use_certificate_file(private_key_and_certificate_path.second, boost::asio::ssl::context::pem); + } + ssl_context.allow_any_cert = allow_any_cert; + + return ssl_context; +} + +void use_ssl_certificate(ssl_context_t &ssl_context, const std::pair<std::string, std::string> &private_key_and_certificate_path) +{ + ssl_context.context.use_private_key_file(private_key_and_certificate_path.first, boost::asio::ssl::context::pem); + ssl_context.context.use_certificate_file(private_key_and_certificate_path.second, boost::asio::ssl::context::pem); +} + +bool is_ssl(const unsigned char *data, size_t len) +{ + if (len < get_ssl_magic_size()) + return false; + + // https://security.stackexchange.com/questions/34780/checking-client-hello-for-https-classification + MDEBUG("SSL detection buffer, " << len << " bytes: " + << (unsigned)(unsigned char)data[0] << " " << (unsigned)(unsigned char)data[1] << " " + << (unsigned)(unsigned char)data[2] << " " << (unsigned)(unsigned char)data[3] << " " + << (unsigned)(unsigned char)data[4] << " " << (unsigned)(unsigned char)data[5] << " " + << (unsigned)(unsigned char)data[6] << " " << (unsigned)(unsigned char)data[7] << " " + << (unsigned)(unsigned char)data[8]); + if (data[0] == 0x16) // record + if (data[1] == 3) // major version + if (data[5] == 1) // ClientHello + if (data[6] == 0 && data[3]*256 + data[4] == data[7]*256 + data[8] + 4) // length check + return true; + return false; +} + +bool is_certificate_allowed(boost::asio::ssl::verify_context &ctx, const ssl_context_t &ssl_context) +{ + X509_STORE_CTX *sctx = ctx.native_handle(); + if (!sctx) + { + MERROR("Error getting verify_context handle"); + return false; + } + X509 *cert =X509_STORE_CTX_get_current_cert(sctx); + if (!cert) + { + MERROR("No certificate found in verify_context"); + return false; + } + + // can we check the certificate against a list of fingerprints? + if (!ssl_context.allowed_fingerprints.empty()) { + // buffer for the certificate digest and the size of the result + std::vector<uint8_t> digest(EVP_MAX_MD_SIZE); + unsigned int size{ 0 }; + + // create the digest from the certificate + if (!X509_digest(cert, EVP_sha1(), digest.data(), &size)) { + MERROR("Failed to create certificate fingerprint"); + return false; + } + + // strip unnecessary bytes from the digest + digest.resize(size); + + // is the certificate fingerprint inside the list of allowed fingerprints? + if (std::find(ssl_context.allowed_fingerprints.begin(), ssl_context.allowed_fingerprints.end(), digest) != ssl_context.allowed_fingerprints.end()) + return true; + } + + if (!ssl_context.allowed_certificates.empty()) { + BIO *bio_cert = BIO_new(BIO_s_mem()); + bool success = PEM_write_bio_X509(bio_cert, cert); + if (!success) + { + BIO_free(bio_cert); + MERROR("Failed to print certificate"); + return false; + } + BUF_MEM *buf = NULL; + BIO_get_mem_ptr(bio_cert, &buf); + if (!buf || !buf->data || !buf->length) + { + BIO_free(bio_cert); + MERROR("Failed to write certificate: " << ERR_get_error()); + return false; + } + std::string certificate(std::string(buf->data, buf->length)); + BIO_free(bio_cert); + if (std::find(ssl_context.allowed_certificates.begin(), ssl_context.allowed_certificates.end(), certificate) != ssl_context.allowed_certificates.end()) + return true; + } + + // if either checklist is non-empty we must have failed it + return ssl_context.allowed_fingerprints.empty() && ssl_context.allowed_certificates.empty(); +} + +bool ssl_handshake(boost::asio::ssl::stream<boost::asio::ip::tcp::socket> &socket, boost::asio::ssl::stream_base::handshake_type type, const epee::net_utils::ssl_context_t &ssl_context) +{ + bool verified = false; + socket.next_layer().set_option(boost::asio::ip::tcp::no_delay(true)); + socket.set_verify_mode(boost::asio::ssl::verify_peer); + socket.set_verify_callback([&](bool preverified, boost::asio::ssl::verify_context &ctx) + { + if (!preverified) + { + const int err = X509_STORE_CTX_get_error(ctx.native_handle()); + const int depth = X509_STORE_CTX_get_error_depth(ctx.native_handle()); + if (err != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT || depth != 0) + { + MERROR("Invalid SSL certificate, error " << err << " at depth " << depth << ", connection dropped"); + return false; + } + } + if (!ssl_context.allow_any_cert && !is_certificate_allowed(ctx, ssl_context)) + { + MERROR("Certificate is not in the allowed list, connection droppped"); + return false; + } + verified = true; + return true; + }); + + boost::system::error_code ec; + socket.handshake(type, ec); + if (ec) + { + MERROR("handshake failed, connection dropped: " << ec.message()); + return false; + } + if (!ssl_context.allow_any_cert && !verified) + { + MERROR("Peer did not provide a certificate in the allowed list, connection dropped"); + return false; + } + MDEBUG("SSL handshake success"); + return true; +} + +bool ssl_support_from_string(ssl_support_t &ssl, boost::string_ref s) +{ + if (s == "enabled") + ssl = epee::net_utils::ssl_support_t::e_ssl_support_enabled; + else if (s == "disabled") + ssl = epee::net_utils::ssl_support_t::e_ssl_support_disabled; + else if (s == "autodetect") + ssl = epee::net_utils::ssl_support_t::e_ssl_support_autodetect; + else + return false; + return true; +} + +} // namespace +} // namespace + diff --git a/contrib/epee/src/network_throttle-detail.cpp b/contrib/epee/src/network_throttle-detail.cpp index d2e776df0..f89e7aec0 100644 --- a/contrib/epee/src/network_throttle-detail.cpp +++ b/contrib/epee/src/network_throttle-detail.cpp @@ -2,7 +2,7 @@ /// @author rfree (current maintainer in monero.cc project) /// @brief implementaion for throttling of connection (count and rate-limit speed etc) -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // @@ -135,6 +135,7 @@ network_throttle::network_throttle(const std::string &nameshort, const std::stri m_slot_size = 1.0; // hard coded in few places m_target_speed = 16 * 1024; // other defaults are probably defined in the command-line parsing code when this class is used e.g. as main global throttle m_last_sample_time = 0; + m_history.resize(m_window_size); } void network_throttle::set_name(const std::string &name) @@ -168,8 +169,7 @@ void network_throttle::tick() { _dbg3("Moving counter buffer by 1 second " << last_sample_time_slot << " < " << current_sample_time_slot << " (last time " << m_last_sample_time<<")"); // rotate buffer - for (size_t i=m_history.size()-1; i>=1; --i) m_history[i] = m_history[i-1]; - m_history[0] = packet_info(); + m_history.push_front(packet_info()); if (! m_any_packet_yet) { m_last_sample_time = time_now; @@ -191,7 +191,7 @@ void network_throttle::_handle_trafic_exact(size_t packet_size, size_t orginal_s calculate_times_struct cts ; calculate_times(packet_size, cts , false, -1); calculate_times_struct cts2; calculate_times(packet_size, cts2, false, 5); - m_history[0].m_size += packet_size; + m_history.front().m_size += packet_size; std::ostringstream oss; oss << "["; for (auto sample: m_history) oss << sample.m_size << " "; oss << "]" << std::ends; std::string history_str = oss.str(); diff --git a/contrib/epee/src/network_throttle.cpp b/contrib/epee/src/network_throttle.cpp index 167738855..f4f0b2c46 100644 --- a/contrib/epee/src/network_throttle.cpp +++ b/contrib/epee/src/network_throttle.cpp @@ -26,7 +26,7 @@ Throttling work by: */ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/src/wipeable_string.cpp b/contrib/epee/src/wipeable_string.cpp index 69f92e106..3a6ee5dac 100644 --- a/contrib/epee/src/wipeable_string.cpp +++ b/contrib/epee/src/wipeable_string.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2018, The Monero Project +// Copyright (c) 2017-2019, The Monero Project // // All rights reserved. // |