Repo-Init
 
Loading...
Searching...
No Matches
TelnetServer.hpp
Go to the documentation of this file.
1
30#pragma once
31
33
34#include <array>
35#include <functional>
36#include <list>
37#include <memory>
38#include <string>
39#include <thread>
40#include <vector>
41
42#include <arpa/inet.h>
43#include <netdb.h>
44#include <sys/ioctl.h>
45#include <sys/socket.h>
46#include <unistd.h>
47
48class TelnetServer;
49class TelnetSession;
50
51using Socket = int;
52
56class TelnetSession : public std::enable_shared_from_this<TelnetSession> {
57 public:
59 TelnetSession(Socket ClientSocket, std::shared_ptr<TelnetServer> tServer)
60 : m_socket(ClientSocket), m_telnetServer(std::move(tServer))
61 {
63 };
64
66 void sendLine(std::string data);
68 void closeClient();
70 bool checkTimeout() const;
72 void markTimeout();
73
74 protected:
76 void initialise();
78 void update();
79
80 private:
81 // Returns ip of the peer
82 std::string getPeerIP() const;
83 // Write the prompt and any data sat in the input buffer
85 // Erase all characters on the current line and move prompt back to beginning of line
86 void eraseLine();
87 // Echo back message
88 void echoBack(const char *buffer, unsigned long length);
89 //
90 static void stripNVT(std::string &buffer);
91 // Remove all escape characters from the line
92 static void stripEscapeCharacters(std::string &buffer);
93 // Takes backspace commands and removes them and the preceding character from the m_buffer. Handles arrow key
94 // actions for history management. Returns true if the input buffer was changed.
95 static bool processBackspace(std::string &buffer);
96 // Takes tab commands and completes or suggests commands
97 bool processTab(std::string &buffer);
98 // Add a command into the command history
99 void addToHistory(const std::string &line);
100 // Handles arrow key actions for history management. Returns true if the input buffer was changed.
101 bool processCommandHistory(std::string &buffer);
102 //
103 static std::vector<std::string> getCompleteLines(std::string &buffer);
104
107 // Last seen
108 std::chrono::system_clock::time_point lastSeenTime;
109 // The socket
111 // Parent TelnetServer class
112 std::shared_ptr<TelnetServer> m_telnetServer;
113 // Buffer of input data (mid line)
114 std::string m_buffer;
115 // A history of all completed commands
116 std::list<std::string> m_history;
117 // Iterator to completed commands
118 std::list<std::string>::iterator m_historyCursor;
119
121};
122
123using SP_TelnetSession = std::shared_ptr<TelnetSession>;
124using VEC_SP_TelnetSession = std::vector<SP_TelnetSession>;
125
126using FPTR_ConnectedCallback = std::function<void(SP_TelnetSession)>;
127using FPTR_NewLineCallback = std::function<bool(SP_TelnetSession, std::string)>;
128using FPTR_TabCallback = std::function<std::string(SP_TelnetSession, std::string)>;
129
130class TelnetServer : public std::enable_shared_from_this<TelnetServer> {
131 public:
133 TelnetServer() = default;
134
136 TelnetServer(const TelnetServer & /*unused*/) = delete;
137
139 TelnetServer(TelnetServer && /*unused*/) = delete;
140
142 TelnetServer &operator=(TelnetServer /*unused*/) = delete;
143
145 TelnetServer &operator=(TelnetServer && /*unused*/) = delete;
146
149
159 bool initialise(unsigned long listenPort, const std::shared_ptr<std::atomic_flag> &checkFlag,
160 std::string promptString = "", const std::shared_ptr<prometheus::Registry> &reg = nullptr,
161 const std::string &prependName = "");
162
164 void shutdown();
165
168
171
172 void tabCallback(FPTR_TabCallback func) { m_tabCallback = std::move(func); }
174
175 const VEC_SP_TelnetSession &sessions() const { return m_sessions; }
176
177 bool interactivePrompt() const { return m_promptString.length() > 0; }
178 void promptString(const std::string_view &prompt) { m_promptString = prompt; }
179 const std::string &promptString() const { return m_promptString; }
180
181 private:
182 // Called after the telnet session is initialised. function(SP_TelnetSession) {}
184 // Called after every new line (from CR or LF) function(SP_TelnetSession, std::string) {}
186 // Called after TAB detected. function(SP_TelnetSession, std::string, PredictSignalType) {}
188
189 bool acceptConnection();
190 void threadFunc() noexcept;
191
193 void update();
194
195 unsigned long m_listenPort{};
198 bool m_initialised{false};
199 // A string that denotes the current prompt
200 std::string m_promptString;
201
202 // Statistics
203 std::unique_ptr<TelnetStats> m_stats;
204
205 std::atomic_flag m_shouldStop{false};
206 std::unique_ptr<std::thread> m_serverThread;
207 std::shared_ptr<std::atomic_flag> m_checkFlag;
208};
209
214void TelnetConnectedCallback(const SP_TelnetSession &session);
215
221bool TelnetMessageCallback(const SP_TelnetSession &session, const std::string &line);
222
229std::string TelnetTabCallback(const SP_TelnetSession &session, std::string_view line);
std::vector< SP_TelnetSession > VEC_SP_TelnetSession
std::function< std::string(SP_TelnetSession, std::string)> FPTR_TabCallback
int Socket
void TelnetConnectedCallback(const SP_TelnetSession &session)
std::shared_ptr< TelnetSession > SP_TelnetSession
std::string TelnetTabCallback(const SP_TelnetSession &session, std::string_view line)
std::function< void(SP_TelnetSession)> FPTR_ConnectedCallback
std::function< bool(SP_TelnetSession, std::string)> FPTR_NewLineCallback
bool TelnetMessageCallback(const SP_TelnetSession &session, const std::string &line)
void promptString(const std::string_view &prompt)
TelnetServer()=default
Constructor for server.
std::unique_ptr< TelnetStats > m_stats
bool acceptConnection()
void newLineCallback(FPTR_NewLineCallback func)
FPTR_NewLineCallback m_newlineCallback
FPTR_NewLineCallback newLineCallBack() const
FPTR_TabCallback m_tabCallback
unsigned long m_listenPort
std::atomic_flag m_shouldStop
std::string m_promptString
bool interactivePrompt() const
const VEC_SP_TelnetSession & sessions() const
std::unique_ptr< std::thread > m_serverThread
FPTR_TabCallback tabCallback() const
bool initialise(unsigned long listenPort, const std::shared_ptr< std::atomic_flag > &checkFlag, std::string promptString="", const std::shared_ptr< prometheus::Registry > &reg=nullptr, const std::string &prependName="")
void shutdown()
Closes the Telnet Server.
VEC_SP_TelnetSession m_sessions
void threadFunc() noexcept
void connectedCallback(FPTR_ConnectedCallback func)
TelnetServer(TelnetServer &&)=delete
Move constructor.
void tabCallback(FPTR_TabCallback func)
FPTR_ConnectedCallback connectedCallback() const
std::shared_ptr< std::atomic_flag > m_checkFlag
const std::string & promptString() const
TelnetServer & operator=(TelnetServer &&)=delete
Move assignment operator.
~TelnetServer()
Destructor for server.
void update()
Process new connections and messages.
TelnetServer(const TelnetServer &)=delete
Copy constructor.
Socket m_listenSocket
FPTR_ConnectedCallback m_connectedCallback
TelnetServer & operator=(TelnetServer)=delete
Copy assignment operator.
void update()
Called every frame/loop by the Terminal Server.
TelnetSessionStats stats
Statistics variables.
bool processTab(std::string &buffer)
void markTimeout()
Marks timeout to close session.
bool processCommandHistory(std::string &buffer)
std::chrono::system_clock::time_point lastSeenTime
static bool processBackspace(std::string &buffer)
std::string m_buffer
TelnetSession(Socket ClientSocket, std::shared_ptr< TelnetServer > tServer)
Constructor for session.
static void stripEscapeCharacters(std::string &buffer)
static void stripNVT(std::string &buffer)
bool checkTimeout() const
Checks the connection timeout.
void sendLine(std::string data)
Send a line of data to the Telnet Server.
std::shared_ptr< TelnetServer > m_telnetServer
void sendPromptAndBuffer()
static std::vector< std::string > getCompleteLines(std::string &buffer)
void closeClient()
Finish the session.
std::list< std::string > m_history
void initialise()
Initialise session.
void echoBack(const char *buffer, unsigned long length)
void addToHistory(const std::string &line)
std::string getPeerIP() const
std::list< std::string >::iterator m_historyCursor