|
IBR-DTNSuite 0.6
|
00001 /* 00002 * ApiServer.cpp 00003 * 00004 * Created on: 24.06.2009 00005 * Author: morgenro 00006 */ 00007 00008 #include "config.h" 00009 #include "Configuration.h" 00010 #include "api/ApiServer.h" 00011 #include "core/BundleCore.h" 00012 #include "routing/QueueBundleEvent.h" 00013 #include "net/BundleReceivedEvent.h" 00014 #include "core/NodeEvent.h" 00015 #include <ibrdtn/data/AgeBlock.h> 00016 #include <ibrcommon/Logger.h> 00017 #include <typeinfo> 00018 #include <algorithm> 00019 00020 #ifdef WITH_COMPRESSION 00021 #include <ibrdtn/data/CompressedPayloadBlock.h> 00022 #endif 00023 00024 #ifdef WITH_BUNDLE_SECURITY 00025 #include "security/SecurityManager.h" 00026 #endif 00027 00028 namespace dtn 00029 { 00030 namespace api 00031 { 00032 ApiServer::ApiServer(const ibrcommon::File &socket) 00033 : _srv(socket) 00034 { 00035 } 00036 00037 ApiServer::ApiServer(const ibrcommon::vinterface &net, int port) 00038 : _srv() 00039 { 00040 _srv.bind(net, port); 00041 } 00042 00043 ApiServer::~ApiServer() 00044 { 00045 join(); 00046 } 00047 00048 bool ApiServer::__cancellation() 00049 { 00050 _srv.shutdown(); 00051 return true; 00052 } 00053 00054 void ApiServer::componentUp() 00055 { 00056 _srv.listen(5); 00057 bindEvent(dtn::routing::QueueBundleEvent::className); 00058 bindEvent(dtn::core::NodeEvent::className); 00059 } 00060 00061 void ApiServer::componentRun() 00062 { 00063 try { 00064 while (true) 00065 { 00066 // accept the next client 00067 ibrcommon::tcpstream *conn = _srv.accept(); 00068 00069 // generate some output 00070 IBRCOMMON_LOGGER_DEBUG(5) << "new connected client at the extended API server" << IBRCOMMON_LOGGER_ENDL; 00071 00072 // send welcome banner 00073 (*conn) << "IBR-DTN " << dtn::daemon::Configuration::getInstance().version() << " API 1.0" << std::endl; 00074 00075 ibrcommon::MutexLock l(_connection_lock); 00076 00077 // create a new registration 00078 Registration reg; _registrations.push_back(reg); 00079 IBRCOMMON_LOGGER_DEBUG(5) << "new registration " << reg.getHandle() << IBRCOMMON_LOGGER_ENDL; 00080 00081 ClientHandler *obj = new ClientHandler(*this, _registrations.back(), conn); 00082 _connections.push_back(obj); 00083 00084 // start the client handler 00085 obj->start(); 00086 00087 // breakpoint 00088 ibrcommon::Thread::yield(); 00089 } 00090 } catch (const std::exception&) { 00091 // ignore all errors 00092 return; 00093 } 00094 } 00095 00096 void ApiServer::componentDown() 00097 { 00098 unbindEvent(dtn::routing::QueueBundleEvent::className); 00099 unbindEvent(dtn::core::NodeEvent::className); 00100 00101 { 00102 ibrcommon::MutexLock l(_connection_lock); 00103 00104 // shutdown all clients 00105 for (std::list<ClientHandler*>::iterator iter = _connections.begin(); iter != _connections.end(); iter++) 00106 { 00107 (*iter)->stop(); 00108 } 00109 } 00110 00111 // wait until all clients are down 00112 while (_connections.size() > 0) ::sleep(1); 00113 } 00114 00115 void ApiServer::processIncomingBundle(const dtn::data::EID &source, dtn::data::Bundle &bundle) 00116 { 00117 // check address fields for "api:me", this has to be replaced 00118 static const dtn::data::EID clienteid("api:me"); 00119 00120 // set the source address to the sending EID 00121 bundle._source = source; 00122 00123 if (bundle._destination == clienteid) bundle._destination = source; 00124 if (bundle._reportto == clienteid) bundle._reportto = source; 00125 if (bundle._custodian == clienteid) bundle._custodian = source; 00126 00127 // if the timestamp is not set, add a ageblock 00128 if (bundle._timestamp == 0) 00129 { 00130 // check for ageblock 00131 try { 00132 bundle.getBlock<dtn::data::AgeBlock>(); 00133 } catch (const dtn::data::Bundle::NoSuchBlockFoundException&) { 00134 // add a new ageblock 00135 bundle.push_front<dtn::data::AgeBlock>(); 00136 } 00137 } 00138 00139 #ifdef WITH_COMPRESSION 00140 // if the compression bit is set, then compress the bundle 00141 if (bundle.get(dtn::data::PrimaryBlock::IBRDTN_REQUEST_COMPRESSION)) 00142 { 00143 try { 00144 dtn::data::CompressedPayloadBlock::compress(bundle, dtn::data::CompressedPayloadBlock::COMPRESSION_ZLIB); 00145 } catch (const ibrcommon::Exception &ex) { 00146 IBRCOMMON_LOGGER(warning) << "compression of bundle failed: " << ex.what() << IBRCOMMON_LOGGER_ENDL; 00147 }; 00148 } 00149 #endif 00150 00151 #ifdef WITH_BUNDLE_SECURITY 00152 // if the encrypt bit is set, then try to encrypt the bundle 00153 if (bundle.get(dtn::data::PrimaryBlock::DTNSEC_REQUEST_ENCRYPT)) 00154 { 00155 try { 00156 dtn::security::SecurityManager::getInstance().encrypt(bundle); 00157 00158 bundle.set(dtn::data::PrimaryBlock::DTNSEC_REQUEST_ENCRYPT, false); 00159 } catch (const dtn::security::SecurityManager::KeyMissingException&) { 00160 // sign requested, but no key is available 00161 IBRCOMMON_LOGGER(warning) << "No key available for encrypt process." << IBRCOMMON_LOGGER_ENDL; 00162 } catch (const dtn::security::SecurityManager::EncryptException&) { 00163 IBRCOMMON_LOGGER(warning) << "Encryption of bundle failed." << IBRCOMMON_LOGGER_ENDL; 00164 } 00165 } 00166 00167 // if the sign bit is set, then try to sign the bundle 00168 if (bundle.get(dtn::data::PrimaryBlock::DTNSEC_REQUEST_SIGN)) 00169 { 00170 try { 00171 dtn::security::SecurityManager::getInstance().sign(bundle); 00172 00173 bundle.set(dtn::data::PrimaryBlock::DTNSEC_REQUEST_SIGN, false); 00174 } catch (const dtn::security::SecurityManager::KeyMissingException&) { 00175 // sign requested, but no key is available 00176 IBRCOMMON_LOGGER(warning) << "No key available for sign process." << IBRCOMMON_LOGGER_ENDL; 00177 } 00178 } 00179 #endif 00180 00181 // raise default bundle received event 00182 dtn::net::BundleReceivedEvent::raise(source, bundle, true); 00183 } 00184 00185 const std::string ApiServer::getName() const 00186 { 00187 return "ApiServer"; 00188 } 00189 00190 void ApiServer::connectionUp(ClientHandler *obj) 00191 { 00192 // generate some output 00193 IBRCOMMON_LOGGER_DEBUG(5) << "api connection up" << IBRCOMMON_LOGGER_ENDL; 00194 } 00195 00196 void ApiServer::connectionDown(ClientHandler *obj) 00197 { 00198 // generate some output 00199 IBRCOMMON_LOGGER_DEBUG(5) << "api connection down" << IBRCOMMON_LOGGER_ENDL; 00200 00201 ibrcommon::MutexLock l(_connection_lock); 00202 00203 // remove this object out of the list 00204 for (std::list<ClientHandler*>::iterator iter = _connections.begin(); iter != _connections.end(); iter++) 00205 { 00206 if (obj == (*iter)) 00207 { 00208 _connections.erase(iter); 00209 break; 00210 } 00211 } 00212 } 00213 00214 void ApiServer::freeRegistration(Registration ®) 00215 { 00216 // remove the registration 00217 for (std::list<dtn::api::Registration>::iterator iter = _registrations.begin(); iter != _registrations.end(); iter++) 00218 { 00219 if (reg == (*iter)) 00220 { 00221 IBRCOMMON_LOGGER_DEBUG(5) << "release registration " << reg.getHandle() << IBRCOMMON_LOGGER_ENDL; 00222 _registrations.erase(iter); 00223 break; 00224 } 00225 } 00226 } 00227 00228 void ApiServer::raiseEvent(const dtn::core::Event *evt) 00229 { 00230 try { 00231 const dtn::routing::QueueBundleEvent &queued = dynamic_cast<const dtn::routing::QueueBundleEvent&>(*evt); 00232 00233 ibrcommon::MutexLock l(_connection_lock); 00234 for (std::list<ClientHandler*>::iterator iter = _connections.begin(); iter != _connections.end(); iter++) 00235 { 00236 ClientHandler &conn = **iter; 00237 if (conn.getRegistration().hasSubscribed(queued.bundle.destination)) 00238 { 00239 conn.getRegistration().notify(Registration::NOTIFY_BUNDLE_AVAILABLE); 00240 } 00241 } 00242 } catch (const std::bad_cast&) { }; 00243 00244 try { 00245 const dtn::core::NodeEvent &ne = dynamic_cast<const dtn::core::NodeEvent&>(*evt); 00246 00247 ibrcommon::MutexLock l(_connection_lock); 00248 for (std::list<ClientHandler*>::iterator iter = _connections.begin(); iter != _connections.end(); iter++) 00249 { 00250 ClientHandler &conn = **iter; 00251 00252 if (ne.getAction() == NODE_AVAILABLE) 00253 { 00254 conn.eventNodeAvailable(ne.getNode()); 00255 } 00256 else if (ne.getAction() == NODE_UNAVAILABLE) 00257 { 00258 conn.eventNodeUnavailable(ne.getNode()); 00259 } 00260 } 00261 } catch (const std::bad_cast&) { }; 00262 } 00263 } 00264 }