API
telnetConn.hpp
Go to the documentation of this file.
1 /** \file telnetConn.hpp
2  * \brief Managing a connection to a telnet device.
3  * \author Jared R. Males (jaredmales@gmail.com)
4  *
5  * \ingroup tty_files
6  * History:
7  * - 2018-08-24 created by JRM
8  */
9 #ifndef telnet_telnetConn_hpp
10 #define telnet_telnetConn_hpp
11 
12 
13 /* Much of the code in this file was taken from telnet-client.c in
14  * libtelnet (https://github.com/seanmiddleditch/libtelnet), with modifications for our needs.
15  *
16  * That code was placed in the public domain:
17  *
18  * libtelnet - TELNET protocol handling library
19  *
20  * Sean Middleditch
21  * sean@sourcemud.org
22  *
23  * The author or authors of [the libtelnet] code dedicate any and all copyright interest
24  * in [the libtelnet] to the public domain. We make this dedication for the benefit
25  * of the public at large and to the detriment of our heirs and successors. We
26  * intend this dedication to be an overt act of relinquishment in perpetuity of
27  * all present and future rights to this code under copyright law.
28  */
29 
30 
31 #include <mx/sys/timeUtils.hpp>
32 
33 #include "../../libs/libtelnet/libtelnet.h"
34 #include "ttyErrors.hpp"
35 #include "ttyIOUtils.hpp"
36 
37 namespace MagAOX
38 {
39 namespace tty
40 {
41 
42 #ifndef TELNET_BUFFSIZE
43  #define TELNET_BUFFSIZE (1024)
44 #endif
45 
46 /// libtelnet option table.
47 /** \ingroup tty
48  */
49 static const telnet_telopt_t telopts[] = {
50  { TELNET_TELOPT_ECHO, TELNET_WONT, TELNET_DO },
51  { TELNET_TELOPT_TTYPE, TELNET_WILL, TELNET_DONT },
52  { TELNET_TELOPT_COMPRESS2, TELNET_WONT, TELNET_DO },
53  { TELNET_TELOPT_MSSP, TELNET_WONT, TELNET_DO },
54  { -1, 0, 0 } };
55 
56 #define TELNET_WAITING_USER (0)
57 #define TELNET_GOT_USER (1)
58 #define TELNET_WAITING_PASS (2)
59 #define TELNET_GOT_PASS (3)
60 #define TELNET_WAITING_PROMPT (4)
61 #define TELNET_LOGGED_IN (5)
62 
63 /// A Telnet connection manager, wrapping \p libtelnet.
64 /**
65  * Establishes the connection to the server, and initializes the
66  * \p libtelnet structure, including registering the event handler callback.
67  *
68  * Errors encountered during telnet event handling are indicated by an internal flag,
69  * which must be checked each time a libtelnet function is called. If it is nonzero an
70  * error has occurred.
71  *
72  * Responses from the server are accumulated in the \p m_strRead member. It is typically
73  * cleared before reading, but this can be suppressed when desired.
74  *
75  * Because of the way event handling is managed, and the class-global error and response accumulation
76  * this is not thread-safe. Any calls to this class methods should be mutex-ed.
77  *
78  * \ingroup tty
79  */
80 struct telnetConn
81 {
82  int m_sock {0}; ///< The socket file descriptor.
83 
84  telnet_t * m_telnet {nullptr}; ///< libtelnet telnet_t structure
85 
86  ///The device's username entry prompt, used for managing login.
87  std::string m_usernamePrompt {"Username:"};
88 
89  ///The device's password entry prompt, used for managing login.
90  std::string m_passwordPrompt {"Password:"};
91 
92  std::string m_prompt {"$> "}; ///< The device's prompt, used for detecting end of transmission.
93 
94  ///Flag denoting the login state.
95  /** Used to manage different behaviors in the libtelnet event handler.
96  *
97  * - TELNET_WAITING_USER: waiting on m_usernamePrompt
98  * - TELNET_GOT_USER: got m_usernamePrompt
99  * - TELNET_WAITING_PASS: waiting on m_passwordPrompt
100  * - TELNET_GOT_PASS: got m_passwordPrompt
101  * - TELNET_WAITING_PROMPT: waiting on m_prompt
102  * - TELNET_LOGGED_IN: logged in
103  */
104  int m_loggedin {0};
105 
106  /// Used to indicate an error occurred in the event handler callback.
107  int m_EHError {0};
108 
109  /// The accumulated string read from the device.
110  /** This needs to be clear()-ed when expecting a new response to start.
111  * \warning This makes telnetConn NOT threadsafe.
112  */
113  std::string m_strRead;
114 
115  /// D'tor, conducts connection cleanup.
116  ~telnetConn();
117 
118  /// Connect to the device
119  int connect( const std::string & host, ///< [in] The host specification (i.p. address)
120  const std::string & port ///< [in] the port on the host.
121  );
122 
123  /// Manage the login process on this device.
124  int login( const std::string & username, /// [in] The username
125  const std::string & password /// [in] The password.
126  );
127 
128  /// Set flags as if we're logged in, used when device doesn't require it.
129  int noLogin();
130 
131  /// Write to a telnet connection
132  /**
133  *
134  * \returns TTY_E_NOERROR on success
135  * \returns TTY_E_TIMEOUTONWRITEPOLL if the poll times out.
136  * \returns TTY_E_ERRORONWRITEPOLL if an error is returned by poll.
137  * \returns TTY_E_TIMEOUTONWRITE if a timeout occurs during the write.
138  * \returns TTY_E_ERRORONWRITE if an error occurs writing to the file.
139  */
140  int write( const std::string & buffWrite, ///< [in] The characters to write to the telnet.
141  int timeoutWrite ///< [in] The timeout in milliseconds.
142  );
143 
144  /// Read from a telnet connection, until end-of-transmission string is read.
145  /**
146  * \returns TTY_E_NOERROR on success
147  * \returns TTY_E_TIMEOUTONREADPOLL if the poll times out.
148  * \returns TTY_E_ERRORONREADPOLL if an error is returned by poll.
149  * \returns TTY_E_TIMEOUTONREAD if a timeout occurs during the read.
150  * \returns TTY_E_ERRORONREAD if an error occurs reading from the file.
151  */
152  int read( const std::string & eot, ///< [in] the end-of-transmission indicator
153  int timeoutRead, ///< [in] The timeout in milliseconds.
154  bool clear=true ///< [in] [optional] whether or not to clear the strRead buffer
155  );
156 
157  /// Read from a telnet connection, until m_prompt is read.
158  /**
159  * \returns TTY_E_NOERROR on success
160  * \returns TTY_E_TIMEOUTONREADPOLL if the poll times out.
161  * \returns TTY_E_ERRORONREADPOLL if an error is returned by poll.
162  * \returns TTY_E_TIMEOUTONREAD if a timeout occurs during the read.
163  * \returns TTY_E_ERRORONREAD if an error occurs reading from the file.
164  */
165  int read( int timeoutRead, ///< [in] The timeout in milliseconds.
166  bool clear=true ///< [in] [optional] whether or not to clear the strRead buffer
167  );
168 
169  /// Write to a telnet connection, then get the reply.
170  /** The read is conducted until the m_prompt string is received.
171  * Echo characters are swallowed if desired.
172  *
173  * \returns TTY_E_NOERROR on success
174  * \returns TTY_E_TIMEOUTONWRITEPOLL if the poll times out.
175  * \returns TTY_E_ERRORONWRITEPOLL if an error is returned by poll.
176  * \returns TTY_E_TIMEOUTONWRITE if a timeout occurs during the write.
177  * \returns TTY_E_ERRORONWRITE if an error occurs writing to the file.
178  * \returns TTY_E_TIMEOUTONREADPOLL if the poll times out.
179  * \returns TTY_E_ERRORONREADPOLL if an error is returned by poll.
180  * \returns TTY_E_TIMEOUTONREAD if a timeout occurs during the read.
181  * \returns TTY_E_ERRORONREAD if an error occurs reading from the file.
182  */
183  int writeRead( const std::string & strWrite, ///< [in] The characters to write to the telnet.
184  bool swallowEcho, ///< [in] If true, strWrite.size() characters are read after the write
185  int timeoutWrite, ///< [in] The write timeout in milliseconds.
186  int timeoutRead ///< [in] The read timeout in milliseconds.
187  );
188 
189  /// Internal send for use by event_handler.
190  static int send( int sock,
191  const char *buffer,
192  size_t size
193  );
194 
195  /// Event handler callback for libtelnet processing.
196  /** Resets the internal m_EHError value to TTY_E_NOERROR on entry.
197  * Will set it to an error flag if an error is encountered, so this
198  * flag should be checked after any call to a libtelnet function.
199  * \warning this makes telnetConn not thread safe
200  */
201  static void event_handler( telnet_t *telnet,
202  telnet_event_t *ev,
203  void *user_data
204  );
205 };
206 
207 } //namespace tty
208 } //namespace MagAOX
209 
210 #endif //telnet_telnetConn_hpp
static const telnet_telopt_t telopts[]
libtelnet option table.
Definition: telnetConn.hpp:49
Definition: dm.hpp:24
A Telnet connection manager, wrapping libtelnet.
Definition: telnetConn.hpp:81
int m_EHError
Used to indicate an error occurred in the event handler callback.
Definition: telnetConn.hpp:107
int login(const std::string &username, const std::string &password)
Manage the login process on this device.
Definition: telnetConn.cpp:90
std::string m_usernamePrompt
The device's username entry prompt, used for managing login.
Definition: telnetConn.hpp:87
int write(const std::string &buffWrite, int timeoutWrite)
Write to a telnet connection.
Definition: telnetConn.cpp:182
telnet_t * m_telnet
libtelnet telnet_t structure
Definition: telnetConn.hpp:84
~telnetConn()
D'tor, conducts connection cleanup.
Definition: telnetConn.cpp:24
static int send(int sock, const char *buffer, size_t size)
Internal send for use by event_handler.
Definition: telnetConn.cpp:353
std::string m_strRead
The accumulated string read from the device.
Definition: telnetConn.hpp:113
static void event_handler(telnet_t *telnet, telnet_event_t *ev, void *user_data)
Event handler callback for libtelnet processing.
Definition: telnetConn.cpp:378
int m_loggedin
Flag denoting the login state.
Definition: telnetConn.hpp:104
int m_sock
The socket file descriptor.
Definition: telnetConn.hpp:82
int noLogin()
Set flags as if we're logged in, used when device doesn't require it.
Definition: telnetConn.cpp:176
std::string m_passwordPrompt
The device's password entry prompt, used for managing login.
Definition: telnetConn.hpp:90
std::string m_prompt
The device's prompt, used for detecting end of transmission.
Definition: telnetConn.hpp:92
int writeRead(const std::string &strWrite, bool swallowEcho, int timeoutWrite, int timeoutRead)
Write to a telnet connection, then get the reply.
Definition: telnetConn.cpp:294
int read(const std::string &eot, int timeoutRead, bool clear=true)
Read from a telnet connection, until end-of-transmission string is read.
Definition: telnetConn.cpp:223
int connect(const std::string &host, const std::string &port)
Connect to the device.
Definition: telnetConn.cpp:31
Error numbers for the tty utilities.
Utilities for i/o on a file descriptor pointing to a tty device.