IBR-DTNSuite
0.8
|
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 "api/ManagementConnection.h" 00013 #include "api/EventConnection.h" 00014 #include "api/ExtendedApiHandler.h" 00015 #include "api/OrderedStreamHandler.h" 00016 #include "core/BundleCore.h" 00017 #include <ibrcommon/Logger.h> 00018 #include <ibrdtn/utils/Utils.h> 00019 #include <ibrcommon/net/LinkManager.h> 00020 00021 namespace dtn 00022 { 00023 namespace api 00024 { 00025 ProtocolHandler::ProtocolHandler(ClientHandler &client, ibrcommon::tcpstream &stream) 00026 : _client(client), _stream(stream) 00027 { 00028 } 00029 00030 ProtocolHandler::~ProtocolHandler() 00031 {} 00032 00033 ClientHandler::ClientHandler(ApiServerInterface &srv, Registration ®istration, ibrcommon::tcpstream *conn) 00034 : _srv(srv), _registration(®istration), _stream(conn), _endpoint(dtn::core::BundleCore::local), _handler(NULL) 00035 { 00036 if ( dtn::daemon::Configuration::getInstance().getNetwork().getTCPOptionNoDelay() ) 00037 { 00038 _stream->enableNoDelay(); 00039 } 00040 } 00041 00042 ClientHandler::~ClientHandler() 00043 { 00044 delete _stream; 00045 } 00046 00047 Registration& ClientHandler::getRegistration() 00048 { 00049 return *_registration; 00050 } 00051 00052 ApiServerInterface& ClientHandler::getAPIServer() 00053 { 00054 return _srv; 00055 } 00056 00057 void ClientHandler::switchRegistration(Registration ®) 00058 { 00059 _registration->abort(); 00060 00061 _srv.freeRegistration(*_registration); 00062 00063 _registration = ® 00064 } 00065 00066 void ClientHandler::setup() 00067 { 00068 } 00069 00070 void ClientHandler::run() 00071 { 00072 // signal the active connection to the server 00073 _srv.connectionUp(this); 00074 00075 std::string buffer; 00076 00077 while (_stream->good()) 00078 { 00079 if (_handler != NULL) 00080 { 00081 _handler->setup(); 00082 _handler->run(); 00083 _handler->finally(); 00084 delete _handler; 00085 _handler = NULL; 00086 00087 // end this stream, return to the previous stage 00088 (*_stream) << ClientHandler::API_STATUS_OK << " SWITCHED TO LEVEL 0" << std::endl; 00089 00090 continue; 00091 } 00092 00093 getline(*_stream, buffer); 00094 00095 // search for '\r\n' and remove the '\r' 00096 std::string::reverse_iterator iter = buffer.rbegin(); 00097 if ( (*iter) == '\r' ) buffer = buffer.substr(0, buffer.length() - 1); 00098 00099 std::vector<std::string> cmd = dtn::utils::Utils::tokenize(" ", buffer); 00100 if (cmd.size() == 0) continue; 00101 00102 try { 00103 if (cmd[0] == "protocol") 00104 { 00105 if (cmd[1] == "tcpcl") 00106 { 00107 // switch to binary protocol (old style api) 00108 _handler = new BinaryStreamClient(*this, *_stream); 00109 continue; 00110 } 00111 else if (cmd[1] == "management") 00112 { 00113 // switch to the management protocol 00114 _handler = new ManagementConnection(*this, *_stream); 00115 continue; 00116 } 00117 else if (cmd[1] == "event") 00118 { 00119 // switch to the management protocol 00120 _handler = new EventConnection(*this, *_stream); 00121 continue; 00122 } 00123 else if (cmd[1] == "extended") 00124 { 00125 // switch to the extended api 00126 _handler = new ExtendedApiHandler(*this, *_stream); 00127 continue; 00128 } 00129 else if (cmd[1] == "streaming") 00130 { 00131 // switch to the streaming api 00132 _handler = new OrderedStreamHandler(*this, *_stream); 00133 continue; 00134 } 00135 else 00136 { 00137 error(API_STATUS_NOT_ACCEPTABLE, "UNKNOWN PROTOCOL"); 00138 } 00139 } 00140 else 00141 { 00142 // forward to standard command set 00143 processCommand(cmd); 00144 } 00145 } catch (const std::exception&) { 00146 error(API_STATUS_BAD_REQUEST, "PROTOCOL ERROR"); 00147 } 00148 } 00149 } 00150 00151 void ClientHandler::error(STATUS_CODES code, const std::string &msg) 00152 { 00153 ibrcommon::MutexLock l(_write_lock); 00154 (*_stream) << code << " " << msg << std::endl; 00155 } 00156 00157 void ClientHandler::__cancellation() 00158 { 00159 // close the stream 00160 (*_stream).close(); 00161 } 00162 00163 void ClientHandler::finally() 00164 { 00165 IBRCOMMON_LOGGER_DEBUG(60) << "ApiConnection down" << IBRCOMMON_LOGGER_ENDL; 00166 00167 // remove the client from the list in ApiServer 00168 _srv.connectionDown(this); 00169 00170 _registration->abort(); 00171 _srv.freeRegistration(*_registration); 00172 00173 // close the stream 00174 try { 00175 (*_stream).close(); 00176 } catch (const ibrcommon::ConnectionClosedException&) { }; 00177 } 00178 00179 void ClientHandler::eventNodeAvailable(const dtn::core::Node &node) 00180 { 00181 } 00182 00183 void ClientHandler::eventNodeUnavailable(const dtn::core::Node &node) 00184 { 00185 } 00186 00187 void ClientHandler::processCommand(const std::vector<std::string> &cmd) 00188 { 00189 class BundleFilter : public dtn::storage::BundleStorage::BundleFilterCallback 00190 { 00191 public: 00192 BundleFilter() 00193 {}; 00194 00195 virtual ~BundleFilter() {}; 00196 00197 virtual size_t limit() const { return 0; }; 00198 00199 virtual bool shouldAdd(const dtn::data::MetaBundle &meta) const 00200 { 00201 return true; 00202 } 00203 }; 00204 00205 try { 00206 if (cmd[0] == "set") 00207 { 00208 if (cmd.size() < 2) throw ibrcommon::Exception("not enough parameters"); 00209 00210 if (cmd[1] == "endpoint") 00211 { 00212 if (cmd.size() < 3) throw ibrcommon::Exception("not enough parameters"); 00213 00214 ibrcommon::MutexLock l(_write_lock); 00215 _endpoint = dtn::core::BundleCore::local + "/" + cmd[2]; 00216 00217 // error checking 00218 if (_endpoint == dtn::data::EID()) 00219 { 00220 (*_stream) << API_STATUS_NOT_ACCEPTABLE << " INVALID ENDPOINT" << std::endl; 00221 _endpoint = dtn::core::BundleCore::local; 00222 } 00223 else 00224 { 00225 _registration->subscribe(_endpoint); 00226 (*_stream) << API_STATUS_ACCEPTED << " OK" << std::endl; 00227 } 00228 } 00229 else 00230 { 00231 ibrcommon::MutexLock l(_write_lock); 00232 (*_stream) << API_STATUS_BAD_REQUEST << " UNKNOWN COMMAND" << std::endl; 00233 } 00234 } 00235 else if (cmd[0] == "registration") 00236 { 00237 if (cmd.size() < 2) throw ibrcommon::Exception("not enough parameters"); 00238 00239 if (cmd[1] == "add") 00240 { 00241 if (cmd.size() < 3) throw ibrcommon::Exception("not enough parameters"); 00242 00243 ibrcommon::MutexLock l(_write_lock); 00244 dtn::data::EID endpoint(cmd[2]); 00245 00246 // error checking 00247 if (endpoint == dtn::data::EID()) 00248 { 00249 (*_stream) << API_STATUS_NOT_ACCEPTABLE << " INVALID EID" << std::endl; 00250 } 00251 else 00252 { 00253 _registration->subscribe(endpoint); 00254 (*_stream) << API_STATUS_ACCEPTED << " OK" << std::endl; 00255 } 00256 } 00257 else if (cmd[1] == "del") 00258 { 00259 if (cmd.size() < 3) throw ibrcommon::Exception("not enough parameters"); 00260 00261 ibrcommon::MutexLock l(_write_lock); 00262 dtn::data::EID endpoint(cmd[2]); 00263 00264 // error checking 00265 if (endpoint == dtn::data::EID()) 00266 { 00267 (*_stream) << API_STATUS_NOT_ACCEPTABLE << " INVALID EID" << std::endl; 00268 } 00269 else 00270 { 00271 _registration->unsubscribe(endpoint); 00272 (*_stream) << API_STATUS_ACCEPTED << " OK" << std::endl; 00273 } 00274 } 00275 else if (cmd[1] == "list") 00276 { 00277 ibrcommon::MutexLock l(_write_lock); 00278 const std::set<dtn::data::EID> list = _registration->getSubscriptions(); 00279 00280 (*_stream) << API_STATUS_OK << " REGISTRATION LIST" << std::endl; 00281 for (std::set<dtn::data::EID>::const_iterator iter = list.begin(); iter != list.end(); iter++) 00282 { 00283 (*_stream) << (*iter).getString() << std::endl; 00284 } 00285 (*_stream) << std::endl; 00286 } 00287 else 00288 { 00289 ibrcommon::MutexLock l(_write_lock); 00290 (*_stream) << API_STATUS_BAD_REQUEST << " UNKNOWN COMMAND" << std::endl; 00291 } 00292 } 00293 else 00294 { 00295 ibrcommon::MutexLock l(_write_lock); 00296 (*_stream) << API_STATUS_BAD_REQUEST << " UNKNOWN COMMAND" << std::endl; 00297 } 00298 } catch (const std::exception&) { 00299 ibrcommon::MutexLock l(_write_lock); 00300 (*_stream) << API_STATUS_BAD_REQUEST << " ERROR" << std::endl; 00301 } 00302 } 00303 } 00304 }