mirror of
https://github.com/monero-project/monero.git
synced 2024-11-17 08:17:37 +00:00
epee: better network buffer data structure
avoids pointless allocs and memcpy
This commit is contained in:
parent
6bc0c7e685
commit
85665003a7
22 changed files with 325 additions and 85 deletions
62
contrib/epee/include/net/buffer.h
Normal file
62
contrib/epee/include/net/buffer.h
Normal file
|
@ -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;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -92,7 +92,7 @@
|
||||||
handled = true; \
|
handled = true; \
|
||||||
uint64_t ticks = misc_utils::get_tick_count(); \
|
uint64_t ticks = misc_utils::get_tick_count(); \
|
||||||
boost::value_initialized<command_type::request> req; \
|
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()); \
|
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(); \
|
uint64_t ticks1 = misc_utils::get_tick_count(); \
|
||||||
boost::value_initialized<command_type::response> resp;\
|
boost::value_initialized<command_type::response> resp;\
|
||||||
|
|
|
@ -80,8 +80,8 @@ namespace levin
|
||||||
template<class t_connection_context = net_utils::connection_context_base>
|
template<class t_connection_context = net_utils::connection_context_base>
|
||||||
struct levin_commands_handler
|
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 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 std::string& in_buff, 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 callback(t_connection_context& context){};
|
||||||
|
|
||||||
virtual void on_connection_new(t_connection_context& context){};
|
virtual void on_connection_new(t_connection_context& context){};
|
||||||
|
|
|
@ -57,7 +57,7 @@ namespace levin
|
||||||
bool is_connected();
|
bool is_connected();
|
||||||
bool disconnect();
|
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);
|
virtual int notify(int command, const std::string& in_buff);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -72,7 +72,7 @@ namespace levin
|
||||||
{
|
{
|
||||||
public:
|
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);
|
int notify(int command, const std::string& in_buff);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,7 @@ levin_client_impl::~levin_client_impl()
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
inline
|
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())
|
if(!is_connected())
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -133,7 +133,7 @@ int levin_client_impl::notify(int command, const std::string& in_buff)
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
inline
|
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())
|
if(!is_connected())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
#include "levin_base.h"
|
#include "levin_base.h"
|
||||||
|
#include "buffer.h"
|
||||||
#include "misc_language.h"
|
#include "misc_language.h"
|
||||||
#include "syncobj.h"
|
#include "syncobj.h"
|
||||||
#include "misc_os_dependent.h"
|
#include "misc_os_dependent.h"
|
||||||
|
@ -85,11 +86,11 @@ public:
|
||||||
uint64_t m_max_packet_size;
|
uint64_t m_max_packet_size;
|
||||||
uint64_t m_invoke_timeout;
|
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>
|
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 close(boost::uuids::uuid connection_id);
|
||||||
bool update_connection_context(const t_connection_context& contxt);
|
bool update_connection_context(const t_connection_context& contxt);
|
||||||
bool request_callback(boost::uuids::uuid connection_id);
|
bool request_callback(boost::uuids::uuid connection_id);
|
||||||
|
@ -143,7 +144,7 @@ public:
|
||||||
config_type& m_config;
|
config_type& m_config;
|
||||||
t_connection_context& m_connection_context;
|
t_connection_context& m_connection_context;
|
||||||
|
|
||||||
std::string m_cache_in_buffer;
|
net_utils::buffer m_cache_in_buffer;
|
||||||
stream_state m_state;
|
stream_state m_state;
|
||||||
|
|
||||||
int32_t m_oponent_protocol_ver;
|
int32_t m_oponent_protocol_ver;
|
||||||
|
@ -151,7 +152,7 @@ public:
|
||||||
|
|
||||||
struct invoke_response_handler_base
|
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 bool is_timer_started() const=0;
|
||||||
virtual void cancel()=0;
|
virtual void cancel()=0;
|
||||||
virtual bool cancel_timer()=0;
|
virtual bool cancel_timer()=0;
|
||||||
|
@ -173,7 +174,7 @@ public:
|
||||||
if(ec == boost::asio::error::operation_aborted)
|
if(ec == boost::asio::error::operation_aborted)
|
||||||
return;
|
return;
|
||||||
MINFO(con.get_context_ref() << "Timeout on invoke operation happened, command: " << command << " timeout: " << timeout);
|
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());
|
cb(LEVIN_ERROR_CONNECTION_TIMEDOUT, fake, con.get_context_ref());
|
||||||
con.close();
|
con.close();
|
||||||
con.finish_outer_call();
|
con.finish_outer_call();
|
||||||
|
@ -191,7 +192,7 @@ public:
|
||||||
bool m_timer_cancelled;
|
bool m_timer_cancelled;
|
||||||
uint64_t m_timeout;
|
uint64_t m_timeout;
|
||||||
int m_command;
|
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())
|
if(!cancel_timer())
|
||||||
return false;
|
return false;
|
||||||
|
@ -207,7 +208,7 @@ public:
|
||||||
{
|
{
|
||||||
if(cancel_timer())
|
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_cb(LEVIN_ERROR_CONNECTION_DESTROYED, fake, m_con.get_context_ref());
|
||||||
m_con.finish_outer_call();
|
m_con.finish_outer_call();
|
||||||
}
|
}
|
||||||
|
@ -237,7 +238,7 @@ public:
|
||||||
if(ec == boost::asio::error::operation_aborted)
|
if(ec == boost::asio::error::operation_aborted)
|
||||||
return;
|
return;
|
||||||
MINFO(con.get_context_ref() << "Timeout on invoke operation happened, command: " << command << " timeout: " << timeout);
|
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());
|
cb(LEVIN_ERROR_CONNECTION_TIMEDOUT, fake, con.get_context_ref());
|
||||||
con.close();
|
con.close();
|
||||||
con.finish_outer_call();
|
con.finish_outer_call();
|
||||||
|
@ -265,6 +266,7 @@ public:
|
||||||
m_pservice_endpoint(psnd_hndlr),
|
m_pservice_endpoint(psnd_hndlr),
|
||||||
m_config(config),
|
m_config(config),
|
||||||
m_connection_context(conn_context),
|
m_connection_context(conn_context),
|
||||||
|
m_cache_in_buffer(256 * 1024),
|
||||||
m_state(stream_state_head)
|
m_state(stream_state_head)
|
||||||
{
|
{
|
||||||
m_close_called = 0;
|
m_close_called = 0;
|
||||||
|
@ -405,14 +407,7 @@ public:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::string buff_to_invoke;
|
epee::span<const uint8_t> buff_to_invoke = m_cache_in_buffer.carve((std::string::size_type)m_current_head.m_cb);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_response = (m_oponent_protocol_ver == LEVIN_PROTOCOL_VER_1 && m_current_head.m_flags&LEVIN_PACKET_RESPONSE);
|
bool is_response = (m_oponent_protocol_ver == LEVIN_PROTOCOL_VER_1 && m_current_head.m_flags&LEVIN_PACKET_RESPONSE);
|
||||||
|
|
||||||
|
@ -449,8 +444,8 @@ public:
|
||||||
}else
|
}else
|
||||||
{
|
{
|
||||||
CRITICAL_REGION_BEGIN(m_local_inv_buff_lock);
|
CRITICAL_REGION_BEGIN(m_local_inv_buff_lock);
|
||||||
buff_to_invoke.swap(m_local_inv_buff);
|
m_local_inv_buff = std::string((const char*)buff_to_invoke.data(), buff_to_invoke.size());
|
||||||
buff_to_invoke.clear();
|
buff_to_invoke = epee::span<const uint8_t>((const uint8_t*)NULL, 0);
|
||||||
m_invoke_result_code = m_current_head.m_return_code;
|
m_invoke_result_code = m_current_head.m_return_code;
|
||||||
CRITICAL_REGION_END();
|
CRITICAL_REGION_END();
|
||||||
boost::interprocess::ipcdetail::atomic_write32(&m_invoke_buf_ready, 1);
|
boost::interprocess::ipcdetail::atomic_write32(&m_invoke_buf_ready, 1);
|
||||||
|
@ -503,7 +498,7 @@ public:
|
||||||
{
|
{
|
||||||
if(m_cache_in_buffer.size() < sizeof(bucket_head2))
|
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()) != SWAP64LE(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");
|
MWARNING(m_connection_context << "Signature mismatch, connection will be closed");
|
||||||
return false;
|
return false;
|
||||||
|
@ -513,9 +508,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||||
bucket_head2& phead = *(bucket_head2*)m_cache_in_buffer.data();
|
bucket_head2& phead = *(bucket_head2*)m_cache_in_buffer.span(sizeof(bucket_head2)).data();
|
||||||
#else
|
#else
|
||||||
bucket_head2 phead = *(bucket_head2*)m_cache_in_buffer.data();
|
bucket_head2 phead = *(bucket_head2*)m_cache_in_buffer.span(sizeof(bucket_head2)).data();
|
||||||
phead.m_signature = SWAP64LE(phead.m_signature);
|
phead.m_signature = SWAP64LE(phead.m_signature);
|
||||||
phead.m_cb = SWAP64LE(phead.m_cb);
|
phead.m_cb = SWAP64LE(phead.m_cb);
|
||||||
phead.m_command = SWAP32LE(phead.m_command);
|
phead.m_command = SWAP32LE(phead.m_command);
|
||||||
|
@ -530,7 +525,7 @@ public:
|
||||||
}
|
}
|
||||||
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_state = stream_state_body;
|
||||||
m_oponent_protocol_ver = m_current_head.m_protocol_version;
|
m_oponent_protocol_ver = m_current_head.m_protocol_version;
|
||||||
if(m_current_head.m_cb > m_config.m_max_packet_size)
|
if(m_current_head.m_cb > m_config.m_max_packet_size)
|
||||||
|
@ -562,7 +557,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class callback_t>
|
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(
|
misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler(
|
||||||
boost::bind(&async_protocol_handler::finish_outer_call, this));
|
boost::bind(&async_protocol_handler::finish_outer_call, this));
|
||||||
|
@ -606,7 +601,7 @@ public:
|
||||||
break;
|
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");
|
LOG_ERROR_CC(m_connection_context, "Failed to do_send");
|
||||||
err_code = LEVIN_ERROR_CONNECTION;
|
err_code = LEVIN_ERROR_CONNECTION;
|
||||||
|
@ -623,7 +618,7 @@ public:
|
||||||
|
|
||||||
if (LEVIN_OK != err_code)
|
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
|
// Never call callback inside critical section, that can cause deadlock
|
||||||
cb(err_code, stub_buff, m_connection_context);
|
cb(err_code, stub_buff, m_connection_context);
|
||||||
return false;
|
return false;
|
||||||
|
@ -632,7 +627,7 @@ public:
|
||||||
return true;
|
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(
|
misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler(
|
||||||
boost::bind(&async_protocol_handler::finish_outer_call, this));
|
boost::bind(&async_protocol_handler::finish_outer_call, this));
|
||||||
|
@ -662,7 +657,7 @@ public:
|
||||||
return LEVIN_ERROR_CONNECTION;
|
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");
|
LOG_ERROR_CC(m_connection_context, "Failed to do_send");
|
||||||
return LEVIN_ERROR_CONNECTION;
|
return LEVIN_ERROR_CONNECTION;
|
||||||
|
@ -706,7 +701,7 @@ public:
|
||||||
return m_invoke_result_code;
|
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(
|
misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler(
|
||||||
boost::bind(&async_protocol_handler::finish_outer_call, this));
|
boost::bind(&async_protocol_handler::finish_outer_call, this));
|
||||||
|
@ -734,7 +729,7 @@ public:
|
||||||
return -1;
|
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()");
|
LOG_ERROR_CC(m_connection_context, "Failed to do_send()");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -839,7 +834,7 @@ int async_protocol_handler_config<t_connection_context>::find_and_lock_connectio
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
template<class t_connection_context>
|
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;
|
async_protocol_handler<t_connection_context>* aph;
|
||||||
int r = find_and_lock_connection(connection_id, aph);
|
int r = find_and_lock_connection(connection_id, aph);
|
||||||
|
@ -847,7 +842,7 @@ int async_protocol_handler_config<t_connection_context>::invoke(int command, con
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
template<class t_connection_context> template<class callback_t>
|
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;
|
async_protocol_handler<t_connection_context>* aph;
|
||||||
int r = find_and_lock_connection(connection_id, aph);
|
int r = find_and_lock_connection(connection_id, aph);
|
||||||
|
@ -896,7 +891,7 @@ void async_protocol_handler_config<t_connection_context>::set_handler(levin_comm
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
template<class t_connection_context>
|
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;
|
async_protocol_handler<t_connection_context>* aph;
|
||||||
int r = find_and_lock_connection(connection_id, aph);
|
int r = find_and_lock_connection(connection_id, aph);
|
||||||
|
|
|
@ -163,4 +163,12 @@ namespace epee
|
||||||
static_assert(!has_padding<T>(), "source type may have padding");
|
static_assert(!has_padding<T>(), "source type may have padding");
|
||||||
return {reinterpret_cast<std::uint8_t*>(std::addressof(src)), sizeof(T)};
|
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()};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@ namespace epee
|
||||||
return false;
|
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>
|
template<class t_request, class t_response, class t_transport>
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
#include "portable_storage_template_helper.h"
|
#include "portable_storage_template_helper.h"
|
||||||
#include <boost/utility/value_init.hpp>
|
#include <boost/utility/value_init.hpp>
|
||||||
|
#include "span.h"
|
||||||
#include "net/levin_base.h"
|
#include "net/levin_base.h"
|
||||||
|
|
||||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
#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
|
const_cast<t_arg&>(out_struct).store(stg);//TODO: add true const support to searilzation
|
||||||
std::string buff_to_send;
|
std::string buff_to_send;
|
||||||
stg.store_to_binary(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);
|
t_result result_struct = AUTO_VAL_INIT(result_struct);
|
||||||
if( code <=0 )
|
if( code <=0 )
|
||||||
|
@ -156,7 +157,7 @@ namespace epee
|
||||||
std::string buff_to_send;
|
std::string buff_to_send;
|
||||||
stg.store_to_binary(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 )
|
if(res <=0 )
|
||||||
{
|
{
|
||||||
MERROR("Failed to notify command " << command << " return code " << res);
|
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>
|
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;
|
serialization::portable_storage strg;
|
||||||
if(!strg.load_from_binary(in_buff))
|
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>
|
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;
|
serialization::portable_storage strg;
|
||||||
if(!strg.load_from_binary(in_buff))
|
if(!strg.load_from_binary(in_buff))
|
||||||
|
@ -215,14 +216,14 @@ namespace epee
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CHAIN_LEVIN_INVOKE_MAP2(context_type) \
|
#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; \
|
bool handled = false; \
|
||||||
return handle_invoke_map(false, command, in_buff, buff_out, context, handled); \
|
return handle_invoke_map(false, command, in_buff, buff_out, context, handled); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CHAIN_LEVIN_NOTIFY_MAP2(context_type) \
|
#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;\
|
bool handled = false; std::string fake_str;\
|
||||||
return handle_invoke_map(true, command, in_buff, fake_str, context, handled); \
|
return handle_invoke_map(true, command, in_buff, fake_str, context, handled); \
|
||||||
|
@ -230,27 +231,27 @@ namespace epee
|
||||||
|
|
||||||
|
|
||||||
#define CHAIN_LEVIN_INVOKE_MAP() \
|
#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; \
|
bool handled = false; \
|
||||||
return handle_invoke_map(false, command, in_buff, buff_out, context, handled); \
|
return handle_invoke_map(false, command, in_buff, buff_out, context, handled); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CHAIN_LEVIN_NOTIFY_MAP() \
|
#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;\
|
bool handled = false; std::string fake_str;\
|
||||||
return handle_invoke_map(true, command, in_buff, fake_str, context, handled); \
|
return handle_invoke_map(true, command, in_buff, fake_str, context, handled); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CHAIN_LEVIN_NOTIFY_STUB() \
|
#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; \
|
return -1; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define BEGIN_INVOKE_MAP2(owner_type) \
|
#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;
|
typedef owner_type internal_owner_type_name;
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "portable_storage_to_json.h"
|
#include "portable_storage_to_json.h"
|
||||||
#include "portable_storage_from_json.h"
|
#include "portable_storage_from_json.h"
|
||||||
#include "portable_storage_val_converters.h"
|
#include "portable_storage_val_converters.h"
|
||||||
|
#include "span.h"
|
||||||
#include "int-util.h"
|
#include "int-util.h"
|
||||||
|
|
||||||
namespace epee
|
namespace epee
|
||||||
|
@ -81,7 +82,8 @@ namespace epee
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------
|
||||||
bool store_to_binary(binarybuffer& target);
|
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>
|
template<class trace_policy>
|
||||||
bool dump_as_xml(std::string& targetObj, const std::string& root_name = "");
|
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);
|
bool dump_as_json(std::string& targetObj, size_t indent = 0, bool insert_newlines = true);
|
||||||
|
@ -146,7 +148,7 @@ namespace epee
|
||||||
CATCH_ENTRY("portable_storage::store_to_binary", false)
|
CATCH_ENTRY("portable_storage::store_to_binary", false)
|
||||||
}
|
}
|
||||||
inline
|
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();
|
m_root.m_entries.clear();
|
||||||
if(source.size() < sizeof(storage_block_header))
|
if(source.size() < sizeof(storage_block_header))
|
||||||
|
|
|
@ -84,7 +84,7 @@ namespace epee
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------------------
|
||||||
template<class t_struct>
|
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;
|
portable_storage ps;
|
||||||
bool rs = ps.load_from_binary(binary_buff);
|
bool rs = ps.load_from_binary(binary_buff);
|
||||||
|
@ -95,6 +95,12 @@ namespace epee
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------------------
|
||||||
template<class t_struct>
|
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)
|
bool load_t_from_binary_file(t_struct& out, const std::string& binary_file)
|
||||||
{
|
{
|
||||||
std::string f_buff;
|
std::string f_buff;
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# 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
|
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)
|
if (USE_READLINE AND GNU_READLINE_FOUND)
|
||||||
add_library(epee_readline STATIC readline_buffer.cpp)
|
add_library(epee_readline STATIC readline_buffer.cpp)
|
||||||
endif()
|
endif()
|
||||||
|
|
97
contrib/epee/src/buffer.cpp
Normal file
97
contrib/epee/src/buffer.cpp
Normal file
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -155,7 +155,7 @@ namespace cryptonote
|
||||||
std::string blob;
|
std::string blob;
|
||||||
epee::serialization::store_t_to_binary(arg, blob);
|
epee::serialization::store_t_to_binary(arg, blob);
|
||||||
//handler_response_blocks_now(blob.size()); // XXX
|
//handler_response_blocks_now(blob.size()); // XXX
|
||||||
return m_p2p->invoke_notify_to_peer(t_parameter::ID, blob, context);
|
return m_p2p->invoke_notify_to_peer(t_parameter::ID, epee::strspan<uint8_t>(blob), context);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class t_parameter>
|
template<class t_parameter>
|
||||||
|
@ -164,7 +164,7 @@ namespace cryptonote
|
||||||
LOG_PRINT_L2("[" << epee::net_utils::print_connection_context_short(exclude_context) << "] post relay " << typeid(t_parameter).name() << " -->");
|
LOG_PRINT_L2("[" << epee::net_utils::print_connection_context_short(exclude_context) << "] post relay " << typeid(t_parameter).name() << " -->");
|
||||||
std::string arg_buff;
|
std::string arg_buff;
|
||||||
epee::serialization::store_t_to_binary(arg, arg_buff);
|
epee::serialization::store_t_to_binary(arg, arg_buff);
|
||||||
return m_p2p->relay_notify_to_all(t_parameter::ID, arg_buff, exclude_context);
|
return m_p2p->relay_notify_to_all(t_parameter::ID, epee::strspan<uint8_t>(arg_buff), exclude_context);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1710,13 +1710,13 @@ skip:
|
||||||
{
|
{
|
||||||
std::string fluffyBlob;
|
std::string fluffyBlob;
|
||||||
epee::serialization::store_t_to_binary(fluffy_arg, fluffyBlob);
|
epee::serialization::store_t_to_binary(fluffy_arg, fluffyBlob);
|
||||||
m_p2p->relay_notify_to_list(NOTIFY_NEW_FLUFFY_BLOCK::ID, fluffyBlob, fluffyConnections);
|
m_p2p->relay_notify_to_list(NOTIFY_NEW_FLUFFY_BLOCK::ID, epee::strspan<uint8_t>(fluffyBlob), fluffyConnections);
|
||||||
}
|
}
|
||||||
if (!fullConnections.empty())
|
if (!fullConnections.empty())
|
||||||
{
|
{
|
||||||
std::string fullBlob;
|
std::string fullBlob;
|
||||||
epee::serialization::store_t_to_binary(arg, fullBlob);
|
epee::serialization::store_t_to_binary(arg, fullBlob);
|
||||||
m_p2p->relay_notify_to_list(NOTIFY_NEW_BLOCK::ID, fullBlob, fullConnections);
|
m_p2p->relay_notify_to_list(NOTIFY_NEW_BLOCK::ID, epee::strspan<uint8_t>(fullBlob), fullConnections);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -180,10 +180,10 @@ namespace nodetool
|
||||||
virtual void on_connection_close(p2p_connection_context& context);
|
virtual void on_connection_close(p2p_connection_context& context);
|
||||||
virtual void callback(p2p_connection_context& context);
|
virtual void callback(p2p_connection_context& context);
|
||||||
//----------------- i_p2p_endpoint -------------------------------------------------------------
|
//----------------- i_p2p_endpoint -------------------------------------------------------------
|
||||||
virtual bool relay_notify_to_list(int command, const std::string& data_buff, const std::list<boost::uuids::uuid> &connections);
|
virtual bool relay_notify_to_list(int command, const epee::span<const uint8_t> data_buff, const std::list<boost::uuids::uuid> &connections);
|
||||||
virtual bool relay_notify_to_all(int command, const std::string& data_buff, const epee::net_utils::connection_context_base& context);
|
virtual bool relay_notify_to_all(int command, const epee::span<const uint8_t> data_buff, const epee::net_utils::connection_context_base& context);
|
||||||
virtual bool invoke_command_to_peer(int command, const std::string& req_buff, std::string& resp_buff, const epee::net_utils::connection_context_base& context);
|
virtual bool invoke_command_to_peer(int command, const epee::span<const uint8_t> req_buff, std::string& resp_buff, const epee::net_utils::connection_context_base& context);
|
||||||
virtual bool invoke_notify_to_peer(int command, const std::string& req_buff, const epee::net_utils::connection_context_base& context);
|
virtual bool invoke_notify_to_peer(int command, const epee::span<const uint8_t> req_buff, const epee::net_utils::connection_context_base& context);
|
||||||
virtual bool drop_connection(const epee::net_utils::connection_context_base& context);
|
virtual bool drop_connection(const epee::net_utils::connection_context_base& context);
|
||||||
virtual void request_callback(const epee::net_utils::connection_context_base& context);
|
virtual void request_callback(const epee::net_utils::connection_context_base& context);
|
||||||
virtual void for_each_connection(std::function<bool(typename t_payload_net_handler::connection_context&, peerid_type, uint32_t)> f);
|
virtual void for_each_connection(std::function<bool(typename t_payload_net_handler::connection_context&, peerid_type, uint32_t)> f);
|
||||||
|
|
|
@ -1516,7 +1516,7 @@ namespace nodetool
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
template<class t_payload_net_handler>
|
template<class t_payload_net_handler>
|
||||||
bool node_server<t_payload_net_handler>::relay_notify_to_list(int command, const std::string& data_buff, const std::list<boost::uuids::uuid> &connections)
|
bool node_server<t_payload_net_handler>::relay_notify_to_list(int command, const epee::span<const uint8_t> data_buff, const std::list<boost::uuids::uuid> &connections)
|
||||||
{
|
{
|
||||||
for(const auto& c_id: connections)
|
for(const auto& c_id: connections)
|
||||||
{
|
{
|
||||||
|
@ -1526,7 +1526,7 @@ namespace nodetool
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
template<class t_payload_net_handler>
|
template<class t_payload_net_handler>
|
||||||
bool node_server<t_payload_net_handler>::relay_notify_to_all(int command, const std::string& data_buff, const epee::net_utils::connection_context_base& context)
|
bool node_server<t_payload_net_handler>::relay_notify_to_all(int command, const epee::span<const uint8_t> data_buff, const epee::net_utils::connection_context_base& context)
|
||||||
{
|
{
|
||||||
std::list<boost::uuids::uuid> connections;
|
std::list<boost::uuids::uuid> connections;
|
||||||
m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
|
m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
|
||||||
|
@ -1545,14 +1545,14 @@ namespace nodetool
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
template<class t_payload_net_handler>
|
template<class t_payload_net_handler>
|
||||||
bool node_server<t_payload_net_handler>::invoke_notify_to_peer(int command, const std::string& req_buff, const epee::net_utils::connection_context_base& context)
|
bool node_server<t_payload_net_handler>::invoke_notify_to_peer(int command, const epee::span<const uint8_t> req_buff, const epee::net_utils::connection_context_base& context)
|
||||||
{
|
{
|
||||||
int res = m_net_server.get_config_object().notify(command, req_buff, context.m_connection_id);
|
int res = m_net_server.get_config_object().notify(command, req_buff, context.m_connection_id);
|
||||||
return res > 0;
|
return res > 0;
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
template<class t_payload_net_handler>
|
template<class t_payload_net_handler>
|
||||||
bool node_server<t_payload_net_handler>::invoke_command_to_peer(int command, const std::string& req_buff, std::string& resp_buff, const epee::net_utils::connection_context_base& context)
|
bool node_server<t_payload_net_handler>::invoke_command_to_peer(int command, const epee::span<const uint8_t> req_buff, std::string& resp_buff, const epee::net_utils::connection_context_base& context)
|
||||||
{
|
{
|
||||||
int res = m_net_server.get_config_object().invoke(command, req_buff, resp_buff, context.m_connection_id);
|
int res = m_net_server.get_config_object().invoke(command, req_buff, resp_buff, context.m_connection_id);
|
||||||
return res > 0;
|
return res > 0;
|
||||||
|
|
|
@ -43,10 +43,10 @@ namespace nodetool
|
||||||
template<class t_connection_context>
|
template<class t_connection_context>
|
||||||
struct i_p2p_endpoint
|
struct i_p2p_endpoint
|
||||||
{
|
{
|
||||||
virtual bool relay_notify_to_list(int command, const std::string& data_buff, const std::list<boost::uuids::uuid>& connections)=0;
|
virtual bool relay_notify_to_list(int command, const epee::span<const uint8_t> data_buff, const std::list<boost::uuids::uuid>& connections)=0;
|
||||||
virtual bool relay_notify_to_all(int command, const std::string& data_buff, const epee::net_utils::connection_context_base& context)=0;
|
virtual bool relay_notify_to_all(int command, const epee::span<const uint8_t> data_buff, const epee::net_utils::connection_context_base& context)=0;
|
||||||
virtual bool invoke_command_to_peer(int command, const std::string& req_buff, std::string& resp_buff, const epee::net_utils::connection_context_base& context)=0;
|
virtual bool invoke_command_to_peer(int command, const epee::span<const uint8_t> req_buff, std::string& resp_buff, const epee::net_utils::connection_context_base& context)=0;
|
||||||
virtual bool invoke_notify_to_peer(int command, const std::string& req_buff, const epee::net_utils::connection_context_base& context)=0;
|
virtual bool invoke_notify_to_peer(int command, const epee::span<const uint8_t> req_buff, const epee::net_utils::connection_context_base& context)=0;
|
||||||
virtual bool drop_connection(const epee::net_utils::connection_context_base& context)=0;
|
virtual bool drop_connection(const epee::net_utils::connection_context_base& context)=0;
|
||||||
virtual void request_callback(const epee::net_utils::connection_context_base& context)=0;
|
virtual void request_callback(const epee::net_utils::connection_context_base& context)=0;
|
||||||
virtual uint64_t get_connections_count()=0;
|
virtual uint64_t get_connections_count()=0;
|
||||||
|
@ -61,19 +61,19 @@ namespace nodetool
|
||||||
template<class t_connection_context>
|
template<class t_connection_context>
|
||||||
struct p2p_endpoint_stub: public i_p2p_endpoint<t_connection_context>
|
struct p2p_endpoint_stub: public i_p2p_endpoint<t_connection_context>
|
||||||
{
|
{
|
||||||
virtual bool relay_notify_to_list(int command, const std::string& data_buff, const std::list<boost::uuids::uuid>& connections)
|
virtual bool relay_notify_to_list(int command, const epee::span<const uint8_t> data_buff, const std::list<boost::uuids::uuid>& connections)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
virtual bool relay_notify_to_all(int command, const std::string& data_buff, const epee::net_utils::connection_context_base& context)
|
virtual bool relay_notify_to_all(int command, const epee::span<const uint8_t> data_buff, const epee::net_utils::connection_context_base& context)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
virtual bool invoke_command_to_peer(int command, const std::string& req_buff, std::string& resp_buff, const epee::net_utils::connection_context_base& context)
|
virtual bool invoke_command_to_peer(int command, const epee::span<const uint8_t> req_buff, std::string& resp_buff, const epee::net_utils::connection_context_base& context)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
virtual bool invoke_notify_to_peer(int command, const std::string& req_buff, const epee::net_utils::connection_context_base& context)
|
virtual bool invoke_notify_to_peer(int command, const epee::span<const uint8_t> req_buff, const epee::net_utils::connection_context_base& context)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,22 +65,22 @@ namespace
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int invoke(int command, const std::string& in_buff, std::string& buff_out, test_levin_connection_context& context)
|
virtual int invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, test_levin_connection_context& context)
|
||||||
{
|
{
|
||||||
m_invoke_counter.inc();
|
m_invoke_counter.inc();
|
||||||
boost::unique_lock<boost::mutex> lock(m_mutex);
|
boost::unique_lock<boost::mutex> lock(m_mutex);
|
||||||
m_last_command = command;
|
m_last_command = command;
|
||||||
m_last_in_buf = in_buff;
|
m_last_in_buf = std::string((const char*)in_buff.data(), in_buff.size());
|
||||||
buff_out = m_invoke_out_buf;
|
buff_out = m_invoke_out_buf;
|
||||||
return m_return_code;
|
return m_return_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int notify(int command, const std::string& in_buff, test_levin_connection_context& context)
|
virtual int notify(int command, const epee::span<const uint8_t> in_buff, test_levin_connection_context& context)
|
||||||
{
|
{
|
||||||
m_notify_counter.inc();
|
m_notify_counter.inc();
|
||||||
boost::unique_lock<boost::mutex> lock(m_mutex);
|
boost::unique_lock<boost::mutex> lock(m_mutex);
|
||||||
m_last_command = command;
|
m_last_command = command;
|
||||||
m_last_in_buf = in_buff;
|
m_last_in_buf = std::string((const char*)in_buff.data(), in_buff.size());
|
||||||
return m_return_code;
|
return m_return_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ namespace net_load_tests
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int invoke(int command, const std::string& in_buff, std::string& buff_out, test_connection_context& context)
|
virtual int invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, test_connection_context& context)
|
||||||
{
|
{
|
||||||
//m_invoke_counter.inc();
|
//m_invoke_counter.inc();
|
||||||
//std::unique_lock<std::mutex> lock(m_mutex);
|
//std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
|
@ -73,7 +73,7 @@ namespace net_load_tests
|
||||||
return LEVIN_OK;
|
return LEVIN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int notify(int command, const std::string& in_buff, test_connection_context& context)
|
virtual int notify(int command, const epee::span<const uint8_t> in_buff, test_connection_context& context)
|
||||||
{
|
{
|
||||||
//m_notify_counter.inc();
|
//m_notify_counter.inc();
|
||||||
//std::unique_lock<std::mutex> lock(m_mutex);
|
//std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
|
|
|
@ -56,22 +56,22 @@ namespace
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int invoke(int command, const std::string& in_buff, std::string& buff_out, test_levin_connection_context& context)
|
virtual int invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, test_levin_connection_context& context)
|
||||||
{
|
{
|
||||||
m_invoke_counter.inc();
|
m_invoke_counter.inc();
|
||||||
boost::unique_lock<boost::mutex> lock(m_mutex);
|
boost::unique_lock<boost::mutex> lock(m_mutex);
|
||||||
m_last_command = command;
|
m_last_command = command;
|
||||||
m_last_in_buf = in_buff;
|
m_last_in_buf = std::string((const char*)in_buff.data(), in_buff.size());
|
||||||
buff_out = m_invoke_out_buf;
|
buff_out = m_invoke_out_buf;
|
||||||
return m_return_code;
|
return m_return_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int notify(int command, const std::string& in_buff, test_levin_connection_context& context)
|
virtual int notify(int command, const epee::span<const uint8_t> in_buff, test_levin_connection_context& context)
|
||||||
{
|
{
|
||||||
m_notify_counter.inc();
|
m_notify_counter.inc();
|
||||||
boost::unique_lock<boost::mutex> lock(m_mutex);
|
boost::unique_lock<boost::mutex> lock(m_mutex);
|
||||||
m_last_command = command;
|
m_last_command = command;
|
||||||
m_last_in_buf = in_buff;
|
m_last_in_buf = std::string((const char*)in_buff.data(), in_buff.size());
|
||||||
return m_return_code;
|
return m_return_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
#include "hex.h"
|
#include "hex.h"
|
||||||
#include "net/net_utils_base.h"
|
#include "net/net_utils_base.h"
|
||||||
#include "net/local_ip.h"
|
#include "net/local_ip.h"
|
||||||
|
#include "net/buffer.h"
|
||||||
#include "p2p/net_peerlist_boost_serialization.h"
|
#include "p2p/net_peerlist_boost_serialization.h"
|
||||||
#include "span.h"
|
#include "span.h"
|
||||||
#include "string_tools.h"
|
#include "string_tools.h"
|
||||||
|
@ -764,3 +765,71 @@ TEST(NetUtils, PrivateRanges)
|
||||||
ASSERT_EQ(is_local("0.0.30.172"), false);
|
ASSERT_EQ(is_local("0.0.30.172"), false);
|
||||||
ASSERT_EQ(is_local("0.0.30.127"), false);
|
ASSERT_EQ(is_local("0.0.30.127"), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(net_buffer, basic)
|
||||||
|
{
|
||||||
|
epee::net_utils::buffer buf;
|
||||||
|
|
||||||
|
ASSERT_EQ(buf.size(), 0);
|
||||||
|
EXPECT_THROW(buf.span(1), std::runtime_error);
|
||||||
|
buf.append("a", 1);
|
||||||
|
epee::span<const uint8_t> span = buf.span(1);
|
||||||
|
ASSERT_EQ(span.size(), 1);
|
||||||
|
ASSERT_EQ(span.data()[0], 'a');
|
||||||
|
EXPECT_THROW(buf.span(2), std::runtime_error);
|
||||||
|
buf.append("bc", 2);
|
||||||
|
buf.erase(1);
|
||||||
|
EXPECT_THROW(buf.span(3), std::runtime_error);
|
||||||
|
span = buf.span(2);
|
||||||
|
ASSERT_EQ(span.size(), 2);
|
||||||
|
ASSERT_EQ(span.data()[0], 'b');
|
||||||
|
ASSERT_EQ(span.data()[1], 'c');
|
||||||
|
buf.erase(1);
|
||||||
|
EXPECT_THROW(buf.span(2), std::runtime_error);
|
||||||
|
span = buf.span(1);
|
||||||
|
ASSERT_EQ(span.size(), 1);
|
||||||
|
ASSERT_EQ(span.data()[0], 'c');
|
||||||
|
EXPECT_THROW(buf.erase(2), std::runtime_error);
|
||||||
|
buf.erase(1);
|
||||||
|
EXPECT_EQ(buf.size(), 0);
|
||||||
|
EXPECT_THROW(buf.span(1), std::runtime_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(net_buffer, existing_capacity)
|
||||||
|
{
|
||||||
|
epee::net_utils::buffer buf;
|
||||||
|
|
||||||
|
buf.append("123456789", 9);
|
||||||
|
buf.erase(9);
|
||||||
|
buf.append("abc", 3);
|
||||||
|
buf.append("def", 3);
|
||||||
|
ASSERT_EQ(buf.size(), 6);
|
||||||
|
epee::span<const uint8_t> span = buf.span(6);
|
||||||
|
ASSERT_TRUE(!memcmp(span.data(), "abcdef", 6));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(net_buffer, reallocate)
|
||||||
|
{
|
||||||
|
epee::net_utils::buffer buf;
|
||||||
|
|
||||||
|
buf.append(std::string(4000, ' ').c_str(), 4000);
|
||||||
|
buf.append(std::string(8000, '0').c_str(), 8000);
|
||||||
|
ASSERT_EQ(buf.size(), 12000);
|
||||||
|
epee::span<const uint8_t> span = buf.span(12000);
|
||||||
|
ASSERT_TRUE(!memcmp(span.data(), std::string(4000, ' ').c_str(), 4000));
|
||||||
|
ASSERT_TRUE(!memcmp(span.data() + 4000, std::string(8000, '0').c_str(), 8000));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(net_buffer, move)
|
||||||
|
{
|
||||||
|
epee::net_utils::buffer buf;
|
||||||
|
|
||||||
|
buf.append(std::string(400, ' ').c_str(), 400);
|
||||||
|
buf.erase(399);
|
||||||
|
buf.append(std::string(4000, '0').c_str(), 4000);
|
||||||
|
ASSERT_EQ(buf.size(), 4001);
|
||||||
|
epee::span<const uint8_t> span = buf.span(4001);
|
||||||
|
ASSERT_TRUE(!memcmp(span.data(), std::string(1, ' ').c_str(), 1));
|
||||||
|
ASSERT_TRUE(!memcmp(span.data() + 1, std::string(4000, '0').c_str(), 4000));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue