diff --git a/Console/Server.cc b/Console/Server.cc index 248e07b6d2ddea4168eeef0cb20b823e8626f2c6..d990bb3e6cae071cdebd9482f3176a69bba79f96 100644 --- a/Console/Server.cc +++ b/Console/Server.cc @@ -83,27 +83,18 @@ senf::console::Server::start(senf::INet6SocketAddress const & address) return server; } -prefix_ boost::scoped_ptr<senf::console::Server> & senf::console::Server::instancePtr() -{ - // We cannot make 'instance' a global or class-static variable, since it will then be destructed - // at an unknown time which may fail if the scheduler or the file-handle pool allocators have - // already been destructed. - static boost::scoped_ptr<senf::console::Server> instance; - return instance; -} - prefix_ senf::console::Server & senf::console::Server::start(ServerHandle handle) { // Uah .... ensure the scheduler is created before the instance pointer so it get's destructed // AFTER it. (void) senf::Scheduler::instance(); - SENF_ASSERT( ! instancePtr() ); - instancePtr().reset(new Server(handle)); - return * instancePtr(); + boost::intrusive_ptr<Server> p (new Server(handle)); + detail::ServerManager::add(boost::intrusive_ptr<Server>(p)); + return *p; } prefix_ senf::console::Server::Server(ServerHandle handle) - : handle_ (handle), mode_ (Automatic) + : handle_ (handle), root_ (root().thisptr()), mode_ (Automatic) { Scheduler::instance().add( handle_, senf::membind(&Server::newClient, this) ); } @@ -238,6 +229,7 @@ prefix_ senf::console::Client::Client(Server & server, ClientHandle handle) name_ (server.name()), reader_ (), mode_ (server.mode()) { handle_.facet<senf::TCPSocketProtocol>().nodelay(); + executor_.chroot(root()); switch (mode_) { case Server::Interactive : setInteractive(); diff --git a/Console/Server.cci b/Console/Server.cci index 405347ce97a716db99a3fdd7dcbfb6516c8066ad..e4601f67c915d9d0358f11dd13fdac7fcec89101 100644 --- a/Console/Server.cci +++ b/Console/Server.cci @@ -30,6 +30,19 @@ #define prefix_ inline ///////////////////////////////cci.p/////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////// +// senf::console::detail::ServerManager + +prefix_ void senf::console::detail::ServerManager::add(ptr server) +{ + instance().servers_.insert(server); +} + +prefix_ void senf::console::detail::ServerManager::remove(ptr server) +{ + instance().servers_.erase(instance().servers_.find(server)); +} + /////////////////////////////////////////////////////////////////////////// // senf::console::detail::NonblockingSocketSink @@ -58,6 +71,12 @@ prefix_ std::string const & senf::console::Server::name() return name_; } +prefix_ senf::console::DirectoryNode & senf::console::Server::root() + const +{ + return *root_; +} + prefix_ senf::console::Server & senf::console::Server::root(DirectoryNode & root) { root_ = root.thisptr(); @@ -79,7 +98,7 @@ prefix_ senf::console::Server::Mode senf::console::Server::mode() prefix_ void senf::console::Server::stop() { // commit suicide - instancePtr().reset(0); + detail::ServerManager::remove(boost::intrusive_ptr<Server>(this)); } /////////////////////////////////////////////////////////////////////////// diff --git a/Console/Server.hh b/Console/Server.hh index 52925d0a2fd8e8747e03352008ec2b98af07a009..1756e14717b3fb79164ddf869691c1ffda1f69be 100644 --- a/Console/Server.hh +++ b/Console/Server.hh @@ -56,7 +56,6 @@ namespace console { This class provides an interactive console TCP server. - \todo Add interactivity detection using timeout \idea To support blocking commands, we could give the Client 'suspend()' and 'resume()' members. suspend() would probably throw some kind of exception to transfer control back to the Client instance. on resume(), the command would be called again, maybe setting @@ -64,15 +63,11 @@ namespace console { our own little host-name cache. When the name is not found, we ask the resolver to resolve it and call 'resume' when the name is found. Since it is in the cache now, the command will now complete. - - \implementation We do \e not provide an \c instance() member so we can easily later extend - the server to allow registering more than one instance, e.g. with each instance on a - differently firewalled port and with different security restrictions. - + \ingroup console_access */ class Server - : boost::noncopyable + : public senf::intrusive_refcount { SENF_LOG_CLASS_AREA(); SENF_LOG_DEFAULT_LEVEL( senf::log::NOTICE ); @@ -124,16 +119,15 @@ namespace console { opened. */ void stop(); ///< Stop the server - /**< All clients will be closed */ + /**< All clients will be closed + \warning The Server instance itself will be deleted */ - protected: private: Server(ServerHandle handle); static Server & start(ServerHandle handle); - static boost::scoped_ptr<Server> & instancePtr(); void newClient(Scheduler::EventId event); void removeClient(Client & client); diff --git a/Console/Server.ih b/Console/Server.ih index d31f7133f4187512a421d5cd23c98e69ae7d846d..b107867e37214a6c9f734229737f194992a70601 100644 --- a/Console/Server.ih +++ b/Console/Server.ih @@ -29,6 +29,7 @@ // Custom includes #include <boost/iostreams/concepts.hpp> #include <boost/iostreams/stream.hpp> +#include <set> ///////////////////////////////ih.p//////////////////////////////////////// @@ -40,6 +41,24 @@ namespace console { namespace detail { + class ServerManager + : public senf::singleton<ServerManager> + { + public: + typedef boost::intrusive_ptr<Server> ptr; + + protected: + + private: + static void add(ptr server); + static void remove(ptr server); + + typedef std::set<ptr> Servers; + Servers servers_; + + friend class senf::console::Server; + }; + /** \brief Internal: Nonblocking boost::iostreams::sink The sink discards data if the output socket would.