4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 // Stefan Bund <g0dil@berlios.de>
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 \brief Telnet non-inline non-template implementation */
27 //#include "Telnet.ih"
30 #include "../membind.hh"
31 #include "../Logger/SenfLog.hh"
33 //#include "Telnet.mpp"
35 ///////////////////////////////cc.p////////////////////////////////////////
37 prefix_ senf::console::detail::BaseTelnetProtocol::BaseTelnetProtocol(Handle handle)
38 : handle_ (handle), charState_ (NORMAL), command_ (CMD_NONE), option_ (0),
39 inputEvent_ ("senf::console::detail::BaseTelnetProtocol::input",
40 senf::membind(&BaseTelnetProtocol::readHandler, this), handle,
41 senf::scheduler::FdEvent::EV_READ),
42 outputEvent_ ("senf::console::detail::BaseTelnetProtocol::output",
43 senf::membind(&BaseTelnetProtocol::writeHandler, this), handle,
44 senf::scheduler::FdEvent::EV_WRITE, false)
47 prefix_ senf::console::detail::BaseTelnetProtocol::BaseTelnetProtocol()
48 : handle_ (), charState_ (NORMAL), command_ (CMD_NONE), option_ (0),
49 inputEvent_ ("senf::console::detail::BaseTelnetProtocol::input", 0),
50 outputEvent_ ("senf::console::detail::BaseTelnetProtocol::output", 0)
53 prefix_ void senf::console::detail::BaseTelnetProtocol::write(std::string const & s)
55 for (std::string::const_iterator i (s.begin()); i != s.end(); ++i)
59 prefix_ void senf::console::detail::BaseTelnetProtocol::write(char c)
81 senf::console::detail::BaseTelnetProtocol::sendOptionParameters(option_type option,
82 std::string const & data)
87 for (std::string::const_iterator i (data.begin()); i != data.end(); ++i)
98 prefix_ void senf::console::detail::BaseTelnetProtocol::v_handleNOP()
101 prefix_ void senf::console::detail::BaseTelnetProtocol::v_handleBRK()
104 prefix_ void senf::console::detail::BaseTelnetProtocol::v_handleIP()
107 prefix_ void senf::console::detail::BaseTelnetProtocol::v_handleAO()
110 prefix_ void senf::console::detail::BaseTelnetProtocol::v_handleAYT()
113 prefix_ void senf::console::detail::BaseTelnetProtocol::v_handleEC()
116 prefix_ void senf::console::detail::BaseTelnetProtocol::v_handleEL()
119 prefix_ void senf::console::detail::BaseTelnetProtocol::v_handleGA()
122 prefix_ void senf::console::detail::BaseTelnetProtocol::handleChar(char c)
124 switch (charState_) {
129 handleCommand(static_cast<unsigned char>(c));
149 prefix_ void senf::console::detail::BaseTelnetProtocol::handleNormalChar(char c)
153 charState_ = CR_SEEN;
156 charState_ = IAC_SEEN;
164 prefix_ void senf::console::detail::BaseTelnetProtocol::handleCommand(char c)
168 // Ignore spurious SE commands .. they should only occur while in subnegotiation mode
180 command_ = Command(static_cast<unsigned char>(c));
186 charState_ = SB_OPTION;
192 command_ = Command(static_cast<unsigned char>(c));
193 charState_ = EXPECT_OPTION;
207 prefix_ void senf::console::detail::BaseTelnetProtocol::handleOption(char c)
214 prefix_ void senf::console::detail::BaseTelnetProtocol::handleCR(char c)
233 prefix_ void senf::console::detail::BaseTelnetProtocol::handleSBOption(char c)
236 charState_ = SB_DATA;
240 prefix_ void senf::console::detail::BaseTelnetProtocol::handleSBData(char c)
243 charState_ = SB_IAC_SEEN;
248 prefix_ void senf::console::detail::BaseTelnetProtocol::handleSBIAC(char c)
253 charState_ = SB_DATA;
260 charState_ = IAC_SEEN;
266 prefix_ void senf::console::detail::BaseTelnetProtocol::processCommand()
300 OptionHandlerMap::const_iterator i (handlers_.find(option_));
301 if (i != handlers_.end())
302 i->second->v_handleOptionParameters(data_);
307 response(getOption(false, option_), command_ == CMD_WILL);
311 response(getOption(true, option_), command_ == CMD_DO);
316 prefix_ void senf::console::detail::BaseTelnetProtocol::transmit(char c)
318 sendQueue_.push_back(c);
319 outputEvent_.enable();
322 prefix_ void senf::console::detail::BaseTelnetProtocol::readHandler(int state)
324 if (state != senf::scheduler::FdEvent::EV_READ || handle_.eof()) {
325 inputEvent_.disable();
330 handle_.read(data, 0u);
331 for (std::string::const_iterator i (data.begin()); i != data.end(); ++i)
335 prefix_ void senf::console::detail::BaseTelnetProtocol::writeHandler(int state)
337 if (state != senf::scheduler::FdEvent::EV_WRITE) {
338 outputEvent_.disable();
339 inputEvent_.disable();
343 sendQueue_.erase(sendQueue_.begin(),
344 handle_.write(std::make_pair(sendQueue_.begin(), sendQueue_.end())));
345 if (sendQueue_.empty())
346 outputEvent_.disable();
349 prefix_ senf::console::detail::BaseTelnetProtocol::OptInfo &
350 senf::console::detail::BaseTelnetProtocol::getOption(bool local, option_type option)
352 OptionsMap::iterator i (options_.find(std::make_pair(local, option)));
353 if (i == options_.end())
354 i = options_.insert(std::make_pair(std::make_pair(local, option),
355 OptInfo(local, option))).first;
359 prefix_ void senf::console::detail::BaseTelnetProtocol::request(OptInfo & info, bool enabled)
361 info.wantState = enabled ? OptInfo::WANTED : OptInfo::DISABLED;
362 if (enabled != info.enabled) {
364 transmit((info.local ? CMD_WILL : CMD_DO) + (enabled ? 0 : 1));
365 transmit(info.option);
366 info.optionState = OptInfo::REQUEST_SENT;
370 prefix_ void senf::console::detail::BaseTelnetProtocol::response(OptInfo & info, bool enabled)
372 // If this is a response, we need to unconditionally accept it. If this is a remote
373 // configuration request, we accept it if wantState is wither WANTED or ACCEPTED. If this is a
374 // response, we never send out a reply. If it is a remote request we send out a reply only if
375 // either a) we reject the request or b) we accept it AND we have changed our own mode.
376 if (info.optionState == OptInfo::REQUEST_SENT) {
377 // This is a response
378 info.optionState = OptInfo::ACKNOWLEDGED;
379 info.enabled = enabled;
381 else if (enabled != info.enabled) {
382 // Request to change the current state
383 bool accept (enabled);
385 enabled && (info.wantState == OptInfo::WANTED || info.wantState == OptInfo::ACCEPTED)) {
386 // Accept the request
387 info.optionState = OptInfo::ACKNOWLEDGED;
388 info.enabled = enabled;
391 // Reject the request
392 accept = info.enabled;
394 transmit((info.local ? CMD_WILL : CMD_DO) + (accept ? 0 : 1));
395 transmit(info.option);
400 OptionHandlerMap::const_iterator i (handlers_.find(info.option));
401 if (i != handlers_.end())
406 ///////////////////////////////////////////////////////////////////////////
407 // senf::console::detail::telnethandler::TerminalType
409 prefix_ senf::console::detail::telnethandler::TerminalType::TerminalType()
411 registerHandler(this);
414 prefix_ void senf::console::detail::telnethandler::TerminalType::nextTerminalType()
416 sendOptionParameters(telnetopt::TERMINAL_TYPE, "\x01");
419 prefix_ void senf::console::detail::telnethandler::TerminalType::
420 v_handleOptionParameters(std::string const & data)
422 if (data.size() <= 0)
424 if (data[0] == '\x00')
425 v_handleTerminalType(data.substr(1));
428 prefix_ void senf::console::detail::telnethandler::TerminalType::v_init()
433 ///////////////////////////////////////////////////////////////////////////
434 // senf::console::detail::telnethandler::NAWS
436 prefix_ senf::console::detail::telnethandler::NAWS::NAWS()
438 registerHandler(this);
441 prefix_ void senf::console::detail::telnethandler::NAWS::v_init()
445 senf::console::detail::telnethandler::NAWS::v_handleOptionParameters(std::string const & data)
447 if (data.size() != 4)
450 (static_cast<unsigned char>(data[0])<<8)+static_cast<unsigned char>(data[1]),
451 (static_cast<unsigned char>(data[2])<<8)+static_cast<unsigned char>(data[3]));
454 ///////////////////////////////cc.e////////////////////////////////////////
456 //#include "Telnet.mpp"
462 // comment-column: 40
463 // c-file-style: "senf"
464 // indent-tabs-mode: nil
465 // ispell-local-dictionary: "american"
466 // compile-command: "scons -u test"