#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 "Parse.hh"
#include "Executor.hh"
#include "../Socket/Protocols/INet/INetAddressing.hh"
+#include "../Utils/Logger.hh"
//#include "Server.mpp"
+#include "Server.ih"
///////////////////////////////hh.p////////////////////////////////////////
namespace senf {
\todo Add readline support
\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
+ some flag or something. Example for use: Host name resolution: Here we can just built
+ 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.
*/
class Server
: boost::noncopyable
///< Start server on given IPv4 address/port
static Server & start(senf::INet6SocketAddress const & address);
///< Start server on given IPv6 address/port
+ static Server & instance();
void name(std::string const & name); ///< Set server name
/**< This information is used in the prompt string. */
Server(ServerHandle handle);
static void start(ServerHandle handle);
+ static boost::scoped_ptr<Server> & instancePtr();
void newClient(Scheduler::EventId event);
void removeClient(Client & client);
Clients clients_;
std::string name_;
- static boost::scoped_ptr<Server> instance_;
-
friend class Client;
};
and passes the commands to an Executor instance.
\fixme Fix Client::clientData implementation
- \fixme Remove the 'dup' needed here so we don't close the same fd twice (see Client
- constructor)
- \fixme Make output non-blocking (use a non-blocking/discarding streambuf) and possibly set
- socket send buffer size
\fixme Don't register a new ReadHelper every round
*/
class Client
- : public senf::intrusive_refcount
+ : public senf::intrusive_refcount,
+ private boost::base_from_member< detail::NonblockingSocketOStream >,
+ public senf::log::IOStreamTarget
{
+ typedef boost::base_from_member< detail::NonblockingSocketOStream > out_t;
+
SENF_LOG_CLASS_AREA();
SENF_LOG_DEFAULT_LEVEL( senf::log::NOTICE );
public:
void clientData(ReadHelper<ClientHandle>::ptr helper);
void showPrompt();
+
+ virtual void v_write(boost::posix_time::ptime timestamp, std::string const & stream,
+ std::string const & area, unsigned level,
+ std::string const & message);
ClientHandle handle_;
std::string tail_;
CommandParser parser_;
Executor executor_;
std::string name_;
-
- typedef boost::iostreams::stream<boost::iostreams::file_descriptor_sink> fdostream;
- fdostream out_;
+ unsigned promptLen_;
+ std::string lastCommand_;
friend class Server;
};