IBR-DTNSuite 0.6

daemon/src/api/ApiServer.cpp

Go to the documentation of this file.
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 &reg)
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 }