std::ostream & output)
{
# warning Implement Executor::operator()
- SENF_LOG(( "Executing '" << command.commandPath() << "'" ));
+ SENF_LOG(( "Executing: " << command ));
return true;
}
#include "Parse.ih"
// Custom includes
+#include "../Utils/String.hh"
#include <boost/iterator/transform_iterator.hpp>
//#include "Parse.mpp"
static void init(ParseCommandInfo & info)
{ info.init(); }
- static void setCommand(ParseCommandInfo & info, std::string const & commandPath)
+ static void setBuiltin(ParseCommandInfo & info, ParseCommandInfo::BuiltinCommand builtin)
+ { info.setBuiltin(builtin); }
+
+ static void setCommand(ParseCommandInfo & info, std::vector<std::string> & commandPath)
{ info.setCommand(commandPath); }
static void startArgument(ParseCommandInfo & info)
ParseDispatcher & dispatcher;
};
- void beginCommand(std::string const & command)
+ void beginCommand(std::vector<std::string> & command)
{ ParserAccess::init(info());
ParserAccess::setCommand(info(), command); }
void pushWord(std::string const & token)
{ ParserAccess::addToken(info(), ParserAccess::makeToken(token)); }
+
+ void builtin_cd(std::vector<std::string> & path)
+ { ParserAccess::init(info());
+ ParserAccess::setBuiltin(info(), ParseCommandInfo::BuiltinCD);
+ setBuiltinPathArg(path);
+ ParserAccess::finalize(info()); }
+
+ void builtin_ls(std::vector<std::string> & path)
+ { ParserAccess::init(info());
+ ParserAccess::setBuiltin(info(), ParseCommandInfo::BuiltinLS);
+ setBuiltinPathArg(path);
+ ParserAccess::finalize(info()); }
+
+ void setBuiltinPathArg(std::vector<std::string> & path)
+ {
+ ParserAccess::startArgument(info());
+ for (std::vector<std::string>::const_iterator i (path.begin());
+ i != path.end(); ++i)
+ ParserAccess::addToken(info(), ParserAccess::makeToken(*i));
+ ParserAccess::endArgument(info());
+ }
};
}}}
tempArguments_.clear();
}
+prefix_ std::ostream & senf::console::operator<<(std::ostream & stream,
+ ParseCommandInfo const & info)
+{
+ if (info.builtin() == ParseCommandInfo::NoBuiltin)
+ stream << senf::stringJoin(info.commandPath(), "/");
+ else {
+ char const * builtins[] = { "", "cd", "ls" };
+ stream << "builtin-" << builtins[info.builtin()];
+ }
+
+ ParseCommandInfo::ArgumentsRange args (info.arguments());
+ for (ParseCommandInfo::argument_iterator i (args.begin()); i != args.end(); ++i) {
+ ParseCommandInfo::token_iterator j (i->begin());
+ stream << " [";
+ if ( j != i->end() ) {
+ for (;;) {
+ stream << "'" << j->value() << "'";
+ if ( ++j != i->end() ) stream << ' ';
+ else break;
+ }
+ }
+ stream << "]";
+ }
+
+ return stream;
+}
+
///////////////////////////////////////////////////////////////////////////
// senf::console::SingleCommandParser
struct senf::console::SingleCommandParser::Impl
{
+ typedef detail::CommandGrammar<detail::ParseDispatcher> Grammar;
+
detail::ParseDispatcher dispatcher;
- detail::CommandGrammar<detail::ParseDispatcher>::Context context;
- detail::CommandGrammar<detail::ParseDispatcher> grammar;
- detail::SkipGrammar skipGrammar;
+ Grammar::Context context;
+ Grammar grammar;
Impl() : dispatcher(), context(), grammar(dispatcher, context) {}
};
ParseCommandInfo & info)
{
detail::ParseDispatcher::BindInfo bind (impl().dispatcher, info);
- return boost::spirit::parse( command.c_str(), impl().grammar, impl().skipGrammar ).full;
+ return boost::spirit::parse( command.c_str(),
+ impl().grammar.use_parser<Impl::Grammar::CommandParser>(),
+ impl().grammar.use_parser<Impl::Grammar::SkipParser>()
+ ).full;
}
///////////////////////////////cc.e////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// senf::console::ParseCommandInfo
-prefix_ std::string const & senf::console::ParseCommandInfo::commandPath()
+prefix_ senf::console::ParseCommandInfo::BuiltinCommand
+senf::console::ParseCommandInfo::builtin()
const
{
- return commandPath_;
+ return builtin_;
}
-prefix_ senf::console::ParseCommandInfo::size_type senf::console::ParseCommandInfo::arguments()
+prefix_ senf::console::ParseCommandInfo::CommandPathRange
+senf::console::ParseCommandInfo::commandPath()
const
{
- return arguments_.size();
+ return boost::make_iterator_range(commandPath_.begin(), commandPath_.end());
}
-prefix_ senf::console::ParseCommandInfo::argument_iterator
-senf::console::ParseCommandInfo::begin_arguments()
+prefix_ senf::console::ParseCommandInfo::ArgumentsRange
+senf::console::ParseCommandInfo::arguments()
const
{
- return arguments_.begin();
+ return boost::make_iterator_range(arguments_.begin(), arguments_.end());
}
-prefix_ senf::console::ParseCommandInfo::argument_iterator
-senf::console::ParseCommandInfo::end_arguments()
+prefix_ senf::console::ParseCommandInfo::TokensRange senf::console::ParseCommandInfo::tokens()
const
{
- return arguments_.end();
-}
-
-prefix_ senf::console::ParseCommandInfo::size_type senf::console::ParseCommandInfo::tokens()
- const
-{
- return tokens_.size();
-}
-
-prefix_ senf::console::ParseCommandInfo::token_iterator
-senf::console::ParseCommandInfo::begin_tokens()
- const
-{
- return tokens_.begin();
-}
-
-prefix_ senf::console::ParseCommandInfo::token_iterator
-senf::console::ParseCommandInfo::end_tokens()
- const
-{
- return tokens_.end();
+ return boost::make_iterator_range(tokens_.begin(), tokens_.end());
}
////////////////////////////////////////
prefix_ void senf::console::ParseCommandInfo::init()
{
- commandPath_ = "";
+ builtin_ = NoBuiltin;
+ commandPath_.clear();
tokens_.clear();
arguments_.clear();
tempArguments_.clear();
}
-prefix_ void senf::console::ParseCommandInfo::setCommand(std::string const & commandPath)
+prefix_ void senf::console::ParseCommandInfo::setBuiltin(BuiltinCommand builtin)
+{
+ builtin_ = builtin;
+}
+
+prefix_ void
+senf::console::ParseCommandInfo::setCommand(std::vector<std::string> & commandPath)
{
- commandPath_ = commandPath;
+ commandPath_.clear();
+ commandPath_.swap(commandPath);
}
prefix_ void senf::console::ParseCommandInfo::startArgument()
class ParseCommandInfo
{
typedef std::vector<ArgumentToken> Tokens;
+ typedef std::vector<std::string> CommandPath;
public:
+ typedef CommandPath::const_iterator path_iterator;
typedef Tokens::const_iterator token_iterator;
typedef boost::iterator_range<token_iterator> argument_value_type;
+
private:
typedef std::vector<argument_value_type> Arguments;
typedef Arguments::const_iterator argument_iterator;
typedef Arguments::size_type size_type;
- std::string const & commandPath() const;
-
- size_type arguments() const;
- argument_iterator begin_arguments() const;
- argument_iterator end_arguments() const;
-
- size_type tokens() const;
- token_iterator begin_tokens() const;
- token_iterator end_tokens() const;
+ typedef boost::iterator_range<path_iterator> CommandPathRange;
+ typedef boost::iterator_range<argument_iterator> ArgumentsRange;
+ typedef boost::iterator_range<token_iterator> TokensRange;
+
+ enum BuiltinCommand { NoBuiltin, BuiltinCD, BuiltinLS };
+
+ BuiltinCommand builtin() const;
+ CommandPathRange commandPath() const;
+ ArgumentsRange arguments() const;
+ TokensRange tokens() const;
protected:
private:
void init();
- void setCommand(std::string const & commandPath);
+ void setBuiltin(BuiltinCommand builtin);
+ void setCommand(std::vector<std::string> & commandPath);
void startArgument();
void endArgument();
void addToken(ArgumentToken const & token);
struct MakeRange;
- std::string commandPath_;
+ std::vector<std::string> commandPath_;
typedef std::pair<Tokens::size_type, Tokens::size_type> TempArgumentRange;
typedef std::vector<TempArgumentRange> TempArguments;
+ BuiltinCommand builtin_;
Tokens tokens_;
Arguments arguments_;
TempArguments tempArguments_;
friend class detail::ParserAccess;
};
+ std::ostream & operator<<(std::ostream & stream, ParseCommandInfo const & info);
+
/** \brief
*/
class SingleCommandParser
#define IH_Parse_ 1
// Custom includes
+#include <vector>
#include <boost/regex.hpp>
#include <boost/spirit.hpp>
-#include <boost/spirit/utility/regex.hpp>
+#include <boost/spirit/utility/grammar_def.hpp>
#include <boost/spirit/actor.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>
struct CommandGrammar : boost::spirit::grammar<CommandGrammar<ParseDispatcher> >
{
///////////////////////////////////////////////////////////////////////////
+ // Start rules
+
+ enum { CommandParser, SkipParser };
+
+ ///////////////////////////////////////////////////////////////////////////
// The parse context (variables needed while parsing)
struct Context {
std::string str;
+ std::vector<std::string> path;
char ch;
};
: context(c), dispatcher(d) {}
template <class Scanner>
- struct definition
+ struct definition
+ : public boost::spirit::grammar_def< boost::spirit::rule<Scanner>,
+ boost::spirit::rule<Scanner> >
{
boost::spirit::rule<Scanner> command, path, argument, word, string, hexstring, token;
boost::spirit::rule<Scanner> punctuation, hexbyte, balanced_tokens, simple_argument;
- boost::spirit::rule<Scanner> complex_argument;
+ boost::spirit::rule<Scanner> complex_argument, builtin, skip;
+
+ boost::spirit::chset<> special_p, punctuation_p, space_p, invalid_p, word_p;
+
+ boost::spirit::distinct_parser<> keyword_p;
+
+ definition(CommandGrammar const & self) :
+
+ // Characters with a special meaning within the parser
+ // and characters reserved for future extensions
+ special_p ("/(){};"),
- definition(CommandGrammar const & self) {
+ // Characters which are returned as punctuation tokens
+ punctuation_p (",="),
+
+ // Whitespace characters (we don't want newlines in there)
+ space_p (" \t"),
+
+ // Invalid characters: All chars below \x20 (space) which are not space_p
+ // (don't put a \0 in the chset<> argument *string* ...)
+ invalid_p (
+ boost::spirit::chset<>('\0') | boost::spirit::chset<>("\x01-\x20") - space_p ),
+
+ // Valid word characters
+ word_p (
+ boost::spirit::anychar_p - special_p - punctuation_p - space_p - invalid_p),
+
+ // Keywords must not be followed by a word char or '/'
+ keyword_p ( word_p | boost::spirit::ch_p('/') )
+
+ {
using namespace boost::spirit;
typedef ParseDispatcher PD;
-
+
+ builtin
+ = keyword_p("cd")
+ >> path
+ >> eps_p [ self.dispatch(&PD::builtin_cd,
+ boost::ref(self.context.path)) ]
+ | keyword_p("ls")
+ >> ! path
+ >> eps_p [ self.dispatch(&PD::builtin_cd,
+ boost::ref(self.context.path)) ]
+ ;
+
command
- = path [ self.dispatch(&PD::beginCommand,
- boost::cref(self.context.str)) ]
+ = builtin
+ | path [ self.dispatch(&PD::beginCommand,
+ boost::ref(self.context.path)) ]
>> * argument
>> ! ch_p(';')
>> eps_p [ self.dispatch(&PD::endCommand) ]
argument
= simple_argument [ self.dispatch(&PD::pushArgument,
- boost::cref(self.context.str)) ]
+ boost::ref(self.context.str)) ]
| complex_argument
;
simple_argument // All these return their value in context.str
= string
| hexstring
- | path
+ | word
;
complex_argument // Argument consists of multiple tokens
>> confix_p( "x\"", * hexbyte, '"' )
;
- path // Returns value in context.str
- = eps_p [ clear_a(self.context.str) ]
- >> ( ! ch_p('/') [ append_a(self.context.str) ]
- )
- >> ( word [ append_a(self.context.str) ]
- % ch_p('/') [ append_a(self.context.str) ]
- )
+ path // Returns value in context.path
+ = eps_p [ clear_a(self.context.path) ]
+ >> ( ! ch_p('/') [ push_back_a(self.context.path, "") ] )
+ >> ( word [ push_back_a(self.context.path) ]
+ % ch_p('/') )
+ >> ( ! ch_p('/') [ push_back_a(self.context.path,"") ] )
;
balanced_tokens
token
= simple_argument [ self.dispatch(&PD::pushWord,
- boost::cref(self.context.str)) ]
+ boost::ref(self.context.str)) ]
| punctuation [ self.dispatch(&PD::pushPunctuation,
- boost::cref(self.context.str)) ]
+ boost::ref(self.context.str)) ]
| balanced_tokens
;
punctuation // Returns value in context.str
- = regex_p("[,=]") [ assign_a(self.context.str) ]
+ = punctuation_p [ assign_a(self.context.str) ]
;
- word
- = regex_p("[^ \t\n\r;,=(){}/\"]+")
+ word // Returns value in context.str
+ = lexeme_d[ + word_p ] [ assign_a(self.context.str) ]
;
hexbyte
[ append_a(self.context.str) ]
;
- BOOST_SPIRIT_DEBUG_RULE(command);
- BOOST_SPIRIT_DEBUG_RULE(path);
- BOOST_SPIRIT_DEBUG_RULE(argument);
- BOOST_SPIRIT_DEBUG_RULE(word);
- BOOST_SPIRIT_DEBUG_RULE(string);
- BOOST_SPIRIT_DEBUG_RULE(hexstring);
- BOOST_SPIRIT_DEBUG_RULE(token);
- BOOST_SPIRIT_DEBUG_RULE(punctuation);
- BOOST_SPIRIT_DEBUG_RULE(hexbyte);
- BOOST_SPIRIT_DEBUG_RULE(balanced_tokens);
- BOOST_SPIRIT_DEBUG_RULE(simple_argument);
- BOOST_SPIRIT_DEBUG_RULE(complex_argument);
- }
-
- boost::spirit::rule<Scanner> const & start() const { return command; }
- };
- };
+ skip
+ = space_p
+ | comment_p('#')
+ ;
- struct SkipGrammar
- : public boost::spirit::grammar<SkipGrammar>
- {
- template <class Scanner>
- struct definition
- {
- boost::spirit::rule<Scanner> rule;
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(command,1);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(path,1);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(argument,1);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(word,1);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(string,1);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(hexstring,1);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(token,1);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(punctuation,1);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(hexbyte,1);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(balanced_tokens,1);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(simple_argument,1);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(complex_argument,1);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(builtin,1);
+
+ start_parsers(
+ command, // CommandParser
+ skip // SkipParser
+ );
- definition(SkipGrammar const & self) {
- rule
- = boost::spirit::regex_p("[ \t]+")
- | boost::spirit::comment_p('#')
- ;
}
-
- boost::spirit::rule<Scanner> const & start() const { return rule; }
};
};
//#include "Parse.test.hh"
//#include "Parse.test.ih"
+// #define BOOST_SPIRIT_DEBUG
+// #define BOOST_SPIRIT_DEBUG_TRACENODE 0
+
// Custom includes
#include <sstream>
#include "Parse.hh"
#include "Parse.ih"
+#include "../Utils/String.hh"
#include <boost/test/auto_unit_test.hpp>
#include <boost/test/test_tools.hpp>
namespace
{
+
+
struct TestParseDispatcher
{
TestParseDispatcher(std::ostream & os) : os_ (os) {}
std::ostream & os_;
- void beginCommand(std::string const & command)
- { os_ << "beginCommand( " << command << " )\n"; }
+ void beginCommand(std::vector<std::string> const & command)
+ { os_ << "beginCommand( " << senf::stringJoin(command, "/") << " )\n"; }
void endCommand()
{ os_ << "endCommand()\n"; }
{ os_ << "pushPunctuation( " << token << " )\n"; }
void pushWord(std::string const & token)
{ os_ << "pushWord( " << token << " )\n"; }
+
+ void builtin_cd(std::vector<std::string> const & path)
+ { os_ << "builtin_cd( " << senf::stringJoin(path, "/") << " )\n"; }
+ void builtin_ls(std::vector<std::string> const & path)
+ { os_ << "builtin_cd( " << senf::stringJoin(path, "/") << " )\n"; }
};
}
senf::console::detail::CommandGrammar<TestParseDispatcher>::Context context;
std::stringstream ss;
TestParseDispatcher dispatcher (ss);
- senf::console::detail::CommandGrammar<TestParseDispatcher> grammar (dispatcher, context);
- senf::console::detail::SkipGrammar skipGrammar;
+
+ typedef senf::console::detail::CommandGrammar<TestParseDispatcher> Grammar;
+ Grammar grammar (dispatcher, context);
char text[] =
"# Comment\n"
- "doo / bii / doo arg/../path"
+ "doo / bii / doo arg"
" flab::blub"
" 123.434>a"
" (a,b,c (huhu))"
BOOST_CHECK( boost::spirit::parse(
text,
- grammar,
- skipGrammar ) . full );
+ grammar.use_parser<Grammar::CommandParser>(),
+ grammar.use_parser<Grammar::SkipParser>() ) . full );
BOOST_CHECK_EQUAL( ss.str(),
"beginCommand( doo/bii/doo )\n"
- "pushArgument( arg/../path )\n"
+ "pushArgument( arg )\n"
"pushArgument( flab::blub )\n"
"pushArgument( 123.434>a )\n"
"openGroup()\n"
char const text[] =
"# Comment\n"
- "doo / bii / doo arg/../path"
+ "doo / bii / doo arg"
" flab::blub"
" 123.434>a"
" (a,b,c (huhu))"
senf::console::ParseCommandInfo info;
BOOST_CHECK( parser.parseCommand(text, info) );
- BOOST_CHECK_EQUAL( info.commandPath(), "doo/bii/doo" );
- BOOST_REQUIRE_EQUAL( info.arguments(), 6u );
- BOOST_REQUIRE_EQUAL( info.tokens(), 13u );
+ char const * path[] = { "doo", "bii", "doo" };
+
+ BOOST_CHECK_EQUAL_COLLECTIONS( info.commandPath().begin(), info.commandPath().end(),
+ path, path + sizeof(path)/sizeof(path[0]) );
+ BOOST_REQUIRE_EQUAL( info.arguments().size(), 6u );
+ BOOST_REQUIRE_EQUAL( info.tokens().size(), 13u );
- char const * tokens[] = { "arg/../path",
+ char const * tokens[] = { "arg",
"flab::blub",
"123.434>a",
"a", ",", "b", ",", "c", "(", "huhu", ")",
"foo\"bar",
"\x01\x02\x03\x04" };
- BOOST_REQUIRE_EQUAL( info.begin_arguments()[0].size(), 1u );
- BOOST_CHECK_EQUAL( info.begin_arguments()[0].begin()->value(), tokens[0] );
+ BOOST_REQUIRE_EQUAL( info.arguments().begin()[0].size(), 1u );
+ BOOST_CHECK_EQUAL( info.arguments().begin()[0].begin()->value(), tokens[0] );
- BOOST_REQUIRE_EQUAL( info.begin_arguments()[1].size(), 1u );
- BOOST_CHECK_EQUAL( info.begin_arguments()[1].begin()->value(), tokens[1] );
+ BOOST_REQUIRE_EQUAL( info.arguments().begin()[1].size(), 1u );
+ BOOST_CHECK_EQUAL( info.arguments().begin()[1].begin()->value(), tokens[1] );
- BOOST_REQUIRE_EQUAL( info.begin_arguments()[2].size(), 1u );
- BOOST_CHECK_EQUAL( info.begin_arguments()[2].begin()->value(), tokens[2] );
+ BOOST_REQUIRE_EQUAL( info.arguments().begin()[2].size(), 1u );
+ BOOST_CHECK_EQUAL( info.arguments().begin()[2].begin()->value(), tokens[2] );
- BOOST_REQUIRE_EQUAL( info.begin_arguments()[3].size(), 8u );
+ BOOST_REQUIRE_EQUAL( info.arguments().begin()[3].size(), 8u );
for (unsigned i (0); i<8; ++i)
- BOOST_CHECK_EQUAL( info.begin_arguments()[3].begin()[i].value(), tokens[3+i] );
+ BOOST_CHECK_EQUAL( info.arguments().begin()[3].begin()[i].value(), tokens[3+i] );
- BOOST_REQUIRE_EQUAL( info.begin_arguments()[4].size(), 1u );
- BOOST_CHECK_EQUAL( info.begin_arguments()[4].begin()->value(), tokens[11] );
+ BOOST_REQUIRE_EQUAL( info.arguments().begin()[4].size(), 1u );
+ BOOST_CHECK_EQUAL( info.arguments().begin()[4].begin()->value(), tokens[11] );
- BOOST_REQUIRE_EQUAL( info.begin_arguments()[5].size(), 1u );
- BOOST_CHECK_EQUAL( info.begin_arguments()[5].begin()->value(), tokens[12] );
+ BOOST_REQUIRE_EQUAL( info.arguments().begin()[5].size(), 1u );
+ BOOST_CHECK_EQUAL( info.arguments().begin()[5].begin()->value(), tokens[12] );
}
///////////////////////////////cc.e////////////////////////////////////////
\brief Server non-inline non-template implementation */
#include "Server.hh"
-#include "Server.ih"
+//#include "Server.ih"
// Custom includes
#include <unistd.h>
#define prefix_
///////////////////////////////cc.p////////////////////////////////////////
-prefix_ void senf::console::start(senf::INet4SocketAddress const & address)
+prefix_ senf::console::Server &
+senf::console::Server::start(senf::INet4SocketAddress const & address)
{
senf::TCPv4ServerSocketHandle handle (address);
- handle.protocol().reuseaddr();
- senf::console::detail::Server::start(handle);
- SENF_LOG((detail::Server::SENFLogArea)(log::NOTICE)(
+ senf::console::Server::start(handle);
+ SENF_LOG((Server::SENFLogArea)(log::NOTICE)(
"Console server started at " << address ));
+ return *instance_;
}
-prefix_ void senf::console::start(senf::INet6SocketAddress const & address)
+prefix_ senf::console::Server &
+senf::console::Server::start(senf::INet6SocketAddress const & address)
{
senf::TCPv6ServerSocketHandle handle (address);
- handle.protocol().reuseaddr();
- senf::console::detail::Server::start(handle);
- SENF_LOG((detail::Server::SENFLogArea)(log::NOTICE)(
+ senf::console::Server::start(handle);
+ SENF_LOG((Server::SENFLogArea)(log::NOTICE)(
"Console server started at " << address ));
+ return *instance_;
}
///////////////////////////////////////////////////////////////////////////
-// senf::console::detail::Server
+// senf::console::Server
-boost::scoped_ptr<senf::console::detail::Server> senf::console::detail::Server::instance_;
+boost::scoped_ptr<senf::console::Server> senf::console::Server::instance_;
-prefix_ void senf::console::detail::Server::start(ServerHandle handle)
+prefix_ void senf::console::Server::start(ServerHandle handle)
{
SENF_ASSERT( ! instance_ );
instance_.reset(new Server(handle));
}
-prefix_ senf::console::detail::Server::Server(ServerHandle handle)
+prefix_ senf::console::Server::Server(ServerHandle handle)
: handle_ (handle)
{
Scheduler::instance().add( handle_, senf::membind(&Server::newClient, this) );
}
-prefix_ senf::console::detail::Server::~Server()
+prefix_ senf::console::Server::~Server()
{
Scheduler::instance().remove(handle_);
}
-prefix_ void senf::console::detail::Server::newClient(Scheduler::EventId event)
+prefix_ void senf::console::Server::newClient(Scheduler::EventId event)
{
ServerHandle::ClientSocketHandle client (handle_.accept());
- boost::intrusive_ptr<Client> p (new Client(client));
+ boost::intrusive_ptr<Client> p (new Client(client, name_));
clients_.insert( p );
SENF_LOG(( "Registered new client " << p.get() ));
}
-prefix_ void senf::console::detail::Server::removeClient(Client & client)
+prefix_ void senf::console::Server::removeClient(Client & client)
{
SENF_LOG(( "Disposing client " << & client ));
// THIS DELETES THE CLIENT INSTANCE !!
}
///////////////////////////////////////////////////////////////////////////
-// senf::console::detail::Client
+// senf::console::Client
-prefix_ senf::console::detail::Client::Client(ClientHandle handle)
- : handle_ (handle), out_(::dup(handle.fd()))
+prefix_ senf::console::Client::Client(ClientHandle handle, std::string const & name)
+ : handle_ (handle), name_ (name), out_(::dup(handle.fd()))
{
- out_ << "# " << std::flush;
+ out_ << name_ << "# " << std::flush;
ReadHelper<ClientHandle>::dispatch( handle_, 16384u, ReadUntil("\n"),
senf::membind(&Client::clientData, this) );
}
-prefix_ senf::console::detail::Client::~Client()
+prefix_ senf::console::Client::~Client()
{}
-prefix_ void senf::console::detail::Client::stopClient()
+prefix_ void senf::console::Client::stopClient()
{
// THIS COMMITS SUICIDE. THE INSTANCE IS GONE AFTER removeClient RETURNS
Server::instance_->removeClient(*this);
}
-prefix_ void senf::console::detail::Client::clientData(ReadHelper<ClientHandle>::ptr helper)
+prefix_ void senf::console::Client::clientData(ReadHelper<ClientHandle>::ptr helper)
{
if (helper->error() || handle_.eof()) {
// THIS COMMITS SUICIDE. THE INSTANCE IS GONE AFTER stopClient RETURNS
tail_ = helper->tail();
boost::trim(data); // Gets rid of superfluous \r or \n characters
+ if (data == "exit") {
+ // THIS COMMITS SUICIDE. THE INSTANCE IS GONE AFTER stopClient RETURNS
+ stopClient();
+ return;
+ }
+
ParseCommandInfo command;
if (parser_.parseCommand(data, command))
executor_(command, out_);
else
out_ << "syntax error" << std::endl;
- out_ << "# " << std::flush;
+ out_ << name_ << "# " << std::flush;
ReadHelper<ClientHandle>::dispatch( handle_, 16384u, ReadUntil("\n"),
senf::membind(&Client::clientData, this) );
}
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2008
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief Server inline non-template implementation */
+
+//#include "Server.ih"
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::Server
+
+prefix_ void senf::console::Server::name(std::string const & name)
+{
+ name_ = name;
+}
+
+///////////////////////////////cci.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
#define HH_Server_ 1
// Custom includes
+#include <set>
+#include <boost/utility.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/iostreams/device/file_descriptor.hpp>
+#include <boost/iostreams/stream.hpp>
+#include "../Utils/intrusive_refcount.hh"
+#include "../Socket/Protocols/INet/TCPSocketHandle.hh"
+#include "../Socket/ServerSocketHandle.hh"
+#include "../Scheduler/Scheduler.hh"
+#include "../Scheduler/ReadHelper.hh"
+#include "Parse.hh"
+#include "Executor.hh"
#include "../Socket/Protocols/INet/INetAddressing.hh"
//#include "Server.mpp"
namespace senf {
namespace console {
- void start(senf::INet4SocketAddress const & address);
- void start(senf::INet6SocketAddress const & address);
+ class Client;
+
+ /** \brief
+ */
+ class Server
+ : boost::noncopyable
+ {
+ SENF_LOG_CLASS_AREA();
+ SENF_LOG_DEFAULT_LEVEL( senf::log::NOTICE );
+ public:
+ ///////////////////////////////////////////////////////////////////////////
+ // Types
+
+ typedef senf::ServerSocketHandle<
+ senf::MakeSocketPolicy< senf::TCPv4SocketProtocol::Policy,
+ senf::UnspecifiedAddressingPolicy>::policy > ServerHandle;
+
+ ~Server();
+
+ static Server & start(senf::INet4SocketAddress const & address);
+ static Server & start(senf::INet6SocketAddress const & address);
+
+ void name(std::string const & name);
+
+ protected:
+
+ private:
+ Server(ServerHandle handle);
+
+ static void start(ServerHandle handle);
+
+ void newClient(Scheduler::EventId event);
+ void removeClient(Client & client);
+
+ ServerHandle handle_;
+
+ typedef std::set< boost::intrusive_ptr<Client> > Clients;
+ Clients clients_;
+ std::string name_;
+
+ static boost::scoped_ptr<Server> instance_;
+
+ friend class Client;
+ };
+
+ /** \brief
+ */
+ class Client
+ : public senf::intrusive_refcount
+ {
+ SENF_LOG_CLASS_AREA();
+ SENF_LOG_DEFAULT_LEVEL( senf::log::NOTICE );
+ public:
+ typedef Server::ServerHandle::ClientSocketHandle ClientHandle;
+
+ ~Client();
+
+ void stopClient();
+
+ protected:
+
+ private:
+ Client(ClientHandle handle, std::string const & name);
+
+ void clientData(ReadHelper<ClientHandle>::ptr helper);
+
+ ClientHandle handle_;
+ std::string tail_;
+ SingleCommandParser parser_;
+ Executor executor_;
+ std::string name_;
+
+ typedef boost::iostreams::stream<boost::iostreams::file_descriptor_sink> fdostream;
+ fdostream out_;
+
+ friend class Server;
+ };
}}
///////////////////////////////hh.e////////////////////////////////////////
-//#include "Server.cci"
+#include "Server.cci"
//#include "Server.ct"
//#include "Server.cti"
#endif
+++ /dev/null
-// $Id$
-//
-// Copyright (C) 2008
-// Fraunhofer Institute for Open Communication Systems (FOKUS)
-// Competence Center NETwork research (NET), St. Augustin, GERMANY
-// Stefan Bund <g0dil@berlios.de>
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the
-// Free Software Foundation, Inc.,
-// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-/** \file
- \brief Server internal header */
-
-#ifndef IH_Server_
-#define IH_Server_ 1
-
-// Custom includes
-#include <set>
-#include <boost/utility.hpp>
-#include <boost/scoped_ptr.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/iostreams/device/file_descriptor.hpp>
-#include <boost/iostreams/stream.hpp>
-#include "../Utils/intrusive_refcount.hh"
-#include "../Socket/Protocols/INet/TCPSocketHandle.hh"
-#include "../Socket/ServerSocketHandle.hh"
-#include "../Scheduler/Scheduler.hh"
-#include "../Scheduler/ReadHelper.hh"
-#include "Parse.hh"
-#include "Executor.hh"
-
-///////////////////////////////ih.p////////////////////////////////////////
-
-namespace senf {
-namespace console {
-namespace detail {
-
- class Client;
-
- /** \brief
- */
- class Server
- : boost::noncopyable
- {
- SENF_LOG_CLASS_AREA();
- SENF_LOG_DEFAULT_LEVEL( senf::log::NOTICE );
- public:
- ///////////////////////////////////////////////////////////////////////////
- // Types
-
- typedef senf::ServerSocketHandle<
- senf::MakeSocketPolicy< senf::TCPv4SocketProtocol::Policy,
- senf::UnspecifiedAddressingPolicy>::policy > ServerHandle;
-
- ~Server();
-
- static void start(ServerHandle handle);
-
- protected:
-
- private:
- Server(ServerHandle handle);
-
- void newClient(Scheduler::EventId event);
- void removeClient(Client & client);
-
- ServerHandle handle_;
-
- typedef std::set< boost::intrusive_ptr<Client> > Clients;
- Clients clients_;
-
- static boost::scoped_ptr<Server> instance_;
-
- friend class Client;
- };
-
- /** \brief
- */
- class Client
- : public senf::intrusive_refcount
- {
- SENF_LOG_CLASS_AREA();
- SENF_LOG_DEFAULT_LEVEL( senf::log::NOTICE );
- public:
- typedef Server::ServerHandle::ClientSocketHandle ClientHandle;
-
- ~Client();
-
- void stopClient();
-
- protected:
-
- private:
- Client(ClientHandle handle);
-
- void clientData(ReadHelper<ClientHandle>::ptr helper);
-
- ClientHandle handle_;
- std::string tail_;
- SingleCommandParser parser_;
- Executor executor_;
-
- typedef boost::iostreams::stream<boost::iostreams::file_descriptor_sink> fdostream;
- fdostream out_;
-
- friend class Server;
- };
-
-}}}
-
-///////////////////////////////ih.e////////////////////////////////////////
-#endif
-
-\f
-// Local Variables:
-// mode: c++
-// fill-column: 100
-// comment-column: 40
-// c-file-style: "senf"
-// indent-tabs-mode: nil
-// ispell-local-dictionary: "american"
-// compile-command: "scons -u test"
-// End:
{
senf::log::ConsoleTarget::instance().route< senf::SenfLog, senf::log::NOTICE >();
- senf::console::start( senf::INet4SocketAddress("127.0.0.1:23232") );
+ senf::console::Server::start( senf::INet4SocketAddress("127.0.0.1:23232") )
+ .name("testServer ");
senf::Scheduler::instance().process();
}