My Project
telnet.h
1 /*
2  * uuid-telnet - Telnet service
3  * Copyright 2019 Simon Arlott
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifndef UUID_TELNET_H_
20 #define UUID_TELNET_H_
21 
22 #include <Arduino.h>
23 #ifdef ARDUINO_ARCH_ESP8266
24 # include <ESP8266WiFi.h>
25 #else
26 # include <WiFi.h>
27 #endif
28 #include <WiFiUdp.h>
29 
30 #include <functional>
31 #include <list>
32 #include <memory>
33 #include <string>
34 #include <vector>
35 
36 #include <uuid/console.h>
37 
38 namespace uuid {
39 
46 namespace telnet {
47 
54 class TelnetStream: public ::Stream {
55 public:
62  explicit TelnetStream(WiFiClient &client);
63  virtual ~TelnetStream() = default;
64 
70  void start();
71 
78  int available() override;
85  int read() override;
93  int peek() override;
103  size_t write(uint8_t data) override;
114  size_t write(const uint8_t *buffer, size_t size) override;
125  void flush() override;
126 
127 private:
128  static constexpr const unsigned char NUL = 0;
129  static constexpr const unsigned char BEL = 7;
130  static constexpr const unsigned char BS = 8;
131  static constexpr const unsigned char HT = 9;
132  static constexpr const unsigned char LF = 10;
133  static constexpr const unsigned char VT = 11;
134  static constexpr const unsigned char FF = 12;
135  static constexpr const unsigned char CR = 13;
136  static constexpr const unsigned char SE = 240;
137  static constexpr const unsigned char NOP = 241;
138  static constexpr const unsigned char DM = 242;
139  static constexpr const unsigned char BRK = 243;
140  static constexpr const unsigned char IP = 244;
141  static constexpr const unsigned char AO = 245;
142  static constexpr const unsigned char AYT = 246;
143  static constexpr const unsigned char EC = 247;
144  static constexpr const unsigned char EL = 248;
145  static constexpr const unsigned char GA = 249;
146  static constexpr const unsigned char SB = 250;
147  static constexpr const unsigned char WILL = 251;
148  static constexpr const unsigned char WONT = 252;
149  static constexpr const unsigned char DO = 253;
150  static constexpr const unsigned char DONT = 254;
151  static constexpr const unsigned char IAC = 255;
153  static constexpr const unsigned char OPT_BINARY = 0;
154  static constexpr const unsigned char OPT_ECHO = 1;
155  static constexpr const unsigned char OPT_SGA = 3;
157  static constexpr const size_t BUFFER_SIZE = 536;
159  TelnetStream(const TelnetStream&) = delete;
160  TelnetStream& operator=(const TelnetStream&) = delete;
161 
168  int raw_available();
175  int raw_read();
183  void buffer_flush();
193  size_t raw_write(unsigned char data);
203  size_t raw_write(const std::vector<unsigned char> &data);
214  size_t raw_write(const uint8_t *buffer, size_t size);
215 
216  WiFiClient &client_;
217  unsigned char previous_raw_in_ = 0;
218  bool sub_negotiation_ = false;
219  unsigned char previous_in_ = 0;
220  unsigned char previous_out_ = 0;
221  int peek_ = -1;
222  std::vector<char> output_buffer_;
223 };
224 
231 public:
232  static constexpr size_t MAX_CONNECTIONS = 3;
233  static constexpr uint16_t DEFAULT_PORT = 23;
234  static constexpr unsigned long DEFAULT_IDLE_TIMEOUT = 600;
235  static constexpr unsigned long DEFAULT_WRITE_TIMEOUT = 0;
245  using shell_factory_function = std::function<std::shared_ptr<uuid::console::Shell>(Stream &stream, const IPAddress &addr, uint16_t port)>;
246 
255  TelnetService(std::shared_ptr<uuid::console::Commands> commands, unsigned int context = 0, unsigned int flags = 0);
256 
266  TelnetService(uint16_t port, std::shared_ptr<uuid::console::Commands> commands, unsigned int context = 0, unsigned int flags = 0);
267 
274  explicit TelnetService(shell_factory_function shell_factory);
275 
283  TelnetService(uint16_t port, shell_factory_function shell_factory);
284 
285  ~TelnetService() = default;
286 
292  void start();
300  void close_all();
308  void stop();
309 
316  size_t maximum_connections() const;
324  void maximum_connections(size_t count);
325 
332  unsigned long initial_idle_timeout() const;
341  void initial_idle_timeout(unsigned long timeout);
342 
350  unsigned long default_write_timeout() const;
361  void default_write_timeout(unsigned long timeout);
362 
368  void loop();
369 
370 private:
378  class Connection {
379  public:
389  Connection(shell_factory_function &shell_factory, WiFiClient &&client, unsigned long idle_timeout, unsigned long write_timeout);
390  ~Connection() = default;
391 
398  bool loop();
405  bool stop();
406 
407  private:
408  Connection(const Connection&) = delete;
409  Connection& operator=(const Connection&) = delete;
410 
411  WiFiClient client_;
413  std::weak_ptr<uuid::console::Shell> shell_;
414  IPAddress addr_;
415  uint16_t port_;
416  };
417 
418  TelnetService(const TelnetService&) = delete;
419  TelnetService& operator=(const TelnetService&) = delete;
420 
423  WiFiServer server_;
425  std::list<Connection> connections_;
429 };
430 
431 } // namespace telnet
432 
433 } // namespace uuid
434 
435 #endif
uuid::telnet::TelnetService::initial_idle_timeout
unsigned long initial_idle_timeout() const
Get the initial idle timeout for new connections.
Definition: telnet.cpp:130
uuid::telnet::TelnetStream::HT
static constexpr const unsigned char HT
Definition: telnet.h:131
uuid::log::Logger
Logger instance used to make log messages.
Definition: log.h:347
uuid::telnet::TelnetService::Connection
Telnet connection.
Definition: telnet.h:378
uuid::telnet::TelnetService::Connection::port_
uint16_t port_
Definition: telnet.h:415
uuid::telnet::TelnetStream::VT
static constexpr const unsigned char VT
Definition: telnet.h:133
uuid::telnet::TelnetService::server_
WiFiServer server_
Definition: telnet.h:423
uuid::telnet::TelnetStream::IAC
static constexpr const unsigned char IAC
Definition: telnet.h:151
uuid::telnet::TelnetService::TelnetService
TelnetService(std::shared_ptr< uuid::console::Commands > commands, unsigned int context=0, unsigned int flags=0)
Create a new telnet service listening on the default port.
Definition: telnet.cpp:73
uuid::telnet::TelnetService::logger_
static uuid::log::Logger logger_
Definition: telnet.h:421
uuid::telnet::TelnetStream::client_
WiFiClient & client_
Definition: telnet.h:216
uuid::telnet::TelnetService::close_all
void close_all()
Close all connections.
Definition: telnet.cpp:100
uuid::telnet::TelnetStream::raw_read
int raw_read()
Read one byte directly from the available input.
Definition: stream.cpp:295
uuid::telnet::TelnetStream::IP
static constexpr const unsigned char IP
Definition: telnet.h:140
uuid::telnet::TelnetService::stop
void stop()
Stop listening for connections.
Definition: telnet.cpp:107
uuid::telnet::TelnetService::start
void start()
Start listening for connections on the configured port.
Definition: telnet.cpp:96
uuid::telnet::TelnetStream::OPT_SGA
static constexpr const unsigned char OPT_SGA
Definition: telnet.h:155
uuid::telnet::TelnetService::initial_idle_timeout_
unsigned long initial_idle_timeout_
Definition: telnet.h:427
uuid::telnet::TelnetService::MAX_CONNECTIONS
static constexpr size_t MAX_CONNECTIONS
Definition: telnet.h:232
uuid::telnet::TelnetStream::previous_raw_in_
unsigned char previous_raw_in_
Definition: telnet.h:217
uuid::telnet::TelnetStream::raw_write
size_t raw_write(unsigned char data)
Write one byte directly to the output stream.
Definition: stream.cpp:310
uuid::telnet::TelnetStream::NOP
static constexpr const unsigned char NOP
Definition: telnet.h:137
uuid::telnet::TelnetStream::sub_negotiation_
bool sub_negotiation_
Definition: telnet.h:218
uuid::telnet::TelnetService::default_write_timeout
unsigned long default_write_timeout() const
Get the default socket write timeout for new connections.
Definition: telnet.cpp:138
uuid::telnet::TelnetStream::LF
static constexpr const unsigned char LF
Definition: telnet.h:132
uuid::telnet::TelnetStream::WILL
static constexpr const unsigned char WILL
Definition: telnet.h:147
uuid::telnet::TelnetStream::AYT
static constexpr const unsigned char AYT
Definition: telnet.h:142
uuid::telnet::TelnetStream::write
size_t write(uint8_t data) override
Write one byte to the output stream.
Definition: stream.cpp:234
uuid::telnet::TelnetStream::DM
static constexpr const unsigned char DM
Definition: telnet.h:138
uuid::telnet::TelnetService::maximum_connections_
size_t maximum_connections_
Definition: telnet.h:424
uuid::telnet::TelnetStream::CR
static constexpr const unsigned char CR
Definition: telnet.h:135
uuid::telnet::TelnetService
Provides access to a console shell as a telnet server.
Definition: telnet.h:230
uuid::telnet::TelnetService::Connection::addr_
IPAddress addr_
Definition: telnet.h:414
uuid::telnet::TelnetService::connections_
std::list< Connection > connections_
Definition: telnet.h:425
uuid::telnet::TelnetService::DEFAULT_IDLE_TIMEOUT
static constexpr unsigned long DEFAULT_IDLE_TIMEOUT
Definition: telnet.h:234
uuid::telnet::TelnetStream
Stream wrapper that performs telnet protocol handling, option negotiation and output buffering.
Definition: telnet.h:54
uuid::telnet::TelnetStream::SB
static constexpr const unsigned char SB
Definition: telnet.h:146
uuid::telnet::TelnetStream::previous_in_
unsigned char previous_in_
Definition: telnet.h:219
uuid::telnet::TelnetService::DEFAULT_PORT
static constexpr uint16_t DEFAULT_PORT
Definition: telnet.h:233
uuid::telnet::TelnetStream::FF
static constexpr const unsigned char FF
Definition: telnet.h:134
uuid::telnet::TelnetStream::BS
static constexpr const unsigned char BS
Definition: telnet.h:130
uuid::telnet::TelnetService::maximum_connections
size_t maximum_connections() const
Get the maximum number of concurrent open connections.
Definition: telnet.cpp:111
uuid::telnet::TelnetStream::DONT
static constexpr const unsigned char DONT
Definition: telnet.h:150
uuid::telnet::TelnetStream::available
int available() override
Check for available input.
Definition: stream.cpp:47
uuid::telnet::TelnetStream::GA
static constexpr const unsigned char GA
Definition: telnet.h:145
uuid::telnet::TelnetStream::read
int read() override
Read one byte from the available input.
Definition: stream.cpp:55
uuid::telnet::TelnetStream::buffer_flush
void buffer_flush()
Flush output stream buffer.
Definition: stream.cpp:299
uuid::telnet::TelnetStream::BEL
static constexpr const unsigned char BEL
Definition: telnet.h:129
uuid::telnet::TelnetStream::TelnetStream
TelnetStream(WiFiClient &client)
Create a new telnet stream wrapper.
Definition: stream.cpp:31
uuid::telnet::TelnetStream::BRK
static constexpr const unsigned char BRK
Definition: telnet.h:139
uuid::telnet::TelnetStream::peek_
int peek_
Definition: telnet.h:221
uuid::telnet::TelnetStream::WONT
static constexpr const unsigned char WONT
Definition: telnet.h:148
uuid::telnet::TelnetService::write_timeout_
unsigned long write_timeout_
Definition: telnet.h:428
uuid::telnet::TelnetStream::NUL
static constexpr const unsigned char NUL
Definition: telnet.h:128
uuid
Common utilities.
Definition: get_uptime_ms.cpp:28
uuid::telnet::TelnetStream::EC
static constexpr const unsigned char EC
Definition: telnet.h:143
uuid::telnet::TelnetStream::output_buffer_
std::vector< char > output_buffer_
Definition: telnet.h:222
uuid::telnet::TelnetService::shell_factory_function
std::function< std::shared_ptr< uuid::console::Shell >(Stream &stream, const IPAddress &addr, uint16_t port)> shell_factory_function
Function to handle the creation of a shell.
Definition: telnet.h:245
uuid::telnet::TelnetStream::OPT_ECHO
static constexpr const unsigned char OPT_ECHO
Definition: telnet.h:154
uuid::telnet::TelnetStream::OPT_BINARY
static constexpr const unsigned char OPT_BINARY
Definition: telnet.h:153
uuid::telnet::TelnetStream::flush
void flush() override
Does nothing.
Definition: stream.cpp:284
uuid::telnet::TelnetStream::raw_available
int raw_available()
Directly check for available input.
Definition: stream.cpp:291
uuid::telnet::TelnetService::Connection::stop
bool stop()
Stop the shell.
Definition: telnet.cpp:230
uuid::telnet::TelnetService::DEFAULT_WRITE_TIMEOUT
static constexpr unsigned long DEFAULT_WRITE_TIMEOUT
Definition: telnet.h:235
uuid::telnet::TelnetStream::peek
int peek() override
Read one byte from the available input without advancing to the next one.
Definition: stream.cpp:221
uuid::telnet::TelnetStream::BUFFER_SIZE
static constexpr const size_t BUFFER_SIZE
Definition: telnet.h:157
uuid::telnet::TelnetService::shell_factory_
shell_factory_function shell_factory_
Definition: telnet.h:426
uuid::telnet::TelnetStream::previous_out_
unsigned char previous_out_
Definition: telnet.h:220
uuid::telnet::TelnetService::Connection::stream_
TelnetStream stream_
Definition: telnet.h:412
uuid::telnet::TelnetStream::DO
static constexpr const unsigned char DO
Definition: telnet.h:149
uuid::telnet::TelnetStream::AO
static constexpr const unsigned char AO
Definition: telnet.h:141
uuid::telnet::TelnetStream::SE
static constexpr const unsigned char SE
Definition: telnet.h:136
uuid::telnet::TelnetStream::EL
static constexpr const unsigned char EL
Definition: telnet.h:144
uuid::telnet::TelnetService::Connection::shell_
std::weak_ptr< uuid::console::Shell > shell_
Definition: telnet.h:413
uuid::telnet::TelnetService::Connection::client_
WiFiClient client_
Definition: telnet.h:411
uuid::telnet::TelnetStream::start
void start()
Perform initial negotiation.
Definition: stream.cpp:36
uuid::telnet::TelnetService::Connection::Connection
Connection(shell_factory_function &shell_factory, WiFiClient &&client, unsigned long idle_timeout, unsigned long write_timeout)
Create a telnet connection shell.
Definition: telnet.cpp:177
uuid::telnet::TelnetService::loop
void loop()
Accept new connections.
Definition: telnet.cpp:146
uuid::telnet::TelnetService::Connection::loop
bool loop()
Stop the shell if the client is not connected.
Definition: telnet.cpp:210