aboutsummaryrefslogtreecommitdiff
path: root/contrib/epee
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/epee')
-rw-r--r--contrib/epee/include/file_io_utils.h8
-rw-r--r--contrib/epee/include/misc_log_ex.h3
-rw-r--r--contrib/epee/include/net/abstract_tcp_server2.h10
-rw-r--r--contrib/epee/include/net/abstract_tcp_server2.inl80
-rw-r--r--contrib/epee/include/net/http_protocol_handler.h9
-rw-r--r--contrib/epee/include/net/http_protocol_handler.inl30
-rw-r--r--contrib/epee/include/net/local_ip.h2
-rw-r--r--contrib/epee/include/net/net_utils_base.h1
-rw-r--r--contrib/epee/include/serialization/keyvalue_serialization_overloads.h2
-rw-r--r--contrib/epee/src/mlog.cpp53
10 files changed, 152 insertions, 46 deletions
diff --git a/contrib/epee/include/file_io_utils.h b/contrib/epee/include/file_io_utils.h
index 196610674..4434f7383 100644
--- a/contrib/epee/include/file_io_utils.h
+++ b/contrib/epee/include/file_io_utils.h
@@ -28,7 +28,7 @@
#ifndef _FILE_IO_UTILS_H_
#define _FILE_IO_UTILS_H_
-#include <iostream>
+#include <fstream>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#ifdef WIN32
@@ -128,7 +128,7 @@ namespace file_io_utils
inline
- bool load_file_to_string(const std::string& path_to_file, std::string& target_str)
+ bool load_file_to_string(const std::string& path_to_file, std::string& target_str, size_t max_size = 1000000000)
{
#ifdef WIN32
WCHAR wide_path[1000];
@@ -139,7 +139,7 @@ namespace file_io_utils
if (file_handle == INVALID_HANDLE_VALUE)
return false;
DWORD file_size = GetFileSize(file_handle, NULL);
- if ((file_size == INVALID_FILE_SIZE) || (file_size > 1000000000)) {
+ if ((file_size == INVALID_FILE_SIZE) || (uint64_t)file_size > (uint64_t)max_size) {
CloseHandle(file_handle);
return false;
}
@@ -159,7 +159,7 @@ namespace file_io_utils
std::ifstream::pos_type file_size = fstream.tellg();
- if(file_size > 1000000000)
+ 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);
diff --git a/contrib/epee/include/misc_log_ex.h b/contrib/epee/include/misc_log_ex.h
index 35ec0950b..530f8e636 100644
--- a/contrib/epee/include/misc_log_ex.h
+++ b/contrib/epee/include/misc_log_ex.h
@@ -34,6 +34,7 @@
#define MONERO_DEFAULT_LOG_CATEGORY "default"
#define MAX_LOG_FILE_SIZE 104850000 // 100 MB - 7600 bytes
+#define MAX_LOG_FILES 50
#define MCFATAL(cat,x) CLOG(FATAL,cat) << x
#define MCERROR(cat,x) CLOG(ERROR,cat) << x
@@ -105,7 +106,7 @@
#endif
std::string mlog_get_default_log_path(const char *default_filename);
-void mlog_configure(const std::string &filename_base, bool console, const std::size_t max_log_file_size = MAX_LOG_FILE_SIZE);
+void mlog_configure(const std::string &filename_base, bool console, const std::size_t max_log_file_size = MAX_LOG_FILE_SIZE, const std::size_t max_log_files = MAX_LOG_FILES);
void mlog_set_categories(const char *categories);
std::string mlog_get_categories();
void mlog_set_log_level(int level);
diff --git a/contrib/epee/include/net/abstract_tcp_server2.h b/contrib/epee/include/net/abstract_tcp_server2.h
index 2f7325be5..7ca6ac872 100644
--- a/contrib/epee/include/net/abstract_tcp_server2.h
+++ b/contrib/epee/include/net/abstract_tcp_server2.h
@@ -119,6 +119,7 @@ namespace net_utils
//----------------- i_service_endpoint ---------------------
virtual bool do_send(const void* ptr, size_t cb); ///< (see do_send from i_service_endpoint)
virtual bool do_send_chunk(const void* ptr, size_t cb); ///< will send (or queue) a part of data
+ virtual bool send_done();
virtual bool close();
virtual bool call_run_once_service_io();
virtual bool request_callback();
@@ -137,8 +138,11 @@ namespace net_utils
/// reset connection timeout timer and callback
void reset_timer(boost::posix_time::milliseconds ms, bool add);
- boost::posix_time::milliseconds get_default_time() const;
- boost::posix_time::milliseconds get_timeout_from_bytes_read(size_t bytes) const;
+ boost::posix_time::milliseconds get_default_timeout();
+ boost::posix_time::milliseconds get_timeout_from_bytes_read(size_t bytes);
+
+ /// host connection count tracking
+ unsigned int host_count(const std::string &host, int delta = 0);
/// Buffer for incoming data.
boost::array<char, 8192> buffer_;
@@ -165,6 +169,8 @@ namespace net_utils
boost::asio::deadline_timer m_timer;
bool m_local;
+ bool m_ready_to_close;
+ std::string m_host;
public:
void setRpcStation();
diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl
index 91a94c21e..134bb4199 100644
--- a/contrib/epee/include/net/abstract_tcp_server2.inl
+++ b/contrib/epee/include/net/abstract_tcp_server2.inl
@@ -56,8 +56,8 @@
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "net"
-#define DEFAULT_TIMEOUT_MS_LOCAL boost::posix_time::milliseconds(120000) // 2 minutes
-#define DEFAULT_TIMEOUT_MS_REMOTE boost::posix_time::milliseconds(10000) // 10 seconds
+#define DEFAULT_TIMEOUT_MS_LOCAL 1800000 // 30 minutes
+#define DEFAULT_TIMEOUT_MS_REMOTE 300000 // 5 minutes
#define TIMEOUT_EXTRA_MS_PER_BYTE 0.2
PRAGMA_WARNING_PUSH
@@ -86,7 +86,8 @@ PRAGMA_WARNING_DISABLE_VS(4355)
m_throttle_speed_in("speed_in", "throttle_speed_in"),
m_throttle_speed_out("speed_out", "throttle_speed_out"),
m_timer(io_service),
- m_local(false)
+ m_local(false),
+ m_ready_to_close(false)
{
MDEBUG("test, connection constructor set m_connection_type="<<m_connection_type);
}
@@ -146,7 +147,7 @@ PRAGMA_WARNING_DISABLE_VS(4355)
context = boost::value_initialized<t_connection_context>();
const unsigned long ip_{boost::asio::detail::socket_ops::host_to_network_long(remote_ep.address().to_v4().to_ulong())};
- m_local = epee::net_utils::is_ip_loopback(ip_);
+ m_local = epee::net_utils::is_ip_loopback(ip_) || epee::net_utils::is_ip_local(ip_);
// create a random uuid
boost::uuids::uuid random_uuid;
@@ -165,9 +166,12 @@ PRAGMA_WARNING_DISABLE_VS(4355)
return false;
}
+ m_host = context.m_remote_address.host_str();
+ try { host_count(m_host, 1); } catch(...) { /* ignore */ }
+
m_protocol_handler.after_init_connection();
- reset_timer(get_default_time(), false);
+ reset_timer(get_default_timeout(), false);
socket_.async_read_some(boost::asio::buffer(buffer_),
strand_.wrap(
@@ -324,6 +328,7 @@ PRAGMA_WARNING_DISABLE_VS(4355)
logger_handle_net_read(bytes_transferred);
context.m_last_recv = time(NULL);
context.m_recv_cnt += bytes_transferred;
+ m_ready_to_close = false;
bool recv_res = m_protocol_handler.handle_recv(buffer_.data(), bytes_transferred);
if(!recv_res)
{
@@ -356,6 +361,13 @@ PRAGMA_WARNING_DISABLE_VS(4355)
_dbg3("[sock " << socket_.native_handle() << "] Some problems at read: " << e.message() << ':' << e.value());
shutdown();
}
+ else
+ {
+ _dbg3("[sock " << socket_.native_handle() << "] peer closed connection");
+ if (m_ready_to_close)
+ shutdown();
+ }
+ m_ready_to_close = true;
}
// If an error occurs then no new asynchronous operations are started. This
// means that all shared_ptr references to the connection object will
@@ -531,7 +543,7 @@ PRAGMA_WARNING_DISABLE_VS(4355)
if(m_send_que.size() > 1)
{ // active operation should be in progress, nothing to do, just wait last operation callback
auto size_now = cb;
- MDEBUG("do_send() NOW just queues: packet="<<size_now<<" B, is added to queue-size="<<m_send_que.size());
+ MDEBUG("do_send_chunk() NOW just queues: packet="<<size_now<<" B, is added to queue-size="<<m_send_que.size());
//do_send_handler_delayed( ptr , size_now ); // (((H))) // empty function
LOG_TRACE_CC(context, "[sock " << socket_.native_handle() << "] Async send requested " << m_send_que.front().size());
@@ -546,12 +558,12 @@ PRAGMA_WARNING_DISABLE_VS(4355)
}
auto size_now = m_send_que.front().size();
- MDEBUG("do_send() NOW SENSD: packet="<<size_now<<" B");
+ MDEBUG("do_send_chunk() NOW SENSD: packet="<<size_now<<" B");
if (speed_limit_is_enabled())
do_send_handler_write( ptr , size_now ); // (((H)))
CHECK_AND_ASSERT_MES( size_now == m_send_que.front().size(), false, "Unexpected queue size");
- reset_timer(get_default_time(), false);
+ reset_timer(get_default_timeout(), false);
boost::asio::async_write(socket_, boost::asio::buffer(m_send_que.front().data(), size_now ) ,
//strand_.wrap(
boost::bind(&connection<t_protocol_handler>::handle_write, self, _1, _2)
@@ -566,29 +578,51 @@ PRAGMA_WARNING_DISABLE_VS(4355)
return true;
- CATCH_ENTRY_L0("connection<t_protocol_handler>::do_send", false);
+ CATCH_ENTRY_L0("connection<t_protocol_handler>::do_send_chunk", false);
} // do_send_chunk
//---------------------------------------------------------------------------------
template<class t_protocol_handler>
- boost::posix_time::milliseconds connection<t_protocol_handler>::get_default_time() const
+ boost::posix_time::milliseconds connection<t_protocol_handler>::get_default_timeout()
{
+ unsigned count;
+ try { count = host_count(m_host); } catch (...) { count = 0; }
+ const unsigned shift = std::min(std::max(count, 1u) - 1, 8u);
+ boost::posix_time::milliseconds timeout(0);
if (m_local)
- return DEFAULT_TIMEOUT_MS_LOCAL;
+ timeout = boost::posix_time::milliseconds(DEFAULT_TIMEOUT_MS_LOCAL >> shift);
else
- return DEFAULT_TIMEOUT_MS_REMOTE;
+ timeout = boost::posix_time::milliseconds(DEFAULT_TIMEOUT_MS_REMOTE >> shift);
+ return timeout;
}
//---------------------------------------------------------------------------------
template<class t_protocol_handler>
- boost::posix_time::milliseconds connection<t_protocol_handler>::get_timeout_from_bytes_read(size_t bytes) const
+ boost::posix_time::milliseconds connection<t_protocol_handler>::get_timeout_from_bytes_read(size_t bytes)
{
boost::posix_time::milliseconds ms = (boost::posix_time::milliseconds)(unsigned)(bytes * TIMEOUT_EXTRA_MS_PER_BYTE);
ms += m_timer.expires_from_now();
- if (ms > get_default_time())
- ms = get_default_time();
+ if (ms > get_default_timeout())
+ ms = get_default_timeout();
return ms;
}
//---------------------------------------------------------------------------------
template<class t_protocol_handler>
+ unsigned int connection<t_protocol_handler>::host_count(const std::string &host, int delta)
+ {
+ static boost::mutex hosts_mutex;
+ CRITICAL_REGION_LOCAL(hosts_mutex);
+ static std::map<std::string, unsigned int> hosts;
+ unsigned int &val = hosts[host];
+ if (delta > 0)
+ MTRACE("New connection from host " << host << ": " << val);
+ else if (delta < 0)
+ MTRACE("Closed connection from host " << host << ": " << val);
+ CHECK_AND_ASSERT_THROW_MES(delta >= 0 || val >= (unsigned)-delta, "Count would go negative");
+ CHECK_AND_ASSERT_THROW_MES(delta <= 0 || val <= std::numeric_limits<unsigned int>::max() - (unsigned)delta, "Count would wrap");
+ val += delta;
+ return val;
+ }
+ //---------------------------------------------------------------------------------
+ template<class t_protocol_handler>
void connection<t_protocol_handler>::reset_timer(boost::posix_time::milliseconds ms, bool add)
{
if (m_connection_type != e_connection_type_RPC)
@@ -621,6 +655,11 @@ PRAGMA_WARNING_DISABLE_VS(4355)
socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec);
m_was_shutdown = true;
m_protocol_handler.release_protocol();
+ if (!m_host.empty())
+ {
+ try { host_count(m_host, -1); } catch (...) { /* ignore */ }
+ m_host = "";
+ }
return true;
}
//---------------------------------------------------------------------------------
@@ -645,6 +684,15 @@ PRAGMA_WARNING_DISABLE_VS(4355)
}
//---------------------------------------------------------------------------------
template<class t_protocol_handler>
+ bool connection<t_protocol_handler>::send_done()
+ {
+ if (m_ready_to_close)
+ return close();
+ m_ready_to_close = true;
+ return true;
+ }
+ //---------------------------------------------------------------------------------
+ template<class t_protocol_handler>
bool connection<t_protocol_handler>::cancel()
{
return close();
@@ -687,7 +735,7 @@ PRAGMA_WARNING_DISABLE_VS(4355)
}else
{
//have more data to send
- reset_timer(get_default_time(), false);
+ reset_timer(get_default_timeout(), false);
auto size_now = m_send_que.front().size();
MDEBUG("handle_write() NOW SENDS: packet="<<size_now<<" B" <<", from queue size="<<m_send_que.size());
if (speed_limit_is_enabled())
diff --git a/contrib/epee/include/net/http_protocol_handler.h b/contrib/epee/include/net/http_protocol_handler.h
index e602fac2b..1780f2393 100644
--- a/contrib/epee/include/net/http_protocol_handler.h
+++ b/contrib/epee/include/net/http_protocol_handler.h
@@ -69,7 +69,7 @@ namespace net_utils
typedef t_connection_context connection_context;//t_connection_context net_utils::connection_context_base connection_context;
typedef http_server_config config_type;
- simple_http_connection_handler(i_service_endpoint* psnd_hndlr, config_type& config);
+ simple_http_connection_handler(i_service_endpoint* psnd_hndlr, config_type& config, t_connection_context& conn_context);
virtual ~simple_http_connection_handler(){}
bool release_protocol()
@@ -144,6 +144,7 @@ namespace net_utils
size_t m_newlines;
protected:
i_service_endpoint* m_psnd_hndlr;
+ t_connection_context& m_conn_context;
};
template<class t_connection_context>
@@ -175,9 +176,8 @@ namespace net_utils
typedef custum_handler_config<t_connection_context> config_type;
http_custom_handler(i_service_endpoint* psnd_hndlr, config_type& config, t_connection_context& conn_context)
- : simple_http_connection_handler<t_connection_context>(psnd_hndlr, config),
+ : simple_http_connection_handler<t_connection_context>(psnd_hndlr, config, conn_context),
m_config(config),
- m_conn_context(conn_context),
m_auth(m_config.m_user ? http_server_auth{*m_config.m_user, config.rng} : http_server_auth{})
{}
inline bool handle_request(const http_request_info& query_info, http_response_info& response)
@@ -197,7 +197,7 @@ namespace net_utils
response.m_response_comment = "OK";
response.m_body.clear();
- return m_config.m_phandler->handle_http_request(query_info, response, m_conn_context);
+ return m_config.m_phandler->handle_http_request(query_info, response, this->m_conn_context);
}
virtual bool thread_init()
@@ -219,7 +219,6 @@ namespace net_utils
private:
//simple_http_connection_handler::config_type m_stub_config;
config_type& m_config;
- t_connection_context& m_conn_context;
http_server_auth m_auth;
};
}
diff --git a/contrib/epee/include/net/http_protocol_handler.inl b/contrib/epee/include/net/http_protocol_handler.inl
index f1da5067a..0bdba0bfe 100644
--- a/contrib/epee/include/net/http_protocol_handler.inl
+++ b/contrib/epee/include/net/http_protocol_handler.inl
@@ -196,16 +196,17 @@ namespace net_utils
//--------------------------------------------------------------------------------------------
template<class t_connection_context>
- simple_http_connection_handler<t_connection_context>::simple_http_connection_handler(i_service_endpoint* psnd_hndlr, config_type& config):
+ simple_http_connection_handler<t_connection_context>::simple_http_connection_handler(i_service_endpoint* psnd_hndlr, config_type& config, t_connection_context& conn_context):
m_state(http_state_retriving_comand_line),
m_body_transfer_type(http_body_transfer_undefined),
- m_is_stop_handling(false),
+ m_is_stop_handling(false),
m_len_summary(0),
m_len_remain(0),
- m_config(config),
+ m_config(config),
m_want_close(false),
m_newlines(0),
- m_psnd_hndlr(psnd_hndlr)
+ m_psnd_hndlr(psnd_hndlr),
+ m_conn_context(conn_context)
{
}
@@ -281,7 +282,7 @@ namespace net_utils
m_is_stop_handling = true;
if(m_cache.size() > HTTP_MAX_URI_LEN)
{
- LOG_ERROR("simple_http_connection_handler::handle_buff_out: Too long URI line");
+ LOG_ERROR_CC(m_conn_context, "simple_http_connection_handler::handle_buff_out: Too long URI line");
m_state = http_state_error;
return false;
}
@@ -295,7 +296,7 @@ namespace net_utils
m_is_stop_handling = true;
if(m_cache.size() > HTTP_MAX_HEADER_LEN)
{
- LOG_ERROR("simple_http_connection_handler::handle_buff_in: Too long header area");
+ LOG_ERROR_CC(m_conn_context, "simple_http_connection_handler::handle_buff_in: Too long header area");
m_state = http_state_error;
return false;
}
@@ -310,10 +311,10 @@ namespace net_utils
case http_state_connection_close:
return false;
default:
- LOG_ERROR("simple_http_connection_handler::handle_char_out: Wrong state: " << m_state);
+ LOG_ERROR_CC(m_conn_context, "simple_http_connection_handler::handle_char_out: Wrong state: " << m_state);
return false;
case http_state_error:
- LOG_ERROR("simple_http_connection_handler::handle_char_out: Error state!!!");
+ LOG_ERROR_CC(m_conn_context, "simple_http_connection_handler::handle_char_out: Error state!!!");
return false;
}
@@ -375,7 +376,7 @@ namespace net_utils
}else
{
m_state = http_state_error;
- LOG_ERROR("simple_http_connection_handler<t_connection_context>::handle_invoke_query_line(): Failed to match first line: " << m_cache);
+ LOG_ERROR_CC(m_conn_context, "simple_http_connection_handler<t_connection_context>::handle_invoke_query_line(): Failed to match first line: " << m_cache);
return false;
}
@@ -399,14 +400,14 @@ namespace net_utils
template<class t_connection_context>
bool simple_http_connection_handler<t_connection_context>::analize_cached_request_header_and_invoke_state(size_t pos)
{
- //LOG_PRINT_L4("HTTP HEAD:\r\n" << m_cache.substr(0, pos));
+ LOG_PRINT_L3("HTTP HEAD:\r\n" << m_cache.substr(0, pos));
m_query_info.m_full_request_buf_size = pos;
m_query_info.m_request_head.assign(m_cache.begin(), m_cache.begin()+pos);
if(!parse_cached_header(m_query_info.m_header_info, m_cache, pos))
{
- LOG_ERROR("simple_http_connection_handler<t_connection_context>::analize_cached_request_header_and_invoke_state(): failed to anilize request header: " << m_cache);
+ LOG_ERROR_CC(m_conn_context, "simple_http_connection_handler<t_connection_context>::analize_cached_request_header_and_invoke_state(): failed to anilize request header: " << m_cache);
m_state = http_state_error;
return false;
}
@@ -422,7 +423,7 @@ namespace net_utils
m_body_transfer_type = http_body_transfer_measure;
if(!get_len_from_content_lenght(m_query_info.m_header_info.m_content_length, m_len_summary))
{
- LOG_ERROR("simple_http_connection_handler<t_connection_context>::analize_cached_request_header_and_invoke_state(): Failed to get_len_from_content_lenght();, m_query_info.m_content_length="<<m_query_info.m_header_info.m_content_length);
+ LOG_ERROR_CC(m_conn_context, "simple_http_connection_handler<t_connection_context>::analize_cached_request_header_and_invoke_state(): Failed to get_len_from_content_lenght();, m_query_info.m_content_length="<<m_query_info.m_header_info.m_content_length);
m_state = http_state_error;
return false;
}
@@ -455,7 +456,7 @@ namespace net_utils
case http_body_transfer_multipart:
case http_body_transfer_undefined:
default:
- LOG_ERROR("simple_http_connection_handler<t_connection_context>::handle_retriving_query_body(): Unexpected m_body_query_type state:" << m_body_transfer_type);
+ LOG_ERROR_CC(m_conn_context, "simple_http_connection_handler<t_connection_context>::handle_retriving_query_body(): Unexpected m_body_query_type state:" << m_body_transfer_type);
m_state = http_state_error;
return false;
}
@@ -536,7 +537,7 @@ namespace net_utils
body_info.m_etc_fields.push_back(std::pair<std::string, std::string>(result[field_etc_name], result[field_val]));
else
{
- LOG_ERROR("simple_http_connection_handler<t_connection_context>::parse_cached_header() not matched last entry in:"<<m_cache_to_process);
+ LOG_ERROR_CC(m_conn_context, "simple_http_connection_handler<t_connection_context>::parse_cached_header() not matched last entry in:" << m_cache_to_process);
}
it_current_bound = result[(int)result.size()-1]. first;
@@ -582,6 +583,7 @@ namespace net_utils
m_psnd_hndlr->do_send((void*)response_data.data(), response_data.size());
if ((response.m_body.size() && (query_info.m_http_method != http::http_method_head)) || (query_info.m_http_method == http::http_method_options))
m_psnd_hndlr->do_send((void*)response.m_body.data(), response.m_body.size());
+ m_psnd_hndlr->send_done();
return res;
}
//-----------------------------------------------------------------------------------
diff --git a/contrib/epee/include/net/local_ip.h b/contrib/epee/include/net/local_ip.h
index 0d458963c..52c5855b9 100644
--- a/contrib/epee/include/net/local_ip.h
+++ b/contrib/epee/include/net/local_ip.h
@@ -48,7 +48,7 @@ namespace epee
if( (ip | 0xffffff00) == 0xffffffac)
{
- uint32_t second_num = (ip << 8) & 0xff000000;
+ uint32_t second_num = (ip >> 8) & 0xff;
if(second_num >= 16 && second_num <= 31 )
return true;
}
diff --git a/contrib/epee/include/net/net_utils_base.h b/contrib/epee/include/net/net_utils_base.h
index 7615786be..a133942fb 100644
--- a/contrib/epee/include/net/net_utils_base.h
+++ b/contrib/epee/include/net/net_utils_base.h
@@ -281,6 +281,7 @@ namespace net_utils
{
virtual bool do_send(const void* ptr, size_t cb)=0;
virtual bool close()=0;
+ virtual bool send_done()=0;
virtual bool call_run_once_service_io()=0;
virtual bool request_callback()=0;
virtual boost::asio::io_service& get_io_service()=0;
diff --git a/contrib/epee/include/serialization/keyvalue_serialization_overloads.h b/contrib/epee/include/serialization/keyvalue_serialization_overloads.h
index 7087136cc..09087f785 100644
--- a/contrib/epee/include/serialization/keyvalue_serialization_overloads.h
+++ b/contrib/epee/include/serialization/keyvalue_serialization_overloads.h
@@ -156,7 +156,7 @@ namespace epee
typename stl_container::value_type* pelem = (typename stl_container::value_type*)buff.data();
CHECK_AND_ASSERT_MES(!(loaded_size%sizeof(typename stl_container::value_type)),
false,
- "size in blob " << loaded_size << " not have not zero modulo for sizeof(value_type) = " << sizeof(typename stl_container::value_type));
+ "size in blob " << loaded_size << " not have not zero modulo for sizeof(value_type) = " << sizeof(typename stl_container::value_type) << ", type " << typeid(typename stl_container::value_type).name());
size_t count = (loaded_size/sizeof(typename stl_container::value_type));
for(size_t i = 0; i < count; i++)
container.insert(container.end(), *(pelem++));
diff --git a/contrib/epee/src/mlog.cpp b/contrib/epee/src/mlog.cpp
index 0c810729d..e8248c958 100644
--- a/contrib/epee/src/mlog.cpp
+++ b/contrib/epee/src/mlog.cpp
@@ -117,7 +117,7 @@ static const char *get_default_categories(int level)
return categories;
}
-void mlog_configure(const std::string &filename_base, bool console, const std::size_t max_log_file_size)
+void mlog_configure(const std::string &filename_base, bool console, const std::size_t max_log_file_size, const std::size_t max_log_files)
{
el::Configurations c;
c.setGlobally(el::ConfigurationType::Filename, filename_base);
@@ -135,9 +135,58 @@ void mlog_configure(const std::string &filename_base, bool console, const std::s
el::Loggers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog);
el::Loggers::addFlag(el::LoggingFlag::ColoredTerminalOutput);
el::Loggers::addFlag(el::LoggingFlag::StrictLogFileSizeCheck);
- el::Helpers::installPreRollOutCallback([filename_base](const char *name, size_t){
+ el::Helpers::installPreRollOutCallback([filename_base, max_log_files](const char *name, size_t){
std::string rname = generate_log_filename(filename_base.c_str());
rename(name, rname.c_str());
+ if (max_log_files != 0)
+ {
+ std::vector<boost::filesystem::path> found_files;
+ const boost::filesystem::directory_iterator end_itr;
+ for (boost::filesystem::directory_iterator iter(boost::filesystem::path(filename_base).parent_path()); iter != end_itr; ++iter)
+ {
+ const std::string filename = iter->path().string();
+ if (filename.size() >= filename_base.size() && std::memcmp(filename.data(), filename_base.data(), filename_base.size()) == 0)
+ {
+ found_files.push_back(iter->path());
+ }
+ }
+ if (found_files.size() >= max_log_files)
+ {
+ std::sort(found_files.begin(), found_files.end(), [](const boost::filesystem::path &a, const boost::filesystem::path &b) {
+ boost::system::error_code ec;
+ std::time_t ta = boost::filesystem::last_write_time(boost::filesystem::path(a), ec);
+ if (ec)
+ {
+ MERROR("Failed to get timestamp from " << a << ": " << ec);
+ ta = std::time(nullptr);
+ }
+ std::time_t tb = boost::filesystem::last_write_time(boost::filesystem::path(b), ec);
+ if (ec)
+ {
+ MERROR("Failed to get timestamp from " << b << ": " << ec);
+ tb = std::time(nullptr);
+ }
+ static_assert(std::is_integral<time_t>(), "bad time_t");
+ return ta < tb;
+ });
+ for (size_t i = 0; i <= found_files.size() - max_log_files; ++i)
+ {
+ try
+ {
+ boost::system::error_code ec;
+ boost::filesystem::remove(found_files[i], ec);
+ if (ec)
+ {
+ MERROR("Failed to remove " << found_files[i] << ": " << ec);
+ }
+ }
+ catch (const std::exception &e)
+ {
+ MERROR("Failed to remove " << found_files[i] << ": " << e.what());
+ }
+ }
+ }
+ }
});
mlog_set_common_prefix();
const char *monero_log = getenv("MONERO_LOGS");