aboutsummaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
Diffstat (limited to 'contrib')
-rw-r--r--contrib/epee/include/byte_slice.h2
-rw-r--r--contrib/epee/include/misc_language.h17
-rw-r--r--contrib/epee/include/net/abstract_tcp_server2.h6
-rw-r--r--contrib/epee/include/net/abstract_tcp_server2.inl11
-rw-r--r--contrib/epee/include/net/http_server_handlers_map2.h16
-rw-r--r--contrib/epee/include/net/levin_protocol_handler_async.h60
-rw-r--r--contrib/epee/include/net/net_ssl.h4
-rw-r--r--contrib/epee/include/serialization/keyvalue_serialization.h3
-rw-r--r--contrib/epee/include/storages/portable_storage.h206
-rw-r--r--contrib/epee/include/storages/portable_storage_base.h2
-rw-r--r--contrib/epee/include/storages/portable_storage_from_json.h1
-rw-r--r--contrib/epee/include/storages/portable_storage_template_helper.h1
-rw-r--r--contrib/epee/include/storages/portable_storage_to_bin.h1
-rw-r--r--contrib/epee/include/storages/portable_storage_val_converters.h7
-rw-r--r--contrib/epee/src/CMakeLists.txt16
-rw-r--r--contrib/epee/src/byte_slice.cpp24
-rw-r--r--contrib/epee/src/misc_language.cpp44
-rw-r--r--contrib/epee/src/net_ssl.cpp47
-rw-r--r--contrib/epee/src/portable_storage.cpp215
19 files changed, 415 insertions, 268 deletions
diff --git a/contrib/epee/include/byte_slice.h b/contrib/epee/include/byte_slice.h
index 6b79f6d92..18d60e088 100644
--- a/contrib/epee/include/byte_slice.h
+++ b/contrib/epee/include/byte_slice.h
@@ -112,7 +112,7 @@ namespace epee
explicit byte_slice(std::string&& buffer);
//! Convert `stream` into a slice with zero allocations.
- explicit byte_slice(byte_stream&& stream) noexcept;
+ explicit byte_slice(byte_stream&& stream, bool shrink = true);
byte_slice(byte_slice&& source) noexcept;
~byte_slice() noexcept = default;
diff --git a/contrib/epee/include/misc_language.h b/contrib/epee/include/misc_language.h
index a04c63231..5ccfe6fcc 100644
--- a/contrib/epee/include/misc_language.h
+++ b/contrib/epee/include/misc_language.h
@@ -28,9 +28,11 @@
#pragma once
-#include <limits>
-#include <boost/thread.hpp>
#include <boost/utility/value_init.hpp>
+#include <boost/shared_ptr.hpp>
+#include <limits>
+#include <functional>
+#include <vector>
namespace epee
{
#define STD_TRY_BEGIN() try {
@@ -95,16 +97,7 @@ namespace misc_utils
return memcmp(&_Left, &_Right, sizeof(_Left)) < 0;
}
-
- inline
- bool sleep_no_w(long ms )
- {
- boost::this_thread::sleep(
- boost::get_system_time() +
- boost::posix_time::milliseconds( std::max<long>(ms,0) ) );
-
- return true;
- }
+ bool sleep_no_w(long ms );
template <typename T>
T get_mid(const T &a, const T &b)
diff --git a/contrib/epee/include/net/abstract_tcp_server2.h b/contrib/epee/include/net/abstract_tcp_server2.h
index 3c31cf22b..f40cd108a 100644
--- a/contrib/epee/include/net/abstract_tcp_server2.h
+++ b/contrib/epee/include/net/abstract_tcp_server2.h
@@ -265,6 +265,12 @@ namespace net_utils
template<class t_callback>
bool connect_async(const std::string& adr, const std::string& port, uint32_t conn_timeot, const t_callback &cb, const std::string& bind_ip = "0.0.0.0", epee::net_utils::ssl_support_t ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_autodetect);
+ boost::asio::ssl::context& get_ssl_context() noexcept
+ {
+ assert(m_state != nullptr);
+ return m_state->ssl_context;
+ }
+
typename t_protocol_handler::config_type& get_config_object()
{
assert(m_state != nullptr); // always set in constructor
diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl
index cb1388f3b..61e2b30fe 100644
--- a/contrib/epee/include/net/abstract_tcp_server2.inl
+++ b/contrib/epee/include/net/abstract_tcp_server2.inl
@@ -40,6 +40,7 @@
#include <boost/date_time/posix_time/posix_time.hpp> // TODO
#include <boost/thread/condition_variable.hpp> // TODO
#include <boost/make_shared.hpp>
+#include <boost/thread.hpp>
#include "warnings.h"
#include "string_tools.h"
#include "misc_language.h"
@@ -269,8 +270,6 @@ PRAGMA_WARNING_DISABLE_VS(4355)
//_dbg3("[sock " << socket().native_handle() << "] add_ref, m_peer_number=" << mI->m_peer_number);
CRITICAL_REGION_LOCAL(self->m_self_refs_lock);
//_dbg3("[sock " << socket().native_handle() << "] add_ref 2, m_peer_number=" << mI->m_peer_number);
- if(m_was_shutdown)
- return false;
++m_reference_count;
m_self_ref = std::move(self);
return true;
@@ -562,7 +561,7 @@ PRAGMA_WARNING_DISABLE_VS(4355)
{ // LOCK: chunking
epee::critical_region_t<decltype(m_chunking_lock)> send_guard(m_chunking_lock); // *** critical ***
- MDEBUG("do_send() will SPLIT into small chunks, from packet="<<message_size<<" B for ptr="<<message_data);
+ MDEBUG("do_send() will SPLIT into small chunks, from packet="<<message_size<<" B for ptr="<<(const void*)message_data);
// 01234567890
// ^^^^ (pos=0, len=4) ; pos:=pos+len, pos=4
// ^^^^ (pos=4, len=4) ; pos:=pos+len, pos=8
@@ -575,14 +574,14 @@ PRAGMA_WARNING_DISABLE_VS(4355)
while (!message.empty()) {
byte_slice chunk = message.take_slice(chunksize_good);
- MDEBUG("chunk_start="<<(void*)chunk.data()<<" ptr="<<message_data<<" pos="<<(chunk.data() - message_data));
+ MDEBUG("chunk_start="<<(void*)chunk.data()<<" ptr="<<(const void*)message_data<<" pos="<<(chunk.data() - message_data));
MDEBUG("part of " << message.size() << ": pos="<<(chunk.data() - message_data) << " len="<<chunk.size());
bool ok = do_send_chunk(std::move(chunk)); // <====== ***
all_ok = all_ok && ok;
if (!all_ok) {
- MDEBUG("do_send() DONE ***FAILED*** from packet="<<message_size<<" B for ptr="<<message_data);
+ MDEBUG("do_send() DONE ***FAILED*** from packet="<<message_size<<" B for ptr="<<(const void*)message_data);
MDEBUG("do_send() SEND was aborted in middle of big package - this is mostly harmless "
<< " (e.g. peer closed connection) but if it causes trouble tell us at #monero-dev. " << message_size);
return false; // partial failure in sending
@@ -590,7 +589,7 @@ PRAGMA_WARNING_DISABLE_VS(4355)
// (in catch block, or uniq pointer) delete buf;
} // each chunk
- MDEBUG("do_send() DONE SPLIT from packet="<<message_size<<" B for ptr="<<message_data);
+ MDEBUG("do_send() DONE SPLIT from packet="<<message_size<<" B for ptr="<<(const void*)message_data);
MDEBUG("do_send() m_connection_type = " << m_connection_type);
diff --git a/contrib/epee/include/net/http_server_handlers_map2.h b/contrib/epee/include/net/http_server_handlers_map2.h
index 1665fdac7..ffb3f3b7e 100644
--- a/contrib/epee/include/net/http_server_handlers_map2.h
+++ b/contrib/epee/include/net/http_server_handlers_map2.h
@@ -74,7 +74,13 @@
uint64_t ticks = misc_utils::get_tick_count(); \
boost::value_initialized<command_type::request> req; \
bool parse_res = epee::serialization::load_t_from_json(static_cast<command_type::request&>(req), query_info.m_body); \
- CHECK_AND_ASSERT_MES(parse_res, false, "Failed to parse json: \r\n" << query_info.m_body); \
+ if (!parse_res) \
+ { \
+ MERROR("Failed to parse json: \r\n" << query_info.m_body); \
+ response_info.m_response_code = 400; \
+ response_info.m_response_comment = "Bad request"; \
+ return true; \
+ } \
uint64_t ticks1 = epee::misc_utils::get_tick_count(); \
boost::value_initialized<command_type::response> resp;\
MINFO(m_conn_context << "calling " << s_pattern); \
@@ -104,7 +110,13 @@
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), 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()); \
+ if (!parse_res) \
+ { \
+ MERROR("Failed to parse bin body data, body size=" << query_info.m_body.size()); \
+ response_info.m_response_code = 400; \
+ response_info.m_response_comment = "Bad request"; \
+ return true; \
+ } \
uint64_t ticks1 = misc_utils::get_tick_count(); \
boost::value_initialized<command_type::response> resp;\
MINFO(m_conn_context << "calling " << s_pattern); \
diff --git a/contrib/epee/include/net/levin_protocol_handler_async.h b/contrib/epee/include/net/levin_protocol_handler_async.h
index ddde701ee..f6b73a2d5 100644
--- a/contrib/epee/include/net/levin_protocol_handler_async.h
+++ b/contrib/epee/include/net/levin_protocol_handler_async.h
@@ -146,7 +146,6 @@ public:
stream_state_body
};
- std::atomic<bool> m_deletion_initiated;
std::atomic<bool> m_protocol_released;
volatile uint32_t m_invoke_buf_ready;
@@ -297,7 +296,6 @@ public:
m_state(stream_state_head)
{
m_close_called = 0;
- m_deletion_initiated = false;
m_protocol_released = false;
m_wait_count = 0;
m_oponent_protocol_ver = 0;
@@ -310,7 +308,6 @@ public:
try
{
- m_deletion_initiated = true;
if(m_connection_initialized)
{
m_config.del_connection(this);
@@ -633,20 +630,8 @@ public:
int err_code = LEVIN_OK;
do
{
- if(m_deletion_initiated)
- {
- err_code = LEVIN_ERROR_CONNECTION_DESTROYED;
- break;
- }
-
CRITICAL_REGION_LOCAL(m_call_lock);
- if(m_deletion_initiated)
- {
- err_code = LEVIN_ERROR_CONNECTION_DESTROYED;
- break;
- }
-
boost::interprocess::ipcdetail::atomic_write32(&m_invoke_buf_ready, 0);
CRITICAL_REGION_BEGIN(m_invoke_response_handlers_lock);
@@ -684,14 +669,8 @@ public:
misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler(
boost::bind(&async_protocol_handler::finish_outer_call, this));
- if(m_deletion_initiated)
- return LEVIN_ERROR_CONNECTION_DESTROYED;
-
CRITICAL_REGION_LOCAL(m_call_lock);
- if(m_deletion_initiated)
- return LEVIN_ERROR_CONNECTION_DESTROYED;
-
boost::interprocess::ipcdetail::atomic_write32(&m_invoke_buf_ready, 0);
if (command == m_connection_context.handshake_command())
@@ -706,7 +685,7 @@ public:
uint64_t ticks_start = misc_utils::get_tick_count();
size_t prev_size = 0;
- while(!boost::interprocess::ipcdetail::atomic_read32(&m_invoke_buf_ready) && !m_deletion_initiated && !m_protocol_released)
+ while(!boost::interprocess::ipcdetail::atomic_read32(&m_invoke_buf_ready) && !m_protocol_released)
{
if(m_cache_in_buffer.size() - prev_size >= MIN_BYTES_WANTED)
{
@@ -723,7 +702,7 @@ public:
return LEVIN_ERROR_CONNECTION_DESTROYED;
}
- if(m_deletion_initiated || m_protocol_released)
+ if(m_protocol_released)
return LEVIN_ERROR_CONNECTION_DESTROYED;
CRITICAL_REGION_BEGIN(m_local_inv_buff_lock);
@@ -739,14 +718,8 @@ public:
misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler(
boost::bind(&async_protocol_handler::finish_outer_call, this));
- if(m_deletion_initiated)
- return LEVIN_ERROR_CONNECTION_DESTROYED;
-
CRITICAL_REGION_LOCAL(m_call_lock);
- if(m_deletion_initiated)
- return LEVIN_ERROR_CONNECTION_DESTROYED;
-
if (!send_message(command, in_buff, LEVIN_PACKET_REQUEST, false))
{
LOG_ERROR_CC(m_connection_context, "Failed to send notify message");
@@ -768,9 +741,6 @@ public:
boost::bind(&async_protocol_handler::finish_outer_call, this)
);
- if(m_deletion_initiated)
- return LEVIN_ERROR_CONNECTION_DESTROYED;
-
const std::size_t length = message.size();
if (!m_pservice_endpoint->do_send(std::move(message)))
{
@@ -817,7 +787,7 @@ void async_protocol_handler_config<t_connection_context>::delete_connections(siz
{
auto i = connections.end() - 1;
async_protocol_handler<t_connection_context> *conn = m_connects.at(*i);
- del_connection(conn);
+ m_connects.erase(*i);
conn->close();
connections.erase(i);
}
@@ -891,12 +861,22 @@ template<class t_connection_context> template<class callback_t>
bool async_protocol_handler_config<t_connection_context>::foreach_connection(const callback_t &cb)
{
CRITICAL_REGION_LOCAL(m_connects_lock);
- for(auto& c: m_connects)
- {
- async_protocol_handler<t_connection_context>* aph = c.second;
- if(!cb(aph->get_context_ref()))
+ std::vector<typename connections_map::mapped_type> conn;
+ conn.reserve(m_connects.size());
+
+ auto scope_exit_handler = misc_utils::create_scope_leave_handler([&conn]{
+ for (auto &aph: conn)
+ aph->finish_outer_call();
+ });
+
+ for (auto &e: m_connects)
+ if (e.second->start_outer_call())
+ conn.push_back(e.second);
+
+ for (auto &aph: conn)
+ if (!cb(aph->get_context_ref()))
return false;
- }
+
return true;
}
//------------------------------------------------------------------------------------------
@@ -907,6 +887,10 @@ bool async_protocol_handler_config<t_connection_context>::for_connection(const b
async_protocol_handler<t_connection_context>* aph = find_connection(connection_id);
if (!aph)
return false;
+ if (!aph->start_outer_call())
+ return false;
+ auto scope_exit_handler = misc_utils::create_scope_leave_handler(
+ boost::bind(&async_protocol_handler<t_connection_context>::finish_outer_call, aph));
if(!cb(aph->get_context_ref()))
return false;
return true;
diff --git a/contrib/epee/include/net/net_ssl.h b/contrib/epee/include/net/net_ssl.h
index 1b1577e77..58cd7e45f 100644
--- a/contrib/epee/include/net/net_ssl.h
+++ b/contrib/epee/include/net/net_ssl.h
@@ -36,6 +36,7 @@
#include <boost/utility/string_ref.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ssl.hpp>
+#include <boost/filesystem/path.hpp>
#include <boost/system/error_code.hpp>
#define SSL_FINGERPRINT_SIZE 32
@@ -144,6 +145,9 @@ namespace net_utils
bool create_ec_ssl_certificate(EVP_PKEY *&pkey, X509 *&cert);
bool create_rsa_ssl_certificate(EVP_PKEY *&pkey, X509 *&cert);
+
+ //! Store private key for `ssl` at `base + ".key"` unencrypted and certificate for `ssl` at `base + ".crt"`.
+ boost::system::error_code store_ssl_keys(boost::asio::ssl::context& ssl, const boost::filesystem::path& base);
}
}
diff --git a/contrib/epee/include/serialization/keyvalue_serialization.h b/contrib/epee/include/serialization/keyvalue_serialization.h
index fd343865c..2e4a0faad 100644
--- a/contrib/epee/include/serialization/keyvalue_serialization.h
+++ b/contrib/epee/include/serialization/keyvalue_serialization.h
@@ -73,7 +73,8 @@ public: \
template<bool is_store, class t_storage> \
bool serialize_map(t_storage& stg, typename t_storage::hsection hparent_section) \
{ \
- decltype(*this) &this_ref = *this;
+ decltype(*this) &this_ref = *this; \
+ (void) this_ref; // Suppress unused var warnings. Sometimes this var is used, sometimes not.
#define KV_SERIALIZE_N(varialble, val_name) \
epee::serialization::selector<is_store>::serialize(this_ref.varialble, stg, hparent_section, val_name);
diff --git a/contrib/epee/include/storages/portable_storage.h b/contrib/epee/include/storages/portable_storage.h
index f77e89cb6..c5d0c48ee 100644
--- a/contrib/epee/include/storages/portable_storage.h
+++ b/contrib/epee/include/storages/portable_storage.h
@@ -24,20 +24,12 @@
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
-
-
#pragma once
-#include <type_traits>
-
-#include "misc_language.h"
#include "portable_storage_base.h"
-#include "portable_storage_from_bin.h"
-#include "portable_storage_to_json.h"
-#include "portable_storage_from_json.h"
#include "portable_storage_val_converters.h"
+#include "misc_log_ex.h"
#include "span.h"
-#include "int-util.h"
namespace epee
{
@@ -92,7 +84,7 @@ namespace epee
//-------------------------------------------------------------------------------
bool store_to_binary(byte_slice& target, std::size_t initial_buffer_size = 8192);
bool load_from_binary(const epee::span<const uint8_t> target, const limits_t *limits = NULL);
- bool load_from_binary(const std::string& target, const limits_t *limits = NULL) { return load_from_binary(epee::strspan<uint8_t>(target), limits); }
+ bool load_from_binary(const std::string& target, const limits_t *limits = NULL);
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);
@@ -117,85 +109,13 @@ namespace epee
};
#pragma pack(pop)
};
- inline
- bool portable_storage::dump_as_json(std::string& buff, size_t indent, bool insert_newlines)
- {
- TRY_ENTRY();
- std::stringstream ss;
- epee::serialization::dump_as_json(ss, m_root, indent, insert_newlines);
- buff = ss.str();
- return true;
- CATCH_ENTRY("portable_storage::dump_as_json", false)
- }
- inline
- bool portable_storage::load_from_json(const std::string& source)
- {
- TRY_ENTRY();
- return json::load_from_json(source, *this);
- CATCH_ENTRY("portable_storage::load_from_json", false)
- }
-
+
template<class trace_policy>
bool portable_storage::dump_as_xml(std::string& targetObj, const std::string& root_name)
{
return false;//TODO: don't think i ever again will use xml - ambiguous and "overtagged" format
- }
- inline
- bool portable_storage::load_from_binary(const epee::span<const uint8_t> source, const limits_t *limits)
- {
- m_root.m_entries.clear();
- if(source.size() < sizeof(storage_block_header))
- {
- LOG_ERROR("portable_storage: wrong binary format, packet size = " << source.size() << " less than expected sizeof(storage_block_header)=" << sizeof(storage_block_header));
- return false;
- }
- storage_block_header* pbuff = (storage_block_header*)source.data();
- 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");
- return false;
- }
- if(pbuff->m_ver != PORTABLE_STORAGE_FORMAT_VER)
- {
- LOG_ERROR("portable_storage: wrong binary format - unknown format ver = " << pbuff->m_ver);
- return false;
- }
- TRY_ENTRY();
- throwable_buffer_reader buf_reader(source.data()+sizeof(storage_block_header), source.size()-sizeof(storage_block_header));
- if (limits)
- buf_reader.set_limits(limits->n_objects, limits->n_fields, limits->n_strings);
- buf_reader.read(m_root);
- return true;//TODO:
- CATCH_ENTRY("portable_storage::load_from_binary", false);
- }
- //---------------------------------------------------------------------------------------------------------------
- inline
- hsection portable_storage::open_section(const std::string& section_name, hsection hparent_section, bool create_if_notexist)
- {
- TRY_ENTRY();
- hparent_section = hparent_section ? hparent_section:&m_root;
- storage_entry* pentry = find_storage_entry(section_name, hparent_section);
- if(!pentry)
- {
- if(!create_if_notexist)
- return nullptr;
- return insert_new_section(section_name, hparent_section);
- }
- CHECK_AND_ASSERT(pentry , nullptr);
- //check that section_entry we find is real "CSSection"
- if(pentry->type() != typeid(section))
- {
- if(create_if_notexist)
- *pentry = storage_entry(section());//replace
- else
- return nullptr;
- }
- return &boost::get<section>(*pentry);
- CATCH_ENTRY("portable_storage::open_section", nullptr);
- }
- //---------------------------------------------------------------------------------------------------------------
+ }
+
template<class to_type>
struct get_value_visitor: boost::static_visitor<void>
{
@@ -221,20 +141,6 @@ namespace epee
//CATCH_ENTRY("portable_storage::template<>get_value", false);
}
//---------------------------------------------------------------------------------------------------------------
- inline
- bool portable_storage::get_value(const std::string& value_name, storage_entry& val, hsection hparent_section)
- {
- //TRY_ENTRY();
- if(!hparent_section) hparent_section = &m_root;
- storage_entry* pentry = find_storage_entry(value_name, hparent_section);
- if(!pentry)
- return false;
-
- val = *pentry;
- return true;
- //CATCH_ENTRY("portable_storage::template<>get_value", false);
- }
- //---------------------------------------------------------------------------------------------------------------
template<class t_value>
bool portable_storage::set_value(const std::string& value_name, t_value&& v, hsection hparent_section)
{
@@ -256,19 +162,6 @@ namespace epee
CATCH_ENTRY("portable_storage::template<>set_value", false);
}
//---------------------------------------------------------------------------------------------------------------
- inline
- storage_entry* portable_storage::find_storage_entry(const std::string& pentry_name, hsection psection)
- {
- TRY_ENTRY();
- CHECK_AND_ASSERT(psection, nullptr);
- auto it = psection->m_entries.find(pentry_name);
- if(it == psection->m_entries.end())
- return nullptr;
-
- return &it->second;
- CATCH_ENTRY("portable_storage::find_storage_entry", nullptr);
- }
- //---------------------------------------------------------------------------------------------------------------
template<class entry_type>
storage_entry* portable_storage::insert_new_entry_get_storage_entry(const std::string& pentry_name, hsection psection, entry_type&& entry)
{
@@ -281,16 +174,6 @@ namespace epee
CATCH_ENTRY("portable_storage::insert_new_entry_get_storage_entry", nullptr);
}
//---------------------------------------------------------------------------------------------------------------
- inline
- hsection portable_storage::insert_new_section(const std::string& pentry_name, hsection psection)
- {
- TRY_ENTRY();
- storage_entry* pse = insert_new_entry_get_storage_entry(pentry_name, psection, section());
- if(!pse) return nullptr;
- return &boost::get<section>(*pse);
- CATCH_ENTRY("portable_storage::insert_new_section", nullptr);
- }
- //---------------------------------------------------------------------------------------------------------------
template<class to_type>
struct get_first_value_visitor: boost::static_visitor<bool>
{
@@ -344,7 +227,6 @@ namespace epee
}
};
-
template<class t_value>
bool portable_storage::get_next_value(harray hval_array, t_value& target)
{
@@ -402,83 +284,5 @@ namespace epee
return true;
CATCH_ENTRY("portable_storage::insert_next_value", false);
}
- //---------------------------------------------------------------------------------------------------------------
- //sections
- inline
- harray portable_storage::get_first_section(const std::string& sec_name, hsection& h_child_section, hsection hparent_section)
- {
- TRY_ENTRY();
- if(!hparent_section) hparent_section = &m_root;
- storage_entry* pentry = find_storage_entry(sec_name, hparent_section);
- if(!pentry)
- return nullptr;
- if(pentry->type() != typeid(array_entry))
- return nullptr;
- array_entry& ar_entry = boost::get<array_entry>(*pentry);
- if(ar_entry.type() != typeid(array_entry_t<section>))
- return nullptr;
- array_entry_t<section>& sec_array = boost::get<array_entry_t<section>>(ar_entry);
- section* psec = sec_array.get_first_val();
- if(!psec)
- return nullptr;
- h_child_section = psec;
- return &ar_entry;
- CATCH_ENTRY("portable_storage::get_first_section", nullptr);
- }
- //---------------------------------------------------------------------------------------------------------------
- inline
- bool portable_storage::get_next_section(harray hsec_array, hsection& h_child_section)
- {
- TRY_ENTRY();
- CHECK_AND_ASSERT(hsec_array, false);
- if(hsec_array->type() != typeid(array_entry_t<section>))
- return false;
- array_entry_t<section>& sec_array = boost::get<array_entry_t<section>>(*hsec_array);
- h_child_section = sec_array.get_next_val();
- if(!h_child_section)
- return false;
- return true;
- CATCH_ENTRY("portable_storage::get_next_section", false);
- }
- //---------------------------------------------------------------------------------------------------------------
- inline
- harray portable_storage::insert_first_section(const std::string& sec_name, hsection& hinserted_childsection, hsection hparent_section)
- {
- TRY_ENTRY();
- if(!hparent_section) hparent_section = &m_root;
- storage_entry* pentry = find_storage_entry(sec_name, hparent_section);
- if(!pentry)
- {
- pentry = insert_new_entry_get_storage_entry(sec_name, hparent_section, array_entry(array_entry_t<section>()));
- if(!pentry)
- return nullptr;
- }
- if(pentry->type() != typeid(array_entry))
- *pentry = storage_entry(array_entry(array_entry_t<section>()));
-
- array_entry& ar_entry = boost::get<array_entry>(*pentry);
- if(ar_entry.type() != typeid(array_entry_t<section>))
- ar_entry = array_entry(array_entry_t<section>());
-
- array_entry_t<section>& sec_array = boost::get<array_entry_t<section>>(ar_entry);
- hinserted_childsection = &sec_array.insert_first_val(section());
- return &ar_entry;
- CATCH_ENTRY("portable_storage::insert_first_section", nullptr);
- }
- //---------------------------------------------------------------------------------------------------------------
- inline
- bool portable_storage::insert_next_section(harray hsec_array, hsection& hinserted_childsection)
- {
- TRY_ENTRY();
- CHECK_AND_ASSERT(hsec_array, false);
- CHECK_AND_ASSERT_MES(hsec_array->type() == typeid(array_entry_t<section>),
- false, "unexpected type(not 'section') in insert_next_section, type: " << hsec_array->type().name());
-
- array_entry_t<section>& sec_array = boost::get<array_entry_t<section>>(*hsec_array);
- hinserted_childsection = &sec_array.insert_next_value(section());
- return true;
- CATCH_ENTRY("portable_storage::insert_next_section", false);
- }
- //---------------------------------------------------------------------------------------------------------------
}
}
diff --git a/contrib/epee/include/storages/portable_storage_base.h b/contrib/epee/include/storages/portable_storage_base.h
index 1676f41fb..ae0be6a34 100644
--- a/contrib/epee/include/storages/portable_storage_base.h
+++ b/contrib/epee/include/storages/portable_storage_base.h
@@ -29,10 +29,10 @@
#pragma once
#include <boost/variant.hpp>
-#include <boost/any.hpp>
#include <string>
#include <vector>
#include <deque>
+#include <map>
#define PORTABLE_STORAGE_SIGNATUREA 0x01011101
#define PORTABLE_STORAGE_SIGNATUREB 0x01020101 // bender's nightmare
diff --git a/contrib/epee/include/storages/portable_storage_from_json.h b/contrib/epee/include/storages/portable_storage_from_json.h
index 2b2dc7ff9..3021598f5 100644
--- a/contrib/epee/include/storages/portable_storage_from_json.h
+++ b/contrib/epee/include/storages/portable_storage_from_json.h
@@ -26,6 +26,7 @@
#pragma once
#include <boost/lexical_cast.hpp>
+#include <boost/utility/string_ref.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include "parserse_base_utils.h"
#include "file_io_utils.h"
diff --git a/contrib/epee/include/storages/portable_storage_template_helper.h b/contrib/epee/include/storages/portable_storage_template_helper.h
index 16dd565ec..e7250e895 100644
--- a/contrib/epee/include/storages/portable_storage_template_helper.h
+++ b/contrib/epee/include/storages/portable_storage_template_helper.h
@@ -32,6 +32,7 @@
#include "parserse_base_utils.h"
#include "portable_storage.h"
#include "file_io_utils.h"
+#include "span.h"
namespace epee
{
diff --git a/contrib/epee/include/storages/portable_storage_to_bin.h b/contrib/epee/include/storages/portable_storage_to_bin.h
index 49a7be185..b82cf532b 100644
--- a/contrib/epee/include/storages/portable_storage_to_bin.h
+++ b/contrib/epee/include/storages/portable_storage_to_bin.h
@@ -32,6 +32,7 @@
#include "misc_language.h"
#include "portable_storage_base.h"
#include "portable_storage_bin_utils.h"
+#include "misc_log_ex.h"
namespace epee
{
diff --git a/contrib/epee/include/storages/portable_storage_val_converters.h b/contrib/epee/include/storages/portable_storage_val_converters.h
index e54cda828..96b0c024c 100644
--- a/contrib/epee/include/storages/portable_storage_val_converters.h
+++ b/contrib/epee/include/storages/portable_storage_val_converters.h
@@ -28,12 +28,17 @@
#pragma once
-#include <time.h>
#include <boost/regex.hpp>
#include "misc_language.h"
#include "portable_storage_base.h"
+#include "parserse_base_utils.h"
#include "warnings.h"
+#include "misc_log_ex.h"
+
+#include <boost/lexical_cast.hpp>
+#include <typeinfo>
+#include <iomanip>
namespace epee
{
diff --git a/contrib/epee/src/CMakeLists.txt b/contrib/epee/src/CMakeLists.txt
index 5e101a86a..881ae5746 100644
--- a/contrib/epee/src/CMakeLists.txt
+++ b/contrib/epee/src/CMakeLists.txt
@@ -26,10 +26,21 @@
# 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.
+set(EPEE_INCLUDE_DIR_BASE "${CMAKE_CURRENT_SOURCE_DIR}/../include")
+
+# Adding headers to the file list, to be able to search for them in IDEs.
+file(GLOB EPEE_HEADERS_PUBLIC
+ "${EPEE_INCLUDE_DIR_BASE}/*.h*" # h* will include hpps as well.
+ "${EPEE_INCLUDE_DIR_BASE}/**/*.h*" # Any number of subdirs will be included.
+)
add_library(epee STATIC byte_slice.cpp byte_stream.cpp hex.cpp abstract_http_client.cpp http_auth.cpp mlog.cpp net_helper.cpp net_utils_base.cpp string_tools.cpp
wipeable_string.cpp levin_base.cpp memwipe.c connection_basic.cpp network_throttle.cpp network_throttle-detail.cpp mlocker.cpp buffer.cpp net_ssl.cpp
- int-util.cpp portable_storage.cpp)
+ int-util.cpp portable_storage.cpp
+ misc_language.cpp
+
+ ${EPEE_HEADERS_PUBLIC}
+ )
if (USE_READLINE AND (GNU_READLINE_FOUND OR (DEPENDS AND NOT MINGW)))
add_library(epee_readline STATIC readline_buffer.cpp)
@@ -71,3 +82,6 @@ if (USE_READLINE AND (GNU_READLINE_FOUND OR (DEPENDS AND NOT MINGW)))
PRIVATE
${GNU_READLINE_LIBRARY})
endif()
+
+target_include_directories(epee PUBLIC "${EPEE_INCLUDE_DIR_BASE}")
+
diff --git a/contrib/epee/src/byte_slice.cpp b/contrib/epee/src/byte_slice.cpp
index faf7689be..453b63a4c 100644
--- a/contrib/epee/src/byte_slice.cpp
+++ b/contrib/epee/src/byte_slice.cpp
@@ -36,6 +36,11 @@
#include "byte_slice.h"
#include "byte_stream.h"
+namespace
+{
+ const std::size_t page_size = 4096;
+}
+
namespace epee
{
struct byte_slice_data
@@ -173,16 +178,27 @@ namespace epee
: byte_slice(adapt_buffer{}, std::move(buffer))
{}
- byte_slice::byte_slice(byte_stream&& stream) noexcept
+ byte_slice::byte_slice(byte_stream&& stream, const bool shrink)
: storage_(nullptr), portion_(stream.data(), stream.size())
{
- if (stream.size())
+ if (portion_.size())
{
- std::uint8_t* const data = stream.take_buffer().release() - sizeof(raw_byte_slice);
+ byte_buffer buf;
+ if (shrink && page_size <= stream.available())
+ {
+ buf = byte_buffer_resize(stream.take_buffer(), portion_.size());
+ if (!buf)
+ throw std::bad_alloc{};
+ portion_ = {buf.get(), portion_.size()};
+ }
+ else // no need to shrink buffer
+ buf = stream.take_buffer();
+
+ std::uint8_t* const data = buf.release() - sizeof(raw_byte_slice);
new (data) raw_byte_slice{};
storage_.reset(reinterpret_cast<raw_byte_slice*>(data));
}
- else
+ else // empty stream
portion_ = nullptr;
}
diff --git a/contrib/epee/src/misc_language.cpp b/contrib/epee/src/misc_language.cpp
new file mode 100644
index 000000000..6e8f2daef
--- /dev/null
+++ b/contrib/epee/src/misc_language.cpp
@@ -0,0 +1,44 @@
+// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * 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.
+// * Neither the name of the Andrey N. Sabelnikov 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 OWNER 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 "misc_language.h"
+
+#include <boost/thread.hpp>
+
+namespace epee
+{
+namespace misc_utils
+{
+ bool sleep_no_w(long ms )
+ {
+ boost::this_thread::sleep(
+ boost::get_system_time() +
+ boost::posix_time::milliseconds( std::max<long>(ms,0) ) );
+
+ return true;
+ }
+}
+}
diff --git a/contrib/epee/src/net_ssl.cpp b/contrib/epee/src/net_ssl.cpp
index 6ed27efa9..765dadce3 100644
--- a/contrib/epee/src/net_ssl.cpp
+++ b/contrib/epee/src/net_ssl.cpp
@@ -29,6 +29,8 @@
#include <string.h>
#include <thread>
#include <boost/asio/ssl.hpp>
+#include <boost/cerrno.hpp>
+#include <boost/filesystem/operations.hpp>
#include <boost/lambda/lambda.hpp>
#include <openssl/ssl.h>
#include <openssl/pem.h>
@@ -567,6 +569,51 @@ bool ssl_support_from_string(ssl_support_t &ssl, boost::string_ref s)
return true;
}
+boost::system::error_code store_ssl_keys(boost::asio::ssl::context& ssl, const boost::filesystem::path& base)
+{
+ EVP_PKEY* ssl_key = nullptr;
+ X509* ssl_cert = nullptr;
+ const auto ctx = ssl.native_handle();
+ CHECK_AND_ASSERT_MES(ctx, boost::system::error_code(EINVAL, boost::system::system_category()), "Context is null");
+ CHECK_AND_ASSERT_MES(base.has_filename(), boost::system::error_code(EINVAL, boost::system::system_category()), "Need filename");
+ if (!(ssl_key = SSL_CTX_get0_privatekey(ctx)) || !(ssl_cert = SSL_CTX_get0_certificate(ctx)))
+ return {EINVAL, boost::system::system_category()};
+
+ using file_closer = int(std::FILE*);
+ boost::system::error_code error{};
+ std::unique_ptr<std::FILE, file_closer*> file{nullptr, std::fclose};
+
+ // write key file unencrypted
+ {
+ const boost::filesystem::path key_file{base.string() + ".key"};
+ file.reset(std::fopen(key_file.string().c_str(), "wb"));
+ if (!file)
+ return {errno, boost::system::system_category()};
+ boost::filesystem::permissions(key_file, boost::filesystem::owner_read, error);
+ if (error)
+ return error;
+ if (!PEM_write_PrivateKey(file.get(), ssl_key, nullptr, nullptr, 0, nullptr, nullptr))
+ return boost::asio::error::ssl_errors(ERR_get_error());
+ if (std::fclose(file.release()) != 0)
+ return {errno, boost::system::system_category()};
+ }
+
+ // write certificate file in standard SSL X.509 unencrypted
+ const boost::filesystem::path cert_file{base.string() + ".crt"};
+ file.reset(std::fopen(cert_file.string().c_str(), "wb"));
+ if (!file)
+ return {errno, boost::system::system_category()};
+ const auto cert_perms = (boost::filesystem::owner_read | boost::filesystem::group_read | boost::filesystem::others_read);
+ boost::filesystem::permissions(cert_file, cert_perms, error);
+ if (error)
+ return error;
+ if (!PEM_write_X509(file.get(), ssl_cert))
+ return boost::asio::error::ssl_errors(ERR_get_error());
+ if (std::fclose(file.release()) != 0)
+ return {errno, boost::system::system_category()};
+ return error;
+}
+
} // namespace
} // namespace
diff --git a/contrib/epee/src/portable_storage.cpp b/contrib/epee/src/portable_storage.cpp
index 4534deff3..c3c9ccc02 100644
--- a/contrib/epee/src/portable_storage.cpp
+++ b/contrib/epee/src/portable_storage.cpp
@@ -1,10 +1,43 @@
+// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * 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.
+// * Neither the name of the Andrey N. Sabelnikov 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 OWNER 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 "byte_slice.h"
#include "byte_stream.h"
#include "misc_log_ex.h"
#include "span.h"
#include "storages/portable_storage.h"
+#include "storages/portable_storage_to_json.h"
+#include "storages/portable_storage_from_json.h"
#include "storages/portable_storage_to_bin.h"
+#include "storages/portable_storage_from_bin.h"
+
+#include <boost/utility/string_ref.hpp>
+
+#include <string>
+#include <sstream>
namespace epee
{
@@ -25,5 +58,187 @@ namespace serialization
return true;
CATCH_ENTRY("portable_storage::store_to_binary", false)
}
+
+ bool portable_storage::dump_as_json(std::string& buff, size_t indent, bool insert_newlines)
+ {
+ TRY_ENTRY();
+ std::stringstream ss;
+ epee::serialization::dump_as_json(ss, m_root, indent, insert_newlines);
+ buff = ss.str();
+ return true;
+ CATCH_ENTRY("portable_storage::dump_as_json", false)
+ }
+
+ bool portable_storage::load_from_json(const std::string& source)
+ {
+ TRY_ENTRY();
+ return json::load_from_json(source, *this);
+ CATCH_ENTRY("portable_storage::load_from_json", false)
+ }
+
+ bool portable_storage::load_from_binary(const std::string& target, const limits_t *limits)
+ {
+ return load_from_binary(epee::strspan<uint8_t>(target), limits);
+ }
+
+ bool portable_storage::load_from_binary(const epee::span<const uint8_t> source, const limits_t *limits)
+ {
+ m_root.m_entries.clear();
+ if(source.size() < sizeof(storage_block_header))
+ {
+ LOG_ERROR("portable_storage: wrong binary format, packet size = " << source.size() << " less than expected sizeof(storage_block_header)=" << sizeof(storage_block_header));
+ return false;
+ }
+ storage_block_header* pbuff = (storage_block_header*)source.data();
+ 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");
+ return false;
+ }
+ if(pbuff->m_ver != PORTABLE_STORAGE_FORMAT_VER)
+ {
+ LOG_ERROR("portable_storage: wrong binary format - unknown format ver = " << pbuff->m_ver);
+ return false;
+ }
+ TRY_ENTRY();
+ throwable_buffer_reader buf_reader(source.data()+sizeof(storage_block_header), source.size()-sizeof(storage_block_header));
+ if (limits)
+ buf_reader.set_limits(limits->n_objects, limits->n_fields, limits->n_strings);
+ buf_reader.read(m_root);
+ return true;//TODO:
+ CATCH_ENTRY("portable_storage::load_from_binary", false);
+ }
+
+ hsection portable_storage::open_section(const std::string& section_name, hsection hparent_section, bool create_if_notexist)
+ {
+ TRY_ENTRY();
+ hparent_section = hparent_section ? hparent_section:&m_root;
+ storage_entry* pentry = find_storage_entry(section_name, hparent_section);
+ if(!pentry)
+ {
+ if(!create_if_notexist)
+ return nullptr;
+ return insert_new_section(section_name, hparent_section);
+ }
+ CHECK_AND_ASSERT(pentry , nullptr);
+ //check that section_entry we find is real "CSSection"
+ if(pentry->type() != typeid(section))
+ {
+ if(create_if_notexist)
+ *pentry = storage_entry(section());//replace
+ else
+ return nullptr;
+ }
+ return &boost::get<section>(*pentry);
+ CATCH_ENTRY("portable_storage::open_section", nullptr);
+ }
+
+ bool portable_storage::get_value(const std::string& value_name, storage_entry& val, hsection hparent_section)
+ {
+ //TRY_ENTRY();
+ if(!hparent_section) hparent_section = &m_root;
+ storage_entry* pentry = find_storage_entry(value_name, hparent_section);
+ if(!pentry)
+ return false;
+
+ val = *pentry;
+ return true;
+ //CATCH_ENTRY("portable_storage::template<>get_value", false);
+ }
+
+ storage_entry* portable_storage::find_storage_entry(const std::string& pentry_name, hsection psection)
+ {
+ TRY_ENTRY();
+ CHECK_AND_ASSERT(psection, nullptr);
+ auto it = psection->m_entries.find(pentry_name);
+ if(it == psection->m_entries.end())
+ return nullptr;
+
+ return &it->second;
+ CATCH_ENTRY("portable_storage::find_storage_entry", nullptr);
+ }
+
+ hsection portable_storage::insert_new_section(const std::string& pentry_name, hsection psection)
+ {
+ TRY_ENTRY();
+ storage_entry* pse = insert_new_entry_get_storage_entry(pentry_name, psection, section());
+ if(!pse) return nullptr;
+ return &boost::get<section>(*pse);
+ CATCH_ENTRY("portable_storage::insert_new_section", nullptr);
+ }
+
+ harray portable_storage::get_first_section(const std::string& sec_name, hsection& h_child_section, hsection hparent_section)
+ {
+ TRY_ENTRY();
+ if(!hparent_section) hparent_section = &m_root;
+ storage_entry* pentry = find_storage_entry(sec_name, hparent_section);
+ if(!pentry)
+ return nullptr;
+ if(pentry->type() != typeid(array_entry))
+ return nullptr;
+ array_entry& ar_entry = boost::get<array_entry>(*pentry);
+ if(ar_entry.type() != typeid(array_entry_t<section>))
+ return nullptr;
+ array_entry_t<section>& sec_array = boost::get<array_entry_t<section>>(ar_entry);
+ section* psec = sec_array.get_first_val();
+ if(!psec)
+ return nullptr;
+ h_child_section = psec;
+ return &ar_entry;
+ CATCH_ENTRY("portable_storage::get_first_section", nullptr);
+ }
+
+ bool portable_storage::get_next_section(harray hsec_array, hsection& h_child_section)
+ {
+ TRY_ENTRY();
+ CHECK_AND_ASSERT(hsec_array, false);
+ if(hsec_array->type() != typeid(array_entry_t<section>))
+ return false;
+ array_entry_t<section>& sec_array = boost::get<array_entry_t<section>>(*hsec_array);
+ h_child_section = sec_array.get_next_val();
+ if(!h_child_section)
+ return false;
+ return true;
+ CATCH_ENTRY("portable_storage::get_next_section", false);
+ }
+
+ harray portable_storage::insert_first_section(const std::string& sec_name, hsection& hinserted_childsection, hsection hparent_section)
+ {
+ TRY_ENTRY();
+ if(!hparent_section) hparent_section = &m_root;
+ storage_entry* pentry = find_storage_entry(sec_name, hparent_section);
+ if(!pentry)
+ {
+ pentry = insert_new_entry_get_storage_entry(sec_name, hparent_section, array_entry(array_entry_t<section>()));
+ if(!pentry)
+ return nullptr;
+ }
+ if(pentry->type() != typeid(array_entry))
+ *pentry = storage_entry(array_entry(array_entry_t<section>()));
+
+ array_entry& ar_entry = boost::get<array_entry>(*pentry);
+ if(ar_entry.type() != typeid(array_entry_t<section>))
+ ar_entry = array_entry(array_entry_t<section>());
+
+ array_entry_t<section>& sec_array = boost::get<array_entry_t<section>>(ar_entry);
+ hinserted_childsection = &sec_array.insert_first_val(section());
+ return &ar_entry;
+ CATCH_ENTRY("portable_storage::insert_first_section", nullptr);
+ }
+
+ bool portable_storage::insert_next_section(harray hsec_array, hsection& hinserted_childsection)
+ {
+ TRY_ENTRY();
+ CHECK_AND_ASSERT(hsec_array, false);
+ CHECK_AND_ASSERT_MES(hsec_array->type() == typeid(array_entry_t<section>),
+ false, "unexpected type(not 'section') in insert_next_section, type: " << hsec_array->type().name());
+
+ array_entry_t<section>& sec_array = boost::get<array_entry_t<section>>(*hsec_array);
+ hinserted_childsection = &sec_array.insert_next_value(section());
+ return true;
+ CATCH_ENTRY("portable_storage::insert_next_section", false);
+ }
}
}