--- /dev/null
+// $Id$
+//
+// Copyright (C) 2008
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief FancyReader public header */
+
+#ifndef HH_SENF_Scheduler_Console_FancyReader_
+#define HH_SENF_Scheduler_Console_FancyReader_ 1
+
+// Custom includes
+#include "Server.hh"
+
+//#include "FancyReader.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace senf {
+namespace console {
+namespace detail {
+
+ class FancyClientReader
+ : public ClientReader
+ {
+ };
+
+}}
+
+///////////////////////////////hh.e////////////////////////////////////////
+//#include "FancyReader.cci"
+//#include "FancyReader.ct"
+//#include "FancyReader.cti"
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
###########################################################################
-sources, includes = SENFSCons.Glob(env, exclude=['testServer.cc'])
+sources, includes = SENFSCons.Glob(env, exclude=['testServer.cc', 'telnetServer.cc'])
SENFSCons.StandardTargets(env)
SENFSCons.Lib(env, sources)
SENFSCons.Doxygen(env)
SENFSCons.InstallIncludeFiles(env, includes)
+SENFSCons.Binary(env, "testServer", ['testServer.cc'])
+SENFSCons.Binary(env, "telnetServer", ['telnetServer.cc'])
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2008
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief Telnet non-inline non-template implementation */
+
+#include "Telnet.hh"
+//#include "Telnet.ih"
+
+// Custom includes
+#include "../membind.hh"
+#include "../Logger/SenfLog.hh"
+
+//#include "Telnet.mpp"
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+prefix_ senf::console::detail::BaseTelnetProtocol::BaseTelnetProtocol(Handle handle)
+ : handle_ (handle), charState_ (NORMAL), command_ (CMD_NONE), option_ (0),
+ inputEvent_ ("senf::console::detail::BaseTelnetProtocol::input",
+ senf::membind(&BaseTelnetProtocol::readHandler, this), handle,
+ senf::scheduler::FdEvent::EV_READ),
+ outputEvent_ ("senf::console::detail::BaseTelnetProtocol::output",
+ senf::membind(&BaseTelnetProtocol::writeHandler, this), handle,
+ senf::scheduler::FdEvent::EV_WRITE, false)
+{}
+
+prefix_ senf::console::detail::BaseTelnetProtocol::BaseTelnetProtocol()
+ : handle_ (), charState_ (NORMAL), command_ (CMD_NONE), option_ (0),
+ inputEvent_ ("senf::console::detail::BaseTelnetProtocol::input", 0),
+ outputEvent_ ("senf::console::detail::BaseTelnetProtocol::output", 0)
+{}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::write(std::string const & s)
+{
+ for (std::string::const_iterator i (s.begin()); i != s.end(); ++i)
+ write(*i);
+}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::write(char c)
+{
+ switch (c) {
+ case '\r':
+ transmit('\r');
+ transmit('\0');
+ break;
+ case '\n':
+ transmit('\r');
+ transmit('\n');
+ break;
+ case '\xff':
+ transmit('\xff');
+ transmit('\xff');
+ break;
+ default:
+ transmit(c);
+ break;
+ }
+}
+
+prefix_ void
+senf::console::detail::BaseTelnetProtocol::sendOptionParameters(option_type option,
+ std::string const & data)
+{
+ transmit(CMD_IAC);
+ transmit(CMD_SB);
+ transmit(option);
+ for (std::string::const_iterator i (data.begin()); i != data.end(); ++i)
+ if (*i == '\xff') {
+ transmit('\xff');
+ transmit('\xff');
+ }
+ else
+ transmit(*i);
+ transmit(CMD_IAC);
+ transmit(CMD_SE);
+}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::v_handleNOP()
+{}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::v_handleBRK()
+{}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::v_handleIP()
+{}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::v_handleAO()
+{}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::v_handleAYT()
+{}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::v_handleEC()
+{}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::v_handleEL()
+{}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::v_handleGA()
+{}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::handleChar(char c)
+{
+ switch (charState_) {
+ case NORMAL:
+ handleNormalChar(c);
+ break;
+ case IAC_SEEN:
+ handleCommand(static_cast<unsigned char>(c));
+ break;
+ case EXPECT_OPTION:
+ handleOption(c);
+ break;
+ case CR_SEEN:
+ handleCR(c);
+ break;
+ case SB_OPTION:
+ handleSBOption(c);
+ break;
+ case SB_DATA:
+ handleSBData(c);
+ break;
+ case SB_IAC_SEEN:
+ handleSBIAC(c);
+ break;
+ }
+}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::handleNormalChar(char c)
+{
+ switch (c) {
+ case '\r':
+ charState_ = CR_SEEN;
+ break;
+ case '\xff':
+ charState_ = IAC_SEEN;
+ break;
+ default:
+ emit(c);
+ break;
+ }
+}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::handleCommand(char c)
+{
+ switch (c) {
+ case CMD_SE:
+ // Ignore spurious SE commands .. they should only occur while in subnegotiation mode
+ charState_ = NORMAL;
+ break;
+ case CMD_NOP:
+ case CMD_DM:
+ case CMD_BRK:
+ case CMD_IP:
+ case CMD_AO:
+ case CMD_AYT:
+ case CMD_EC:
+ case CMD_EL:
+ case CMD_GA:
+ command_ = Command(static_cast<unsigned char>(c));
+ processCommand();
+ charState_ = NORMAL;
+ break;
+ case CMD_SB:
+ command_ = CMD_SB;
+ charState_ = SB_OPTION;
+ break;
+ case CMD_WILL:
+ case CMD_WONT:
+ case CMD_DO:
+ case CMD_DONT:
+ command_ = Command(static_cast<unsigned char>(c));
+ charState_ = EXPECT_OPTION;
+ break;
+ case CMD_IAC:
+ charState_ = NORMAL;
+ emit(CMD_IAC);
+ break;
+ default:
+ emit(CMD_IAC);
+ charState_ = NORMAL;
+ handleChar(c);
+ break;
+ }
+}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::handleOption(char c)
+{
+ option_ = c;
+ processCommand();
+ charState_ = NORMAL;
+}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::handleCR(char c)
+{
+ switch (c) {
+ case '\0':
+ emit('\r');
+ charState_ = NORMAL;
+ break;
+ case '\n':
+ emit('\n');
+ charState_ = NORMAL;
+ break;
+ default:
+ emit('\r');
+ charState_ = NORMAL;
+ handleChar(c);
+ break;
+ }
+}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::handleSBOption(char c)
+{
+ option_ = c;
+ charState_ = SB_DATA;
+ data_.clear();
+}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::handleSBData(char c)
+{
+ if (c == '\xff')
+ charState_ = SB_IAC_SEEN;
+ else
+ data_.push_back(c);
+}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::handleSBIAC(char c)
+{
+ switch (c) {
+ case CMD_IAC:
+ data_.push_back(c);
+ charState_ = SB_DATA;
+ break;
+ case CMD_SE:
+ processCommand();
+ charState_ = NORMAL;
+ break;
+ default:
+ charState_ = IAC_SEEN;
+ handleChar(c);
+ break;
+ }
+}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::processCommand()
+{
+ switch (command_) {
+ case CMD_NONE:
+ case CMD_SE:
+ case CMD_DM:
+ case CMD_IAC:
+ break;
+ case CMD_NOP:
+ v_handleNOP();
+ break;
+ case CMD_BRK:
+ v_handleBRK();
+ break;
+ case CMD_IP:
+ v_handleIP();
+ break;
+ case CMD_AO:
+ v_handleAO();
+ break;
+ case CMD_AYT:
+ v_handleAYT();
+ break;
+ case CMD_EC:
+ v_handleEC();
+ break;
+ case CMD_EL:
+ v_handleEL();
+ break;
+ case CMD_GA:
+ v_handleGA();
+ break;
+ case CMD_SB:
+ {
+ OptionHandlerMap::const_iterator i (handlers_.find(option_));
+ if (i != handlers_.end())
+ i->second->v_handleOptionParameters(data_);
+ break;
+ }
+ case CMD_WILL:
+ case CMD_WONT:
+ response(getOption(false, option_), command_ == CMD_WILL);
+ break;
+ case CMD_DO:
+ case CMD_DONT:
+ response(getOption(true, option_), command_ == CMD_DO);
+ break;
+ }
+}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::transmit(char c)
+{
+ sendQueue_.push_back(c);
+ outputEvent_.enable();
+}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::readHandler(int state)
+{
+ if (state != senf::scheduler::FdEvent::EV_READ || handle_.eof()) {
+ inputEvent_.disable();
+ v_eof();
+ return;
+ }
+ std::string data;
+ handle_.read(data, 0u);
+ for (std::string::const_iterator i (data.begin()); i != data.end(); ++i)
+ handleChar(*i);
+}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::writeHandler(int state)
+{
+ if (state != senf::scheduler::FdEvent::EV_WRITE) {
+ outputEvent_.disable();
+ inputEvent_.disable();
+ v_eof();
+ return;
+ }
+ sendQueue_.erase(sendQueue_.begin(),
+ handle_.write(std::make_pair(sendQueue_.begin(), sendQueue_.end())));
+ if (sendQueue_.empty())
+ outputEvent_.disable();
+}
+
+prefix_ senf::console::detail::BaseTelnetProtocol::OptInfo &
+senf::console::detail::BaseTelnetProtocol::getOption(bool local, option_type option)
+{
+ OptionsMap::iterator i (options_.find(std::make_pair(local, option)));
+ if (i == options_.end())
+ i = options_.insert(std::make_pair(std::make_pair(local, option),
+ OptInfo(local, option))).first;
+ return i->second;
+}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::request(OptInfo & info, bool enabled)
+{
+ info.wantState = enabled ? OptInfo::WANTED : OptInfo::DISABLED;
+ if (enabled != info.enabled) {
+ transmit(CMD_IAC);
+ transmit((info.local ? CMD_WILL : CMD_DO) + (enabled ? 0 : 1));
+ transmit(info.option);
+ info.optionState = OptInfo::REQUEST_SENT;
+ }
+}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::response(OptInfo & info, bool enabled)
+{
+ // If this is a response, we need to unconditionally accept it. If this is a remote
+ // configuration request, we accept it if wantState is wither WANTED or ACCEPTED. If this is a
+ // response, we never send out a reply. If it is a remote request we send out a reply only if
+ // either a) we reject the request or b) we accept it AND we have changed our own mode.
+ if (info.optionState == OptInfo::REQUEST_SENT) {
+ // This is a response
+ info.optionState = OptInfo::ACKNOWLEDGED;
+ info.enabled = enabled;
+ }
+ else if (enabled != info.enabled) {
+ // Request to change the current state
+ bool accept (enabled);
+ if (!enabled ||
+ enabled && (info.wantState == OptInfo::WANTED || info.wantState == OptInfo::ACCEPTED)) {
+ // Accept the request
+ info.optionState = OptInfo::ACKNOWLEDGED;
+ info.enabled = enabled;
+ }
+ else
+ // Reject the request
+ accept = info.enabled;
+ transmit(CMD_IAC);
+ transmit((info.local ? CMD_WILL : CMD_DO) + (accept ? 0 : 1));
+ transmit(info.option);
+ }
+ else
+ return;
+ if (info.enabled) {
+ OptionHandlerMap::const_iterator i (handlers_.find(info.option));
+ if (i != handlers_.end())
+ i->second->v_init();
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::telnethandler::TerminalType
+
+prefix_ senf::console::detail::telnethandler::TerminalType::TerminalType()
+{
+ registerHandler(this);
+}
+
+prefix_ void senf::console::detail::telnethandler::TerminalType::nextTerminalType()
+{
+ sendOptionParameters(telnetopt::TERMINAL_TYPE, "\x01");
+}
+
+prefix_ void senf::console::detail::telnethandler::TerminalType::
+v_handleOptionParameters(std::string const & data)
+{
+ if (data.size() <= 0)
+ return;
+ if (data[0] == '\x00')
+ v_handleTerminalType(data.substr(1));
+}
+
+prefix_ void senf::console::detail::telnethandler::TerminalType::v_init()
+{
+ nextTerminalType();
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::telnethandler::NAWS
+
+prefix_ senf::console::detail::telnethandler::NAWS::NAWS()
+{
+ registerHandler(this);
+}
+
+prefix_ void senf::console::detail::telnethandler::NAWS::v_init()
+{}
+
+prefix_ void
+senf::console::detail::telnethandler::NAWS::v_handleOptionParameters(std::string const & data)
+{
+ if (data.size() != 4)
+ return;
+ v_handleWindowSize(
+ (static_cast<unsigned char>(data[0])<<8)+static_cast<unsigned char>(data[1]),
+ (static_cast<unsigned char>(data[2])<<8)+static_cast<unsigned char>(data[3]));
+}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+//#include "Telnet.mpp"
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2008
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief Telnet inline non-template implementation */
+
+//#include "Telnet.ih"
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::BaseTelnetProtocol::OptInfo
+
+prefix_ senf::console::detail::BaseTelnetProtocol::OptInfo::OptInfo()
+ : local (false), option (0u), wantState (DISABLED), optionState (NONE), enabled (false)
+{}
+
+prefix_ senf::console::detail::BaseTelnetProtocol::OptInfo::OptInfo(bool l, option_type o)
+ : local (l), option (o), wantState (DISABLED), optionState (NONE), enabled (false)
+{}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::BaseTelnetProtocol::TelnetHandler
+
+prefix_ senf::console::detail::BaseTelnetProtocol::TelnetHandler::~TelnetHandler()
+{}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::BaseTelnetProtocol
+
+prefix_ senf::console::detail::BaseTelnetProtocol::~BaseTelnetProtocol()
+{}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::sendNOP()
+{
+ transmit(CMD_IAC);
+ transmit(CMD_NOP);
+}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::sendBRK()
+{
+ transmit(CMD_IAC);
+ transmit(CMD_BRK);
+}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::sendIP()
+{
+ transmit(CMD_IAC);
+ transmit(CMD_IP);
+}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::sendAO()
+{
+ transmit(CMD_IAC);
+ transmit(CMD_AO);
+}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::sendAYT()
+{
+ transmit(CMD_IAC);
+ transmit(CMD_AYT);
+}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::sendEC()
+{
+ transmit(CMD_IAC);
+ transmit(CMD_EC);
+}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::sendEL()
+{
+ transmit(CMD_IAC);
+ transmit(CMD_EL);
+}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::sendGA()
+{
+ transmit(CMD_IAC);
+ transmit(CMD_GA);
+}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::requestLocalOption(option_type option,
+ bool enabled)
+{
+ request(getOption(true, option), enabled);
+}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::acceptLocalOption(option_type option,
+ bool enabled)
+{
+ getOption(true, option).wantState = OptInfo::ACCEPTED;
+}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::requestPeerOption(option_type option,
+ bool enabled)
+{
+ request(getOption(false, option), enabled);
+}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::acceptPeerOption(option_type option,
+ bool enabled)
+{
+ getOption(false, option).wantState = OptInfo::ACCEPTED;
+}
+
+prefix_ void senf::console::detail::BaseTelnetProtocol::emit(char c)
+{
+ v_charReceived(c);
+}
+
+///////////////////////////////cci.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2008
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief Telnet inline template implementation */
+
+//#include "Telnet.ih"
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////cti.p///////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::BaseTelnetProtocol
+
+template <class Handler>
+prefix_ void senf::console::detail::BaseTelnetProtocol::registerHandler(Handler * h,
+ bool request)
+{
+ handlers_.insert(std::make_pair(Handler::OPTION_CODE, h));
+ if (request)
+ requestPeerOption(Handler::OPTION_CODE);
+}
+
+///////////////////////////////cti.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2008
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief Telnet public header */
+
+#ifndef HH_SENF_Scheduler_Console_Telnet_
+#define HH_SENF_Scheduler_Console_Telnet_ 1
+
+// Custom includes
+#include <vector>
+#include <map>
+#include <senf/Socket.hh>
+#include <senf/Scheduler/Scheduler.hh>
+
+//#include "Telnet.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace senf {
+namespace console {
+namespace detail {
+
+ /** \brief Telnet server
+
+ \see
+ <a href="http://tools.ietf.org/html/rfc854>RFC 854</a> The Telnet protocol \n
+ <a href="http://tools.ietf.org/html/rfc854>RFC 855</a> Telnet option specifications
+
+ \todo SYNCH handling
+ */
+ class BaseTelnetProtocol
+ {
+ public:
+ typedef ClientSocketHandle<senf::MakeSocketPolicy<
+ ConnectedCommunicationPolicy,
+ StreamFramingPolicy,
+ ReadablePolicy,
+ WriteablePolicy>::policy> Handle;
+
+ typedef unsigned char option_type;
+
+ struct TelnetHandler;
+
+ void write(std::string const & s);
+ void write(char c);
+
+ void sendNOP();
+ void sendBRK();
+ void sendIP();
+ void sendAO();
+ void sendAYT();
+ void sendEC();
+ void sendEL();
+ void sendGA();
+
+ void sendOptionParameters(option_type option, std::string const & data);
+
+ void requestLocalOption(option_type option, bool enabled = true);
+ void acceptLocalOption(option_type option, bool enabled = true);
+
+ void requestPeerOption(option_type option, bool enabled = true);
+ void acceptPeerOption(option_type option, bool enabled = true);
+
+ protected:
+ explicit BaseTelnetProtocol(Handle handle);
+ BaseTelnetProtocol();
+ virtual ~BaseTelnetProtocol();
+
+ template <class Handler>
+ void registerHandler(Handler * h, bool request=true);
+
+ private:
+
+#ifndef DOXYGEN
+ private:
+#endif
+ virtual void v_charReceived(char c) = 0;
+ virtual void v_eof() = 0;
+
+ virtual void v_handleNOP();
+ virtual void v_handleBRK();
+ virtual void v_handleIP();
+ virtual void v_handleAO();
+ virtual void v_handleAYT();
+ virtual void v_handleEC();
+ virtual void v_handleEL();
+ virtual void v_handleGA();
+
+#ifdef DOXYGEN
+ private:
+#endif
+ void handleChar(char c);
+ void handleNormalChar(char c);
+ void handleCommand(char c);
+ void handleOption(char c);
+ void handleCR(char c);
+ void handleSBOption(char c);
+ void handleSBData(char c);
+ void handleSBIAC(char c);
+ void emit(char c);
+ void processCommand();
+ void transmit(char c);
+
+ void sendWILL(char option);
+ void sendWONT(char option);
+ void sendDO(char option);
+ void sendDONT(char option);
+
+ void readHandler(int state);
+ void writeHandler(int state);
+
+ enum Command {
+ CMD_NONE = 0,
+ CMD_SE = 240,
+ CMD_NOP = 241,
+ CMD_DM = 242,
+ CMD_BRK = 243,
+ CMD_IP = 244,
+ CMD_AO = 245,
+ CMD_AYT = 246,
+ CMD_EC = 247,
+ CMD_EL = 248,
+ CMD_GA = 249,
+ CMD_SB = 250,
+ CMD_WILL = 251,
+ CMD_WONT = 252,
+ CMD_DO = 253,
+ CMD_DONT = 254,
+ CMD_IAC = 255,
+ };
+
+ struct OptInfo
+ {
+ enum WantState { WANTED, ACCEPTED, DISABLED };
+ enum OptionState { NONE, REQUEST_SENT, ACKNOWLEDGED };
+
+ OptInfo();
+ OptInfo(bool local, option_type option);
+
+ ///////////////////////////////////////////////////////////////
+
+ bool const local;
+ option_type const option;
+
+ WantState wantState;
+ OptionState optionState;
+ bool enabled;
+
+ };
+
+ OptInfo & getOption(bool local, option_type option);
+ void request(OptInfo & info, bool enabled);
+ void response(OptInfo & info, bool enabled);
+
+ typedef std::map<std::pair<bool, option_type>, OptInfo> OptionsMap;
+ OptionsMap options_;
+
+ typedef std::map<option_type, TelnetHandler*> OptionHandlerMap;
+ OptionHandlerMap handlers_;
+
+ Handle handle_;
+
+ typedef std::vector<char> SendQueue;
+ SendQueue sendQueue_;
+
+ enum CharState { NORMAL, IAC_SEEN, EXPECT_OPTION, CR_SEEN,
+ SB_OPTION, SB_DATA, SB_IAC_SEEN };
+ CharState charState_;
+
+ Command command_;
+ option_type option_;
+ std::string data_;
+
+ senf::scheduler::FdEvent inputEvent_;
+ senf::scheduler::FdEvent outputEvent_;
+
+ friend class TelnetHandler;
+ };
+
+ struct BaseTelnetProtocol::TelnetHandler
+ : public virtual BaseTelnetProtocol
+ {
+ virtual ~TelnetHandler();
+ virtual void v_init() = 0;
+ virtual void v_handleOptionParameters(std::string const & data) = 0;
+ };
+
+ // See http://www.iana.org/assignments/telnet-options for a list of options
+ namespace telnetopt { BaseTelnetProtocol::option_type const ECHO = 1u; }
+ namespace telnetopt { BaseTelnetProtocol::option_type const TRANSMIT_BINARY = 0u; }
+ namespace telnetopt { BaseTelnetProtocol::option_type const SUPPRESS_GO_AHEAD = 3u; }
+ namespace telnetopt { BaseTelnetProtocol::option_type const TERMINAL_TYPE = 24u; }
+ namespace telnetopt { BaseTelnetProtocol::option_type const NAWS = 31u; }
+ namespace telnetopt { BaseTelnetProtocol::option_type const LINEMODE = 34u; }
+
+namespace telnethandler {
+
+ class TerminalType
+ : public BaseTelnetProtocol::TelnetHandler
+ {
+ public:
+ static option_type const OPTION_CODE = telnetopt::TERMINAL_TYPE;
+
+ void nextTerminalType();
+
+ protected:
+ TerminalType();
+
+ private:
+ virtual void v_handleTerminalType(std::string const & type) = 0;
+
+ virtual void v_init();
+ virtual void v_handleOptionParameters(std::string const & data);
+ };
+
+ class NAWS
+ : public BaseTelnetProtocol::TelnetHandler
+ {
+ public:
+ static option_type const OPTION_CODE = telnetopt::NAWS;
+
+ protected:
+ NAWS();
+
+ private:
+ virtual void v_handleWindowSize(unsigned width, unsigned height) = 0;
+
+ virtual void v_init();
+ virtual void v_handleOptionParameters(std::string const & data);
+ };
+
+}
+
+}}}
+
+///////////////////////////////hh.e////////////////////////////////////////
+#include "Telnet.cci"
+
+//#include "Telnet.ct"
+#include "Telnet.cti"
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2008
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief Telnet.test unit tests */
+
+//#include "Telnet.test.hh"
+//#include "Telnet.test.ih"
+
+// Custom includes
+#include "Telnet.hh"
+
+#include "../../Utils/auto_unit_test.hh"
+#include <boost/test/test_tools.hpp>
+
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+BOOST_AUTO_UNIT_TEST(telnet)
+{}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2008
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief telnetServer non-inline non-template implementation */
+
+//#include "telnetServer.hh"
+//#include "telnetServer.ih"
+
+// Custom includes
+#include "Telnet.hh"
+#include "../Logger.hh"
+#include "../../Socket/Protocols/INet.hh"
+
+//#include "telnetServer.mpp"
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+namespace {
+
+ class MyTelnet
+ : public virtual senf::console::detail::BaseTelnetProtocol,
+ public senf::console::detail::telnethandler::TerminalType,
+ public senf::console::detail::telnethandler::NAWS
+ {
+ public:
+ explicit MyTelnet(Handle handle) : senf::console::detail::BaseTelnetProtocol(handle)
+ {
+ requestPeerOption(senf::console::detail::telnetopt::SUPPRESS_GO_AHEAD);
+ requestLocalOption(senf::console::detail::telnetopt::SUPPRESS_GO_AHEAD);
+ requestLocalOption(senf::console::detail::telnetopt::ECHO);
+ }
+
+ private:
+ virtual void v_charReceived(char c)
+ {
+ SENF_LOG(("Char: " << c));
+ }
+ virtual void v_eof()
+ {
+ SENF_LOG(("EOF"));
+ senf::scheduler::terminate();
+ }
+ virtual void v_handleTerminalType(std::string const & type)
+ {
+ SENF_LOG(("Terminal type: " << type));
+ }
+
+ virtual void v_handleWindowSize(unsigned width, unsigned height)
+ {
+ SENF_LOG(("Window size: " << width << "x" << height));
+ }
+ };
+
+ typedef senf::TCPv4ServerSocketHandle ServerHandle;
+ typedef ServerHandle::ClientHandle ClientHandle;
+
+}
+
+int main(int argc, char const ** argv)
+{
+ SENF_LOG(("Starting server."));
+ ServerHandle server (ServerHandle::Address("127.0.0.1:22344"));
+ ClientHandle client (server.accept());
+ SENF_LOG(("Starting MyTelnet"));
+ MyTelnet telnet (client);
+
+ senf::scheduler::process();
+
+ return 0;
+}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+//#include "telnetServer.mpp"
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u telnetServer"
+// End: