IBR-DTNSuite 0.6

daemon/src/api/ClientHandler.cpp

Go to the documentation of this file.
00001 /*
00002  * ClientHandler.cpp
00003  *
00004  *  Created on: 24.06.2009
00005  *      Author: morgenro
00006  */
00007 
00008 #include "config.h"
00009 #include "Configuration.h"
00010 #include "api/ClientHandler.h"
00011 #include "api/BinaryStreamClient.h"
00012 #include "core/BundleCore.h"
00013 #include <ibrcommon/Logger.h>
00014 #include <ibrdtn/utils/Utils.h>
00015 
00016 namespace dtn
00017 {
00018         namespace api
00019         {
00020                 ProtocolHandler::ProtocolHandler(ClientHandler &client, ibrcommon::tcpstream &stream)
00021                  : _client(client), _stream(stream)
00022                 {
00023                 }
00024 
00025                 ProtocolHandler::~ProtocolHandler()
00026                 {}
00027 
00028                 ClientHandler::ClientHandler(ApiServerInterface &srv, Registration &registration, ibrcommon::tcpstream *conn)
00029                  : _srv(srv), _registration(registration), _stream(conn), _endpoint(dtn::core::BundleCore::local), _handler(NULL)
00030                 {
00031                         if ( dtn::daemon::Configuration::getInstance().getNetwork().getTCPOptionNoDelay() )
00032                         {
00033                                 _stream->enableNoDelay();
00034                         }
00035                 }
00036 
00037                 ClientHandler::~ClientHandler()
00038                 {
00039                         delete _stream;
00040                 }
00041 
00042                 Registration& ClientHandler::getRegistration()
00043                 {
00044                         return _registration;
00045                 }
00046 
00047                 ApiServerInterface& ClientHandler::getAPIServer()
00048                 {
00049                         return _srv;
00050                 }
00051 
00052                 void ClientHandler::setup()
00053                 {
00054                 }
00055 
00056                 void ClientHandler::run()
00057                 {
00058                         // signal the active connection to the server
00059                         _srv.connectionUp(this);
00060 
00061                         std::string buffer;
00062 
00063                         while (_stream->good())
00064                         {
00065                                 if (_handler != NULL)
00066                                 {
00067                                         _handler->setup();
00068                                         _handler->run();
00069                                         delete _handler;
00070                                         _handler = NULL;
00071                                         continue;
00072                                 }
00073 
00074                                 getline(*_stream, buffer);
00075 
00076                                 std::vector<std::string> cmd = dtn::utils::Utils::tokenize(" ", buffer);
00077                                 if (cmd.size() == 0) continue;
00078 
00079                                 try {
00080                                         if (cmd[0] == "protocol")
00081                                         {
00082                                                 if (cmd[1] == "tcpcl")
00083                                                 {
00084                                                         // switch to binary protocol (old style api)
00085                                                         _handler = new BinaryStreamClient(*this, *_stream);
00086                                                         continue;
00087                                                 }
00088                                                 else
00089                                                 {
00090                                                         error(API_STATUS_NOT_ACCEPTABLE, "UNKNOWN PROTOCOL");
00091                                                 }
00092                                         }
00093                                         else
00094                                         {
00095                                                 // forward to standard command set
00096                                                 processCommand(cmd);
00097                                         }
00098                                 } catch (const std::exception&) {
00099                                         error(API_STATUS_BAD_REQUEST, "PROTOCOL ERROR");
00100                                 }
00101                         }
00102                 }
00103 
00104                 void ClientHandler::error(STATUS_CODES code, const std::string &msg)
00105                 {
00106                         ibrcommon::MutexLock l(_write_lock);
00107                         (*_stream) << code << " " << msg << std::endl;
00108                 }
00109 
00110                 bool ClientHandler::__cancellation()
00111                 {
00112                         // close the stream
00113                         (*_stream).close();
00114 
00115                         return true;
00116                 }
00117 
00118                 void ClientHandler::finally()
00119                 {
00120                         IBRCOMMON_LOGGER_DEBUG(60) << "ApiConnection down" << IBRCOMMON_LOGGER_ENDL;
00121 
00122                         // remove the client from the list in ApiServer
00123                         _srv.connectionDown(this);
00124 
00125                         _registration.abort();
00126                         _srv.freeRegistration(_registration);
00127 
00128                         // close the stream
00129                         try {
00130                                 (*_stream).close();
00131                         } catch (const ibrcommon::ConnectionClosedException&) { };
00132                 }
00133 
00134                 void ClientHandler::eventNodeAvailable(const dtn::core::Node &node)
00135                 {
00136                 }
00137 
00138                 void ClientHandler::eventNodeUnavailable(const dtn::core::Node &node)
00139                 {
00140                 }
00141 
00142                 void ClientHandler::processCommand(const std::vector<std::string> &cmd)
00143                 {
00144                         try {
00145                                 if (cmd[0] == "set")
00146                                 {
00147                                         if (cmd.size() < 2) throw ibrcommon::Exception("not enough parameters");
00148 
00149                                         if (cmd[1] == "endpoint")
00150                                         {
00151                                                 if (cmd.size() < 3) throw ibrcommon::Exception("not enough parameters");
00152 
00153                                                 ibrcommon::MutexLock l(_write_lock);
00154                                                 _endpoint = dtn::core::BundleCore::local + "/" + cmd[2];
00155 
00156                                                 // error checking
00157                                                 if (_endpoint == dtn::data::EID())
00158                                                 {
00159                                                         (*_stream) << API_STATUS_NOT_ACCEPTABLE << " INVALID ENDPOINT" << std::endl;
00160                                                         _endpoint = dtn::core::BundleCore::local;
00161                                                 }
00162                                                 else
00163                                                 {
00164                                                         _registration.subscribe(_endpoint);
00165                                                         (*_stream) << API_STATUS_ACCEPTED << " OK" << std::endl;
00166                                                 }
00167                                         }
00168                                         else
00169                                         {
00170                                                 ibrcommon::MutexLock l(_write_lock);
00171                                                 (*_stream) << API_STATUS_BAD_REQUEST << " UNKNOWN COMMAND" << std::endl;
00172                                         }
00173                                 }
00174                                 else if (cmd[0] == "registration")
00175                                 {
00176                                         if (cmd.size() < 2) throw ibrcommon::Exception("not enough parameters");
00177 
00178                                         if (cmd[1] == "add")
00179                                         {
00180                                                 if (cmd.size() < 3) throw ibrcommon::Exception("not enough parameters");
00181 
00182                                                 ibrcommon::MutexLock l(_write_lock);
00183                                                 dtn::data::EID endpoint(cmd[2]);
00184 
00185                                                 // error checking
00186                                                 if (endpoint == dtn::data::EID())
00187                                                 {
00188                                                         (*_stream) << API_STATUS_NOT_ACCEPTABLE << " INVALID EID" << std::endl;
00189                                                 }
00190                                                 else
00191                                                 {
00192                                                         _registration.subscribe(endpoint);
00193                                                         (*_stream) << API_STATUS_ACCEPTED << " OK" << std::endl;
00194                                                 }
00195                                         }
00196                                         else if (cmd[1] == "del")
00197                                         {
00198                                                 if (cmd.size() < 3) throw ibrcommon::Exception("not enough parameters");
00199 
00200                                                 ibrcommon::MutexLock l(_write_lock);
00201                                                 dtn::data::EID endpoint(cmd[2]);
00202 
00203                                                 // error checking
00204                                                 if (endpoint == dtn::data::EID())
00205                                                 {
00206                                                         (*_stream) << API_STATUS_NOT_ACCEPTABLE << " INVALID EID" << std::endl;
00207                                                 }
00208                                                 else
00209                                                 {
00210                                                         _registration.unsubscribe(endpoint);
00211                                                         (*_stream) << API_STATUS_ACCEPTED << " OK" << std::endl;
00212                                                 }
00213                                         }
00214                                         else if (cmd[1] == "list")
00215                                         {
00216                                                 ibrcommon::MutexLock l(_write_lock);
00217                                                 const std::set<dtn::data::EID> &list = _registration.getSubscriptions();
00218 
00219                                                 (*_stream) << API_STATUS_OK << " REGISTRATION LIST" << std::endl;
00220                                                 for (std::set<dtn::data::EID>::const_iterator iter = list.begin(); iter != list.end(); iter++)
00221                                                 {
00222                                                         (*_stream) << (*iter).getString() << std::endl;
00223                                                 }
00224                                                 (*_stream) << std::endl;
00225                                         }
00226                                         else
00227                                         {
00228                                                 ibrcommon::MutexLock l(_write_lock);
00229                                                 (*_stream) << API_STATUS_BAD_REQUEST << " UNKNOWN COMMAND" << std::endl;
00230                                         }
00231                                 }
00232                                 else if (cmd[0] == "neighbor")
00233                                 {
00234                                         if (cmd.size() < 2) throw ibrcommon::Exception("not enough parameters");
00235 
00236                                         if (cmd[1] == "list")
00237                                         {
00238                                                 ibrcommon::MutexLock l(_write_lock);
00239                                                 const std::set<dtn::core::Node> nlist = dtn::core::BundleCore::getInstance().getNeighbors();
00240 
00241                                                 (*_stream) << API_STATUS_OK << " NEIGHBOR LIST" << std::endl;
00242                                                 for (std::set<dtn::core::Node>::const_iterator iter = nlist.begin(); iter != nlist.end(); iter++)
00243                                                 {
00244                                                         (*_stream) << (*iter).getEID().getString() << std::endl;
00245                                                 }
00246                                                 (*_stream) << std::endl;
00247                                         }
00248                                         else
00249                                         {
00250                                                 ibrcommon::MutexLock l(_write_lock);
00251                                                 (*_stream) << API_STATUS_BAD_REQUEST << " UNKNOWN COMMAND" << std::endl;
00252                                         }
00253                                 }
00254                                 else
00255                                 {
00256                                         ibrcommon::MutexLock l(_write_lock);
00257                                         (*_stream) << API_STATUS_BAD_REQUEST << " UNKNOWN COMMAND" << std::endl;
00258                                 }
00259                         } catch (const std::exception&) {
00260                                 ibrcommon::MutexLock l(_write_lock);
00261                                 (*_stream) << API_STATUS_BAD_REQUEST << " ERROR" << std::endl;
00262                         }
00263                 }
00264         }
00265 }