// 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 bool empty_commands_handler(t_server* psrv, const std::string& command) { return true; } template 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 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 bool start_default_console(t_server* ptsrv, t_handler handlr, const std::string& usage = "") { boost::thread( boost::bind(default_console_handler, ptsrv, handlr, usage) ); return true; } template bool start_default_console(t_server* ptsrv, const std::string& usage = "") { return start_default_console(ptsrv, empty_commands_handler, usage); } template bool no_srv_param_adapter(t_server* ptsrv, const std::string& cmd, t_handler handlr) { return handlr(cmd); } template 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(no_srv_param_adapter, _1, _2, handlr), usage); } template 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, ptsrv, handlr, usage) ); return true; } /*template bool f(int i, a l) { return true; }*/ /* template bool default_console_handler2(chain_handler ch_handler, const std::string usage) */ /*template bool start_default_console2(t_handler handlr, const std::string& usage = "") { //std::string usage_local = usage; boost::thread( boost::bind(default_console_handler2, handlr, usage) ); //boost::function p__ = boost::bind(f, 1, handlr); //boost::function p__ = boost::bind(default_console_handler2, handlr, usage); //boost::thread tr(p__); return true; }*/ /************************************************************************/ /* */ /************************************************************************/ class console_handlers_binder { typedef boost::function &)> console_command_handler; typedef std::map > command_handlers_map; std::unique_ptr 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& cmd) { if(!cmd.size()) return false; auto it = m_command_handlers.find(cmd.front()); if(it == m_command_handlers.end()) return false; std::vector cmd_local(cmd.begin()+1, cmd.end()); return it->second.first(cmd_local); } bool process_command_str(const std::string& cmd) { std::vector cmd_v; boost::split(cmd_v,cmd,boost::is_any_of(" "), boost::token_compress_on); return process_command_vec(cmd_v); } /*template 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 bool run_handling(t_srv& srv, const std::string& usage_string) { return run_default_console_handler_no_srv_param(&srv, boost::bind(&console_handlers_binder::process_command_str, this, _1), usage_string); }*/ }; /* work around because of broken boost bind */ template 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::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::process_command_str, this, _1, _2), usage_string); } }; }