From: g0dil Date: Mon, 8 Jun 2009 08:10:44 +0000 (+0000) Subject: Utils/Console: Console UDPServer X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=731a143df4de38d4c8b0a81121990951971cd858;p=senf.git Utils/Console: Console UDPServer git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1225 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Socket/Protocols/UN/UNAddressing.cc b/Socket/Protocols/UN/UNAddressing.cc index bcf1641..09ee9c7 100644 --- a/Socket/Protocols/UN/UNAddressing.cc +++ b/Socket/Protocols/UN/UNAddressing.cc @@ -37,7 +37,7 @@ prefix_ void senf::UNSocketAddress::path(std::string const & path) if (path.size() > sizeof(sockaddr_un)-sizeof(short)-1) throw AddressSyntaxException() << "UNSocketAddress path too long: " << path; socklen(path.size()+sizeof(short)); - memcpy(addr_.sun_path, path.c_str(), socklen()-sizeof(short)); + strncpy(addr_.sun_path, path.c_str(), socklen()-sizeof(short)); addr_.sun_path[socklen()-sizeof(short)+1] = 0; } diff --git a/Utils/Console/Executor.cci b/Utils/Console/Executor.cci index 81df7ed..e647702 100644 --- a/Utils/Console/Executor.cci +++ b/Utils/Console/Executor.cci @@ -46,6 +46,15 @@ prefix_ void senf::console::Executor::operator()(std::ostream & output, return execute(output, command); } +prefix_ void senf::console::Executor::cwd(DirectoryNode & dir) +{ + cwd_.clear(); + cwd_.push_back(dir.thisptr()); + oldCwd_ = cwd_; + dirstack_.clear(); +} + + prefix_ bool senf::console::Executor::autocd() const { diff --git a/Utils/Console/Executor.hh b/Utils/Console/Executor.hh index ce8b86c..ba4cdce 100644 --- a/Utils/Console/Executor.hh +++ b/Utils/Console/Executor.hh @@ -94,6 +94,7 @@ namespace console { Same as execute(). */ GenericNode & getNode(ParseCommandInfo const & command); DirectoryNode & cwd() const; ///< Current working directory + void cwd(DirectoryNode & dir); ///< Change current directory std::string cwdPath() const; ///< Return pathname of current directory bool skipping() const; ///< \c true, if currently skipping a directory group diff --git a/Utils/Console/Server.cc b/Utils/Console/Server.cc index 26a625f..58a3dcc 100644 --- a/Utils/Console/Server.cc +++ b/Utils/Console/Server.cc @@ -349,7 +349,7 @@ prefix_ void senf::console::Client::SysBacktrace::backtrace(std::ostream & os) { Client & client (Client::get(os)); if (client.backtrace().empty()) - os << "(no backtrace)"; + os << "(no backtrace)\n"; else os << client.backtrace(); } diff --git a/Utils/Console/UDPServer.cc b/Utils/Console/UDPServer.cc new file mode 100644 index 0000000..f67030a --- /dev/null +++ b/Utils/Console/UDPServer.cc @@ -0,0 +1,149 @@ +// $Id$ +// +// Copyright (C) 2009 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Stefan Bund +// +// 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 UDPServer non-inline non-template implementation */ + +#include "UDPServer.hh" +//#include "UDPServer.ih" + +// Custom includes +#include +#include "../membind.hh" + +//#include "UDPServer.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +prefix_ senf::console::UDPServer::UDPServer(senf::INet4SocketAddress const & address) + : replies_ (true), target_ (), handle_ (senf::UDPv4ClientSocketHandle(address)), + readevent_ ("senf::console::UDPServer::readevent", + senf::membind(&UDPServer::handleInput, this), + handle_, + senf::scheduler::FdEvent::EV_READ), + parser_ (), executor_ () +{ + if (address.address().multicast()) + handle_.facet().mcAddMembership(address.address()); + SENF_LOG(("UDP Console server started at " << address)); +} + +prefix_ senf::console::UDPServer::UDPServer(senf::INet6SocketAddress const & address) + : replies_ (true), target_ (), handle_ (senf::UDPv6ClientSocketHandle(address)), + readevent_ ("senf::console::UDPServer::readevent", + senf::membind(&UDPServer::handleInput, this), + handle_, + senf::scheduler::FdEvent::EV_READ), + parser_ (), executor_ () +{ + if (address.address().multicast()) + handle_.facet().mcAddMembership(address.address()); + SENF_LOG(("UDP Console server started at " << address)); +} + +prefix_ senf::console::UDPServer & senf::console::UDPServer::replies(bool enable) +{ + replies_ = enable; + return *this; +} + +prefix_ senf::console::UDPServer & +senf::console::UDPServer::replies(senf::INet4SocketAddress const & address) +{ + SENF_ASSERT( handle_.local().family() == senf::INet4SocketAddress::addressFamily ); + target_ = address; + return *this; +} + +prefix_ senf::console::UDPServer & +senf::console::UDPServer::replies(senf::INet6SocketAddress const & address) +{ + SENF_ASSERT( handle_.local().family() == senf::INet6SocketAddress::addressFamily ); + target_ = address; + return *this; +} + +prefix_ senf::console::DirectoryNode & senf::console::UDPServer::root() + const +{ + return executor_.chroot(); +} + +prefix_ senf::console::UDPServer & senf::console::UDPServer::root(DirectoryNode & root) +{ + executor_.chroot(root); + return *this; +} + +prefix_ void senf::console::UDPServer::handleInput(int events) +{ + if (events != senf::scheduler::FdEvent::EV_READ) { + SENF_LOG((senf::log::IMPORTANT)("Input handle read error. Closing socket.")); + readevent_.disable(); + handle_.close(); + return; + } + + std::string data; + senf::GenericBSDSocketAddress address; + handle_.readfrom(data, address, 0u); + boost::trim(data); + + executor_.cwd(executor_.chroot()); + std::stringstream stream; + try { + parser_.parse(data, boost::bind( boost::ref(executor_), boost::ref(stream), _1)); + } + catch (Executor::ExitException &) { + // Ignored + } + catch (std::exception & ex) { + std::string msg (ex.what()); + std::string::size_type i (msg.find("-- \n")); + if (i != std::string::npos) + msg = msg.substr(i+4); + stream << msg << std::endl; + } + if (replies_) { + if (target_) + address = target_; + if (stream.str().empty()) + stream << '\0'; + handle_.writeto(address, stream.str()); + } + +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "UDPServer.mpp" + + +// 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: diff --git a/Utils/Console/UDPServer.hh b/Utils/Console/UDPServer.hh new file mode 100644 index 0000000..7ee589a --- /dev/null +++ b/Utils/Console/UDPServer.hh @@ -0,0 +1,110 @@ +// $Id$ +// +// Copyright (C) 2009 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Stefan Bund +// +// 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 UDPServer public header */ + +#ifndef HH_SENF_Utils_Console_UDPServer_ +#define HH_SENF_Utils_Console_UDPServer_ 1 + +// Custom includes +#include +#include "../../Socket/Protocols/INet/UDPSocketHandle.hh" +#include "../Logger/SenfLog.hh" +#include "../../Scheduler/Scheduler.hh" +#include "Parse.hh" +#include "Executor.hh" + +//#include "UDPServer.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace senf { +namespace console { + + /** \brief + */ + class UDPServer + : public boost::noncopyable + { + SENF_LOG_CLASS_AREA(); + SENF_LOG_DEFAULT_LEVEL(senf::log::NOTICE); + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef senf::ClientSocketHandle< + senf::MakeSocketPolicy::policy > Handle; + + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + + explicit UDPServer(senf::INet4SocketAddress const & address); + explicit UDPServer(senf::INet6SocketAddress const & address); + + ///@} + /////////////////////////////////////////////////////////////////////////// + + UDPServer & replies(bool enable); + UDPServer & replies(senf::INet4SocketAddress const & address); + UDPServer & replies(senf::INet6SocketAddress const & address); + + DirectoryNode & root() const; ///< Get root node + + UDPServer & root(DirectoryNode & root); ///< Set root node + /**< \a node will be the root node for all clients launched + from this server. */ + + protected: + + private: + void handleInput(int events); + + bool replies_; + senf::GenericBSDSocketAddress target_; + + Handle handle_; + senf::scheduler::FdEvent readevent_; + CommandParser parser_; + Executor executor_; + }; + + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "UDPServer.cci" +//#include "UDPServer.ct" +//#include "UDPServer.cti" +#endif + + +// 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: diff --git a/Utils/Console/UDPServer.test.cc b/Utils/Console/UDPServer.test.cc new file mode 100644 index 0000000..1aa61fb --- /dev/null +++ b/Utils/Console/UDPServer.test.cc @@ -0,0 +1,127 @@ +// $Id$ +// +// Copyright (C) 2009 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Stefan Bund +// +// 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 UDPServer.test unit tests */ + +//#include "UDPServer.test.hh" +//#include "UDPServer.test.ih" + +// Custom includes +#include "UDPServer.hh" + +#include "../../Utils/auto_unit_test.hh" +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +namespace { + + void timeout() + { + senf::scheduler::terminate(); + } + + unsigned nread (0); + unsigned flags (0); + std::string data; + + void read(senf::ConnectedUDPv4ClientSocketHandle socket, int ev) + { + flags |= ev; + ++nread; + data = socket.read(); + } + + senf::ClockService::clock_type delay(unsigned ms) + { + return senf::ClockService::now() + senf::ClockService::milliseconds(ms); + } + +} + +BOOST_AUTO_UNIT_TEST(udpServer) +{ + senf::console::UDPServer server (senf::INet4SocketAddress("127.0.0.1:23232")); + senf::ConnectedUDPv4ClientSocketHandle socket (senf::INet4SocketAddress("127.0.0.1:23232")); + senf::scheduler::TimerEvent timer ("udpServer test timer", &timeout); + senf::scheduler::FdEvent fdev ("udpServer test fd", boost::bind(&read, socket, _1), + socket, senf::scheduler::FdEvent::EV_READ); + + nread = 0; + flags = 0; + data = ""; + socket.write("ls"); + timer.timeout(delay(300)); + senf::scheduler::process(); + BOOST_CHECK_EQUAL( nread, 1 ); + BOOST_CHECK_EQUAL( flags, senf::scheduler::FdEvent::EV_READ ); + BOOST_CHECK_EQUAL( data, "sys/ \n" ); + + // Check exception handling + nread = 0; + flags = 0; + data = ""; + socket.write("sys"); + timer.timeout(delay(300)); + senf::scheduler::process(); + BOOST_CHECK_EQUAL( nread, 1 ); + BOOST_CHECK_EQUAL( flags, senf::scheduler::FdEvent::EV_READ ); + BOOST_CHECK_EQUAL( data, "invalid command\n" "at :1:4\n" ); + + // switch directory + nread = 0; + flags = 0; + data = ""; + socket.write("cd sys"); + timer.timeout(delay(300)); + senf::scheduler::process(); + BOOST_CHECK_EQUAL( nread, 1 ); + BOOST_CHECK_EQUAL( flags, senf::scheduler::FdEvent::EV_READ ); + BOOST_CHECK_EQUAL( data, std::string(1, '\0') ); + + // Check that we go back to the root dir for every packet + nread = 0; + flags = 0; + data = ""; + socket.write("ls"); + timer.timeout(delay(300)); + senf::scheduler::process(); + BOOST_CHECK_EQUAL( nread, 1 ); + BOOST_CHECK_EQUAL( flags, senf::scheduler::FdEvent::EV_READ ); + BOOST_CHECK_EQUAL( data, "sys/ \n" ); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// 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: