aboutsummaryrefslogtreecommitdiff
path: root/contrib/epee
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/epee')
-rw-r--r--contrib/epee/include/byte_slice.h2
-rw-r--r--contrib/epee/include/file_io_utils.h206
-rw-r--r--contrib/epee/include/misc_log_ex.h4
-rw-r--r--contrib/epee/include/net/abstract_tcp_server2.h6
-rw-r--r--contrib/epee/include/net/abstract_tcp_server2.inl8
-rw-r--r--contrib/epee/include/net/levin_protocol_handler_async.h52
-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_template_helper.h2
-rw-r--r--contrib/epee/src/CMakeLists.txt11
-rw-r--r--contrib/epee/src/byte_slice.cpp24
-rw-r--r--contrib/epee/src/file_io_utils.cpp231
-rw-r--r--contrib/epee/src/net_ssl.cpp47
13 files changed, 361 insertions, 239 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/file_io_utils.h b/contrib/epee/include/file_io_utils.h
index 25f8c648b..84dc79266 100644
--- a/contrib/epee/include/file_io_utils.h
+++ b/contrib/epee/include/file_io_utils.h
@@ -24,211 +24,23 @@
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
-
#ifndef _FILE_IO_UTILS_H_
#define _FILE_IO_UTILS_H_
-#include <fstream>
-#include <boost/filesystem/path.hpp>
-#include <boost/filesystem/operations.hpp>
-#ifdef WIN32
-#include <windows.h>
-#include "string_tools.h"
-#endif
-
-// On Windows there is a problem with non-ASCII characters in path and file names
-// as far as support by the standard components used is concerned:
-
-// The various file stream classes, e.g. std::ifstream and std::ofstream, are
-// part of the GNU C++ Library / libstdc++. On the most basic level they use the
-// fopen() call as defined / made accessible to programs compiled within MSYS2
-// by the stdio.h header file maintained by the MinGW project.
-
-// The critical point: The implementation of fopen() is part of MSVCRT, the
-// Microsoft Visual C/C++ Runtime Library, and this method does NOT offer any
-// Unicode support.
-
-// Monero code that would want to continue to use the normal file stream classes
-// but WITH Unicode support could therefore not solve this problem on its own,
-// but 2 different projects from 2 different maintaining groups would need changes
-// in this particular direction - something probably difficult to achieve and
-// with a long time to wait until all new versions / releases arrive.
-
-// Implemented solution approach: Circumvent the problem by stopping to use std
-// file stream classes on Windows and directly use Unicode-capable WIN32 API
-// calls. Most of the code doing so is concentrated in this header file here.
+#include <string>
+#include <ctime>
namespace epee
{
namespace file_io_utils
{
- inline
- bool is_file_exist(const std::string& path)
- {
- boost::filesystem::path p(path);
- return boost::filesystem::exists(p);
- }
-
- inline
- bool save_string_to_file(const std::string& path_to_file, const std::string& str)
- {
-#ifdef WIN32
- std::wstring wide_path;
- try { wide_path = string_tools::utf8_to_utf16(path_to_file); } catch (...) { return false; }
- HANDLE file_handle = CreateFileW(wide_path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
- if (file_handle == INVALID_HANDLE_VALUE)
- return false;
- DWORD bytes_written;
- DWORD bytes_to_write = (DWORD)str.size();
- BOOL result = WriteFile(file_handle, str.data(), bytes_to_write, &bytes_written, NULL);
- CloseHandle(file_handle);
- if (bytes_written != bytes_to_write)
- result = FALSE;
- return result;
-#else
- try
- {
- std::ofstream fstream;
- fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
- fstream.open(path_to_file, std::ios_base::binary | std::ios_base::out | std::ios_base::trunc);
- fstream << str;
- fstream.close();
- return true;
- }
-
- catch(...)
- {
- return false;
- }
-#endif
- }
-
- inline
- bool get_file_time(const std::string& path_to_file, time_t& ft)
- {
- boost::system::error_code ec;
- ft = boost::filesystem::last_write_time(boost::filesystem::path(path_to_file), ec);
- if(!ec)
- return true;
- else
- return false;
- }
-
- inline
- bool set_file_time(const std::string& path_to_file, const time_t& ft)
- {
- boost::system::error_code ec;
- boost::filesystem::last_write_time(boost::filesystem::path(path_to_file), ft, ec);
- if(!ec)
- return true;
- else
- return false;
- }
-
-
- inline
- bool load_file_to_string(const std::string& path_to_file, std::string& target_str, size_t max_size = 1000000000)
- {
-#ifdef WIN32
- std::wstring wide_path;
- try { wide_path = string_tools::utf8_to_utf16(path_to_file); } catch (...) { return false; }
- HANDLE file_handle = CreateFileW(wide_path.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (file_handle == INVALID_HANDLE_VALUE)
- return false;
- DWORD file_size = GetFileSize(file_handle, NULL);
- if ((file_size == INVALID_FILE_SIZE) || (uint64_t)file_size > (uint64_t)max_size) {
- CloseHandle(file_handle);
- return false;
- }
- target_str.resize(file_size);
- DWORD bytes_read;
- BOOL result = ReadFile(file_handle, &target_str[0], file_size, &bytes_read, NULL);
- CloseHandle(file_handle);
- if (bytes_read != file_size)
- result = FALSE;
- return result;
-#else
- try
- {
- std::ifstream fstream;
- fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
- fstream.open(path_to_file, std::ios_base::binary | std::ios_base::in | std::ios::ate);
-
- std::ifstream::pos_type file_size = fstream.tellg();
-
- if((uint64_t)file_size > (uint64_t)max_size) // ensure a large domain for comparison, and negative -> too large
- return false;//don't go crazy
- size_t file_size_t = static_cast<size_t>(file_size);
-
- target_str.resize(file_size_t);
-
- fstream.seekg (0, std::ios::beg);
- fstream.read((char*)target_str.data(), target_str.size());
- fstream.close();
- return true;
- }
-
- catch(...)
- {
- return false;
- }
-#endif
- }
-
- inline
- bool append_string_to_file(const std::string& path_to_file, const std::string& str)
- {
- // No special Windows implementation because so far not used in Monero code
- try
- {
- std::ofstream fstream;
- fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
- fstream.open(path_to_file.c_str(), std::ios_base::binary | std::ios_base::out | std::ios_base::app);
- fstream << str;
- fstream.close();
- return true;
- }
-
- catch(...)
- {
- return false;
- }
- }
-
- inline
- bool get_file_size(const std::string& path_to_file, uint64_t &size)
- {
-#ifdef WIN32
- std::wstring wide_path;
- try { wide_path = string_tools::utf8_to_utf16(path_to_file); } catch (...) { return false; }
- HANDLE file_handle = CreateFileW(wide_path.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (file_handle == INVALID_HANDLE_VALUE)
- return false;
- LARGE_INTEGER file_size;
- BOOL result = GetFileSizeEx(file_handle, &file_size);
- CloseHandle(file_handle);
- if (result) {
- size = file_size.QuadPart;
- }
- return size;
-#else
- try
- {
- std::ifstream fstream;
- fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
- fstream.open(path_to_file, std::ios_base::binary | std::ios_base::in | std::ios::ate);
- size = fstream.tellg();
- fstream.close();
- return true;
- }
-
- catch(...)
- {
- return false;
- }
-#endif
- }
-
+ bool is_file_exist(const std::string& path);
+ bool save_string_to_file(const std::string& path_to_file, const std::string& str);
+ bool get_file_time(const std::string& path_to_file, time_t& ft);
+ bool set_file_time(const std::string& path_to_file, const time_t& ft);
+ bool load_file_to_string(const std::string& path_to_file, std::string& target_str, size_t max_size = 1000000000);
+ bool append_string_to_file(const std::string& path_to_file, const std::string& str);
+ bool get_file_size(const std::string& path_to_file, uint64_t &size);
}
}
diff --git a/contrib/epee/include/misc_log_ex.h b/contrib/epee/include/misc_log_ex.h
index 3be335e85..392ec11eb 100644
--- a/contrib/epee/include/misc_log_ex.h
+++ b/contrib/epee/include/misc_log_ex.h
@@ -41,7 +41,7 @@
#define MAX_LOG_FILES 50
#define MCLOG_TYPE(level, cat, color, type, x) do { \
- if (ELPP->vRegistry()->allowed(level, cat)) { \
+ if (el::Loggers::allowed(level, cat)) { \
el::base::Writer(level, color, __FILE__, __LINE__, ELPP_FUNC, type).construct(cat) << x; \
} \
} while (0)
@@ -89,7 +89,7 @@
#define IFLOG(level, cat, color, type, init, x) \
do { \
- if (ELPP->vRegistry()->allowed(level, cat)) { \
+ if (el::Loggers::allowed(level, cat)) { \
init; \
el::base::Writer(level, color, __FILE__, __LINE__, ELPP_FUNC, type).construct(cat) << x; \
} \
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 b03a03cad..61e2b30fe 100644
--- a/contrib/epee/include/net/abstract_tcp_server2.inl
+++ b/contrib/epee/include/net/abstract_tcp_server2.inl
@@ -561,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
@@ -574,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
@@ -589,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/levin_protocol_handler_async.h b/contrib/epee/include/net/levin_protocol_handler_async.h
index 65edfa1b8..a6816cafc 100644
--- a/contrib/epee/include/net/levin_protocol_handler_async.h
+++ b/contrib/epee/include/net/levin_protocol_handler_async.h
@@ -760,36 +760,32 @@ void async_protocol_handler_config<t_connection_context>::del_connection(async_p
template<class t_connection_context>
void async_protocol_handler_config<t_connection_context>::delete_connections(size_t count, bool incoming)
{
- std::vector <boost::uuids::uuid> connections;
+ std::vector<typename connections_map::mapped_type> connections;
+
+ auto scope_exit_handler = misc_utils::create_scope_leave_handler([&connections]{
+ for (auto &aph: connections)
+ aph->finish_outer_call();
+ });
+
CRITICAL_REGION_BEGIN(m_connects_lock);
for (auto& c: m_connects)
{
if (c.second->m_connection_context.m_is_income == incoming)
- connections.push_back(c.first);
+ if (c.second->start_outer_call())
+ connections.push_back(c.second);
}
// close random connections from the provided set
// TODO or better just keep removing random elements (performance)
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
shuffle(connections.begin(), connections.end(), std::default_random_engine(seed));
- while (count > 0 && connections.size() > 0)
- {
- try
- {
- auto i = connections.end() - 1;
- async_protocol_handler<t_connection_context> *conn = m_connects.at(*i);
- m_connects.erase(*i);
- conn->close();
- connections.erase(i);
- }
- catch (const std::out_of_range &e)
- {
- MWARNING("Connection not found in m_connects, continuing");
- }
- --count;
- }
+ for (size_t i = 0; i < connections.size() && i < count; ++i)
+ m_connects.erase(connections[i]->get_connection_id());
CRITICAL_REGION_END();
+
+ for (size_t i = 0; i < connections.size() && i < count; ++i)
+ connections[i]->close();
}
//------------------------------------------------------------------------------------------
template<class t_connection_context>
@@ -851,18 +847,19 @@ int async_protocol_handler_config<t_connection_context>::invoke_async(int comman
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);
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();
});
+ CRITICAL_REGION_BEGIN(m_connects_lock);
+ conn.reserve(m_connects.size());
for (auto &e: m_connects)
if (e.second->start_outer_call())
conn.push_back(e.second);
+ CRITICAL_REGION_END()
for (auto &aph: conn)
if (!cb(aph->get_context_ref()))
@@ -874,11 +871,8 @@ bool async_protocol_handler_config<t_connection_context>::foreach_connection(con
template<class t_connection_context> template<class callback_t>
bool async_protocol_handler_config<t_connection_context>::for_connection(const boost::uuids::uuid &connection_id, const callback_t &cb)
{
- CRITICAL_REGION_LOCAL(m_connects_lock);
- async_protocol_handler<t_connection_context>* aph = find_connection(connection_id);
- if (!aph)
- return false;
- if (!aph->start_outer_call())
+ async_protocol_handler<t_connection_context>* aph = nullptr;
+ if (find_and_lock_connection(connection_id, aph) != LEVIN_OK)
return false;
auto scope_exit_handler = misc_utils::create_scope_leave_handler(
boost::bind(&async_protocol_handler<t_connection_context>::finish_outer_call, aph));
@@ -936,12 +930,14 @@ int async_protocol_handler_config<t_connection_context>::send(byte_slice message
template<class t_connection_context>
bool async_protocol_handler_config<t_connection_context>::close(boost::uuids::uuid connection_id)
{
- CRITICAL_REGION_LOCAL(m_connects_lock);
- async_protocol_handler<t_connection_context>* aph = find_connection(connection_id);
- if (!aph)
+ async_protocol_handler<t_connection_context>* aph = nullptr;
+ if (find_and_lock_connection(connection_id, aph) != LEVIN_OK)
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 (!aph->close())
return false;
+ CRITICAL_REGION_LOCAL(m_connects_lock);
m_connects.erase(connection_id);
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_template_helper.h b/contrib/epee/include/storages/portable_storage_template_helper.h
index a06f0c2d3..7f6596f36 100644
--- a/contrib/epee/include/storages/portable_storage_template_helper.h
+++ b/contrib/epee/include/storages/portable_storage_template_helper.h
@@ -29,7 +29,7 @@
#include <string>
#include "byte_slice.h"
-#include "parserse_base_utils.h"
+#include "parserse_base_utils.h" /// TODO: (mj-xmr) This will be reduced in an another PR
#include "portable_storage.h"
#include "file_io_utils.h"
#include "span.h"
diff --git a/contrib/epee/src/CMakeLists.txt b/contrib/epee/src/CMakeLists.txt
index 641d4718e..132fed355 100644
--- a/contrib/epee/src/CMakeLists.txt
+++ b/contrib/epee/src/CMakeLists.txt
@@ -26,11 +26,20 @@
# 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
misc_language.cpp
+ file_io_utils.cpp
+ ${EPEE_HEADERS_PUBLIC}
)
if (USE_READLINE AND (GNU_READLINE_FOUND OR (DEPENDS AND NOT MINGW)))
@@ -74,5 +83,5 @@ if (USE_READLINE AND (GNU_READLINE_FOUND OR (DEPENDS AND NOT MINGW)))
${GNU_READLINE_LIBRARY})
endif()
-target_include_directories(epee PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../include")
+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/file_io_utils.cpp b/contrib/epee/src/file_io_utils.cpp
new file mode 100644
index 000000000..5072adcbc
--- /dev/null
+++ b/contrib/epee/src/file_io_utils.cpp
@@ -0,0 +1,231 @@
+// 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 "file_io_utils.h"
+
+#include <fstream>
+#include <boost/filesystem/path.hpp>
+#include <boost/filesystem/operations.hpp>
+#ifdef WIN32
+#include <windows.h>
+#include "string_tools.h"
+#endif
+
+// On Windows there is a problem with non-ASCII characters in path and file names
+// as far as support by the standard components used is concerned:
+
+// The various file stream classes, e.g. std::ifstream and std::ofstream, are
+// part of the GNU C++ Library / libstdc++. On the most basic level they use the
+// fopen() call as defined / made accessible to programs compiled within MSYS2
+// by the stdio.h header file maintained by the MinGW project.
+
+// The critical point: The implementation of fopen() is part of MSVCRT, the
+// Microsoft Visual C/C++ Runtime Library, and this method does NOT offer any
+// Unicode support.
+
+// Monero code that would want to continue to use the normal file stream classes
+// but WITH Unicode support could therefore not solve this problem on its own,
+// but 2 different projects from 2 different maintaining groups would need changes
+// in this particular direction - something probably difficult to achieve and
+// with a long time to wait until all new versions / releases arrive.
+
+// Implemented solution approach: Circumvent the problem by stopping to use std
+// file stream classes on Windows and directly use Unicode-capable WIN32 API
+// calls. Most of the code doing so is concentrated in this header file here.
+
+namespace epee
+{
+namespace file_io_utils
+{
+
+ bool is_file_exist(const std::string& path)
+ {
+ boost::filesystem::path p(path);
+ return boost::filesystem::exists(p);
+ }
+
+
+ bool save_string_to_file(const std::string& path_to_file, const std::string& str)
+ {
+#ifdef WIN32
+ std::wstring wide_path;
+ try { wide_path = string_tools::utf8_to_utf16(path_to_file); } catch (...) { return false; }
+ HANDLE file_handle = CreateFileW(wide_path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (file_handle == INVALID_HANDLE_VALUE)
+ return false;
+ DWORD bytes_written;
+ DWORD bytes_to_write = (DWORD)str.size();
+ BOOL result = WriteFile(file_handle, str.data(), bytes_to_write, &bytes_written, NULL);
+ CloseHandle(file_handle);
+ if (bytes_written != bytes_to_write)
+ result = FALSE;
+ return result;
+#else
+ try
+ {
+ std::ofstream fstream;
+ fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
+ fstream.open(path_to_file, std::ios_base::binary | std::ios_base::out | std::ios_base::trunc);
+ fstream << str;
+ fstream.close();
+ return true;
+ }
+
+ catch(...)
+ {
+ return false;
+ }
+#endif
+ }
+
+
+ bool get_file_time(const std::string& path_to_file, time_t& ft)
+ {
+ boost::system::error_code ec;
+ ft = boost::filesystem::last_write_time(boost::filesystem::path(path_to_file), ec);
+ if(!ec)
+ return true;
+ else
+ return false;
+ }
+
+
+ bool set_file_time(const std::string& path_to_file, const time_t& ft)
+ {
+ boost::system::error_code ec;
+ boost::filesystem::last_write_time(boost::filesystem::path(path_to_file), ft, ec);
+ if(!ec)
+ return true;
+ else
+ return false;
+ }
+
+
+
+ bool load_file_to_string(const std::string& path_to_file, std::string& target_str, size_t max_size)
+ {
+#ifdef WIN32
+ std::wstring wide_path;
+ try { wide_path = string_tools::utf8_to_utf16(path_to_file); } catch (...) { return false; }
+ HANDLE file_handle = CreateFileW(wide_path.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (file_handle == INVALID_HANDLE_VALUE)
+ return false;
+ DWORD file_size = GetFileSize(file_handle, NULL);
+ if ((file_size == INVALID_FILE_SIZE) || (uint64_t)file_size > (uint64_t)max_size) {
+ CloseHandle(file_handle);
+ return false;
+ }
+ target_str.resize(file_size);
+ DWORD bytes_read;
+ BOOL result = ReadFile(file_handle, &target_str[0], file_size, &bytes_read, NULL);
+ CloseHandle(file_handle);
+ if (bytes_read != file_size)
+ result = FALSE;
+ return result;
+#else
+ try
+ {
+ std::ifstream fstream;
+ fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
+ fstream.open(path_to_file, std::ios_base::binary | std::ios_base::in | std::ios::ate);
+
+ std::ifstream::pos_type file_size = fstream.tellg();
+
+ if((uint64_t)file_size > (uint64_t)max_size) // ensure a large domain for comparison, and negative -> too large
+ return false;//don't go crazy
+ size_t file_size_t = static_cast<size_t>(file_size);
+
+ target_str.resize(file_size_t);
+
+ fstream.seekg (0, std::ios::beg);
+ fstream.read((char*)target_str.data(), target_str.size());
+ fstream.close();
+ return true;
+ }
+
+ catch(...)
+ {
+ return false;
+ }
+#endif
+ }
+
+
+ bool append_string_to_file(const std::string& path_to_file, const std::string& str)
+ {
+ // No special Windows implementation because so far not used in Monero code
+ try
+ {
+ std::ofstream fstream;
+ fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
+ fstream.open(path_to_file.c_str(), std::ios_base::binary | std::ios_base::out | std::ios_base::app);
+ fstream << str;
+ fstream.close();
+ return true;
+ }
+
+ catch(...)
+ {
+ return false;
+ }
+ }
+
+
+ bool get_file_size(const std::string& path_to_file, uint64_t &size)
+ {
+#ifdef WIN32
+ std::wstring wide_path;
+ try { wide_path = string_tools::utf8_to_utf16(path_to_file); } catch (...) { return false; }
+ HANDLE file_handle = CreateFileW(wide_path.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (file_handle == INVALID_HANDLE_VALUE)
+ return false;
+ LARGE_INTEGER file_size;
+ BOOL result = GetFileSizeEx(file_handle, &file_size);
+ CloseHandle(file_handle);
+ if (result) {
+ size = file_size.QuadPart;
+ }
+ return size;
+#else
+ try
+ {
+ std::ifstream fstream;
+ fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
+ fstream.open(path_to_file, std::ios_base::binary | std::ios_base::in | std::ios::ate);
+ size = fstream.tellg();
+ fstream.close();
+ return true;
+ }
+
+ catch(...)
+ {
+ return false;
+ }
+#endif
+ }
+
+}
+}
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