Telnet++  3.1.0.2
A C++ library for interacting with Telnet streams
option.hpp
1 #pragma once
2 
3 #include "telnetpp/session.hpp"
4 
5 #include <boost/signals2.hpp>
6 
7 namespace telnetpp {
8 
9 //* =========================================================================
39 //* =========================================================================
40 template <
41  telnetpp::command_type LocalPositive,
42  telnetpp::command_type LocalNegative,
43  telnetpp::command_type RemotePositive,
44  telnetpp::command_type RemoteNegative>
45 class option
46 {
47 public:
48  static constexpr auto local_positive = LocalPositive;
49  static constexpr auto local_negative = LocalNegative;
50  static constexpr auto remote_positive = RemotePositive;
51  static constexpr auto remote_negative = RemoteNegative;
52 
53  //* =====================================================================
55  //* =====================================================================
56  virtual ~option() = default;
57 
58  //* =====================================================================
60  //* =====================================================================
61  [[nodiscard]] constexpr telnetpp::option_type option_code() const noexcept
62  {
63  return code_;
64  }
65 
66  //* =====================================================================
68  //* =====================================================================
69  [[nodiscard]] constexpr bool active() const noexcept
70  {
71  return state_ == internal_state::active;
72  }
73 
74  //* =====================================================================
76  //* =====================================================================
77  constexpr void activate()
78  {
79  switch (state_)
80  {
81  case internal_state::inactive:
82  state_ = internal_state::activating;
83  write_negotiation(local_positive);
84  break;
85 
86  case internal_state::activating:
87  break;
88 
89  case internal_state::active:
90  on_state_changed();
91  break;
92 
93  case internal_state::deactivating:
94  break;
95 
96  default:
97  assert(!"Unimplemented");
98  break;
99  }
100  }
101 
102  //* =====================================================================
104  //* =====================================================================
105  constexpr void deactivate()
106  {
107  switch (state_)
108  {
109  case internal_state::active:
110  state_ = internal_state::deactivating;
111  write_negotiation(local_negative);
112  break;
113 
114  case internal_state::activating:
115  break;
116 
117  case internal_state::inactive:
118  on_state_changed();
119  break;
120 
121  case internal_state::deactivating:
122  break;
123 
124  default:
125  assert(!"Unimplemented");
126  break;
127  }
128  }
129 
130  //* =====================================================================
134  //* =====================================================================
135  constexpr void negotiate(telnetpp::negotiation_type neg)
136  {
137  switch (state_)
138  {
139  case internal_state::inactive:
140  if (neg == remote_positive)
141  {
142  state_ = internal_state::active;
143  write_negotiation(local_positive);
144  on_state_changed();
145  }
146  else
147  {
148  write_negotiation(local_negative);
149  }
150  break;
151 
152  case internal_state::activating:
153  if (neg == remote_positive)
154  {
155  state_ = internal_state::active;
156  on_state_changed();
157  }
158  else
159  {
160  state_ = internal_state::inactive;
161  on_state_changed();
162  }
163  break;
164 
165  case internal_state::active:
166  if (neg == remote_positive)
167  {
168  write_negotiation(local_positive);
169  }
170  else
171  {
172  state_ = internal_state::inactive;
173  on_state_changed();
174  write_negotiation(local_negative);
175  }
176  break;
177 
178  case internal_state::deactivating:
179  if (neg == remote_positive)
180  {
181  state_ = internal_state::active;
182  on_state_changed();
183  }
184  else
185  {
186  state_ = internal_state::inactive;
187  on_state_changed();
188  }
189  break;
190 
191  default:
192  assert(!"Unimplemented");
193  break;
194  }
195  }
196 
197  //* =====================================================================
201  //* =====================================================================
202  constexpr void subnegotiate(telnetpp::bytes content)
203  {
204  if (state_ == internal_state::active)
205  {
206  handle_subnegotiation(content);
207  }
208  }
209 
210  //* =====================================================================
221  //* =====================================================================
222  boost::signals2::signal<void()> on_state_changed; // NOLINT
223 
224 protected:
225  //* =====================================================================
227  //* =====================================================================
228  constexpr explicit option(
229  telnetpp::session &sess, telnetpp::option_type code) noexcept
230  : session_{sess}, code_{code}
231  {
232  }
233 
234  //* =====================================================================
236  //* =====================================================================
237  void write_text(telnetpp::bytes content)
238  {
239  session_.write(content);
240  }
241 
242  //* =====================================================================
244  //* =====================================================================
245  void write_subnegotiation(telnetpp::bytes content)
246  {
247  session_.write(telnetpp::subnegotiation{code_, content});
248  }
249 
250 private:
251  //* =====================================================================
253  //* =====================================================================
254  void write_negotiation(telnetpp::negotiation_type neg)
255  {
256  session_.write(telnetpp::negotiation{neg, code_});
257  }
258 
259  //* =====================================================================
262  //* =====================================================================
263  virtual void handle_subnegotiation(telnetpp::bytes data) = 0;
264 
265  enum class internal_state
266  {
267  inactive,
268  activating,
269  active,
270  deactivating,
271  };
272 
273  telnetpp::session &session_;
274  telnetpp::option_type code_;
275  internal_state state_ = internal_state::inactive;
276 };
277 
278 } // namespace telnetpp
A class that encapsulates a Telnet negotiation.
Definition: negotiation.hpp:15
An class that encapsulates one side of a Telnet option.
Definition: option.hpp:46
constexpr void subnegotiate(telnetpp::bytes content)
Subnegotiate with the option. This should be called when a subnegotiation sequence has been received ...
Definition: option.hpp:202
constexpr void negotiate(telnetpp::negotiation_type neg)
Negotiate with the option. This should be called when the remote side either initiates a negotiation ...
Definition: option.hpp:135
virtual ~option()=default
Destructor.
constexpr option(telnetpp::session &sess, telnetpp::option_type code) noexcept
Constructor.
Definition: option.hpp:228
constexpr void deactivate()
Begins the deactivation process for the option.
Definition: option.hpp:105
void write_text(telnetpp::bytes content)
Write plain text to the session.
Definition: option.hpp:237
constexpr void activate()
Begins the activation process for the option.
Definition: option.hpp:77
constexpr bool active() const noexcept
Returns whether the option is active.
Definition: option.hpp:69
void write_subnegotiation(telnetpp::bytes content)
Write a subnegotiation to the session.
Definition: option.hpp:245
constexpr telnetpp::option_type option_code() const noexcept
Returns the code for the option.
Definition: option.hpp:61
An abstraction for a Telnet session.
Definition: session.hpp:141
void write(telnetpp::element const &elem)
Sends a Telnet data element. Translates the element into a sequence of bytes, that is then sent to th...
Definition: session.cpp:96
A class that encapsulates a Telnet subnegotiation.
Definition: subnegotiation.hpp:14