diff options
Diffstat (limited to 'contrib/epee')
40 files changed, 933 insertions, 353 deletions
diff --git a/contrib/epee/include/int-util.h b/contrib/epee/include/int-util.h new file mode 100644 index 000000000..3bcc085e2 --- /dev/null +++ b/contrib/epee/include/int-util.h @@ -0,0 +1,258 @@ +// Copyright (c) 2014-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. +// +// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + +#pragma once + +#include <assert.h> +#include <stdbool.h> +#include <stdint.h> +#include <string.h> + +#ifndef _MSC_VER +#include <sys/param.h> +#endif + +#if defined(__ANDROID__) +#include <byteswap.h> +#endif + +#if defined(__sun) && defined(__SVR4) +#include <endian.h> +#endif + +#if defined(_MSC_VER) +#include <stdlib.h> + +static inline uint32_t rol32(uint32_t x, int r) { + static_assert(sizeof(uint32_t) == sizeof(unsigned int), "this code assumes 32-bit integers"); + return _rotl(x, r); +} + +static inline uint64_t rol64(uint64_t x, int r) { + return _rotl64(x, r); +} + +#else + +static inline uint32_t rol32(uint32_t x, int r) { + return (x << (r & 31)) | (x >> (-r & 31)); +} + +static inline uint64_t rol64(uint64_t x, int r) { + return (x << (r & 63)) | (x >> (-r & 63)); +} + +#endif + +static inline uint64_t hi_dword(uint64_t val) { + return val >> 32; +} + +static inline uint64_t lo_dword(uint64_t val) { + return val & 0xFFFFFFFF; +} + +static inline uint64_t mul128(uint64_t multiplier, uint64_t multiplicand, uint64_t* product_hi) { + // multiplier = ab = a * 2^32 + b + // multiplicand = cd = c * 2^32 + d + // ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d + uint64_t a = hi_dword(multiplier); + uint64_t b = lo_dword(multiplier); + uint64_t c = hi_dword(multiplicand); + uint64_t d = lo_dword(multiplicand); + + uint64_t ac = a * c; + uint64_t ad = a * d; + uint64_t bc = b * c; + uint64_t bd = b * d; + + uint64_t adbc = ad + bc; + uint64_t adbc_carry = adbc < ad ? 1 : 0; + + // multiplier * multiplicand = product_hi * 2^64 + product_lo + uint64_t product_lo = bd + (adbc << 32); + uint64_t product_lo_carry = product_lo < bd ? 1 : 0; + *product_hi = ac + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry; + assert(ac <= *product_hi); + + return product_lo; +} + +static inline uint64_t div_with_reminder(uint64_t dividend, uint32_t divisor, uint32_t* remainder) { + dividend |= ((uint64_t)*remainder) << 32; + *remainder = dividend % divisor; + return dividend / divisor; +} + +// Long division with 2^32 base +static inline uint32_t div128_32(uint64_t dividend_hi, uint64_t dividend_lo, uint32_t divisor, uint64_t* quotient_hi, uint64_t* quotient_lo) { + uint64_t dividend_dwords[4]; + uint32_t remainder = 0; + + dividend_dwords[3] = hi_dword(dividend_hi); + dividend_dwords[2] = lo_dword(dividend_hi); + dividend_dwords[1] = hi_dword(dividend_lo); + dividend_dwords[0] = lo_dword(dividend_lo); + + *quotient_hi = div_with_reminder(dividend_dwords[3], divisor, &remainder) << 32; + *quotient_hi |= div_with_reminder(dividend_dwords[2], divisor, &remainder); + *quotient_lo = div_with_reminder(dividend_dwords[1], divisor, &remainder) << 32; + *quotient_lo |= div_with_reminder(dividend_dwords[0], divisor, &remainder); + + return remainder; +} + +#define IDENT32(x) ((uint32_t) (x)) +#define IDENT64(x) ((uint64_t) (x)) + +#define SWAP32(x) ((((uint32_t) (x) & 0x000000ff) << 24) | \ + (((uint32_t) (x) & 0x0000ff00) << 8) | \ + (((uint32_t) (x) & 0x00ff0000) >> 8) | \ + (((uint32_t) (x) & 0xff000000) >> 24)) +#define SWAP64(x) ((((uint64_t) (x) & 0x00000000000000ff) << 56) | \ + (((uint64_t) (x) & 0x000000000000ff00) << 40) | \ + (((uint64_t) (x) & 0x0000000000ff0000) << 24) | \ + (((uint64_t) (x) & 0x00000000ff000000) << 8) | \ + (((uint64_t) (x) & 0x000000ff00000000) >> 8) | \ + (((uint64_t) (x) & 0x0000ff0000000000) >> 24) | \ + (((uint64_t) (x) & 0x00ff000000000000) >> 40) | \ + (((uint64_t) (x) & 0xff00000000000000) >> 56)) + +static inline uint32_t ident32(uint32_t x) { return x; } +static inline uint64_t ident64(uint64_t x) { return x; } + +#ifndef __OpenBSD__ +# if defined(__ANDROID__) && defined(__swap32) && !defined(swap32) +# define swap32 __swap32 +# elif !defined(swap32) +static inline uint32_t swap32(uint32_t x) { + x = ((x & 0x00ff00ff) << 8) | ((x & 0xff00ff00) >> 8); + return (x << 16) | (x >> 16); +} +# endif +# if defined(__ANDROID__) && defined(__swap64) && !defined(swap64) +# define swap64 __swap64 +# elif !defined(swap64) +static inline uint64_t swap64(uint64_t x) { + x = ((x & 0x00ff00ff00ff00ff) << 8) | ((x & 0xff00ff00ff00ff00) >> 8); + x = ((x & 0x0000ffff0000ffff) << 16) | ((x & 0xffff0000ffff0000) >> 16); + return (x << 32) | (x >> 32); +} +# endif +#endif /* __OpenBSD__ */ + +#if defined(__GNUC__) +#define UNUSED __attribute__((unused)) +#else +#define UNUSED +#endif +static inline void mem_inplace_ident(void *mem UNUSED, size_t n UNUSED) { } +#undef UNUSED + +static inline void mem_inplace_swap32(void *mem, size_t n) { + size_t i; + for (i = 0; i < n; i++) { + ((uint32_t *) mem)[i] = swap32(((const uint32_t *) mem)[i]); + } +} +static inline void mem_inplace_swap64(void *mem, size_t n) { + size_t i; + for (i = 0; i < n; i++) { + ((uint64_t *) mem)[i] = swap64(((const uint64_t *) mem)[i]); + } +} + +static inline void memcpy_ident32(void *dst, const void *src, size_t n) { + memcpy(dst, src, 4 * n); +} +static inline void memcpy_ident64(void *dst, const void *src, size_t n) { + memcpy(dst, src, 8 * n); +} + +static inline void memcpy_swap32(void *dst, const void *src, size_t n) { + size_t i; + for (i = 0; i < n; i++) { + ((uint32_t *) dst)[i] = swap32(((const uint32_t *) src)[i]); + } +} +static inline void memcpy_swap64(void *dst, const void *src, size_t n) { + size_t i; + for (i = 0; i < n; i++) { + ((uint64_t *) dst)[i] = swap64(((const uint64_t *) src)[i]); + } +} + +#ifdef _MSC_VER +# define LITTLE_ENDIAN 1234 +# define BIG_ENDIAN 4321 +# define BYTE_ORDER LITTLE_ENDIAN +#endif + +#if !defined(BYTE_ORDER) || !defined(LITTLE_ENDIAN) || !defined(BIG_ENDIAN) +static_assert(false, "BYTE_ORDER is undefined. Perhaps, GNU extensions are not enabled"); +#endif + +#if BYTE_ORDER == LITTLE_ENDIAN +#define SWAP32LE IDENT32 +#define SWAP32BE SWAP32 +#define swap32le ident32 +#define swap32be swap32 +#define mem_inplace_swap32le mem_inplace_ident +#define mem_inplace_swap32be mem_inplace_swap32 +#define memcpy_swap32le memcpy_ident32 +#define memcpy_swap32be memcpy_swap32 +#define SWAP64LE IDENT64 +#define SWAP64BE SWAP64 +#define swap64le ident64 +#define swap64be swap64 +#define mem_inplace_swap64le mem_inplace_ident +#define mem_inplace_swap64be mem_inplace_swap64 +#define memcpy_swap64le memcpy_ident64 +#define memcpy_swap64be memcpy_swap64 +#endif + +#if BYTE_ORDER == BIG_ENDIAN +#define SWAP32BE IDENT32 +#define SWAP32LE SWAP32 +#define swap32be ident32 +#define swap32le swap32 +#define mem_inplace_swap32be mem_inplace_ident +#define mem_inplace_swap32le mem_inplace_swap32 +#define memcpy_swap32be memcpy_ident32 +#define memcpy_swap32le memcpy_swap32 +#define SWAP64BE IDENT64 +#define SWAP64LE SWAP64 +#define swap64be ident64 +#define swap64le swap64 +#define mem_inplace_swap64be mem_inplace_ident +#define mem_inplace_swap64le mem_inplace_swap64 +#define memcpy_swap64be memcpy_ident64 +#define memcpy_swap64le memcpy_swap64 +#endif diff --git a/contrib/epee/include/math_helper.h b/contrib/epee/include/math_helper.h index ef839f609..e22e8ee6e 100644 --- a/contrib/epee/include/math_helper.h +++ b/contrib/epee/include/math_helper.h @@ -230,35 +230,56 @@ namespace math_helper } } - template<int default_interval, bool start_immediate = true> - class once_a_time_seconds + template<uint64_t scale, int default_interval, bool start_immediate = true> + class once_a_time { + uint64_t get_time() const + { +#ifdef _WIN32 + FILETIME fileTime; + GetSystemTimeAsFileTime(&fileTime); + unsigned __int64 present = 0; + present |= fileTime.dwHighDateTime; + present = present << 32; + present |= fileTime.dwLowDateTime; + present /= 10; // mic-sec +#else + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000000 + tv.tv_usec; +#endif + } + public: - once_a_time_seconds():m_interval(default_interval) + once_a_time():m_interval(default_interval * scale) { m_last_worked_time = 0; if(!start_immediate) - time(&m_last_worked_time); + m_last_worked_time = get_time(); } template<class functor_t> bool do_call(functor_t functr) { - time_t current_time = 0; - time(¤t_time); + uint64_t current_time = get_time(); if(current_time - m_last_worked_time > m_interval) { bool res = functr(); - time(&m_last_worked_time); + m_last_worked_time = get_time(); return res; } return true; } private: - time_t m_last_worked_time; - time_t m_interval; + uint64_t m_last_worked_time; + uint64_t m_interval; }; + + template<int default_interval, bool start_immediate = true> + class once_a_time_seconds: public once_a_time<1000000, default_interval, start_immediate> {}; + template<int default_interval, bool start_immediate = true> + class once_a_time_milliseconds: public once_a_time<1000, default_interval, start_immediate> {}; } } diff --git a/contrib/epee/include/misc_log_ex.h b/contrib/epee/include/misc_log_ex.h index 530f8e636..602b6a371 100644 --- a/contrib/epee/include/misc_log_ex.h +++ b/contrib/epee/include/misc_log_ex.h @@ -32,18 +32,27 @@ #include "easylogging++.h" +#undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "default" + #define MAX_LOG_FILE_SIZE 104850000 // 100 MB - 7600 bytes #define MAX_LOG_FILES 50 -#define MCFATAL(cat,x) CLOG(FATAL,cat) << x -#define MCERROR(cat,x) CLOG(ERROR,cat) << x -#define MCWARNING(cat,x) CLOG(WARNING,cat) << x -#define MCINFO(cat,x) CLOG(INFO,cat) << x -#define MCDEBUG(cat,x) CLOG(DEBUG,cat) << x -#define MCTRACE(cat,x) CLOG(TRACE,cat) << x -#define MCLOG(level,cat,x) ELPP_WRITE_LOG(el::base::Writer, level, el::base::DispatchAction::NormalLog, cat) << x -#define MCLOG_FILE(level,cat,x) ELPP_WRITE_LOG(el::base::Writer, level, el::base::DispatchAction::FileOnlyLog, cat) << x +#define MCLOG_TYPE(level, cat, type, x) do { \ + if (ELPP->vRegistry()->allowed(level, cat)) { \ + el::base::Writer(level, __FILE__, __LINE__, ELPP_FUNC, type).construct(cat) << x; \ + } \ + } while (0) + +#define MCLOG(level, cat, x) MCLOG_TYPE(level, cat, el::base::DispatchAction::NormalLog, x) +#define MCLOG_FILE(level, cat, x) MCLOG_TYPE(level, cat, el::base::DispatchAction::FileOnlyLog, x) + +#define MCFATAL(cat,x) MCLOG(el::Level::Fatal,cat, x) +#define MCERROR(cat,x) MCLOG(el::Level::Error,cat, x) +#define MCWARNING(cat,x) MCLOG(el::Level::Warning,cat, x) +#define MCINFO(cat,x) MCLOG(el::Level::Info,cat, x) +#define MCDEBUG(cat,x) MCLOG(el::Level::Debug,cat, x) +#define MCTRACE(cat,x) MCLOG(el::Level::Trace,cat, x) #define MCLOG_COLOR(level,cat,color,x) MCLOG(level,cat,"\033[1;" color "m" << x << "\033[0m") #define MCLOG_RED(level,cat,x) MCLOG_COLOR(level,cat,"31",x) @@ -76,6 +85,16 @@ #define MGINFO_MAGENTA(x) MCLOG_MAGENTA(el::Level::Info, "global",x) #define MGINFO_CYAN(x) MCLOG_CYAN(el::Level::Info, "global",x) +#define IFLOG(level, cat, type, init, x) \ + do { \ + if (ELPP->vRegistry()->allowed(level, cat)) { \ + init; \ + el::base::Writer(level, __FILE__, __LINE__, ELPP_FUNC, type).construct(cat) << x; \ + } \ + } while(0) +#define MIDEBUG(init, x) IFLOG(el::Level::Debug, MONERO_DEFAULT_LOG_CATEGORY, el::base::DispatchAction::NormalLog, init, x) + + #define LOG_ERROR(x) MERROR(x) #define LOG_PRINT_L0(x) MWARNING(x) #define LOG_PRINT_L1(x) MINFO(x) diff --git a/contrib/epee/include/misc_os_dependent.h b/contrib/epee/include/misc_os_dependent.h index 0d09683d6..5fffde8d5 100644 --- a/contrib/epee/include/misc_os_dependent.h +++ b/contrib/epee/include/misc_os_dependent.h @@ -124,5 +124,14 @@ namespace misc_utils return boost::lexical_cast<std::string>(pthread_self()); #endif } + + inline bool get_gmt_time(time_t t, struct tm &tm) + { +#ifdef _WIN32 + return gmtime_s(&tm, &t); +#else + return gmtime_r(&t, &tm); +#endif + } } } diff --git a/contrib/epee/include/mlocker.h b/contrib/epee/include/mlocker.h index d2fc2ed58..a6d94b3d2 100644 --- a/contrib/epee/include/mlocker.h +++ b/contrib/epee/include/mlocker.h @@ -73,7 +73,7 @@ namespace epee mlocked(const T &&t): T(t) { mlocker::lock(this, sizeof(T)); } mlocked(const mlocked<T> &&mt): T(mt) { mlocker::lock(this, sizeof(T)); } mlocked<T> &operator=(const mlocked<T> &mt) { T::operator=(mt); return *this; } - ~mlocked() { mlocker::unlock(this, sizeof(T)); } + ~mlocked() { try { mlocker::unlock(this, sizeof(T)); } catch (...) { /* do not propagate */ } } }; template<typename T> diff --git a/contrib/epee/include/net/abstract_tcp_server2.h b/contrib/epee/include/net/abstract_tcp_server2.h index 3f726a352..e6b2755af 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.h +++ b/contrib/epee/include/net/abstract_tcp_server2.h @@ -36,7 +36,6 @@ #define _ABSTRACT_TCP_SERVER2_H_ -#include <boost/asio.hpp> #include <string> #include <vector> #include <boost/noncopyable.hpp> @@ -155,7 +154,8 @@ namespace net_utils //this should be the last one, because it could be wait on destructor, while other activities possible on other threads t_protocol_handler m_protocol_handler; //typename t_protocol_handler::config_type m_dummy_config; - std::list<boost::shared_ptr<connection<t_protocol_handler> > > m_self_refs; // add_ref/release support + size_t m_reference_count = 0; // reference count managed through add_ref/release support + boost::shared_ptr<connection<t_protocol_handler> > m_self_ref; // the reference to hold critical_section m_self_refs_lock; critical_section m_chunking_lock; // held while we add small chunks of the big do_send() to small do_send_chunk() critical_section m_shutdown_lock; // held while shutting down diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl index 5dbb7a478..457ee2dd4 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.inl +++ b/contrib/epee/include/net/abstract_tcp_server2.inl @@ -32,16 +32,13 @@ -//#include "net_utils_base.h" -#include <boost/lambda/bind.hpp> +#include <boost/bind.hpp> #include <boost/foreach.hpp> -#include <boost/lambda/lambda.hpp> #include <boost/uuid/random_generator.hpp> #include <boost/chrono.hpp> #include <boost/utility/value_init.hpp> #include <boost/asio/deadline_timer.hpp> #include <boost/date_time/posix_time/posix_time.hpp> // TODO -#include <boost/thread/thread.hpp> // TODO #include <boost/thread/condition_variable.hpp> // TODO #include "warnings.h" #include "string_tools.h" @@ -230,7 +227,8 @@ PRAGMA_WARNING_DISABLE_VS(4355) //_dbg3("[sock " << socket_.native_handle() << "] add_ref 2, m_peer_number=" << mI->m_peer_number); if(m_was_shutdown) return false; - m_self_refs.push_back(self); + ++m_reference_count; + m_self_ref = std::move(self); return true; CATCH_ENTRY_L0("connection<t_protocol_handler>::add_ref()", false); } @@ -242,10 +240,12 @@ PRAGMA_WARNING_DISABLE_VS(4355) boost::shared_ptr<connection<t_protocol_handler> > back_connection_copy; LOG_TRACE_CC(context, "[sock " << socket_.native_handle() << "] release"); CRITICAL_REGION_BEGIN(m_self_refs_lock); - CHECK_AND_ASSERT_MES(m_self_refs.size(), false, "[sock " << socket_.native_handle() << "] m_self_refs empty at connection<t_protocol_handler>::release() call"); - //erasing from container without additional copy can cause start deleting object, including m_self_refs - back_connection_copy = m_self_refs.back(); - m_self_refs.pop_back(); + CHECK_AND_ASSERT_MES(m_reference_count, false, "[sock " << socket_.native_handle() << "] m_reference_count already at 0 at connection<t_protocol_handler>::release() call"); + // is this the last reference? + if (--m_reference_count == 0) { + // move the held reference to a local variable, keeping the object alive until the function terminates + std::swap(back_connection_copy, m_self_ref); + } CRITICAL_REGION_END(); return true; CATCH_ENTRY_L0("connection<t_protocol_handler>::release()", false); @@ -295,6 +295,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) CRITICAL_REGION_LOCAL(m_throttle_speed_in_mutex); m_throttle_speed_in.handle_trafic_exact(bytes_transferred); context.m_current_speed_down = m_throttle_speed_in.get_current_speed(); + context.m_max_speed_down = std::max(context.m_max_speed_down, context.m_current_speed_down); } { @@ -393,7 +394,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) //ask it inside(!) critical region if we still able to go in event wait... size_t cnt = socket_.get_io_service().poll_one(); if(!cnt) - misc_utils::sleep_no_w(0); + misc_utils::sleep_no_w(1); } return true; @@ -497,6 +498,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) CRITICAL_REGION_LOCAL(m_throttle_speed_out_mutex); m_throttle_speed_out.handle_trafic_exact(cb); context.m_current_speed_up = m_throttle_speed_out.get_current_speed(); + context.m_max_speed_up = std::max(context.m_max_speed_up, context.m_current_speed_up); } //_info("[sock " << socket_.native_handle() << "] SEND " << cb); @@ -889,7 +891,9 @@ POP_WARNINGS { try { - io_service_.run(); + size_t cnt = io_service_.run(); + if (cnt == 0) + misc_utils::sleep_no_w(1); } catch(const std::exception& ex) { diff --git a/contrib/epee/include/net/buffer.h b/contrib/epee/include/net/buffer.h new file mode 100644 index 000000000..56c67f6bf --- /dev/null +++ b/contrib/epee/include/net/buffer.h @@ -0,0 +1,62 @@ +// 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. + +#pragma once + +#include <vector> +#include "misc_log_ex.h" +#include "span.h" + +#undef MONERO_DEFAULT_LOG_CATEGORY +#define MONERO_DEFAULT_LOG_CATEGORY "net.buffer" + +//#define NET_BUFFER_LOG(x) MDEBUG(x) +#define NET_BUFFER_LOG(x) ((void)0) + +namespace epee +{ +namespace net_utils +{ +class buffer +{ +public: + buffer(size_t reserve = 0): offset(0) { storage.reserve(reserve); } + + void append(const void *data, size_t sz); + void erase(size_t sz) { NET_BUFFER_LOG("erasing " << sz << "/" << size()); CHECK_AND_ASSERT_THROW_MES(offset + sz <= storage.size(), "erase: sz too large"); offset += sz; if (offset == storage.size()) { storage.resize(0); offset = 0; } } + epee::span<const uint8_t> span(size_t sz) const { CHECK_AND_ASSERT_THROW_MES(sz <= size(), "span is too large"); return epee::span<const uint8_t>(storage.data() + offset, sz); } + // carve must keep the data in scope till next call, other API calls (such as append, erase) can invalidate the carved buffer + epee::span<const uint8_t> carve(size_t sz) { CHECK_AND_ASSERT_THROW_MES(sz <= size(), "span is too large"); offset += sz; return epee::span<const uint8_t>(storage.data() + offset - sz, sz); } + size_t size() const { return storage.size() - offset; } + +private: + std::vector<uint8_t> storage; + size_t offset; +}; +} +} diff --git a/contrib/epee/include/net/connection_basic.hpp b/contrib/epee/include/net/connection_basic.hpp index 7e8750047..9b6fc14a7 100644 --- a/contrib/epee/include/net/connection_basic.hpp +++ b/contrib/epee/include/net/connection_basic.hpp @@ -42,22 +42,11 @@ #define INCLUDED_p2p_connection_basic_hpp -#include <boost/asio.hpp> #include <string> -#include <vector> -#include <boost/noncopyable.hpp> -#include <boost/shared_ptr.hpp> #include <atomic> +#include <memory> #include <boost/asio.hpp> -#include <boost/array.hpp> -#include <boost/noncopyable.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> -#include <boost/interprocess/detail/atomic.hpp> -#include <boost/thread/thread.hpp> - -#include <memory> #include "net/net_utils_base.h" #include "syncobj.h" diff --git a/contrib/epee/include/net/http_server_handlers_map2.h b/contrib/epee/include/net/http_server_handlers_map2.h index 00a867d3e..64d035df9 100644 --- a/contrib/epee/include/net/http_server_handlers_map2.h +++ b/contrib/epee/include/net/http_server_handlers_map2.h @@ -39,7 +39,7 @@ epee::net_utils::http::http_response_info& response, \ context_type& m_conn_context) \ {\ - LOG_PRINT_L2("HTTP [" << m_conn_context.m_remote_address.host_str() << "] " << query_info.m_http_method_str << " " << query_info.m_URI); \ + MINFO("HTTP [" << m_conn_context.m_remote_address.host_str() << "] " << query_info.m_http_method_str << " " << query_info.m_URI); \ response.m_response_code = 200; \ response.m_response_comment = "Ok"; \ if(!handle_http_request_map(query_info, response, m_conn_context)) \ @@ -68,6 +68,7 @@ CHECK_AND_ASSERT_MES(parse_res, false, "Failed to parse json: \r\n" << query_info.m_body); \ uint64_t ticks1 = epee::misc_utils::get_tick_count(); \ boost::value_initialized<command_type::response> resp;\ + MINFO(m_conn_context << "calling " << s_pattern); \ if(!callback_f(static_cast<command_type::request&>(req), static_cast<command_type::response&>(resp))) \ { \ LOG_ERROR("Failed to " << #callback_f << "()"); \ @@ -91,10 +92,11 @@ handled = true; \ uint64_t ticks = misc_utils::get_tick_count(); \ boost::value_initialized<command_type::request> req; \ - bool parse_res = epee::serialization::load_t_from_binary(static_cast<command_type::request&>(req), query_info.m_body); \ + bool parse_res = epee::serialization::load_t_from_binary(static_cast<command_type::request&>(req), epee::strspan<uint8_t>(query_info.m_body)); \ CHECK_AND_ASSERT_MES(parse_res, false, "Failed to parse bin body data, body size=" << query_info.m_body.size()); \ uint64_t ticks1 = misc_utils::get_tick_count(); \ boost::value_initialized<command_type::response> resp;\ + MINFO(m_conn_context << "calling " << s_pattern); \ if(!callback_f(static_cast<command_type::request&>(req), static_cast<command_type::response&>(resp))) \ { \ LOG_ERROR("Failed to " << #callback_f << "()"); \ @@ -179,6 +181,7 @@ epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \ fail_resp.jsonrpc = "2.0"; \ fail_resp.id = req.id; \ + MINFO(m_conn_context << "Calling RPC method " << method_name); \ if(!callback_f(req.params, resp.result, fail_resp.error)) \ { \ epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(fail_resp), response_info.m_body); \ @@ -197,6 +200,7 @@ epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \ fail_resp.jsonrpc = "2.0"; \ fail_resp.id = req.id; \ + MINFO(m_conn_context << "calling RPC method " << method_name); \ if(!callback_f(req.params, resp.result, fail_resp.error, m_conn_context, response_info)) \ { \ epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(fail_resp), response_info.m_body); \ @@ -210,6 +214,7 @@ else if(callback_name == method_name) \ { \ PREPARE_OBJECTS_FROM_JSON(command_type) \ + MINFO(m_conn_context << "calling RPC method " << method_name); \ if(!callback_f(req.params, resp.result)) \ { \ epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \ diff --git a/contrib/epee/include/net/http_server_impl_base.h b/contrib/epee/include/net/http_server_impl_base.h index 1a97e610a..5669824c1 100644 --- a/contrib/epee/include/net/http_server_impl_base.h +++ b/contrib/epee/include/net/http_server_impl_base.h @@ -33,7 +33,8 @@ #include <boost/thread.hpp> #include <boost/bind.hpp> -#include "net/http_server_cp2.h" +#include "net/abstract_tcp_server2.h" +#include "http_protocol_handler.h" #include "net/http_server_handlers_map2.h" #undef MONERO_DEFAULT_LOG_CATEGORY diff --git a/contrib/epee/include/net/levin_base.h b/contrib/epee/include/net/levin_base.h index 7d060f5ef..a88a1eb49 100644 --- a/contrib/epee/include/net/levin_base.h +++ b/contrib/epee/include/net/levin_base.h @@ -80,8 +80,8 @@ namespace levin template<class t_connection_context = net_utils::connection_context_base> struct levin_commands_handler { - virtual int invoke(int command, const std::string& in_buff, std::string& buff_out, t_connection_context& context)=0; - virtual int notify(int command, const std::string& in_buff, t_connection_context& context)=0; + virtual int invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, t_connection_context& context)=0; + virtual int notify(int command, const epee::span<const uint8_t> in_buff, t_connection_context& context)=0; virtual void callback(t_connection_context& context){}; virtual void on_connection_new(t_connection_context& context){}; diff --git a/contrib/epee/include/net/levin_client.h b/contrib/epee/include/net/levin_client.h index 335f6ba02..76d528234 100644 --- a/contrib/epee/include/net/levin_client.h +++ b/contrib/epee/include/net/levin_client.h @@ -57,7 +57,7 @@ namespace levin bool is_connected(); bool disconnect(); - virtual int invoke(int command, const std::string& in_buff, std::string& buff_out); + virtual int invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out); virtual int notify(int command, const std::string& in_buff); protected: @@ -72,7 +72,7 @@ namespace levin { public: - int invoke(int command, const std::string& in_buff, std::string& buff_out); + int invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out); int notify(int command, const std::string& in_buff); }; diff --git a/contrib/epee/include/net/levin_client.inl b/contrib/epee/include/net/levin_client.inl index ab7c32c32..2f048b027 100644 --- a/contrib/epee/include/net/levin_client.inl +++ b/contrib/epee/include/net/levin_client.inl @@ -74,16 +74,16 @@ levin_client_impl::~levin_client_impl() } //------------------------------------------------------------------------------ inline -int levin_client_impl::invoke(int command, const std::string& in_buff, std::string& buff_out) +int levin_client_impl::invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out) { if(!is_connected()) return -1; bucket_head head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); + head.m_signature = SWAP64LE(LEVIN_SIGNATURE); + head.m_cb = SWAP64LE(in_buff.size()); head.m_have_to_return_data = true; - head.m_command = command; + head.m_command = SWAP32LE(command); if(!m_transport.send(&head, sizeof(head))) return -1; @@ -97,7 +97,7 @@ int levin_client_impl::invoke(int command, const std::string& in_buff, std::stri head = *(bucket_head*)local_buff.data(); - if(head.m_signature!=LEVIN_SIGNATURE) + if(head.m_signature!=SWAP64LE(LEVIN_SIGNATURE)) { LOG_PRINT_L1("Signature mismatch in response"); return -1; @@ -116,10 +116,10 @@ int levin_client_impl::notify(int command, const std::string& in_buff) return -1; bucket_head head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); + head.m_signature = SWAP64LE(LEVIN_SIGNATURE); + head.m_cb = SWAP64LE(in_buff.size()); head.m_have_to_return_data = false; - head.m_command = command; + head.m_command = SWAP32LE(command); if(!m_transport.send((const char*)&head, sizeof(head))) return -1; @@ -133,18 +133,19 @@ int levin_client_impl::notify(int command, const std::string& in_buff) //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ inline - int levin_client_impl2::invoke(int command, const std::string& in_buff, std::string& buff_out) + int levin_client_impl2::invoke(int command, epee::span<const uint8_t>string& in_buff, std::string& buff_out) { if(!is_connected()) return -1; bucket_head2 head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); + head.m_signature = SWAP64LE(LEVIN_SIGNATURE); + head.m_cb = SWAP64LE(in_buff.size()); head.m_have_to_return_data = true; - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - head.m_flags = LEVIN_PACKET_REQUEST; + head.m_command = SWAP32LE(command); + head.m_return_code = SWAP32LE(0); + head.m_flags = SWAP32LE(LEVIN_PACKET_REQUEST); + head.m_protocol_version = SWAP32LE(LEVIN_PROTOCOL_VER_1); if(!m_transport.send(&head, sizeof(head))) return -1; @@ -157,14 +158,13 @@ inline head = *(bucket_head2*)local_buff.data(); - - if(head.m_signature!=LEVIN_SIGNATURE) + if(head.m_signature != SWAP64LE(LEVIN_SIGNATURE)) { LOG_PRINT_L1("Signature mismatch in response"); return -1; } - if(!m_transport.recv_n(buff_out, head.m_cb)) + if(!m_transport.recv_n(buff_out, SWAP64LE(head.m_cb))) return -1; return head.m_return_code; @@ -177,12 +177,13 @@ inline return -1; bucket_head2 head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); + head.m_signature = SWAP64LE(LEVIN_SIGNATURE); + head.m_cb = SWAP64LE(in_buff.size()); head.m_have_to_return_data = false; - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - head.m_flags = LEVIN_PACKET_REQUEST; + head.m_command = SWAP32LE(command); + head.m_return_code = SWAP32LE(0); + head.m_flags = SWAP32LE(LEVIN_PACKET_REQUEST); + head.m_protocol_version = SWAP32LE(LEVIN_PROTOCOL_VER_1); if(!m_transport.send((const char*)&head, sizeof(head))) return -1; diff --git a/contrib/epee/include/net/levin_client_async.h b/contrib/epee/include/net/levin_client_async.h index b3a46465b..ed92f4b95 100644 --- a/contrib/epee/include/net/levin_client_async.h +++ b/contrib/epee/include/net/levin_client_async.h @@ -431,7 +431,7 @@ namespace levin } CRITICAL_REGION_END(); - LOG_PRINT_L4("LEVIN_PACKET_RECIEVED. [len=" << head.m_cb << ", flags=" << head.m_flags << ", is_cmd=" << head.m_have_to_return_data <<", cmd_id = " << head.m_command << ", pr_v=" << head.m_protocol_version << ", uid=" << string_tools::get_str_from_guid_a(head.m_id) << "]"); + LOG_PRINT_L4("LEVIN_PACKET_RECEIVED. [len=" << head.m_cb << ", flags=" << head.m_flags << ", is_cmd=" << head.m_have_to_return_data <<", cmd_id = " << head.m_command << ", pr_v=" << head.m_protocol_version << ", uid=" << string_tools::get_str_from_guid_a(head.m_id) << "]"); if(is_request) { diff --git a/contrib/epee/include/net/levin_helper.h b/contrib/epee/include/net/levin_helper.h index 05560dd90..da926a914 100644 --- a/contrib/epee/include/net/levin_helper.h +++ b/contrib/epee/include/net/levin_helper.h @@ -30,6 +30,7 @@ #include "levin_base.h" #include "serializeble_struct_helper.h" +#include "int-util.h" #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "net" @@ -43,11 +44,11 @@ namespace levin { buff.resize(sizeof(levin::bucket_head)); levin::bucket_head& head = *(levin::bucket_head*)(&buff[0]); - head.m_signature = LEVIN_SIGNATURE; + head.m_signature = SWAP64LE(LEVIN_SIGNATURE); head.m_cb = 0; head.m_have_to_return_data = true; - head.m_command = command_id; - head.m_return_code = 1; + head.m_command = SWAP32LE(command_id); + head.m_return_code = SWAP32LE(1); head.m_reservedA = rand(); //probably some flags in future head.m_reservedB = rand(); //probably some check summ in future @@ -55,7 +56,7 @@ namespace levin if(!StorageNamed::save_struct_as_storage_to_buff_t<t_struct, StorageNamed::DefaultStorageType>(t, buff_strg)) return false; - head.m_cb = buff_strg.size(); + head.m_cb = SWAP64LE(buff_strg.size()); buff.append(buff_strg); return true; } @@ -65,15 +66,15 @@ namespace levin { buff.resize(sizeof(levin::bucket_head)); levin::bucket_head& head = *(levin::bucket_head*)(&buff[0]); - head.m_signature = LEVIN_SIGNATURE; + head.m_signature = SWAP64LE(LEVIN_SIGNATURE); head.m_cb = 0; head.m_have_to_return_data = true; - head.m_command = command_id; - head.m_return_code = 1; + head.m_command = SWAP32LE(command_id); + head.m_return_code = SWAP32LE(1); head.m_reservedA = rand(); //probably some flags in future head.m_reservedB = rand(); //probably some check summ in future - head.m_cb = data.size(); + head.m_cb = SWAP64LE(data.size()); buff.append(data); return true; } @@ -86,7 +87,17 @@ namespace levin return false; } - levin::bucket_head& head = *(levin::bucket_head*)(&buff[0]); +#if BYTE_ORDER == LITTLE_ENDIAN + levin::bucket_head &head = *(levin::bucket_head*)(&buff[0]); +#else + levin::bucket_head head = *(levin::bucket_head*)(&buff[0]); + head.m_signature = SWAP64LE(head.m_signature); + head.m_cb = SWAP64LE(head.m_cb); + head.m_command = SWAP32LE(head.m_command); + head.m_return_code = SWAP32LE(head.m_return_code); + head.m_reservedA = SWAP32LE(head.m_reservedA); + head.m_reservedB = SWAP32LE(head.m_reservedB); +#endif if(head.m_signature != LEVIN_SIGNATURE) { LOG_PRINT_L3("Failed to read signature in levin message, at load_struct_from_levin_message"); @@ -113,7 +124,17 @@ namespace levin return false; } - levin::bucket_head& head = *(levin::bucket_head*)(&buff[0]); +#if BYTE_ORDER == LITTLE_ENDIAN + levin::bucket_head &head = *(levin::bucket_head*)(&buff[0]); +#else + levin::bucket_head head = *(levin::bucket_head*)(&buff[0]); + head.m_signature = SWAP64LE(head.m_signature); + head.m_cb = SWAP64LE(head.m_cb); + head.m_command = SWAP32LE(head.m_command); + head.m_return_code = SWAP32LE(head.m_return_code); + head.m_reservedA = SWAP32LE(head.m_reservedA); + head.m_reservedB = SWAP32LE(head.m_reservedB); +#endif if(head.m_signature != LEVIN_SIGNATURE) { LOG_ERROR("Failed to read signature in levin message, at load_struct_from_levin_message"); diff --git a/contrib/epee/include/net/levin_protocol_handler.h b/contrib/epee/include/net/levin_protocol_handler.h index b3a75bedc..791766762 100644 --- a/contrib/epee/include/net/levin_protocol_handler.h +++ b/contrib/epee/include/net/levin_protocol_handler.h @@ -31,6 +31,7 @@ #include <boost/uuid/uuid_generators.hpp> #include "levin_base.h" +#include "int-util.h" #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "net" @@ -103,7 +104,7 @@ namespace levin case conn_state_reading_head: if(m_cach_in_buffer.size() < sizeof(bucket_head)) { - if(m_cach_in_buffer.size() >= sizeof(uint64_t) && *((uint64_t*)m_cach_in_buffer.data()) != LEVIN_SIGNATURE) + if(m_cach_in_buffer.size() >= sizeof(uint64_t) && *((uint64_t*)m_cach_in_buffer.data()) != SWAP64LE(LEVIN_SIGNATURE)) { LOG_ERROR_CC(m_conn_context, "Signature mismatch on accepted connection"); return false; @@ -112,13 +113,23 @@ namespace levin break; } { - bucket_head* phead = (bucket_head*)m_cach_in_buffer.data(); - if(LEVIN_SIGNATURE != phead->m_signature) +#if BYTE_ORDER == LITTLE_ENDIAN + bucket_head &phead = *(bucket_head*)m_cach_in_buffer.data(); +#else + bucket_head phead = *(bucket_head*)m_cach_in_buffer.data(); + phead.m_signature = SWAP64LE(phead.m_signature); + phead.m_cb = SWAP64LE(phead.m_cb); + phead.m_command = SWAP32LE(phead.m_command); + phead.m_return_code = SWAP32LE(phead.m_return_code); + phead.m_reservedA = SWAP32LE(phead.m_reservedA); + phead.m_reservedB = SWAP32LE(phead.m_reservedB); +#endif + if(LEVIN_SIGNATURE != phead.m_signature) { LOG_ERROR_CC(m_conn_context, "Signature mismatch on accepted connection"); return false; } - m_current_head = *phead; + m_current_head = phead; } m_cach_in_buffer.erase(0, sizeof(bucket_head)); m_state = conn_state_reading_body; diff --git a/contrib/epee/include/net/levin_protocol_handler_async.h b/contrib/epee/include/net/levin_protocol_handler_async.h index 08aa1d468..a1ea3e680 100644 --- a/contrib/epee/include/net/levin_protocol_handler_async.h +++ b/contrib/epee/include/net/levin_protocol_handler_async.h @@ -34,9 +34,11 @@ #include <atomic> #include "levin_base.h" +#include "buffer.h" #include "misc_language.h" #include "syncobj.h" #include "misc_os_dependent.h" +#include "int-util.h" #include <random> #include <chrono> @@ -84,11 +86,11 @@ public: uint64_t m_max_packet_size; uint64_t m_invoke_timeout; - int invoke(int command, const std::string& in_buff, std::string& buff_out, boost::uuids::uuid connection_id); + int invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, boost::uuids::uuid connection_id); template<class callback_t> - int invoke_async(int command, const std::string& in_buff, boost::uuids::uuid connection_id, const callback_t &cb, size_t timeout = LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED); + int invoke_async(int command, const epee::span<const uint8_t> in_buff, boost::uuids::uuid connection_id, const callback_t &cb, size_t timeout = LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED); - int notify(int command, const std::string& in_buff, boost::uuids::uuid connection_id); + int notify(int command, const epee::span<const uint8_t> in_buff, boost::uuids::uuid connection_id); bool close(boost::uuids::uuid connection_id); bool update_connection_context(const t_connection_context& contxt); bool request_callback(boost::uuids::uuid connection_id); @@ -142,7 +144,7 @@ public: config_type& m_config; t_connection_context& m_connection_context; - std::string m_cache_in_buffer; + net_utils::buffer m_cache_in_buffer; stream_state m_state; int32_t m_oponent_protocol_ver; @@ -150,7 +152,7 @@ public: struct invoke_response_handler_base { - virtual bool handle(int res, const std::string& buff, connection_context& context)=0; + virtual bool handle(int res, const epee::span<const uint8_t> buff, connection_context& context)=0; virtual bool is_timer_started() const=0; virtual void cancel()=0; virtual bool cancel_timer()=0; @@ -172,7 +174,7 @@ public: if(ec == boost::asio::error::operation_aborted) return; MINFO(con.get_context_ref() << "Timeout on invoke operation happened, command: " << command << " timeout: " << timeout); - std::string fake; + epee::span<const uint8_t> fake; cb(LEVIN_ERROR_CONNECTION_TIMEDOUT, fake, con.get_context_ref()); con.close(); con.finish_outer_call(); @@ -190,7 +192,7 @@ public: bool m_timer_cancelled; uint64_t m_timeout; int m_command; - virtual bool handle(int res, const std::string& buff, typename async_protocol_handler::connection_context& context) + virtual bool handle(int res, const epee::span<const uint8_t> buff, typename async_protocol_handler::connection_context& context) { if(!cancel_timer()) return false; @@ -206,7 +208,7 @@ public: { if(cancel_timer()) { - std::string fake; + epee::span<const uint8_t> fake; m_cb(LEVIN_ERROR_CONNECTION_DESTROYED, fake, m_con.get_context_ref()); m_con.finish_outer_call(); } @@ -236,7 +238,7 @@ public: if(ec == boost::asio::error::operation_aborted) return; MINFO(con.get_context_ref() << "Timeout on invoke operation happened, command: " << command << " timeout: " << timeout); - std::string fake; + epee::span<const uint8_t> fake; cb(LEVIN_ERROR_CONNECTION_TIMEDOUT, fake, con.get_context_ref()); con.close(); con.finish_outer_call(); @@ -264,6 +266,7 @@ public: m_pservice_endpoint(psnd_hndlr), m_config(config), m_connection_context(conn_context), + m_cache_in_buffer(256 * 1024), m_state(stream_state_head) { m_close_called = 0; @@ -404,18 +407,11 @@ public: break; } { - std::string buff_to_invoke; - if(m_cache_in_buffer.size() == m_current_head.m_cb) - buff_to_invoke.swap(m_cache_in_buffer); - else - { - buff_to_invoke.assign(m_cache_in_buffer, 0, (std::string::size_type)m_current_head.m_cb); - m_cache_in_buffer.erase(0, (std::string::size_type)m_current_head.m_cb); - } + epee::span<const uint8_t> buff_to_invoke = m_cache_in_buffer.carve((std::string::size_type)m_current_head.m_cb); bool is_response = (m_oponent_protocol_ver == LEVIN_PROTOCOL_VER_1 && m_current_head.m_flags&LEVIN_PACKET_RESPONSE); - MDEBUG(m_connection_context << "LEVIN_PACKET_RECIEVED. [len=" << m_current_head.m_cb + MDEBUG(m_connection_context << "LEVIN_PACKET_RECEIVED. [len=" << m_current_head.m_cb << ", flags" << m_current_head.m_flags << ", r?=" << m_current_head.m_have_to_return_data <<", cmd = " << m_current_head.m_command @@ -448,8 +444,8 @@ public: }else { CRITICAL_REGION_BEGIN(m_local_inv_buff_lock); - buff_to_invoke.swap(m_local_inv_buff); - buff_to_invoke.clear(); + m_local_inv_buff = std::string((const char*)buff_to_invoke.data(), buff_to_invoke.size()); + buff_to_invoke = epee::span<const uint8_t>((const uint8_t*)NULL, 0); m_invoke_result_code = m_current_head.m_return_code; CRITICAL_REGION_END(); boost::interprocess::ipcdetail::atomic_write32(&m_invoke_buf_ready, 1); @@ -469,7 +465,18 @@ public: m_current_head.m_have_to_return_data = false; m_current_head.m_protocol_version = LEVIN_PROTOCOL_VER_1; m_current_head.m_flags = LEVIN_PACKET_RESPONSE; +#if BYTE_ORDER == LITTLE_ENDIAN std::string send_buff((const char*)&m_current_head, sizeof(m_current_head)); +#else + bucket_head2 head = m_current_head; + head.m_signature = SWAP64LE(head.m_signature); + head.m_cb = SWAP64LE(head.m_cb); + head.m_command = SWAP32LE(head.m_command); + head.m_return_code = SWAP32LE(head.m_return_code); + head.m_flags = SWAP32LE(head.m_flags); + head.m_protocol_version = SWAP32LE(head.m_protocol_version); + std::string send_buff((const char*)&head, sizeof(head)); +#endif send_buff += return_buff; CRITICAL_REGION_BEGIN(m_send_lock); if(!m_pservice_endpoint->do_send(send_buff.data(), send_buff.size())) @@ -491,7 +498,7 @@ public: { if(m_cache_in_buffer.size() < sizeof(bucket_head2)) { - if(m_cache_in_buffer.size() >= sizeof(uint64_t) && *((uint64_t*)m_cache_in_buffer.data()) != LEVIN_SIGNATURE) + if(m_cache_in_buffer.size() >= sizeof(uint64_t) && *((uint64_t*)m_cache_in_buffer.span(8).data()) != SWAP64LE(LEVIN_SIGNATURE)) { MWARNING(m_connection_context << "Signature mismatch, connection will be closed"); return false; @@ -500,15 +507,25 @@ public: break; } - bucket_head2* phead = (bucket_head2*)m_cache_in_buffer.data(); - if(LEVIN_SIGNATURE != phead->m_signature) +#if BYTE_ORDER == LITTLE_ENDIAN + bucket_head2& phead = *(bucket_head2*)m_cache_in_buffer.span(sizeof(bucket_head2)).data(); +#else + bucket_head2 phead = *(bucket_head2*)m_cache_in_buffer.span(sizeof(bucket_head2)).data(); + phead.m_signature = SWAP64LE(phead.m_signature); + phead.m_cb = SWAP64LE(phead.m_cb); + phead.m_command = SWAP32LE(phead.m_command); + phead.m_return_code = SWAP32LE(phead.m_return_code); + phead.m_flags = SWAP32LE(phead.m_flags); + phead.m_protocol_version = SWAP32LE(phead.m_protocol_version); +#endif + if(LEVIN_SIGNATURE != phead.m_signature) { LOG_ERROR_CC(m_connection_context, "Signature mismatch, connection will be closed"); return false; } - m_current_head = *phead; + m_current_head = phead; - m_cache_in_buffer.erase(0, sizeof(bucket_head2)); + m_cache_in_buffer.erase(sizeof(bucket_head2)); m_state = stream_state_body; m_oponent_protocol_ver = m_current_head.m_protocol_version; if(m_current_head.m_cb > m_config.m_max_packet_size) @@ -540,7 +557,7 @@ public: } template<class callback_t> - bool async_invoke(int command, const std::string& in_buff, const callback_t &cb, size_t timeout = LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED) + bool async_invoke(int command, const epee::span<const uint8_t> in_buff, const callback_t &cb, size_t timeout = LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED) { misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler( boost::bind(&async_protocol_handler::finish_outer_call, this)); @@ -566,13 +583,13 @@ public: } bucket_head2 head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); + head.m_signature = SWAP64LE(LEVIN_SIGNATURE); + head.m_cb = SWAP64LE(in_buff.size()); head.m_have_to_return_data = true; - head.m_flags = LEVIN_PACKET_REQUEST; - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; + head.m_flags = SWAP32LE(LEVIN_PACKET_REQUEST); + head.m_command = SWAP32LE(command); + head.m_protocol_version = SWAP32LE(LEVIN_PROTOCOL_VER_1); boost::interprocess::ipcdetail::atomic_write32(&m_invoke_buf_ready, 0); CRITICAL_REGION_BEGIN(m_send_lock); @@ -584,7 +601,7 @@ public: break; } - if(!m_pservice_endpoint->do_send(in_buff.data(), (int)in_buff.size())) + if(!m_pservice_endpoint->do_send(in_buff.data(), in_buff.size())) { LOG_ERROR_CC(m_connection_context, "Failed to do_send"); err_code = LEVIN_ERROR_CONNECTION; @@ -601,7 +618,7 @@ public: if (LEVIN_OK != err_code) { - std::string stub_buff; + epee::span<const uint8_t> stub_buff{(const uint8_t*)"", 0}; // Never call callback inside critical section, that can cause deadlock cb(err_code, stub_buff, m_connection_context); return false; @@ -610,7 +627,7 @@ public: return true; } - int invoke(int command, const std::string& in_buff, std::string& buff_out) + int invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out) { misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler( boost::bind(&async_protocol_handler::finish_outer_call, this)); @@ -624,13 +641,13 @@ public: return LEVIN_ERROR_CONNECTION_DESTROYED; bucket_head2 head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); + head.m_signature = SWAP64LE(LEVIN_SIGNATURE); + head.m_cb = SWAP64LE(in_buff.size()); head.m_have_to_return_data = true; - head.m_flags = LEVIN_PACKET_REQUEST; - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; + head.m_flags = SWAP32LE(LEVIN_PACKET_REQUEST); + head.m_command = SWAP32LE(command); + head.m_protocol_version = SWAP32LE(LEVIN_PROTOCOL_VER_1); boost::interprocess::ipcdetail::atomic_write32(&m_invoke_buf_ready, 0); CRITICAL_REGION_BEGIN(m_send_lock); @@ -640,7 +657,7 @@ public: return LEVIN_ERROR_CONNECTION; } - if(!m_pservice_endpoint->do_send(in_buff.data(), (int)in_buff.size())) + if(!m_pservice_endpoint->do_send(in_buff.data(), in_buff.size())) { LOG_ERROR_CC(m_connection_context, "Failed to do_send"); return LEVIN_ERROR_CONNECTION; @@ -684,7 +701,7 @@ public: return m_invoke_result_code; } - int notify(int command, const std::string& in_buff) + int notify(int command, const epee::span<const uint8_t> in_buff) { misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler( boost::bind(&async_protocol_handler::finish_outer_call, this)); @@ -698,13 +715,13 @@ public: return LEVIN_ERROR_CONNECTION_DESTROYED; bucket_head2 head = {0}; - head.m_signature = LEVIN_SIGNATURE; + head.m_signature = SWAP64LE(LEVIN_SIGNATURE); head.m_have_to_return_data = false; - head.m_cb = in_buff.size(); + head.m_cb = SWAP64LE(in_buff.size()); - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - head.m_flags = LEVIN_PACKET_REQUEST; + head.m_command = SWAP32LE(command); + head.m_protocol_version = SWAP32LE(LEVIN_PROTOCOL_VER_1); + head.m_flags = SWAP32LE(LEVIN_PACKET_REQUEST); CRITICAL_REGION_BEGIN(m_send_lock); if(!m_pservice_endpoint->do_send(&head, sizeof(head))) { @@ -712,7 +729,7 @@ public: return -1; } - if(!m_pservice_endpoint->do_send(in_buff.data(), (int)in_buff.size())) + if(!m_pservice_endpoint->do_send(in_buff.data(), in_buff.size())) { LOG_ERROR_CC(m_connection_context, "Failed to do_send()"); return -1; @@ -817,7 +834,7 @@ int async_protocol_handler_config<t_connection_context>::find_and_lock_connectio } //------------------------------------------------------------------------------------------ template<class t_connection_context> -int async_protocol_handler_config<t_connection_context>::invoke(int command, const std::string& in_buff, std::string& buff_out, boost::uuids::uuid connection_id) +int async_protocol_handler_config<t_connection_context>::invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, boost::uuids::uuid connection_id) { async_protocol_handler<t_connection_context>* aph; int r = find_and_lock_connection(connection_id, aph); @@ -825,7 +842,7 @@ int async_protocol_handler_config<t_connection_context>::invoke(int command, con } //------------------------------------------------------------------------------------------ template<class t_connection_context> template<class callback_t> -int async_protocol_handler_config<t_connection_context>::invoke_async(int command, const std::string& in_buff, boost::uuids::uuid connection_id, const callback_t &cb, size_t timeout) +int async_protocol_handler_config<t_connection_context>::invoke_async(int command, const epee::span<const uint8_t> in_buff, boost::uuids::uuid connection_id, const callback_t &cb, size_t timeout) { async_protocol_handler<t_connection_context>* aph; int r = find_and_lock_connection(connection_id, aph); @@ -874,7 +891,7 @@ void async_protocol_handler_config<t_connection_context>::set_handler(levin_comm } //------------------------------------------------------------------------------------------ template<class t_connection_context> -int async_protocol_handler_config<t_connection_context>::notify(int command, const std::string& in_buff, boost::uuids::uuid connection_id) +int async_protocol_handler_config<t_connection_context>::notify(int command, const epee::span<const uint8_t> in_buff, boost::uuids::uuid connection_id) { async_protocol_handler<t_connection_context>* aph; int r = find_and_lock_connection(connection_id, aph); diff --git a/contrib/epee/include/net/net_utils_base.h b/contrib/epee/include/net/net_utils_base.h index a133942fb..a9e458626 100644 --- a/contrib/epee/include/net/net_utils_base.h +++ b/contrib/epee/include/net/net_utils_base.h @@ -228,6 +228,8 @@ namespace net_utils uint64_t m_send_cnt; double m_current_speed_down; double m_current_speed_up; + double m_max_speed_down; + double m_max_speed_up; connection_context_base(boost::uuids::uuid connection_id, const network_address &remote_address, bool is_income, @@ -242,7 +244,9 @@ namespace net_utils m_recv_cnt(recv_cnt), m_send_cnt(send_cnt), m_current_speed_down(0), - m_current_speed_up(0) + m_current_speed_up(0), + m_max_speed_down(0), + m_max_speed_up(0) {} connection_context_base(): m_connection_id(), @@ -254,7 +258,9 @@ namespace net_utils m_recv_cnt(0), m_send_cnt(0), m_current_speed_down(0), - m_current_speed_up(0) + m_current_speed_up(0), + m_max_speed_down(0), + m_max_speed_up(0) {} connection_context_base& operator=(const connection_context_base& a) diff --git a/contrib/epee/include/readline_buffer.h b/contrib/epee/include/readline_buffer.h index 87c8826cb..5968d243d 100644 --- a/contrib/epee/include/readline_buffer.h +++ b/contrib/epee/include/readline_buffer.h @@ -27,6 +27,7 @@ namespace rdln private: std::streambuf* m_cout_buf; + size_t m_prompt_length; static std::vector<std::string>& completion_commands(); }; diff --git a/contrib/epee/include/span.h b/contrib/epee/include/span.h index 174915ecf..cfb5b1a17 100644 --- a/contrib/epee/include/span.h +++ b/contrib/epee/include/span.h @@ -109,6 +109,8 @@ namespace epee constexpr std::size_t size() const noexcept { return len; } constexpr std::size_t size_bytes() const noexcept { return size() * sizeof(value_type); } + const T &operator[](size_t idx) const { return ptr[idx]; } + private: T* ptr; std::size_t len; @@ -161,4 +163,12 @@ namespace epee static_assert(!has_padding<T>(), "source type may have padding"); return {reinterpret_cast<std::uint8_t*>(std::addressof(src)), sizeof(T)}; } + + //! make a span from a std::string + template<typename T> + span<const T> strspan(const std::string &s) noexcept + { + static_assert(std::is_same<T, char>() || std::is_same<T, unsigned char>() || std::is_same<T, int8_t>() || std::is_same<T, uint8_t>(), "Unexpected type"); + return {reinterpret_cast<const T*>(s.data()), s.size()}; + } } diff --git a/contrib/epee/include/storages/http_abstract_invoke.h b/contrib/epee/include/storages/http_abstract_invoke.h index d93084ab0..18b7f10c1 100644 --- a/contrib/epee/include/storages/http_abstract_invoke.h +++ b/contrib/epee/include/storages/http_abstract_invoke.h @@ -97,7 +97,7 @@ namespace epee return false; } - return serialization::load_t_from_binary(result_struct, pri->m_body); + return serialization::load_t_from_binary(result_struct, epee::strspan<uint8_t>(pri->m_body)); } template<class t_request, class t_response, class t_transport> diff --git a/contrib/epee/include/storages/levin_abstract_invoke2.h b/contrib/epee/include/storages/levin_abstract_invoke2.h index d77e7a1f8..06eb9bdaf 100644 --- a/contrib/epee/include/storages/levin_abstract_invoke2.h +++ b/contrib/epee/include/storages/levin_abstract_invoke2.h @@ -28,6 +28,7 @@ #include "portable_storage_template_helper.h" #include <boost/utility/value_init.hpp> +#include "span.h" #include "net/levin_base.h" #undef MONERO_DEFAULT_LOG_CATEGORY @@ -114,7 +115,7 @@ namespace epee const_cast<t_arg&>(out_struct).store(stg);//TODO: add true const support to searilzation std::string buff_to_send; stg.store_to_binary(buff_to_send); - int res = transport.invoke_async(command, buff_to_send, conn_id, [cb, command](int code, const std::string& buff, typename t_transport::connection_context& context)->bool + int res = transport.invoke_async(command, epee::strspan<uint8_t>(buff_to_send), conn_id, [cb, command](int code, const epee::span<const uint8_t> buff, typename t_transport::connection_context& context)->bool { t_result result_struct = AUTO_VAL_INIT(result_struct); if( code <=0 ) @@ -156,7 +157,7 @@ namespace epee std::string buff_to_send; stg.store_to_binary(buff_to_send); - int res = transport.notify(command, buff_to_send, conn_id); + int res = transport.notify(command, epee::strspan<uint8_t>(buff_to_send), conn_id); if(res <=0 ) { MERROR("Failed to notify command " << command << " return code " << res); @@ -167,7 +168,7 @@ namespace epee //---------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------- template<class t_owner, class t_in_type, class t_out_type, class t_context, class callback_t> - int buff_to_t_adapter(int command, const std::string& in_buff, std::string& buff_out, callback_t cb, t_context& context ) + int buff_to_t_adapter(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, callback_t cb, t_context& context ) { serialization::portable_storage strg; if(!strg.load_from_binary(in_buff)) @@ -197,7 +198,7 @@ namespace epee } template<class t_owner, class t_in_type, class t_context, class callback_t> - int buff_to_t_adapter(t_owner* powner, int command, const std::string& in_buff, callback_t cb, t_context& context) + int buff_to_t_adapter(t_owner* powner, int command, const epee::span<const uint8_t> in_buff, callback_t cb, t_context& context) { serialization::portable_storage strg; if(!strg.load_from_binary(in_buff)) @@ -215,14 +216,14 @@ namespace epee } #define CHAIN_LEVIN_INVOKE_MAP2(context_type) \ - int invoke(int command, const std::string& in_buff, std::string& buff_out, context_type& context) \ + int invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, context_type& context) \ { \ bool handled = false; \ return handle_invoke_map(false, command, in_buff, buff_out, context, handled); \ } #define CHAIN_LEVIN_NOTIFY_MAP2(context_type) \ - int notify(int command, const std::string& in_buff, context_type& context) \ + int notify(int command, const epee::span<const uint8_t> in_buff, context_type& context) \ { \ bool handled = false; std::string fake_str;\ return handle_invoke_map(true, command, in_buff, fake_str, context, handled); \ @@ -230,27 +231,27 @@ namespace epee #define CHAIN_LEVIN_INVOKE_MAP() \ - int invoke(int command, const std::string& in_buff, std::string& buff_out, epee::net_utils::connection_context_base& context) \ + int invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, epee::net_utils::connection_context_base& context) \ { \ bool handled = false; \ return handle_invoke_map(false, command, in_buff, buff_out, context, handled); \ } #define CHAIN_LEVIN_NOTIFY_MAP() \ - int notify(int command, const std::string& in_buff, epee::net_utils::connection_context_base& context) \ + int notify(int command, const epee::span<const uint8_t> in_buff, epee::net_utils::connection_context_base& context) \ { \ bool handled = false; std::string fake_str;\ return handle_invoke_map(true, command, in_buff, fake_str, context, handled); \ } #define CHAIN_LEVIN_NOTIFY_STUB() \ - int notify(int command, const std::string& in_buff, epee::net_utils::connection_context_base& context) \ + int notify(int command, const epee::span<const uint8_t> in_buff, epee::net_utils::connection_context_base& context) \ { \ return -1; \ } #define BEGIN_INVOKE_MAP2(owner_type) \ - template <class t_context> int handle_invoke_map(bool is_notify, int command, const std::string& in_buff, std::string& buff_out, t_context& context, bool& handled) \ + template <class t_context> int handle_invoke_map(bool is_notify, int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, t_context& context, bool& handled) \ { \ typedef owner_type internal_owner_type_name; diff --git a/contrib/epee/include/storages/parserse_base_utils.h b/contrib/epee/include/storages/parserse_base_utils.h index 8c6c1a64d..69b650cd4 100644 --- a/contrib/epee/include/storages/parserse_base_utils.h +++ b/contrib/epee/include/storages/parserse_base_utils.h @@ -29,6 +29,7 @@ #pragma once #include <algorithm> +#include <boost/utility/string_ref.hpp> namespace epee { @@ -36,15 +37,51 @@ namespace misc_utils { namespace parse { + // 1: digit + // 2: .eE (floating point) + // 4: alpha + // 8: whitespace + // 16: allowed in float but doesn't necessarily mean it's a float + static const constexpr uint8_t lut[256]={ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 0, 0, // 16 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32 + 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 16, 18, 0, // 48 + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, // 64 + 0, 4, 4, 4, 4, 22, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // 80 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, // 96 + 0, 4, 4, 4, 4, 22, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // 112 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, // 128 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }; + + inline bool isspace(char c) + { + return lut[(uint8_t)c] & 8; + } + + inline bool isdigit(char c) + { + return lut[(uint8_t)c] & 1; + } + inline std::string transform_to_escape_sequence(const std::string& src) { static const char escaped[] = "\b\f\n\r\t\v\"\\/"; - if (std::find_first_of(src.begin(), src.end(), escaped, escaped + sizeof(escaped)) == src.end()) + std::string::const_iterator it = std::find_first_of(src.begin(), src.end(), escaped, escaped + sizeof(escaped)); + if (it == src.end()) return src; std::string res; res.reserve(2 * src.size()); - for(std::string::const_iterator it = src.begin(); it!=src.end(); ++it) + res.assign(src.begin(), it); + for(; it!=src.end(); ++it) { switch(*it) { @@ -89,11 +126,15 @@ namespace misc_utils */ inline void match_string2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) { - val.clear(); - val.reserve(std::distance(star_end_string, buf_end)); bool escape_mode = false; std::string::const_iterator it = star_end_string; ++it; + std::string::const_iterator fi = it; + while (fi != buf_end && *fi != '\\' && *fi != '\"') + ++fi; + val.assign(it, fi); + val.reserve(std::distance(star_end_string, buf_end)); + it = fi; for(;it != buf_end;it++) { if(escape_mode/*prev_ch == '\\'*/) @@ -153,25 +194,34 @@ namespace misc_utils return false; } } - inline void match_number2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val, bool& is_float_val, bool& is_signed_val) + inline void match_number2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, boost::string_ref& val, bool& is_float_val, bool& is_signed_val) { val.clear(); - is_float_val = false; - for(std::string::const_iterator it = star_end_string;it != buf_end;it++) + uint8_t float_flag = 0; + is_signed_val = false; + size_t chars = 0; + std::string::const_iterator it = star_end_string; + if (it != buf_end && *it == '-') { - if(isdigit(*it) || (it == star_end_string && *it == '-') || (val.size() && *it == '.' ) || (is_float_val && (*it == 'e' || *it == 'E' || *it == '-' || *it == '+' )) ) + is_signed_val = true; + ++chars; + ++it; + } + for(;it != buf_end;it++) + { + const uint8_t flags = lut[(uint8_t)*it]; + if (flags & 16) { - if(!val.size() && *it == '-') - is_signed_val = true; - if(*it == '.' ) - is_float_val = true; - val.push_back(*it); + float_flag |= flags; + ++chars; } else { + val = boost::string_ref(&*star_end_string, chars); if(val.size()) { star_end_string = --it; + is_float_val = !!(float_flag & 2); return; } else @@ -180,7 +230,7 @@ namespace misc_utils } ASSERT_MES_AND_THROW("wrong number in json entry: " << std::string(star_end_string, buf_end)); } - inline bool match_number(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) + inline bool match_number(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, boost::string_ref& val) { try { @@ -193,15 +243,15 @@ namespace misc_utils return false; } } - inline void match_word2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) + inline void match_word2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, boost::string_ref& val) { val.clear(); for(std::string::const_iterator it = star_end_string;it != buf_end;it++) { - if(!isalpha(*it)) + if (!(lut[(uint8_t)*it] & 4)) { - val.assign(star_end_string, it); + val = boost::string_ref(&*star_end_string, std::distance(star_end_string, it)); if(val.size()) { star_end_string = --it; @@ -212,7 +262,7 @@ namespace misc_utils } ASSERT_MES_AND_THROW("failed to match word number in json entry: " << std::string(star_end_string, buf_end)); } - inline bool match_word(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) + inline bool match_word(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, boost::string_ref& val) { try { diff --git a/contrib/epee/include/storages/portable_storage.h b/contrib/epee/include/storages/portable_storage.h index 2023e2f2a..d0e40d606 100644 --- a/contrib/epee/include/storages/portable_storage.h +++ b/contrib/epee/include/storages/portable_storage.h @@ -35,6 +35,8 @@ #include "portable_storage_to_json.h" #include "portable_storage_from_json.h" #include "portable_storage_val_converters.h" +#include "span.h" +#include "int-util.h" namespace epee { @@ -80,7 +82,8 @@ namespace epee //------------------------------------------------------------------------------- bool store_to_binary(binarybuffer& target); - bool load_from_binary(const binarybuffer& target); + bool load_from_binary(const epee::span<const uint8_t> target); + bool load_from_binary(const std::string& target) { return load_from_binary(epee::strspan<uint8_t>(target)); } template<class trace_policy> bool dump_as_xml(std::string& targetObj, const std::string& root_name = ""); bool dump_as_json(std::string& targetObj, size_t indent = 0, bool insert_newlines = true); @@ -135,8 +138,8 @@ namespace epee TRY_ENTRY(); std::stringstream ss; storage_block_header sbh = AUTO_VAL_INIT(sbh); - sbh.m_signature_a = PORTABLE_STORAGE_SIGNATUREA; - sbh.m_signature_b = PORTABLE_STORAGE_SIGNATUREB; + sbh.m_signature_a = SWAP32LE(PORTABLE_STORAGE_SIGNATUREA); + sbh.m_signature_b = SWAP32LE(PORTABLE_STORAGE_SIGNATUREB); sbh.m_ver = PORTABLE_STORAGE_FORMAT_VER; ss.write((const char*)&sbh, sizeof(storage_block_header)); pack_entry_to_buff(ss, m_root); @@ -145,7 +148,7 @@ namespace epee CATCH_ENTRY("portable_storage::store_to_binary", false) } inline - bool portable_storage::load_from_binary(const binarybuffer& source) + bool portable_storage::load_from_binary(const epee::span<const uint8_t> source) { m_root.m_entries.clear(); if(source.size() < sizeof(storage_block_header)) @@ -154,8 +157,8 @@ namespace epee return false; } storage_block_header* pbuff = (storage_block_header*)source.data(); - if(pbuff->m_signature_a != PORTABLE_STORAGE_SIGNATUREA || - pbuff->m_signature_b != PORTABLE_STORAGE_SIGNATUREB + if(pbuff->m_signature_a != SWAP32LE(PORTABLE_STORAGE_SIGNATUREA) || + pbuff->m_signature_b != SWAP32LE(PORTABLE_STORAGE_SIGNATUREB) ) { LOG_ERROR("portable_storage: wrong binary format - signature mismatch"); diff --git a/contrib/epee/include/storages/portable_storage_base.h b/contrib/epee/include/storages/portable_storage_base.h index 93132548b..da84fd8ea 100644 --- a/contrib/epee/include/storages/portable_storage_base.h +++ b/contrib/epee/include/storages/portable_storage_base.h @@ -31,7 +31,8 @@ #include <boost/variant.hpp> #include <boost/any.hpp> #include <string> -#include <list> +#include <vector> +#include <deque> #define PORTABLE_STORAGE_SIGNATUREA 0x01011101 #define PORTABLE_STORAGE_SIGNATUREB 0x01020101 // bender's nightmare @@ -71,6 +72,9 @@ namespace epee { struct section; + template<typename T> struct entry_container { typedef std::vector<T> type; static void reserve(type &t, size_t n) { t.reserve(n); } }; + template<> struct entry_container<bool> { typedef std::deque<bool> type; static void reserve(type &t, size_t n) {} }; + /************************************************************************/ /* */ /************************************************************************/ @@ -119,8 +123,13 @@ namespace epee return m_array.back(); } - std::list<t_entry_type> m_array; - mutable typename std::list<t_entry_type>::const_iterator m_it; + void reserve(size_t n) + { + entry_container<t_entry_type>::reserve(m_array, n); + } + + typename entry_container<t_entry_type>::type m_array; + mutable typename entry_container<t_entry_type>::type::const_iterator m_it; }; diff --git a/contrib/epee/include/storages/portable_storage_from_bin.h b/contrib/epee/include/storages/portable_storage_from_bin.h index f9cc22d27..2884f8c5e 100644 --- a/contrib/epee/include/storages/portable_storage_from_bin.h +++ b/contrib/epee/include/storages/portable_storage_from_bin.h @@ -136,6 +136,7 @@ namespace epee //for pod types array_entry_t<type_name> sa; size_t size = read_varint(); + sa.reserve(size); //TODO: add some optimization here later while(size--) sa.m_array.push_back(read<type_name>()); diff --git a/contrib/epee/include/storages/portable_storage_from_json.h b/contrib/epee/include/storages/portable_storage_from_json.h index 5b2eafa9a..3e3052541 100644 --- a/contrib/epee/include/storages/portable_storage_from_json.h +++ b/contrib/epee/include/storages/portable_storage_from_json.h @@ -39,7 +39,7 @@ namespace epee { namespace json { -#define CHECK_ISSPACE() if(!isspace(*it)){ ASSERT_MES_AND_THROW("Wrong JSON character at: " << std::string(it, buf_end));} +#define CHECK_ISSPACE() if(!epee::misc_utils::parse::isspace(*it)){ ASSERT_MES_AND_THROW("Wrong JSON character at: " << std::string(it, buf_end));} /*inline void parse_error() { @@ -114,33 +114,39 @@ namespace epee std::string val; match_string2(it, buf_end, val); //insert text value - stg.set_value(name, val, current_section); + stg.set_value(name, std::move(val), current_section); state = match_state_wonder_after_value; - }else if (isdigit(*it) || *it == '-') + }else if (epee::misc_utils::parse::isdigit(*it) || *it == '-') {//just a named number value started - std::string val; + boost::string_ref val; bool is_v_float = false;bool is_signed = false; match_number2(it, buf_end, val, is_v_float, is_signed); if(!is_v_float) { if(is_signed) { - int64_t nval = boost::lexical_cast<int64_t>(val); + errno = 0; + int64_t nval = strtoll(val.data(), NULL, 10); + if (errno) throw std::runtime_error("Invalid number: " + std::string(val)); stg.set_value(name, nval, current_section); }else { - uint64_t nval = boost::lexical_cast<uint64_t >(val); + errno = 0; + uint64_t nval = strtoull(val.data(), NULL, 10); + if (errno) throw std::runtime_error("Invalid number: " + std::string(val)); stg.set_value(name, nval, current_section); } }else { - double nval = boost::lexical_cast<double>(val); + errno = 0; + double nval = strtod(val.data(), NULL); + if (errno) throw std::runtime_error("Invalid number: " + std::string(val)); stg.set_value(name, nval, current_section); } state = match_state_wonder_after_value; }else if(isalpha(*it) ) {// could be null, true or false - std::string word; + boost::string_ref word; match_word2(it, buf_end, word); if(boost::iequals(word, "null")) { @@ -197,23 +203,36 @@ namespace epee //mean array of strings std::string val; match_string2(it, buf_end, val); - h_array = stg.insert_first_value(name, val, current_section); + h_array = stg.insert_first_value(name, std::move(val), current_section); CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values entry"); state = match_state_array_after_value; array_md = array_mode_string; - }else if (isdigit(*it) || *it == '-') + }else if (epee::misc_utils::parse::isdigit(*it) || *it == '-') {//array of numbers value started - std::string val; + boost::string_ref val; bool is_v_float = false;bool is_signed_val = false; match_number2(it, buf_end, val, is_v_float, is_signed_val); if(!is_v_float) { - int64_t nval = boost::lexical_cast<int64_t>(val);//bool res = string_tools::string_to_num_fast(val, nval); - h_array = stg.insert_first_value(name, nval, current_section); + if (is_signed_val) + { + errno = 0; + int64_t nval = strtoll(val.data(), NULL, 10); + if (errno) throw std::runtime_error("Invalid number: " + std::string(val)); + h_array = stg.insert_first_value(name, nval, current_section); + }else + { + errno = 0; + uint64_t nval = strtoull(val.data(), NULL, 10); + if (errno) throw std::runtime_error("Invalid number: " + std::string(val)); + h_array = stg.insert_first_value(name, nval, current_section); + } CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values section entry"); }else { - double nval = boost::lexical_cast<double>(val);//bool res = string_tools::string_to_num_fast(val, nval); + errno = 0; + double nval = strtod(val.data(), NULL); + if (errno) throw std::runtime_error("Invalid number: " + std::string(val)); h_array = stg.insert_first_value(name, nval, current_section); CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values section entry"); } @@ -226,7 +245,7 @@ namespace epee state = match_state_wonder_after_value; }else if(isalpha(*it) ) {// array of booleans - std::string word; + boost::string_ref word; match_word2(it, buf_end, word); if(boost::iequals(word, "true")) { @@ -272,27 +291,38 @@ namespace epee { std::string val; match_string2(it, buf_end, val); - bool res = stg.insert_next_value(h_array, val); + bool res = stg.insert_next_value(h_array, std::move(val)); CHECK_AND_ASSERT_THROW_MES(res, "failed to insert values"); state = match_state_array_after_value; }else CHECK_ISSPACE(); break; case array_mode_numbers: - if (isdigit(*it) || *it == '-') + if (epee::misc_utils::parse::isdigit(*it) || *it == '-') {//array of numbers value started - std::string val; + boost::string_ref val; bool is_v_float = false;bool is_signed_val = false; match_number2(it, buf_end, val, is_v_float, is_signed_val); bool insert_res = false; if(!is_v_float) { - int64_t nval = boost::lexical_cast<int64_t>(val); //bool res = string_tools::string_to_num_fast(val, nval); - insert_res = stg.insert_next_value(h_array, nval); - + if (is_signed_val) + { + errno = 0; + int64_t nval = strtoll(val.data(), NULL, 10); + if (errno) throw std::runtime_error("Invalid number: " + std::string(val)); + insert_res = stg.insert_next_value(h_array, nval); + }else + { + errno = 0; + uint64_t nval = strtoull(val.data(), NULL, 10); + if (errno) throw std::runtime_error("Invalid number: " + std::string(val)); + insert_res = stg.insert_next_value(h_array, nval); + } }else { - //TODO: optimize here if need - double nval = boost::lexical_cast<double>(val); //string_tools::string_to_num_fast(val, nval); + errno = 0; + double nval = strtod(val.data(), NULL); + if (errno) throw std::runtime_error("Invalid number: " + std::string(val)); insert_res = stg.insert_next_value(h_array, nval); } CHECK_AND_ASSERT_THROW_MES(insert_res, "Failed to insert next value"); @@ -303,7 +333,7 @@ namespace epee case array_mode_booleans: if(isalpha(*it) ) {// array of booleans - std::string word; + boost::string_ref word; match_word2(it, buf_end, word); if(boost::iequals(word, "true")) { diff --git a/contrib/epee/include/storages/portable_storage_template_helper.h b/contrib/epee/include/storages/portable_storage_template_helper.h index bbd8413fc..13c870d44 100644 --- a/contrib/epee/include/storages/portable_storage_template_helper.h +++ b/contrib/epee/include/storages/portable_storage_template_helper.h @@ -84,7 +84,7 @@ namespace epee } //----------------------------------------------------------------------------------------------------------- template<class t_struct> - bool load_t_from_binary(t_struct& out, const std::string& binary_buff) + bool load_t_from_binary(t_struct& out, const epee::span<const uint8_t> binary_buff) { portable_storage ps; bool rs = ps.load_from_binary(binary_buff); @@ -95,6 +95,12 @@ namespace epee } //----------------------------------------------------------------------------------------------------------- template<class t_struct> + bool load_t_from_binary(t_struct& out, const std::string& binary_buff) + { + return load_t_from_binary(out, epee::strspan<uint8_t>(binary_buff)); + } + //----------------------------------------------------------------------------------------------------------- + template<class t_struct> bool load_t_from_binary_file(t_struct& out, const std::string& binary_file) { std::string f_buff; diff --git a/contrib/epee/include/string_tools.h b/contrib/epee/include/string_tools.h index aba065cc7..2e65876e6 100644 --- a/contrib/epee/include/string_tools.h +++ b/contrib/epee/include/string_tools.h @@ -40,8 +40,6 @@ #include <cstdlib> #include <string> #include <type_traits> -#include <boost/uuid/uuid.hpp> -#include <boost/uuid/uuid_io.hpp> #include <boost/lexical_cast.hpp> #include <boost/algorithm/string/predicate.hpp> #include "hex.h" @@ -59,89 +57,64 @@ #pragma comment (lib, "Rpcrt4.lib") #endif +static const constexpr unsigned char isx[256] = +{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 10, 11, 12, 13, 14, 15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 10, 11, 12, 13, 14, 15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +}; + namespace epee { namespace string_tools { - //---------------------------------------------------------------------------- - inline std::string get_str_from_guid_a(const boost::uuids::uuid& rid) - { - return boost::lexical_cast<std::string>(rid); - } - //---------------------------------------------------------------------------- - inline bool get_guid_from_string(OUT boost::uuids::uuid& inetifer, const std::string& str_id) - { - std::string local_str_id = str_id; - if(local_str_id.size() < 36) - return false; - - if('{' == *local_str_id.begin()) - local_str_id.erase(0, 1); - - if('}' == *(--local_str_id.end())) - local_str_id.erase(--local_str_id.end()); - - try - { - inetifer = boost::lexical_cast<boost::uuids::uuid>(local_str_id); - return true; - } - catch(...) - { - return false; - } - } //---------------------------------------------------------------------------- inline std::string buff_to_hex_nodelimer(const std::string& src) { return to_hex::string(to_byte_span(to_span(src))); } //---------------------------------------------------------------------------- - template<class CharT> - bool parse_hexstr_to_binbuff(const std::basic_string<CharT>& s, std::basic_string<CharT>& res, bool allow_partial_byte = false) + inline bool parse_hexstr_to_binbuff(const epee::span<const char> s, epee::span<char>& res) { - res.clear(); - if (!allow_partial_byte && (s.size() & 1)) - return false; - try - { - long v = 0; - for(size_t i = 0; i < (s.size() + 1) / 2; i++) + if (s.size() != res.size() * 2) + return false; + + unsigned char *dst = (unsigned char *)&res[0]; + const unsigned char *src = (const unsigned char *)s.data(); + for(size_t i = 0; i < s.size(); i += 2) { - CharT byte_str[3]; - size_t copied = s.copy(byte_str, 2, 2 * i); - byte_str[copied] = CharT(0); - CharT* endptr; - v = strtoul(byte_str, &endptr, 16); - if (v < 0 || 0xFF < v || endptr != byte_str + copied) - { - return false; - } - res.push_back(static_cast<unsigned char>(v)); + int tmp = *src++; + tmp = isx[tmp]; + if (tmp == 0xff) return false; + int t2 = *src++; + t2 = isx[t2]; + if (t2 == 0xff) return false; + *dst++ = (tmp << 4) | t2; } return true; - }catch(...) - { - return false; - } } //---------------------------------------------------------------------------- - template<class t_pod_type> - bool parse_tpod_from_hex_string(const std::string& str_hash, t_pod_type& t_pod) + inline bool parse_hexstr_to_binbuff(const std::string& s, std::string& res) { - static_assert(std::is_pod<t_pod_type>::value, "expected pod type"); - std::string buf; - bool res = epee::string_tools::parse_hexstr_to_binbuff(str_hash, buf); - if (!res || buf.size() != sizeof(t_pod_type)) - { + if (s.size() & 1) return false; - } - else - { - buf.copy(reinterpret_cast<char *>(&t_pod), sizeof(t_pod_type)); - return true; - } + res.resize(s.size() / 2); + epee::span<char> rspan((char*)&res[0], res.size()); + return parse_hexstr_to_binbuff(epee::to_span(s), rspan); } //---------------------------------------------------------------------------- PUSH_WARNINGS @@ -233,6 +206,15 @@ POP_WARNINGS return boost::lexical_cast<std::string>(val); } //---------------------------------------------------------------------------- + inline std::string to_string_hex(uint32_t val) + { + std::stringstream ss; + ss << std::hex << val; + std::string s; + ss >> s; + return s; + } + //---------------------------------------------------------------------------- inline bool compare_no_case(const std::string& str1, const std::string& str2) { @@ -340,17 +322,10 @@ POP_WARNINGS bool hex_to_pod(const std::string& hex_str, t_pod_type& s) { static_assert(std::is_pod<t_pod_type>::value, "expected pod type"); - std::string hex_str_tr = trim(hex_str); if(sizeof(s)*2 != hex_str.size()) return false; - std::string bin_buff; - if(!parse_hexstr_to_binbuff(hex_str_tr, bin_buff)) - return false; - if(bin_buff.size()!=sizeof(s)) - return false; - - s = *(t_pod_type*)bin_buff.data(); - return true; + epee::span<char> rspan((char*)&s, sizeof(s)); + return parse_hexstr_to_binbuff(epee::to_span(hex_str), rspan); } //---------------------------------------------------------------------------- template<class t_pod_type> diff --git a/contrib/epee/src/CMakeLists.txt b/contrib/epee/src/CMakeLists.txt index bc437deb9..cea50c9dd 100644 --- a/contrib/epee/src/CMakeLists.txt +++ b/contrib/epee/src/CMakeLists.txt @@ -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) + connection_basic.cpp network_throttle.cpp network_throttle-detail.cpp mlocker.cpp buffer.cpp) if (USE_READLINE AND GNU_READLINE_FOUND) add_library(epee_readline STATIC readline_buffer.cpp) endif() diff --git a/contrib/epee/src/buffer.cpp b/contrib/epee/src/buffer.cpp new file mode 100644 index 000000000..d637b905e --- /dev/null +++ b/contrib/epee/src/buffer.cpp @@ -0,0 +1,97 @@ +// 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 "net/buffer.h" + +#undef MONERO_DEFAULT_LOG_CATEGORY +#define MONERO_DEFAULT_LOG_CATEGORY "net.buffer" + +namespace epee +{ +namespace net_utils +{ + +void buffer::append(const void *data, size_t sz) +{ + const size_t capacity = storage.capacity(); + const size_t avail = capacity - storage.size(); + + CHECK_AND_ASSERT_THROW_MES(storage.size() < std::numeric_limits<size_t>::max() - sz, "Too much data to append"); + + // decide when to move + if (sz > avail) + { + // we have to reallocate or move + const bool move = size() + sz <= capacity; + if (move) + { + const size_t bytes = storage.size() - offset; + NET_BUFFER_LOG("appending " << sz << " from " << size() << " by moving " << bytes << " from offset " << offset << " first (forced)"); + memmove(storage.data(), storage.data() + offset, bytes); + storage.resize(bytes); + offset = 0; + } + else + { + NET_BUFFER_LOG("appending " << sz << " from " << size() << " by reallocating"); + std::vector<uint8_t> new_storage; + size_t reserve = (((size() + sz) * 3 / 2) + 4095) & ~4095; + new_storage.reserve(reserve); + new_storage.resize(size()); + memcpy(new_storage.data(), storage.data() + offset, storage.size() - offset); + offset = 0; + std::swap(storage, new_storage); + } + } + else + { + // we have space already + if (size() <= 4096 && offset > 4096 * 16 && offset >= capacity / 2) + { + // we have little to move, and we're far enough into the buffer that it's probably a win to move anyway + const size_t pos = storage.size() - offset; + NET_BUFFER_LOG("appending " << sz << " from " << size() << " by moving " << pos << " from offset " << offset << " first (unforced)"); + memmove(storage.data(), storage.data() + offset, storage.size() - offset); + storage.resize(pos); + offset = 0; + } + else + { + NET_BUFFER_LOG("appending " << sz << " from " << size() << " by writing to existing capacity"); + } + } + + // add the new data + storage.insert(storage.end(), (const uint8_t*)data, (const uint8_t*)data + sz); + + NET_BUFFER_LOG("storage now " << offset << "/" << storage.size() << "/" << storage.capacity()); +} + +} +} diff --git a/contrib/epee/src/connection_basic.cpp b/contrib/epee/src/connection_basic.cpp index 9ab485839..7d145ee46 100644 --- a/contrib/epee/src/connection_basic.cpp +++ b/contrib/epee/src/connection_basic.cpp @@ -34,47 +34,15 @@ #include "net/connection_basic.hpp" -#include <boost/asio.hpp> -#include <string> -#include <vector> -#include <boost/noncopyable.hpp> -#include <boost/shared_ptr.hpp> -#include <atomic> - -#include <boost/asio.hpp> -#include <boost/array.hpp> -#include <boost/noncopyable.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> -#include <boost/interprocess/detail/atomic.hpp> -#include <boost/thread/thread.hpp> - -#include <memory> - -#include "syncobj.h" - #include "net/net_utils_base.h" #include "misc_log_ex.h" -#include <boost/lambda/bind.hpp> -#include <boost/lambda/lambda.hpp> -#include <boost/uuid/random_generator.hpp> -#include <boost/chrono.hpp> -#include <boost/utility/value_init.hpp> -#include <boost/asio/deadline_timer.hpp> #include <boost/date_time/posix_time/posix_time.hpp> #include <boost/thread/thread.hpp> -#include <boost/filesystem.hpp> #include "misc_language.h" #include "pragma_comp_defs.h" -#include <fstream> -#include <sstream> #include <iomanip> -#include <algorithm> -#include <mutex> #include <boost/asio/basic_socket.hpp> -#include <boost/asio/ip/unicast.hpp> -#include "net/abstract_tcp_server2.h" // TODO: #include "net/network_throttle-detail.hpp" @@ -161,7 +129,6 @@ connection_basic::connection_basic(boost::asio::io_service& io_service, std::ato 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_ref_sock_count); - //boost::filesystem::create_directories("log/dr-monero/net/"); } connection_basic::~connection_basic() noexcept(false) { diff --git a/contrib/epee/src/mlocker.cpp b/contrib/epee/src/mlocker.cpp index 5573d591a..446fa3315 100644 --- a/contrib/epee/src/mlocker.cpp +++ b/contrib/epee/src/mlocker.cpp @@ -38,6 +38,15 @@ #include "syncobj.h" #include "mlocker.h" +#include <atomic> + +#undef MONERO_DEFAULT_LOG_CATEGORY +#define MONERO_DEFAULT_LOG_CATEGORY "mlocker" + +// did an mlock operation previously fail? we only +// want to log an error once and be done with it +static std::atomic<bool> previously_failed{ false }; + static size_t query_page_size() { #if defined HAVE_MLOCK @@ -47,7 +56,6 @@ static size_t query_page_size() MERROR("Failed to determine page size"); return 0; } - MINFO("Page size: " << ret); return ret; #else #warning Missing query_page_size implementation @@ -59,8 +67,8 @@ static void do_lock(void *ptr, size_t len) { #if defined HAVE_MLOCK int ret = mlock(ptr, len); - if (ret < 0) - MERROR("Error locking page at " << ptr << ": " << strerror(errno)); + if (ret < 0 && !previously_failed.exchange(true)) + MERROR("Error locking page at " << ptr << ": " << strerror(errno) << ", subsequent mlock errors will be silenced"); #else #warning Missing do_lock implementation #endif @@ -70,7 +78,10 @@ static void do_unlock(void *ptr, size_t len) { #if defined HAVE_MLOCK int ret = munlock(ptr, len); - if (ret < 0) + // check whether we previously failed, but don't set it, this is just + // to pacify the errors of mlock()ing failed, in which case unlocking + // is also not going to work of course + if (ret < 0 && !previously_failed.load()) MERROR("Error unlocking page at " << ptr << ": " << strerror(errno)); #else #warning Missing implementation of page size detection @@ -84,13 +95,13 @@ namespace epee boost::mutex &mlocker::mutex() { - static boost::mutex vmutex; - return vmutex; + static boost::mutex *vmutex = new boost::mutex(); + return *vmutex; } std::map<size_t, unsigned int> &mlocker::map() { - static std::map<size_t, unsigned int> vmap; - return vmap; + static std::map<size_t, unsigned int> *vmap = new std::map<size_t, unsigned int>(); + return *vmap; } size_t mlocker::get_page_size() @@ -108,11 +119,14 @@ namespace epee mlocker::~mlocker() { - unlock(ptr, len); + try { unlock(ptr, len); } + catch (...) { /* ignore and do not propagate through the dtor */ } } void mlocker::lock(void *ptr, size_t len) { + TRY_ENTRY(); + size_t page_size = get_page_size(); if (page_size == 0) return; @@ -123,10 +137,14 @@ namespace epee for (size_t page = first; page <= last; ++page) lock_page(page); ++num_locked_objects; + + CATCH_ENTRY_L1("mlocker::lock", void()); } void mlocker::unlock(void *ptr, size_t len) { + TRY_ENTRY(); + size_t page_size = get_page_size(); if (page_size == 0) return; @@ -136,6 +154,8 @@ namespace epee for (size_t page = first; page <= last; ++page) unlock_page(page); --num_locked_objects; + + CATCH_ENTRY_L1("mlocker::lock", void()); } size_t mlocker::get_num_locked_pages() diff --git a/contrib/epee/src/mlog.cpp b/contrib/epee/src/mlog.cpp index 638155b6b..9b6b832d1 100644 --- a/contrib/epee/src/mlog.cpp +++ b/contrib/epee/src/mlog.cpp @@ -40,6 +40,7 @@ #include <boost/filesystem.hpp> #include <boost/algorithm/string.hpp> #include "string_tools.h" +#include "misc_os_dependent.h" #include "misc_log_ex.h" #undef MONERO_DEFAULT_LOG_CATEGORY @@ -58,12 +59,7 @@ static std::string generate_log_filename(const char *base) char tmp[200]; struct tm tm; time_t now = time(NULL); - if -#ifdef WIN32 - (!gmtime_s(&tm, &now)) -#else - (!gmtime_r(&now, &tm)) -#endif + if (!epee::misc_utils::get_gmt_time(now, tm)) snprintf(tmp, sizeof(tmp), "part-%u", ++fallback_counter); else strftime(tmp, sizeof(tmp), "%Y-%m-%d-%H-%M-%S", &tm); @@ -107,7 +103,7 @@ static const char *get_default_categories(int level) categories = "*:WARNING,net:FATAL,net.http:FATAL,net.p2p:FATAL,net.cn:FATAL,global:INFO,verify:FATAL,stacktrace:INFO,logging:INFO,msgwriter:INFO"; break; case 1: - categories = "*:INFO,global:INFO,stacktrace:INFO,logging:INFO,msgwriter:INFO"; + categories = "*:INFO,global:INFO,stacktrace:INFO,logging:INFO,msgwriter:INFO,perf.*:DEBUG"; break; case 2: categories = "*:DEBUG"; diff --git a/contrib/epee/src/net_utils_base.cpp b/contrib/epee/src/net_utils_base.cpp index 2f4015e81..263b344b4 100644 --- a/contrib/epee/src/net_utils_base.cpp +++ b/contrib/epee/src/net_utils_base.cpp @@ -1,9 +1,9 @@ #include "net/net_utils_base.h" -#include "string_tools.h" -#include <cstring> -#include <typeindex> +#include <boost/uuid/uuid_io.hpp> + +#include "string_tools.h" #include "net/local_ip.h" namespace epee { namespace net_utils @@ -75,7 +75,7 @@ namespace epee { namespace net_utils std::string print_connection_context(const connection_context_base& ctx) { std::stringstream ss; - ss << ctx.m_remote_address.str() << " " << epee::string_tools::get_str_from_guid_a(ctx.m_connection_id) << (ctx.m_is_income ? " INC":" OUT"); + ss << ctx.m_remote_address.str() << " " << ctx.m_connection_id << (ctx.m_is_income ? " INC":" OUT"); return ss.str(); } diff --git a/contrib/epee/src/network_throttle-detail.cpp b/contrib/epee/src/network_throttle-detail.cpp index 28c85bb78..d2e776df0 100644 --- a/contrib/epee/src/network_throttle-detail.cpp +++ b/contrib/epee/src/network_throttle-detail.cpp @@ -32,20 +32,11 @@ /* rfree: implementation for throttle details */ -#include <boost/asio.hpp> #include <string> #include <vector> -#include <boost/noncopyable.hpp> -#include <boost/shared_ptr.hpp> #include <atomic> #include <boost/asio.hpp> -#include <boost/array.hpp> -#include <boost/noncopyable.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> -#include <boost/interprocess/detail/atomic.hpp> -#include <boost/thread/thread.hpp> #include <memory> @@ -53,14 +44,7 @@ #include "net/net_utils_base.h" #include "misc_log_ex.h" -#include <boost/lambda/bind.hpp> -#include <boost/lambda/lambda.hpp> -#include <boost/uuid/random_generator.hpp> #include <boost/chrono.hpp> -#include <boost/utility/value_init.hpp> -#include <boost/asio/deadline_timer.hpp> -#include <boost/date_time/posix_time/posix_time.hpp> -#include <boost/thread/thread.hpp> #include "misc_language.h" #include "pragma_comp_defs.h" #include <sstream> @@ -150,6 +134,7 @@ network_throttle::network_throttle(const std::string &nameshort, const std::stri m_any_packet_yet = false; 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; } void network_throttle::set_name(const std::string &name) diff --git a/contrib/epee/src/readline_buffer.cpp b/contrib/epee/src/readline_buffer.cpp index 076a63612..c5949da0a 100644 --- a/contrib/epee/src/readline_buffer.cpp +++ b/contrib/epee/src/readline_buffer.cpp @@ -1,9 +1,9 @@ #include "readline_buffer.h" #include <readline/readline.h> #include <readline/history.h> -#include <unistd.h> #include <iostream> -#include <boost/thread.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/lock_guard.hpp> #include <boost/algorithm/string.hpp> static void install_line_handler(); @@ -44,7 +44,7 @@ std::vector<std::string>& rdln::readline_buffer::completion_commands() } rdln::readline_buffer::readline_buffer() -: std::stringbuf(), m_cout_buf(NULL) +: std::stringbuf(), m_cout_buf(NULL), m_prompt_length(0) { current = this; } @@ -86,8 +86,11 @@ void rdln::readline_buffer::set_prompt(const std::string& prompt) if(m_cout_buf == NULL) return; boost::lock_guard<boost::mutex> lock(sync_mutex); + rl_set_prompt(std::string(m_prompt_length, ' ').c_str()); + rl_redisplay(); rl_set_prompt(prompt.c_str()); rl_redisplay(); + m_prompt_length = prompt.size(); } void rdln::readline_buffer::add_completion(const std::string& command) diff --git a/contrib/epee/tests/src/CMakeLists.txt b/contrib/epee/tests/src/CMakeLists.txt index c7d31735b..4807fa7ea 100644 --- a/contrib/epee/tests/src/CMakeLists.txt +++ b/contrib/epee/tests/src/CMakeLists.txt @@ -14,8 +14,8 @@ IF (MSVC) include_directories(SYSTEM platform/msvc) ELSE() # set stuff for other systems - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -Wall -Werror") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Werror -Wno-reorder") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -Wall") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wno-reorder") ENDIF() diff --git a/contrib/epee/tests/src/net/test_net.h b/contrib/epee/tests/src/net/test_net.h index 04fef089c..51b1f1ec6 100644 --- a/contrib/epee/tests/src/net/test_net.h +++ b/contrib/epee/tests/src/net/test_net.h @@ -29,7 +29,9 @@ #include <boost/thread.hpp> #include <boost/bind.hpp> -#include "net/levin_server_cp2.h" +#include "net/abstract_tcp_server2.h" +#include "net/levin_protocol_handler.h" +#include "net/levin_protocol_handler_async.h" #include "storages/abstract_invoke.h" namespace epee |