API
 
Loading...
Searching...
No Matches
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
37namespace MagAOX
38{
39namespace tty
40{
41
42#ifndef TELNET_BUFFSIZE
43 #define TELNET_BUFFSIZE (1024)
44#endif
45
46/// libtelnet option table.
47/** \ingroup tty
48 */
49static 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 */
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 dm.hpp:24
A Telnet connection manager, wrapping libtelnet.
int m_EHError
Used to indicate an error occurred in the event handler callback.
int login(const std::string &username, const std::string &password)
Manage the login process on this device.
std::string m_usernamePrompt
The device's username entry prompt, used for managing login.
int write(const std::string &buffWrite, int timeoutWrite)
Write to a telnet connection.
telnet_t * m_telnet
libtelnet telnet_t structure
~telnetConn()
D'tor, conducts connection cleanup.
static int send(int sock, const char *buffer, size_t size)
Internal send for use by event_handler.
std::string m_strRead
The accumulated string read from the device.
static void event_handler(telnet_t *telnet, telnet_event_t *ev, void *user_data)
Event handler callback for libtelnet processing.
int m_loggedin
Flag denoting the login state.
int m_sock
The socket file descriptor.
int noLogin()
Set flags as if we're logged in, used when device doesn't require it.
std::string m_passwordPrompt
The device's password entry prompt, used for managing login.
std::string m_prompt
The device's prompt, used for detecting end of transmission.
int writeRead(const std::string &strWrite, bool swallowEcho, int timeoutWrite, int timeoutRead)
Write to a telnet connection, then get the reply.
int read(const std::string &eot, int timeoutRead, bool clear=true)
Read from a telnet connection, until end-of-transmission string is read.
int connect(const std::string &host, const std::string &port)
Connect to the device.
Error numbers for the tty utilities.
Utilities for i/o on a file descriptor pointing to a tty device.