00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <algorithm>
00028 #include <string>
00029 #include <cstdlib>
00030 #include <cctype>
00031 #include <cerrno>
00032 #include <rtt/Property.hpp>
00033 #include "NiceHeaderMarshaller.hpp"
00034 #include "TcpReporting.hpp"
00035 #include "command.hpp"
00036 #include "socket.hpp"
00037 #include "datasender.hpp"
00038 #include "socketmarshaller.hpp"
00039
00040 using OCL::TCP::RealCommand;
00041 using OCL::TCP::Socket;
00042 using OCL::TCP::TcpReportingInterpreter;
00043
00044 namespace
00045 {
00049 class prefixbuf : public std::streambuf
00050 {
00051 private:
00052 std::streambuf* _opt;
00053 bool newline;
00054
00055 public:
00056 prefixbuf( std::streambuf* opt ) : _opt(opt)
00057 {
00058 setp(0, 0);
00059 setg(0, 0, 0);
00060 newline = true;
00061 }
00062
00063 ~prefixbuf()
00064 {
00065 sync();
00066 }
00067
00068 protected:
00069 int overflow(int c)
00070 {
00071 if( c != EOF )
00072 {
00073 if( newline )
00074 {
00075 if( _opt->sputn("300 ", 4) != 4 )
00076 {
00077 return EOF;
00078 }
00079 newline = false;
00080 }
00081 int ret = _opt->sputc(c);
00082 newline = ( c == '\n' );
00083 return ret;
00084 }
00085 return 0;
00086 }
00087
00088 int sync()
00089 {
00090 return _opt->pubsync();
00091 }
00092 };
00093
00097 class prefixstr : public std::ostream
00098 {
00099 public:
00100 prefixstr(std::ostream& opt)
00101 : std::ostream( new prefixbuf( opt.rdbuf() ) )
00102 {
00103 }
00104
00105 ~prefixstr()
00106 {
00107 delete rdbuf();
00108 }
00109 };
00110
00111
00112
00113 char to_upper (const char c)
00114 {
00115 return toupper(c);
00116 }
00117
00121 class HeaderCommand : public RealCommand
00122 {
00123 protected:
00124 void maincode( int, std::string* )
00125 {
00126 std::vector<std::string> list = _parent->getConnection()->getMarshaller()->getReporter()->getReport()->list();
00127 for(unsigned int i=0;i<list.size();i++)
00128 socket()<<"305 "<<list[i]<<std::endl;
00129 socket() << "306 End of list" << std::endl;
00130 }
00131
00132 public:
00133 HeaderCommand(TcpReportingInterpreter* parent)
00134 : RealCommand( "HEADERS", parent )
00135 {
00136 }
00137
00138 ~HeaderCommand()
00139 {}
00140
00141 void manualExecute()
00142 {
00143 maincode(0,0);
00144 }
00145 };
00146
00147 class HelpCommand : public RealCommand
00148 {
00149 protected:
00153 void printCommands()
00154 {
00155 const std::vector<Command*> &cmds = _parent->giveCommands();
00156 socket() << "Use HELP <command>" << std::endl;
00157 for( unsigned int i = 0; i < cmds.size(); i++ )
00158 {
00159 if( cmds[i] == cmds[i]->getRealCommand( cmds ) )
00160 {
00161 socket() << cmds[i]->getName() << '\n';
00162 }
00163 }
00164 socket() << '.' << std::endl;
00165 }
00166
00170 void printHelpFor( const std::string& name, const RealCommand* command )
00171 {
00172 socket() << "Name: " << name << std::endl;
00173 socket() << "Usage: " << name;
00174 if( command->getSyntax() )
00175 {
00176 socket() << " " << command->getSyntax();
00177 }
00178 socket() << std::endl;
00179 }
00180
00184 void printHelpFor( const std::string& cmd )
00185 {
00186 const std::vector<Command*> &cmds = _parent->giveCommands();
00187 for( unsigned int i = 0; i < cmds.size(); i++ )
00188 {
00189 if( cmds[i]->getName() == cmd )
00190 {
00191 printHelpFor( cmd, cmds[i]->getRealCommand( cmds ) );
00192 return;
00193 }
00194 }
00195 printCommands();
00196 }
00197
00198 void maincode( int argc, std::string* params )
00199 {
00200 if( argc == 0 )
00201 {
00202 printCommands();
00203 } else {
00204 printHelpFor(params[0]);
00205 }
00206 }
00207 public:
00208 HelpCommand(TcpReportingInterpreter* parent)
00209 : RealCommand( "HELP", parent, 0, 1, "[nothing | <command name>]" )
00210 {
00211 }
00212 };
00213
00214 class ListCommand : public RealCommand
00215 {
00216 protected:
00217 void maincode( int, std::string* )
00218 {
00219 socket() << "103 none" << std::endl;
00220 }
00221
00222 public:
00223 ListCommand(TcpReportingInterpreter* parent)
00224 : RealCommand( "LISTEXTENSIONS", parent )
00225 {
00226 }
00227 };
00228
00229 class QuitCommand : public RealCommand
00230 {
00231 protected:
00232 void maincode( int, std::string* )
00233 {
00234
00235
00236
00237
00238
00239 socket().close();
00240 }
00241
00242 public:
00243 QuitCommand(TcpReportingInterpreter* parent)
00244 : RealCommand( "QUIT", parent )
00245 {
00246 }
00247 };
00248
00249 class SetLimitCommand : public RealCommand
00250 {
00251 protected:
00252 void maincode( int, std::string* args )
00253 {
00254 int olderr = errno;
00255 char* tailptr;
00256 unsigned long long limit = strtoull( args[0].c_str(), &tailptr, 10 );
00257 if( *tailptr != '\0' || ( errno != olderr && errno == ERANGE ) )
00258 {
00259 sendError102();
00260 } else {
00261 _parent->getConnection()->setLimit(limit);
00262 sendOK();
00263 }
00264 }
00265
00266 public:
00267 SetLimitCommand(TcpReportingInterpreter* parent)
00268 : RealCommand( "SETLIMIT", parent, 1, 1, "<frameid>" )
00269 {
00270 }
00271 };
00272
00276 class SilenceCommand : public RealCommand
00277 {
00278 protected:
00279 void maincode( int, std::string* args )
00280 {
00281 toupper( args, 0 );
00282 if( args[0] == "ON" )
00283 {
00284 _parent->getConnection()->silence(true);
00285 } else if( args[0] == "OFF") {
00286 _parent->getConnection()->silence(false);
00287 } else {
00288 sendError102();
00289 return;
00290 }
00291 socket() << "107 Silence " << args[0] << std::endl;
00292 }
00293
00294 public:
00295 SilenceCommand(TcpReportingInterpreter* parent)
00296 : RealCommand( "SILENCE", parent, 1, 1, "[ON | OFF]" )
00297 {
00298 }
00299 };
00300
00304 class SubscribeCommand : public RealCommand
00305 {
00306
00307
00308
00309 protected:
00310 void maincode( int, std::string* args )
00311 {
00312 if( _parent->getConnection()->addSubscription(args[0]) )
00313 {
00314 socket() << "302 " << args[0] << std::endl;
00315 } else {
00316 socket() << "301 " << args[0] << std::endl;
00317 }
00318 }
00319
00320 public:
00321 SubscribeCommand(TcpReportingInterpreter* parent)
00322 : RealCommand( "SUBSCRIBE", parent, 1, 1, "<source name>" )
00323 {
00324 }
00325 };
00326
00327 class SubscriptionsCommand : public RealCommand
00328 {
00329 protected:
00330 void maincode( int, std::string* )
00331 {
00332 _parent->getConnection()->listSubscriptions();
00333 }
00334
00335 public:
00336 SubscriptionsCommand(TcpReportingInterpreter* parent)
00337 : RealCommand( "SUBS", parent )
00338 {
00339 }
00340 };
00341
00342 class UnsubscribeCommand : public RealCommand
00343 {
00344 protected:
00345 void maincode( int, std::string* args )
00346 {
00347 if( _parent->getConnection()->removeSubscription(args[0]) )
00348 {
00349 socket() << "303 " << args[0] << std::endl;
00350 } else {
00351 socket() << "304 " << args[0] << std::endl;
00352 }
00353 }
00354
00355 public:
00356 UnsubscribeCommand(TcpReportingInterpreter* parent)
00357 : RealCommand( "UNSUBSCRIBE", parent, 1, 1, "<source name>" )
00358 {
00359 }
00360 };
00361
00362 class VersionCommand : public RealCommand
00363 {
00364 protected:
00365 void maincode( int, std::string* args )
00366 {
00367 if( args[0] == "1.0" )
00368 {
00369 _parent->setVersion10();
00370 sendOK();
00371 } else {
00372 socket() << "106 Not supported" << std::endl;
00373 }
00374 }
00375
00376 public:
00377 VersionCommand(TcpReportingInterpreter* parent)
00378 : RealCommand( "VERSION", parent, 1, 1, "1.0" )
00379 {
00380 }
00381 };
00382 }
00383
00384 namespace OCL
00385 {
00386 namespace TCP
00387 {
00388
00389
00390
00391
00392 class RealCommand;
00393
00394 Command::Command( std::string name )
00395 : _name( name )
00396 {
00397 }
00398
00399 Command::~Command()
00400 {
00401 }
00402
00403 Command* Command::find(const std::vector<Command*>& cmds, const std::string& cmp)
00404 {
00405 for( unsigned int j = 0; j < cmds.size(); j++ )
00406 {
00407 if( *cmds[j] == cmp )
00408 {
00409 return cmds[j];
00410 }
00411 }
00412 return 0;
00413 }
00414
00415 const std::string& Command::getName() const
00416 {
00417 return _name;
00418 }
00419
00420 bool Command::is(std::string& cmd) const
00421 {
00422 return cmd == _name;
00423 }
00424
00425 bool Command::operator==(const std::string& cmp) const
00426 {
00427 return cmp == _name;
00428 }
00429
00430 bool Command::operator!=(const std::string& cmp) const
00431 {
00432 return cmp != _name;
00433 }
00434
00435 bool Command::operator<( const Command& cmp ) const
00436 {
00437 return _name < cmp.getName();
00438 }
00439
00440 AliasCommand::AliasCommand( std::string name, std::string alias )
00441 : Command( name ), _alias( alias )
00442 {
00443 }
00444
00445 RealCommand* AliasCommand::getRealCommand(const std::vector<Command*>& cmds) const
00446 {
00447 Command* ret = Command::find( cmds, _alias );
00448 if( !ret )
00449 {
00450 return 0;
00451 }
00452 return ret->getRealCommand(cmds);
00453 }
00454
00455 RealCommand::RealCommand( std::string name, TcpReportingInterpreter* parent, unsigned int minargs,
00456 unsigned int maxargs, const char* syntax )
00457 : Command( name ), _parent( parent ), _minargs( minargs ), _maxargs( maxargs ), _syntax( syntax )
00458 {
00459 }
00460
00461 RealCommand::~RealCommand()
00462 {
00463 }
00464
00465 const char* RealCommand::getSyntax() const
00466 {
00467 return _syntax;
00468 }
00469
00470 bool RealCommand::sendError102() const
00471 {
00472 if( _syntax )
00473 {
00474 socket() << "102 Syntax: " << _name << ' ' << _syntax << std::endl;
00475 } else {
00476 socket() << "102 Syntax: " << _name << std::endl;
00477 }
00478 return false;
00479 }
00480
00481 bool RealCommand::sendOK() const
00482 {
00483 socket() << "101 OK" << std::endl;
00484 return true;
00485 }
00486
00487 bool RealCommand::correctSyntax( unsigned int argc, std::string* )
00488 {
00489 if( argc < _minargs || argc > _maxargs )
00490 {
00491 return sendError102();
00492 }
00493 return true;
00494 }
00495
00496 RealCommand* RealCommand::getRealCommand(const std::vector<Command*>& cmds) const
00497 {
00498 return const_cast<RealCommand*>(this);
00499 }
00500
00501 void RealCommand::execute( int argc, std::string* args )
00502 {
00503 if( correctSyntax( argc, args ) )
00504 {
00505 maincode( argc, args );
00506 }
00507 }
00508
00509 void RealCommand::toupper( std::string* args, int i ) const
00510 {
00511 std::transform( args[i].begin(), args[i].end(), args[i].begin(), to_upper );
00512 }
00513
00514 void RealCommand::toupper( std::string* args, int start, int stop ) const
00515 {
00516 for( int i = start; i <= stop; i++ )
00517 {
00518 toupper( args, i );
00519 }
00520 }
00521
00522 Socket& RealCommand::socket() const
00523 {
00524 return _parent->getConnection()->getSocket();
00525 }
00526
00527 TcpReportingInterpreter::TcpReportingInterpreter(Datasender* parent)
00528 : _parent( parent )
00529 {
00530 addCommand( new VersionCommand(this) );
00531 addCommand( new HelpCommand(this) );
00532 addCommand( new QuitCommand(this) );
00533 addCommand( new AliasCommand( "EXIT", "QUIT" ) );
00534 }
00535
00536 TcpReportingInterpreter::~TcpReportingInterpreter()
00537 {
00538 for( std::vector<Command*>::iterator i = cmds.begin();
00539 i != cmds.end();
00540 i++ )
00541 {
00542 delete *i;
00543 }
00544 }
00545
00546 void TcpReportingInterpreter::addCommand( Command* command )
00547 {
00548
00549
00550 commands.lock();
00551 std::vector<Command*>::iterator i = cmds.begin();
00552 while( i != cmds.end() && *command < **i ) {
00553 i++;
00554 }
00555
00556
00557 if( i != cmds.end() && *command == (*i)->getName() )
00558 {
00559 return;
00560 }
00561 cmds.insert( i, command );
00562 commands.unlock();
00563 }
00564
00565 const std::vector<Command*>& TcpReportingInterpreter::giveCommands() const
00566 {
00567 return cmds;
00568 }
00569
00570 Datasender* TcpReportingInterpreter::getConnection() const
00571 {
00572 return _parent;
00573 }
00574
00575 void TcpReportingInterpreter::process()
00576 {
00577 std::string ipt = getConnection()->getSocket().readLine();
00578
00579 if( ipt.empty() )
00580 {
00581 return;
00582 }
00583
00584
00585 std::string cmd;
00586 std::string* params;
00587
00588 unsigned int argc = parseParameters( ipt, cmd, ¶ms );
00589
00590 std::transform( cmd.begin(), cmd.end(), cmd.begin(), to_upper );
00591
00592
00593 bool correct = false;
00594 commands.lock();
00595 Command* obj = Command::find( cmds, cmd );
00596 if( obj )
00597 {
00598 RealCommand* rcommand = obj->getRealCommand(cmds);
00599 if( rcommand )
00600 {
00601 rcommand->execute( argc, params );
00602 correct = true;
00603 }
00604 } else {
00605 Logger::log() << Logger::Error << "Invalid command: " << ipt << Logger::endl;
00606 }
00607 commands.unlock();
00608
00609 if( !correct )
00610 {
00611 getConnection()->getSocket() << "105 Command not found" << std::endl;
00612 }
00613 }
00614
00615 unsigned int TcpReportingInterpreter::parseParameters(
00616 std::string& ipt, std::string& cmd, std::string** params )
00617 {
00618 unsigned int argc = 0;
00619 std::string::size_type pos = ipt.find_first_of("\t ", 0);
00620 while( pos != std::string::npos )
00621 {
00622 pos = ipt.find_first_of("\t ", pos + 1);
00623 argc++;
00624 }
00625 if( argc > 0 )
00626 {
00627 *params = new std::string[argc];
00628 pos = ipt.find_first_of("\t ", 0);
00629 cmd = ipt.substr(0, pos);
00630 unsigned int npos;
00631 for( unsigned int i = 0; i < argc; i++ )
00632 {
00633 npos = ipt.find_first_of("\t ", pos + 1);
00634 (*params)[i] = ipt.substr(pos+1,npos - pos - 1);
00635 pos = npos;
00636 }
00637 } else {
00638 cmd = ipt;
00639 *params = 0;
00640 }
00641 return argc;
00642 }
00643
00644 void TcpReportingInterpreter::removeCommand( const char* ipt )
00645 {
00646 commands.lock();
00647 std::vector<Command*>::iterator i = cmds.begin();
00648 while( i != cmds.end() && **i != ipt ) {
00649 i++;
00650 }
00651 if( i == cmds.end() )
00652 {
00653 Logger::log() << Logger::Error << "TcpReportingInterpreter::removeCommand: removing unknown command" << ipt << Logger::endl;
00654 } else {
00655 Command* todel = *i;
00656 cmds.erase(i);
00657 delete todel;
00658 }
00659 commands.unlock();
00660 }
00661
00662 void TcpReportingInterpreter::setVersion10()
00663 {
00664 commands.lock();
00665 removeCommand( "VERSION" );
00666 addCommand( new ListCommand(this) );
00667 addCommand( new HeaderCommand(this) );
00668 addCommand( new SilenceCommand(this) );
00669 addCommand( new SetLimitCommand(this) );
00670 addCommand( new SubscribeCommand(this) );
00671 addCommand( new UnsubscribeCommand(this) );
00672 addCommand( new SubscriptionsCommand(this) );
00673 commands.unlock();
00674 _parent->silence( false );
00675 }
00676 }
00677 }
00678