00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00026 #include "Telnet.hh"
00027
00028
00029
00030 #include <boost/algorithm/string/case_conv.hpp>
00031 #include <senf/Utils/membind.hh>
00032 #include <senf/Utils/Logger/SenfLog.hh>
00033
00034
00035 #define prefix_
00036
00037
00038 prefix_ senf::term::BaseTelnetProtocol::BaseTelnetProtocol(Handle handle)
00039 : handle_ (handle), charState_ (NORMAL), command_ (CMD_NONE), option_ (0),
00040 inputEvent_ ("senf::term::BaseTelnetProtocol::input",
00041 membind(&BaseTelnetProtocol::readHandler, this), handle,
00042 scheduler::FdEvent::EV_READ),
00043 outputEvent_ ("senf::term::BaseTelnetProtocol::output",
00044 membind(&BaseTelnetProtocol::writeHandler, this), handle,
00045 scheduler::FdEvent::EV_WRITE, false),
00046 pendingRequests_ (0u),
00047 requestTimeout_ (ClockService::milliseconds(DEFAULT_REQUEST_TIMEOUT_MS)),
00048 timeout_ ("senf::term::BaseTelnetProtocol::configTimeout",
00049 membind(&BaseTelnetProtocol::timeout, this))
00050 {}
00051
00052 prefix_ senf::term::BaseTelnetProtocol::BaseTelnetProtocol()
00053 : handle_ (), charState_ (NORMAL), command_ (CMD_NONE), option_ (0),
00054 inputEvent_ ("senf::term::BaseTelnetProtocol::input", 0),
00055 outputEvent_ ("senf::term::BaseTelnetProtocol::output", 0),
00056 pendingRequests_ (0u),
00057 requestTimeout_ (ClockService::milliseconds(DEFAULT_REQUEST_TIMEOUT_MS)),
00058 timeout_ ("senf::term::BaseTelnetProtocol::timeout", 0)
00059 {
00060 SENF_ASSERT( false,
00061 "Missing BaseTelnetProtocol constructor call in derived class "
00062 "(BaseTelnetProtocol is a VIRTUAL base and MUST be constructed explicitly "
00063 "in the most derived class." );
00064 }
00065
00066 prefix_ void senf::term::BaseTelnetProtocol::write(std::string const & s)
00067 {
00068 for (std::string::const_iterator i (s.begin()); i != s.end(); ++i)
00069 write(*i);
00070 }
00071
00072 prefix_ void senf::term::BaseTelnetProtocol::write(char c)
00073 {
00074 switch (c) {
00075 case '\r':
00076 transmit('\r');
00077 transmit('\0');
00078 break;
00079 case '\n':
00080 transmit('\r');
00081 transmit('\n');
00082 break;
00083 case '\xff':
00084 transmit('\xff');
00085 transmit('\xff');
00086 break;
00087 default:
00088 transmit(c);
00089 break;
00090 }
00091 }
00092
00093 prefix_ void
00094 senf::term::BaseTelnetProtocol::sendOptionParameters(option_type option,
00095 std::string const & data)
00096 {
00097 transmit(CMD_IAC);
00098 transmit(CMD_SB);
00099 transmit(option);
00100 for (std::string::const_iterator i (data.begin()); i != data.end(); ++i)
00101 if (*i == '\xff') {
00102 transmit('\xff');
00103 transmit('\xff');
00104 }
00105 else
00106 transmit(*i);
00107 transmit(CMD_IAC);
00108 transmit(CMD_SE);
00109 }
00110
00111 prefix_ void senf::term::BaseTelnetProtocol::v_handleNOP()
00112 {}
00113
00114 prefix_ void senf::term::BaseTelnetProtocol::v_handleBRK()
00115 {}
00116
00117 prefix_ void senf::term::BaseTelnetProtocol::v_handleIP()
00118 {}
00119
00120 prefix_ void senf::term::BaseTelnetProtocol::v_handleAO()
00121 {}
00122
00123 prefix_ void senf::term::BaseTelnetProtocol::v_handleAYT()
00124 {}
00125
00126 prefix_ void senf::term::BaseTelnetProtocol::v_handleEC()
00127 {}
00128
00129 prefix_ void senf::term::BaseTelnetProtocol::v_handleEL()
00130 {}
00131
00132 prefix_ void senf::term::BaseTelnetProtocol::v_handleGA()
00133 {}
00134
00135 prefix_ void senf::term::BaseTelnetProtocol::handleChar(char c)
00136 {
00137 switch (charState_) {
00138 case NORMAL:
00139 handleNormalChar(c);
00140 break;
00141 case IAC_SEEN:
00142 handleCommand(static_cast<unsigned char>(c));
00143 break;
00144 case EXPECT_OPTION:
00145 handleOption(c);
00146 break;
00147 case CR_SEEN:
00148 handleCR(c);
00149 break;
00150 case SB_OPTION:
00151 handleSBOption(c);
00152 break;
00153 case SB_DATA:
00154 handleSBData(c);
00155 break;
00156 case SB_IAC_SEEN:
00157 handleSBIAC(c);
00158 break;
00159 }
00160 }
00161
00162 prefix_ void senf::term::BaseTelnetProtocol::handleNormalChar(char c)
00163 {
00164 switch (c) {
00165 case '\r':
00166 charState_ = CR_SEEN;
00167 break;
00168 case '\xff':
00169 charState_ = IAC_SEEN;
00170 break;
00171 default:
00172 emit(c);
00173 break;
00174 }
00175 }
00176
00177 prefix_ void senf::term::BaseTelnetProtocol::handleCommand(char c)
00178 {
00179 switch (static_cast<unsigned char>(c)) {
00180 case CMD_SE:
00181
00182 charState_ = NORMAL;
00183 break;
00184 case CMD_NOP:
00185 case CMD_DM:
00186 case CMD_BRK:
00187 case CMD_IP:
00188 case CMD_AO:
00189 case CMD_AYT:
00190 case CMD_EC:
00191 case CMD_EL:
00192 case CMD_GA:
00193 command_ = Command(static_cast<unsigned char>(c));
00194 processCommand();
00195 charState_ = NORMAL;
00196 break;
00197 case CMD_SB:
00198 command_ = CMD_SB;
00199 charState_ = SB_OPTION;
00200 break;
00201 case CMD_WILL:
00202 case CMD_WONT:
00203 case CMD_DO:
00204 case CMD_DONT:
00205 command_ = Command(static_cast<unsigned char>(c));
00206 charState_ = EXPECT_OPTION;
00207 break;
00208 case CMD_IAC:
00209 charState_ = NORMAL;
00210 emit(CMD_IAC);
00211 break;
00212 default:
00213 emit(CMD_IAC);
00214 charState_ = NORMAL;
00215 handleChar(c);
00216 break;
00217 }
00218 }
00219
00220 prefix_ void senf::term::BaseTelnetProtocol::handleOption(char c)
00221 {
00222 option_ = c;
00223 processCommand();
00224 charState_ = NORMAL;
00225 }
00226
00227 prefix_ void senf::term::BaseTelnetProtocol::handleCR(char c)
00228 {
00229 switch (c) {
00230 case '\0':
00231 emit('\r');
00232 charState_ = NORMAL;
00233 break;
00234 case '\n':
00235 emit('\n');
00236 charState_ = NORMAL;
00237 break;
00238 default:
00239 emit('\r');
00240 charState_ = NORMAL;
00241 handleChar(c);
00242 break;
00243 }
00244 }
00245
00246 prefix_ void senf::term::BaseTelnetProtocol::handleSBOption(char c)
00247 {
00248 option_ = c;
00249 charState_ = SB_DATA;
00250 data_.clear();
00251 }
00252
00253 prefix_ void senf::term::BaseTelnetProtocol::handleSBData(char c)
00254 {
00255 if (c == '\xff')
00256 charState_ = SB_IAC_SEEN;
00257 else
00258 data_.push_back(c);
00259 }
00260
00261 prefix_ void senf::term::BaseTelnetProtocol::handleSBIAC(char c)
00262 {
00263 switch (static_cast<unsigned char>(c)) {
00264 case CMD_IAC:
00265 data_.push_back(c);
00266 charState_ = SB_DATA;
00267 break;
00268 case CMD_SE:
00269 processCommand();
00270 charState_ = NORMAL;
00271 break;
00272 default:
00273 charState_ = IAC_SEEN;
00274 handleChar(c);
00275 break;
00276 }
00277 }
00278
00279 prefix_ void senf::term::BaseTelnetProtocol::processCommand()
00280 {
00281 switch (command_) {
00282 case CMD_NONE:
00283 case CMD_SE:
00284 case CMD_DM:
00285 case CMD_IAC:
00286 break;
00287 case CMD_NOP:
00288 v_handleNOP();
00289 break;
00290 case CMD_BRK:
00291 v_handleBRK();
00292 break;
00293 case CMD_IP:
00294 v_handleIP();
00295 break;
00296 case CMD_AO:
00297 v_handleAO();
00298 break;
00299 case CMD_AYT:
00300 v_handleAYT();
00301 break;
00302 case CMD_EC:
00303 v_handleEC();
00304 break;
00305 case CMD_EL:
00306 v_handleEL();
00307 break;
00308 case CMD_GA:
00309 v_handleGA();
00310 break;
00311 case CMD_SB:
00312 {
00313 OptionHandlerMap::const_iterator i (handlers_.find(option_));
00314 if (i != handlers_.end())
00315 i->second->v_handleOptionParameters(data_);
00316 break;
00317 }
00318 case CMD_WILL:
00319 case CMD_WONT:
00320 response(getOption(false, option_), command_ == CMD_WILL);
00321 break;
00322 case CMD_DO:
00323 case CMD_DONT:
00324 response(getOption(true, option_), command_ == CMD_DO);
00325 break;
00326 }
00327 }
00328
00329 prefix_ void senf::term::BaseTelnetProtocol::transmit(char c)
00330 {
00331 sendQueue_.push_back(c);
00332 outputEvent_.enable();
00333 }
00334
00335 prefix_ void senf::term::BaseTelnetProtocol::readHandler(int state)
00336 {
00337 if (state != scheduler::FdEvent::EV_READ || handle_.eof()) {
00338 inputEvent_.disable();
00339 v_eof();
00340 return;
00341 }
00342 std::string data;
00343 handle_.read(data, 0u);
00344 for (std::string::const_iterator i (data.begin()); i != data.end(); ++i)
00345 handleChar(*i);
00346 }
00347
00348 prefix_ void senf::term::BaseTelnetProtocol::writeHandler(int state)
00349 {
00350 if (state != scheduler::FdEvent::EV_WRITE) {
00351 outputEvent_.disable();
00352 inputEvent_.disable();
00353 v_eof();
00354 return;
00355 }
00356 sendQueue_.erase(sendQueue_.begin(),
00357 handle_.write(boost::make_iterator_range(
00358 sendQueue_.begin(), sendQueue_.end())));
00359 if (sendQueue_.empty())
00360 outputEvent_.disable();
00361 }
00362
00363 prefix_ void senf::term::BaseTelnetProtocol::timeout()
00364 {
00365 if (pendingRequests_ > 0u) {
00366 pendingRequests_ = 0u;
00367 v_setupComplete();
00368 }
00369 }
00370
00371 prefix_ senf::term::BaseTelnetProtocol::OptInfo &
00372 senf::term::BaseTelnetProtocol::getOption(bool local, option_type option)
00373 {
00374 OptionsMap::iterator i (options_.find(std::make_pair(local, option)));
00375 if (i == options_.end())
00376 i = options_.insert(std::make_pair(std::make_pair(local, option),
00377 OptInfo(local, option))).first;
00378 return i->second;
00379 }
00380
00381 prefix_ void senf::term::BaseTelnetProtocol::request(OptInfo & info, bool enabled)
00382 {
00383 info.wantState = enabled ? OptInfo::WANTED : OptInfo::DISABLED;
00384 if (enabled != info.enabled) {
00385 transmit(CMD_IAC);
00386 transmit((info.local ? CMD_WILL : CMD_DO) + (enabled ? 0 : 1));
00387 transmit(info.option);
00388 info.optionState = OptInfo::REQUEST_SENT;
00389 incrementRequestCounter();
00390 }
00391 }
00392
00393 prefix_ void senf::term::BaseTelnetProtocol::response(OptInfo & info, bool enabled)
00394 {
00395 bool decrementCount (false);
00396
00397
00398
00399
00400
00401 if (info.optionState == OptInfo::REQUEST_SENT) {
00402
00403 info.optionState = OptInfo::ACKNOWLEDGED;
00404 info.enabled = enabled;
00405 decrementCount = true;
00406 }
00407 else if (enabled != info.enabled) {
00408
00409 if (!enabled ||
00410 (enabled && (info.wantState == OptInfo::WANTED || info.wantState == OptInfo::ACCEPTED))) {
00411
00412 info.optionState = OptInfo::ACKNOWLEDGED;
00413 info.enabled = enabled;
00414 }
00415 transmit(CMD_IAC);
00416 transmit((info.local ? CMD_WILL : CMD_DO) + (info.enabled ? 0 : 1));
00417 transmit(info.option);
00418 }
00419 else
00420 return;
00421 if (info.enabled) {
00422 OptionHandlerMap::const_iterator i (handlers_.find(info.option));
00423 if (i != handlers_.end())
00424 i->second->v_init();
00425 }
00426 if (decrementCount)
00427
00428
00429 decrementRequestCounter();
00430 }
00431
00432 prefix_ void senf::term::BaseTelnetProtocol::decrementRequestCounter()
00433 {
00434 if (pendingRequests_ > 0u) {
00435 -- pendingRequests_;
00436 if (pendingRequests_ == 0u) {
00437 timeout_.disable();
00438 v_setupComplete();
00439 }
00440 }
00441 }
00442
00443
00444
00445
00446 prefix_ senf::term::telnethandler::TerminalType::TerminalType()
00447 {
00448 registerHandler(this);
00449 }
00450
00451 prefix_ void senf::term::telnethandler::TerminalType::nextTerminalType()
00452 {
00453 sendOptionParameters(telnetopt::TERMINAL_TYPE, "\x01");
00454 }
00455
00456 prefix_ void senf::term::telnethandler::TerminalType::
00457 v_handleOptionParameters(std::string const & data)
00458 {
00459 if (data.size() <= 0)
00460 return;
00461 if (data[0] == '\x00') {
00462 type_ = data.substr(1);
00463 boost::algorithm::to_lower(type_);
00464 decrementRequestCounter();
00465 }
00466 }
00467
00468 prefix_ void senf::term::telnethandler::TerminalType::v_init()
00469 {
00470 nextTerminalType();
00471 incrementRequestCounter();
00472 }
00473
00474
00475
00476
00477 prefix_ senf::term::telnethandler::NAWS::NAWS()
00478 : width_ (0u), height_ (0u)
00479 {
00480 registerHandler(this);
00481 }
00482
00483 prefix_ void senf::term::telnethandler::NAWS::v_init()
00484 {
00485 incrementRequestCounter();
00486 }
00487
00488 prefix_ void
00489 senf::term::telnethandler::NAWS::v_handleOptionParameters(std::string const & data)
00490 {
00491 if (data.size() != 4)
00492 return;
00493 width_ = (static_cast<unsigned char>(data[0])<<8)+static_cast<unsigned char>(data[1]);
00494 height_ = (static_cast<unsigned char>(data[2])<<8)+static_cast<unsigned char>(data[3]);
00495 if (! requestsPending())
00496 v_windowSizeChanged();
00497 decrementRequestCounter();
00498 }
00499
00500
00501 #undef prefix_
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513