Server.ih
Go to the documentation of this file.
1 //
2 // Copyright (c) 2020 Fraunhofer Institute for Applied Information Technology (FIT)
3 // Network Research Group (NET)
4 // Schloss Birlinghoven, 53754 Sankt Augustin, GERMANY
5 // Contact: support@wiback.org
6 //
7 // This file is part of the SENF code tree.
8 // It is licensed under the 3-clause BSD License (aka New BSD License).
9 // See LICENSE.txt in the top level directory for details or visit
10 // https://opensource.org/licenses/BSD-3-Clause
11 //
12 
13 
14 /** \file
15  \brief Server internal header */
16 
17 #ifndef IH_SENF_Scheduler_Console_Server_
18 #define IH_SENF_Scheduler_Console_Server_ 1
19 
20 // Custom includes
21 #include <boost/iostreams/concepts.hpp>
22 #include <boost/iostreams/stream.hpp>
23 #include <senf/Scheduler/ReadHelper.hh>
24 #include <senf/Socket/Protocols/INet/TCPSocketHandle.hh>
25 #include <senf/Utils/Logger/SenfLog.hh>
26 
27 //-/////////////////////////////////////////////////////////////////////////////////////////////////
28 
29 namespace senf {
30 namespace console {
31 
32  class Server;
33  class Client;
34 
35 namespace detail {
36 
37  class ServerManager
38  {
39  public:
40  typedef boost::intrusive_ptr<Server> ptr;
41 
42  protected:
43 
44  private:
45  static void add(ptr server);
46  static void remove(ptr server);
47 
48  static ServerManager & instance();
49 
50  typedef std::set<ptr> Servers;
51  Servers servers_;
52 
53  friend class senf::console::Server;
54  };
55 
56  /** \brief Internal: Nonblocking boost::iostreams::sink
57 
58  The sink discards data if the output socket would.
59 
60  \fixme Don't throw exceptions ... set stream error indicator (if at all)
61  */
62  class SocketStreamSink
63  : public boost::iostreams::sink
64  {
65  public:
66  SocketStreamSink(Client & client);
67  std::streamsize write(const char * s, std::streamsize n);
68 
69  Client & client() const;
70 
71  private:
72  Client & client_;
73  };
74 
75  typedef boost::iostreams::stream<SocketStreamSink> SocketStreamOStream;
76 
77  typedef senf::ServerSocketHandle<
78  senf::MakeSocketPolicy< senf::TCPv4SocketProtocol::Policy,
79  senf::BSDAddressingPolicy>::policy > ServerHandle;
80 
81  /** \brief Internal: Generic client interface
82 
83  The ClientReader encapsulates the interaction of a single network client with the user: It
84  manages prompt display and reading an interactive command.
85  */
86  class ClientReader
87  {
88  public:
89  SENF_LOG_CLASS_AREA();
90 
91  typedef ServerHandle::ClientHandle ClientHandle;
92 
93  virtual ~ClientReader() = 0;
94 
95  // Called by subclasses to get information from the Client
96 
97  Client & client() const;
98  std::string promptString() const;
99  ClientHandle handle() const;
100  std::ostream & stream() const;
101 
102  // Called by subclasses to perform actions in the Client
103 
104  void stopClient();
105  std::string::size_type handleInput(std::string const & input, bool incremental=false) const;
106 
107  // Called by the Client
108 
109  void disablePrompt();
110  void enablePrompt();
111  void write(std::string const & data);
112  unsigned width() const;
113 
114  protected:
115  ClientReader(Client & client);
116 
117  private:
118  virtual void v_disablePrompt() = 0;
119  virtual void v_enablePrompt() = 0;
120  virtual void v_write(std::string const & data) = 0;
121  virtual unsigned v_width() const = 0;
122 
123  Client & client_;
124  };
125 
126  /** \brief Internal: Primitive ClientReader implementation
127 
128  This implementation uses the cooked telnet mode to read lines from the console. It does not
129  support explicit line editing or any other advanced features.
130  */
131  class DumbClientReader
132  : public ClientReader
133  {
134  public:
135  DumbClientReader(Client & client);
136 
137  private:
138  virtual void v_disablePrompt();
139  virtual void v_enablePrompt();
140  virtual void v_write(std::string const & data);
141  virtual unsigned v_width() const;
142 
143  void clientData(senf::ReadHelper<ClientHandle>::ptr helper);
144  void showPrompt();
145 
146  std::string tail_;
147  unsigned promptLen_;
148  bool promptActive_;
149  };
150 
151  /** \brief Internal: Primitive ClientReader implementation
152 
153  This implementation uses the cooked telnet mode to read lines from the console. It does not
154  support explicit line editing or any other advanced features.
155  */
156  class NoninteractiveClientReader
157  : public ClientReader
158  {
159  public:
160  NoninteractiveClientReader(Client & client);
161 
162  typedef std::vector<char> SendQueue;
163 
164  void streamBufferMaxSize(SendQueue::size_type size);
165  SendQueue::size_type streamBufferMaxSize() const;
166 
167  private:
168  virtual void v_disablePrompt();
169  virtual void v_enablePrompt();
170  virtual void v_write(std::string const & data);
171  virtual unsigned v_width() const;
172 
173  void newData(int event);
174  void writeHandler( int event);
175 
176  SendQueue::size_type streamBufferMaxSize_;
177  SendQueue sendQueue_;
178  scheduler::FdEvent readevent_;
179  scheduler::FdEvent writeevent_;
180  std::string buffer_;
181  };
182 
183 }}}
184 
185 //-/////////////////////////////////////////////////////////////////////////////////////////////////
186 #endif
187 
188 
189 // Local Variables:
190 // mode: c++
191 // fill-column: 100
192 // comment-column: 40
193 // c-file-style: "senf"
194 // indent-tabs-mode: nil
195 // ispell-local-dictionary: "american"
196 // compile-command: "scons -u test"
197 // End: