aboutsummaryrefslogtreecommitdiff
path: root/contrib/epee/include/console_handler.h
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/epee/include/console_handler.h')
-rw-r--r--contrib/epee/include/console_handler.h310
1 files changed, 310 insertions, 0 deletions
diff --git a/contrib/epee/include/console_handler.h b/contrib/epee/include/console_handler.h
new file mode 100644
index 000000000..238abc80c
--- /dev/null
+++ b/contrib/epee/include/console_handler.h
@@ -0,0 +1,310 @@
+// 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.
+//
+
+
+
+#pragma once
+
+namespace epee
+{
+
+
+
+
+ template<class t_server>
+ bool empty_commands_handler(t_server* psrv, const std::string& command)
+ {
+ return true;
+ }
+
+
+ template<class t_server, class chain_handler>
+ bool default_console_handler(t_server* psrv, chain_handler ch_handler, const std::string usage = "")
+ {
+ TRY_ENTRY();
+ bool continue_handle = true;
+ while(continue_handle)
+ {
+ char command_buff[400] = {0};
+ std::string command;
+ std::cin.getline(command_buff, 399);
+ if(std::cin.eof() || std::cin.fail())
+ {
+ LOG_PRINT("std::cin.eof() or std::cin.fail(), stopping...", LOG_LEVEL_0);
+ continue_handle = false;
+ break;
+ }
+ command = command_buff;
+
+ if(!command.compare("exit") || !command.compare("q") )
+ {
+ psrv->send_stop_signal();
+ continue_handle = false;
+ }else if ( !command.compare(0, 7, "set_log"))
+ {
+ //parse set_log command
+ if(command.size() != 9)
+ {
+ std::cout << "wrong syntax: " << command << std::endl << "use set_log n" << std::endl;
+ continue;
+ }
+ int n = 0;
+ if(!string_tools::get_xtype_from_string(n, command.substr(8, 1)))
+ {
+ std::cout << "wrong syntax: " << command << std::endl << "use set_log n" << std::endl;
+ continue;
+ }
+ log_space::get_set_log_detalisation_level(true, n);
+ LOG_PRINT_L0("New log level set " << n);
+ }
+ else if(ch_handler(psrv, command))
+ continue;
+ else
+ {
+ std::cout << "unknown command: " << command << std::endl;
+ std::cout << usage;
+ }
+ }
+ return true;
+ CATCH_ENTRY_L0("console_handler", false);
+ }
+
+ template<class chain_handler>
+ bool default_console_handler2(chain_handler ch_handler, const std::string usage)
+ {
+ TRY_ENTRY();
+ bool continue_handle = true;
+ while(continue_handle)
+ {
+ char command_buff[400] = {0};
+ std::string command;
+ std::cin.getline(command_buff, 399);
+ if(std::cin.eof() || std::cin.fail())
+ {
+
+ LOG_PRINT("std::cin.eof() or std::cin.fail(), stopping...", LOG_LEVEL_0);
+ continue_handle = false;
+ break;
+ }
+ command = command_buff;
+
+ if(!command.compare("exit") || !command.compare("q") )
+ {
+ continue_handle = false;
+ }else if ( !command.compare(0, 7, "set_log"))
+ {
+ //parse set_log command
+ if(command.size() != 9)
+ {
+ std::cout << "wrong syntax: " << command << std::endl << "use set_log n" << std::endl;
+ continue;
+ }
+ int n = 0;
+ if(!string_tools::get_xtype_from_string(n, command.substr(8, 1)))
+ {
+ std::cout << "wrong syntax: " << command << std::endl << "use set_log n" << std::endl;
+ continue;
+ }
+ log_space::get_set_log_detalisation_level(true, n);
+ LOG_PRINT_L0("New log level set " << n);
+ }
+ else if(ch_handler(command))
+ continue;
+ else
+ {
+ std::cout << "unknown command: " << command << std::endl;
+ std::cout << usage;
+ }
+ }
+ return true;
+ CATCH_ENTRY_L0("console_handler", false);
+ }
+
+
+
+
+ template<class t_server, class t_handler>
+ bool start_default_console(t_server* ptsrv, t_handler handlr, const std::string& usage = "")
+ {
+ boost::thread( boost::bind(default_console_handler<t_server, t_handler>, ptsrv, handlr, usage) );
+ return true;
+ }
+
+ template<class t_server>
+ bool start_default_console(t_server* ptsrv, const std::string& usage = "")
+ {
+ return start_default_console(ptsrv, empty_commands_handler<t_server>, usage);
+ }
+
+ template<class t_server, class t_handler>
+ bool no_srv_param_adapter(t_server* ptsrv, const std::string& cmd, t_handler handlr)
+ {
+ return handlr(cmd);
+ }
+
+ template<class t_server, class t_handler>
+ bool run_default_console_handler_no_srv_param(t_server* ptsrv, t_handler handlr, const std::string& usage = "")
+ {
+ return default_console_handler(ptsrv, boost::bind<bool>(no_srv_param_adapter<t_server, t_handler>, _1, _2, handlr), 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& usage = "")
+ {
+ boost::thread( boost::bind(run_default_console_handler_no_srv_param<t_server, t_handler>, ptsrv, handlr, usage) );
+ return true;
+ }
+
+ /*template<class a>
+ bool f(int i, a l)
+ {
+ return true;
+ }*/
+ /*
+ template<class chain_handler>
+ bool default_console_handler2(chain_handler ch_handler, const std::string usage)
+ */
+
+
+ /*template<class t_handler>
+ bool start_default_console2(t_handler handlr, const std::string& usage = "")
+ {
+ //std::string usage_local = usage;
+ boost::thread( boost::bind(default_console_handler2<t_handler>, handlr, usage) );
+ //boost::function<bool ()> p__ = boost::bind(f<t_handler>, 1, handlr);
+ //boost::function<bool ()> p__ = boost::bind(default_console_handler2<t_handler>, handlr, usage);
+ //boost::thread tr(p__);
+ return true;
+ }*/
+
+ /************************************************************************/
+ /* */
+ /************************************************************************/
+ class console_handlers_binder
+ {
+ typedef boost::function<bool (const std::vector<std::string> &)> console_command_handler;
+ typedef std::map<std::string, std::pair<console_command_handler, std::string> > command_handlers_map;
+ std::unique_ptr<boost::thread> m_console_thread;
+ command_handlers_map m_command_handlers;
+ public:
+ std::string get_usage()
+ {
+ std::stringstream ss;
+ size_t max_command_len = 0;
+ for(auto& x:m_command_handlers)
+ if(x.first.size() > max_command_len)
+ max_command_len = x.first.size();
+
+ for(auto& x:m_command_handlers)
+ {
+ ss.width(max_command_len + 3);
+ ss << std::left << x.first << x.second.second << ENDL;
+ }
+ return ss.str();
+ }
+ void set_handler(const std::string& cmd, const console_command_handler& hndlr, const std::string& usage = "")
+ {
+ command_handlers_map::mapped_type & vt = m_command_handlers[cmd];
+ vt.first = hndlr;
+ vt.second = usage;
+ }
+ bool process_command_vec(const std::vector<std::string>& cmd)
+ {
+ if(!cmd.size())
+ return false;
+ auto it = m_command_handlers.find(cmd.front());
+ if(it == m_command_handlers.end())
+ return false;
+ std::vector<std::string> cmd_local(cmd.begin()+1, cmd.end());
+ return it->second.first(cmd_local);
+ }
+
+ bool process_command_str(const std::string& cmd)
+ {
+ std::vector<std::string> cmd_v;
+ boost::split(cmd_v,cmd,boost::is_any_of(" "), boost::token_compress_on);
+ return process_command_vec(cmd_v);
+ }
+
+ /*template<class t_srv>
+ bool start_handling(t_srv& srv, const std::string& usage_string = "")
+ {
+ start_default_console_handler_no_srv_param(&srv, boost::bind(&console_handlers_binder::process_command_str, this, _1));
+ return true;
+ }*/
+
+ bool start_handling(const std::string& usage_string = "")
+ {
+ m_console_thread.reset(new boost::thread(boost::bind(&console_handlers_binder::run_handling, this, usage_string) ));
+ return true;
+ }
+
+ bool stop_handling()
+ {
+ if(m_console_thread.get())
+ m_console_thread->interrupt();
+ return true;
+ }
+
+
+ bool run_handling(const std::string usage_string)
+ {
+ return default_console_handler2(boost::bind(&console_handlers_binder::process_command_str, this, _1), usage_string);
+ }
+
+ /*template<class t_srv>
+ bool run_handling(t_srv& srv, const std::string& usage_string)
+ {
+ return run_default_console_handler_no_srv_param(&srv, boost::bind<bool>(&console_handlers_binder::process_command_str, this, _1), usage_string);
+ }*/
+
+ };
+
+ /* work around because of broken boost bind */
+ template<class t_server>
+ class srv_console_handlers_binder: public console_handlers_binder
+ {
+ bool process_command_str(t_server* /*psrv*/, const std::string& cmd)
+ {
+ return console_handlers_binder::process_command_str(cmd);
+ }
+ public:
+ bool start_handling(t_server* psrv, const std::string& usage_string = "")
+ {
+ boost::thread(boost::bind(&srv_console_handlers_binder<t_server>::run_handling, this, psrv, usage_string) );
+ return true;
+ }
+
+ bool run_handling(t_server* psrv, const std::string usage_string)
+ {
+ return default_console_handler(psrv, boost::bind(&srv_console_handlers_binder<t_server>::process_command_str, this, _1, _2), usage_string);
+ }
+ };
+
+
+}
+
+