diff options
author | luigi1111 <luigi1111w@gmail.com> | 2018-05-31 14:54:55 -0500 |
---|---|---|
committer | luigi1111 <luigi1111w@gmail.com> | 2018-05-31 14:54:55 -0500 |
commit | 8a7b3ff13858c5d879530c99de5c723c88429342 (patch) | |
tree | 985ab3b201002a86714731fe080b3c223f930bee | |
parent | Merge pull request #3640 (diff) | |
parent | http_protocol_handler: limit the number of starting newlines (diff) | |
download | monero-8a7b3ff13858c5d879530c99de5c723c88429342.tar.xz |
Merge pull request #3866
6a58c88 console_handler: fix start_default_console use of prompt parameter (moneromooo-monero)
885a117 http_protocol_handler: speedup newline discarding (moneromooo-monero)
4d15864 abstract_tcp_server2: timeout on RPC connections (moneromooo-monero)
dfd36bb http_protocol_handler: limit the number of starting newlines (moneromooo-monero)
-rw-r--r-- | contrib/epee/include/console_handler.h | 24 | ||||
-rw-r--r-- | contrib/epee/include/net/abstract_tcp_server2.h | 8 | ||||
-rw-r--r-- | contrib/epee/include/net/abstract_tcp_server2.inl | 61 | ||||
-rw-r--r-- | contrib/epee/include/net/http_protocol_handler.h | 1 | ||||
-rw-r--r-- | contrib/epee/include/net/http_protocol_handler.inl | 17 |
5 files changed, 105 insertions, 6 deletions
diff --git a/contrib/epee/include/console_handler.h b/contrib/epee/include/console_handler.h index 4ea3fa54b..0e22a971c 100644 --- a/contrib/epee/include/console_handler.h +++ b/contrib/epee/include/console_handler.h @@ -401,13 +401,19 @@ eof: template<class t_server, class t_handler> - bool start_default_console(t_server* ptsrv, t_handler handlr, const std::string& prompt, const std::string& usage = "") + bool start_default_console(t_server* ptsrv, t_handler handlr, std::function<std::string(void)> prompt, const std::string& usage = "") { std::shared_ptr<async_console_handler> console_handler = std::make_shared<async_console_handler>(); boost::thread([=](){console_handler->run<t_server, t_handler>(ptsrv, handlr, prompt, usage);}).detach(); return true; } + template<class t_server, class t_handler> + bool start_default_console(t_server* ptsrv, t_handler handlr, const std::string& prompt, const std::string& usage = "") + { + return start_default_console(ptsrv, handlr, [prompt](){ return prompt; }, usage); + } + template<class t_server> bool start_default_console(t_server* ptsrv, const std::string& prompt, const std::string& usage = "") { @@ -421,19 +427,31 @@ eof: } template<class t_server, class t_handler> - bool run_default_console_handler_no_srv_param(t_server* ptsrv, t_handler handlr, const std::string& prompt, const std::string& usage = "") + bool run_default_console_handler_no_srv_param(t_server* ptsrv, t_handler handlr, std::function<std::string(void)> prompt, const std::string& usage = "") { async_console_handler console_handler; return console_handler.run(ptsrv, boost::bind<bool>(no_srv_param_adapter<t_server, t_handler>, _1, _2, handlr), prompt, usage); } template<class t_server, class t_handler> - bool start_default_console_handler_no_srv_param(t_server* ptsrv, t_handler handlr, const std::string& prompt, const std::string& usage = "") + bool run_default_console_handler_no_srv_param(t_server* ptsrv, t_handler handlr, const std::string& prompt, const std::string& usage = "") + { + return run_default_console_handler_no_srv_param(ptsrv, handlr, [prompt](){return prompt;},usage); + } + + template<class t_server, class t_handler> + bool start_default_console_handler_no_srv_param(t_server* ptsrv, t_handler handlr, std::function<std::string(void)> prompt, const std::string& usage = "") { boost::thread( boost::bind(run_default_console_handler_no_srv_param<t_server, t_handler>, ptsrv, handlr, prompt, usage) ); return true; } + template<class t_server, class t_handler> + bool start_default_console_handler_no_srv_param(t_server* ptsrv, t_handler handlr, const std::string& prompt, const std::string& usage = "") + { + return start_default_console_handler_no_srv_param(ptsrv, handlr, [prompt](){return prompt;}, usage); + } + /*template<class a> bool f(int i, a l) { diff --git a/contrib/epee/include/net/abstract_tcp_server2.h b/contrib/epee/include/net/abstract_tcp_server2.h index ccde928ba..2f7325be5 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.h +++ b/contrib/epee/include/net/abstract_tcp_server2.h @@ -135,6 +135,11 @@ namespace net_utils /// Handle completion of a write operation. void handle_write(const boost::system::error_code& e, size_t cb); + /// 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; + /// Buffer for incoming data. boost::array<char, 8192> buffer_; //boost::array<char, 1024> buffer_; @@ -158,6 +163,9 @@ namespace net_utils boost::mutex m_throttle_speed_in_mutex; boost::mutex m_throttle_speed_out_mutex; + boost::asio::deadline_timer m_timer; + bool m_local; + public: void setRpcStation(); }; diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl index 52b4c85ba..91a94c21e 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.inl +++ b/contrib/epee/include/net/abstract_tcp_server2.inl @@ -44,6 +44,7 @@ #include <boost/thread/thread.hpp> // TODO #include <boost/thread/condition_variable.hpp> // TODO #include "misc_language.h" +#include "net/local_ip.h" #include "pragma_comp_defs.h" #include <sstream> @@ -55,6 +56,10 @@ #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 TIMEOUT_EXTRA_MS_PER_BYTE 0.2 + PRAGMA_WARNING_PUSH namespace epee { @@ -79,7 +84,9 @@ PRAGMA_WARNING_DISABLE_VS(4355) m_pfilter( pfilter ), m_connection_type( connection_type ), m_throttle_speed_in("speed_in", "throttle_speed_in"), - m_throttle_speed_out("speed_out", "throttle_speed_out") + m_throttle_speed_out("speed_out", "throttle_speed_out"), + m_timer(io_service), + m_local(false) { MDEBUG("test, connection constructor set m_connection_type="<<m_connection_type); } @@ -139,6 +146,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_); // create a random uuid boost::uuids::uuid random_uuid; @@ -159,6 +167,8 @@ PRAGMA_WARNING_DISABLE_VS(4355) m_protocol_handler.after_init_connection(); + reset_timer(get_default_time(), false); + socket_.async_read_some(boost::asio::buffer(buffer_), strand_.wrap( boost::bind(&connection<t_protocol_handler>::handle_read, self, @@ -304,6 +314,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) delay *= 0.5; if (delay > 0) { long int ms = (long int)(delay * 100); + reset_timer(boost::posix_time::milliseconds(ms + 1), true); boost::this_thread::sleep_for(boost::chrono::milliseconds(ms)); } } while(delay > 0); @@ -329,6 +340,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) shutdown(); }else { + reset_timer(get_timeout_from_bytes_read(bytes_transferred), false); socket_.async_read_some(boost::asio::buffer(buffer_), strand_.wrap( boost::bind(&connection<t_protocol_handler>::handle_read, connection<t_protocol_handler>::shared_from_this(), @@ -539,6 +551,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) 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); 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) @@ -557,9 +570,53 @@ PRAGMA_WARNING_DISABLE_VS(4355) } // do_send_chunk //--------------------------------------------------------------------------------- template<class t_protocol_handler> + boost::posix_time::milliseconds connection<t_protocol_handler>::get_default_time() const + { + if (m_local) + return DEFAULT_TIMEOUT_MS_LOCAL; + else + return DEFAULT_TIMEOUT_MS_REMOTE; + } + //--------------------------------------------------------------------------------- + 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 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(); + return ms; + } + //--------------------------------------------------------------------------------- + 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) + return; + MTRACE("Setting " << ms << " expiry"); + auto self = safe_shared_from_this(); + if(!self) + { + MERROR("Resetting timer on a dead object"); + return; + } + if (add) + ms += m_timer.expires_from_now(); + m_timer.expires_from_now(ms); + m_timer.async_wait([=](const boost::system::error_code& ec) + { + if(ec == boost::asio::error::operation_aborted) + return; + MDEBUG(context << "connection timeout, closing"); + self->close(); + }); + } + //--------------------------------------------------------------------------------- + template<class t_protocol_handler> bool connection<t_protocol_handler>::shutdown() { // Initiate graceful connection closure. + m_timer.cancel(); boost::system::error_code ignored_ec; socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec); m_was_shutdown = true; @@ -572,6 +629,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) { TRY_ENTRY(); //_info("[sock " << socket_.native_handle() << "] Que Shutdown called."); + m_timer.cancel(); size_t send_que_size = 0; CRITICAL_REGION_BEGIN(m_send_que_lock); send_que_size = m_send_que.size(); @@ -629,6 +687,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) }else { //have more data to send + reset_timer(get_default_time(), 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 b4485d1cd..e602fac2b 100644 --- a/contrib/epee/include/net/http_protocol_handler.h +++ b/contrib/epee/include/net/http_protocol_handler.h @@ -141,6 +141,7 @@ namespace net_utils size_t m_len_summary, m_len_remain; config_type& m_config; bool m_want_close; + size_t m_newlines; protected: i_service_endpoint* m_psnd_hndlr; }; diff --git a/contrib/epee/include/net/http_protocol_handler.inl b/contrib/epee/include/net/http_protocol_handler.inl index c18f7f706..f1da5067a 100644 --- a/contrib/epee/include/net/http_protocol_handler.inl +++ b/contrib/epee/include/net/http_protocol_handler.inl @@ -38,6 +38,7 @@ #define HTTP_MAX_URI_LEN 9000 #define HTTP_MAX_HEADER_LEN 100000 +#define HTTP_MAX_STARTING_NEWLINES 8 namespace epee { @@ -203,6 +204,7 @@ namespace net_utils m_len_remain(0), m_config(config), m_want_close(false), + m_newlines(0), m_psnd_hndlr(psnd_hndlr) { @@ -216,6 +218,7 @@ namespace net_utils m_body_transfer_type = http_body_transfer_undefined; m_query_info.clear(); m_len_summary = 0; + m_newlines = 0; return true; } //-------------------------------------------------------------------------------------------- @@ -236,6 +239,8 @@ namespace net_utils bool simple_http_connection_handler<t_connection_context>::handle_buff_in(std::string& buf) { + size_t ndel; + if(m_cache.size()) m_cache += buf; else @@ -253,11 +258,19 @@ namespace net_utils break; //check_and_handle_fake_response(); - if((m_cache[0] == '\r' || m_cache[0] == '\n')) + ndel = m_cache.find_first_not_of("\r\n"); + if (ndel != 0) { //some times it could be that before query line cold be few line breaks //so we have to be calm without panic with assers - m_cache.erase(0, 1); + m_newlines += std::string::npos == ndel ? m_cache.size() : ndel; + if (m_newlines > HTTP_MAX_STARTING_NEWLINES) + { + LOG_ERROR("simple_http_connection_handler::handle_buff_out: Too many starting newlines"); + m_state = http_state_error; + return false; + } + m_cache.erase(0, ndel); break; } |