21 #include <boost/algorithm/string/case_conv.hpp> 31 : handle_ (handle), charState_ (NORMAL), command_ (CMD_NONE), option_ (0),
32 inputEvent_ (
"senf::term::BaseTelnetProtocol::input",
34 scheduler::FdEvent::EV_READ),
35 outputEvent_ (
"senf::term::BaseTelnetProtocol::output",
37 scheduler::FdEvent::EV_WRITE, false),
38 pendingRequests_ (0u),
39 requestTimeout_ (
ClockService::milliseconds(DEFAULT_REQUEST_TIMEOUT_MS)),
40 timeout_ (
"senf::term::BaseTelnetProtocol::configTimeout",
45 : handle_ (), charState_ (NORMAL), command_ (CMD_NONE), option_ (0),
46 inputEvent_ (
"senf::term::BaseTelnetProtocol::input", 0),
47 outputEvent_ (
"senf::term::BaseTelnetProtocol::output", 0),
48 pendingRequests_ (0u),
50 timeout_ (
"senf::term::BaseTelnetProtocol::timeout", 0)
53 "Missing BaseTelnetProtocol constructor call in derived class " 54 "(BaseTelnetProtocol is a VIRTUAL base and MUST be constructed explicitly " 55 "in the most derived class." );
60 for (std::string::const_iterator i (s.begin()); i != s.end(); ++i)
87 std::string
const & data)
92 for (std::string::const_iterator i (data.begin()); i != data.end(); ++i)
127 prefix_ void senf::term::BaseTelnetProtocol::handleChar(
char c)
129 switch (charState_) {
134 handleCommand(static_cast<unsigned char>(c));
154 prefix_ void senf::term::BaseTelnetProtocol::handleNormalChar(
char c)
158 charState_ = CR_SEEN;
161 charState_ = IAC_SEEN;
169 prefix_ void senf::term::BaseTelnetProtocol::handleCommand(
char c)
171 switch (static_cast<unsigned char>(c)) {
185 command_ = Command(static_cast<unsigned char>(c));
191 charState_ = SB_OPTION;
197 command_ = Command(static_cast<unsigned char>(c));
198 charState_ = EXPECT_OPTION;
212 prefix_ void senf::term::BaseTelnetProtocol::handleOption(
char c)
219 prefix_ void senf::term::BaseTelnetProtocol::handleCR(
char c)
238 prefix_ void senf::term::BaseTelnetProtocol::handleSBOption(
char c)
241 charState_ = SB_DATA;
245 prefix_ void senf::term::BaseTelnetProtocol::handleSBData(
char c)
248 charState_ = SB_IAC_SEEN;
253 prefix_ void senf::term::BaseTelnetProtocol::handleSBIAC(
char c)
255 switch (static_cast<unsigned char>(c)) {
258 charState_ = SB_DATA;
265 charState_ = IAC_SEEN;
271 prefix_ void senf::term::BaseTelnetProtocol::processCommand()
305 OptionHandlerMap::const_iterator i (handlers_.find(option_));
306 if (i != handlers_.end())
307 i->second->v_handleOptionParameters(data_);
312 response(getOption(
false, option_), command_ == CMD_WILL);
316 response(getOption(
true, option_), command_ == CMD_DO);
321 prefix_ void senf::term::BaseTelnetProtocol::transmit(
char c)
323 sendQueue_.push_back(c);
330 timeout_.
timeout(scheduler::eventTime() + requestTimeout_);
333 prefix_ void senf::term::BaseTelnetProtocol::readHandler(
int state)
341 handle_.
read(data, 0u);
342 for (std::string::const_iterator i (data.begin()); i != data.end(); ++i)
346 prefix_ void senf::term::BaseTelnetProtocol::writeHandler(
int state)
354 sendQueue_.erase(sendQueue_.begin(),
355 handle_.
write(boost::make_iterator_range(
356 sendQueue_.begin(), sendQueue_.end())));
357 if (sendQueue_.empty())
361 prefix_ void senf::term::BaseTelnetProtocol::timeout()
363 if (pendingRequests_ > 0u) {
364 pendingRequests_ = 0u;
369 prefix_ senf::term::BaseTelnetProtocol::OptInfo &
370 senf::term::BaseTelnetProtocol::getOption(
bool local,
option_type option)
372 OptionsMap::iterator i (options_.find(std::make_pair(local, option)));
373 if (i == options_.end())
374 i = options_.insert(std::make_pair(std::make_pair(local, option),
375 OptInfo(local, option))).first;
379 prefix_ void senf::term::BaseTelnetProtocol::request(OptInfo & info,
bool enabled)
381 info.wantState = enabled ? OptInfo::WANTED : OptInfo::DISABLED;
382 if (enabled != info.enabled) {
384 transmit((info.local ? CMD_WILL : CMD_DO) + (enabled ? 0 : 1));
385 transmit(info.option);
386 info.optionState = OptInfo::REQUEST_SENT;
391 prefix_ void senf::term::BaseTelnetProtocol::response(OptInfo & info,
bool enabled)
393 bool decrementCount (
false);
399 if (info.optionState == OptInfo::REQUEST_SENT) {
401 info.optionState = OptInfo::ACKNOWLEDGED;
402 info.enabled = enabled;
403 decrementCount =
true;
405 else if (enabled != info.enabled) {
408 (enabled && (info.wantState == OptInfo::WANTED || info.wantState == OptInfo::ACCEPTED))) {
410 info.optionState = OptInfo::ACKNOWLEDGED;
411 info.enabled = enabled;
414 transmit((info.local ? CMD_WILL : CMD_DO) + (info.enabled ? 0 : 1));
415 transmit(info.option);
420 OptionHandlerMap::const_iterator i (handlers_.find(info.option));
421 if (i != handlers_.end())
432 if (pendingRequests_ > 0u) {
434 if (pendingRequests_ == 0u) {
454 prefix_ void senf::term::telnethandler::TerminalType::
455 v_handleOptionParameters(std::string
const &
data)
457 if (data.size() <= 0)
459 if (data[0] ==
'\x00') {
460 type_ = data.substr(1);
461 boost::algorithm::to_lower(type_);
466 prefix_ void senf::term::telnethandler::TerminalType::v_init()
476 : width_ (0u), height_ (0u)
481 prefix_ void senf::term::telnethandler::NAWS::v_init()
487 senf::term::telnethandler::NAWS::v_handleOptionParameters(std::string
const &
data)
489 if (data.size() != 4)
491 width_ = (
static_cast<unsigned char>(data[0])<<8)+
static_cast<unsigned char>(data[1]);
492 height_ = (
static_cast<unsigned char>(data[2])<<8)+
static_cast<unsigned char>(data[3]);
virtual void v_handleGA()
Called, when the peer sends a GoAhead.
void nextTerminalType()
Request another terminal type.
static unsigned const DEFAULT_REQUEST_TIMEOUT_MS
BaseTelnetProtocol()
Provided for TelnetHandler mixins only.
virtual void v_handleEC()
Called, when the peer sends an EraseCharacter.
virtual void v_handleBRK()
Called, when the peer sends a BReaK.
void write(std::string const &s)
Send string to peer.
u8 data[SPECTRAL_HT20_NUM_BINS]
void incrementRequestCounter()
Increment request counter.
virtual void v_handleEL()
Called, when the peer sends an EraseLine.
void sendOptionParameters(option_type option, std::string const &data)
Send extended option parameter to peer.
boost::function< R(Args)> membind(R(T::*fn)(Args), T *ob)
virtual void v_windowSizeChanged()=0
Called, whenever window size changes.
void registerHandler(Handler *h, bool request=true)
Register a TelnetHandler.
std::string read(unsigned limit=0)
virtual void v_handleIP()
Called, when the peer sends an InterruptProcess.
void timeout(ClockService::clock_type const &timeout, bool initiallyEnabled=true)
bool requestsPending()
true, if there are pending requests
Telnet protocol implementation.
virtual void v_eof()=0
Called on input EOF.
void decrementRequestCounter()
Decrement request counter.
#define SENF_ASSERT(x, comment)
unsigned char option_type
Type of telnet option numbers.
virtual void v_setupComplete()=0
Called, when no further requests are pending.
virtual void v_handleAYT()
Called, when the peer sends an AreYouThere.
virtual void v_handleNOP()
Called, when the peer sends a NOP.
BaseTelnetProtocol::option_type const TERMINAL_TYPE
boost::range_const_iterator< ForwardReadableRange const >::type write(ForwardReadableRange const &range)
virtual void v_handleAO()
Called, when the peer sends an AbortOutput.