IBR-DTNSuite 0.6

daemon/src/net/ConnectionManager.cpp

Go to the documentation of this file.
00001 /*
00002  * ConnectionManager.cpp
00003  *
00004  *  Created on: 24.09.2009
00005  *      Author: morgenro
00006  */
00007 
00008 #include "net/ConnectionManager.h"
00009 #include "net/UDPConvergenceLayer.h"
00010 #include "net/TCPConvergenceLayer.h"
00011 #include "net/BundleReceivedEvent.h"
00012 #include "core/NodeEvent.h"
00013 #include "core/BundleEvent.h"
00014 #include "ibrcommon/net/tcpserver.h"
00015 #include "core/BundleCore.h"
00016 #include "routing/RequeueBundleEvent.h"
00017 #include "net/ConnectionEvent.h"
00018 
00019 #include "core/NodeEvent.h"
00020 #include "core/TimeEvent.h"
00021 
00022 #include <iostream>
00023 #include <iomanip>
00024 #include <algorithm>
00025 #include <functional>
00026 #include <typeinfo>
00027 #include <ibrcommon/Logger.h>
00028 
00029 using namespace dtn::core;
00030 
00031 namespace dtn
00032 {
00033         namespace net
00034         {
00035                 struct CompareNodeDestination:
00036                 public std::binary_function< dtn::core::Node, dtn::data::EID, bool > {
00037                         bool operator() ( const dtn::core::Node &node, const dtn::data::EID &destination ) const {
00038                                 return node.getEID() == destination;
00039                         }
00040                 };
00041 
00042                 ConnectionManager::ConnectionManager()
00043                  : _shutdown(false)
00044                 {
00045                 }
00046 
00047                 ConnectionManager::~ConnectionManager()
00048                 {
00049                 }
00050 
00051                 void ConnectionManager::componentUp()
00052                 {
00053                         bindEvent(TimeEvent::className);
00054                         bindEvent(NodeEvent::className);
00055                         bindEvent(ConnectionEvent::className);
00056                 }
00057 
00058                 void ConnectionManager::componentDown()
00059                 {
00060                         {
00061                                 ibrcommon::MutexLock l(_cl_lock);
00062                                 // clear the list of convergence layers
00063                                 _cl.clear();
00064                         }
00065 
00066                         unbindEvent(NodeEvent::className);
00067                         unbindEvent(TimeEvent::className);
00068                         unbindEvent(ConnectionEvent::className);
00069                 }
00070 
00071                 void ConnectionManager::raiseEvent(const dtn::core::Event *evt)
00072                 {
00073                         try {
00074                                 const NodeEvent &nodeevent = dynamic_cast<const NodeEvent&>(*evt);
00075                                 const Node &n = nodeevent.getNode();
00076 
00077                                 switch (nodeevent.getAction())
00078                                 {
00079                                         case NODE_INFO_UPDATED:
00080                                                 discovered(n);
00081                                                 break;
00082 
00083                                         case NODE_AVAILABLE:
00084                                                 if (n.doConnectImmediately())
00085                                                 {
00086                                                         // open the connection immediately
00087                                                         open(n);
00088                                                 }
00089                                                 break;
00090 
00091                                         default:
00092                                                 break;
00093                                 }
00094                         } catch (const std::bad_cast&) { }
00095 
00096                         try {
00097                                 const TimeEvent &timeevent = dynamic_cast<const TimeEvent&>(*evt);
00098 
00099                                 if (timeevent.getAction() == TIME_SECOND_TICK)
00100                                 {
00101                                         check_discovered();
00102                                 }
00103                         } catch (const std::bad_cast&) { }
00104 
00105                         try {
00106                                 const ConnectionEvent &connection = dynamic_cast<const ConnectionEvent&>(*evt);
00107 
00108                                 switch (connection.state)
00109                                 {
00110                                         case ConnectionEvent::CONNECTION_UP:
00111                                         {
00112                                                 ibrcommon::MutexLock l(_node_lock);
00113 
00114                                                 // if this node was unknown before...
00115                                                 if (!isNeighbor(connection.node))
00116                                                 {
00117                                                         // announce the new node
00118                                                         dtn::core::NodeEvent::raise(connection.node, dtn::core::NODE_AVAILABLE);
00119                                                 }
00120 
00121                                                 _connected_nodes.insert(connection.node);
00122                                                 break;
00123                                         }
00124 
00125                                         case ConnectionEvent::CONNECTION_DOWN:
00126                                         {
00127                                                 ibrcommon::MutexLock l(_node_lock);
00128 
00129                                                 // remove the node from the connected list
00130                                                 _connected_nodes.erase(connection.node);
00131 
00132                                                 // if the node is unknown now ...
00133                                                 if (!isNeighbor(connection.node))
00134                                                 {
00135                                                         // announce the unavailable event
00136                                                         dtn::core::NodeEvent::raise(connection.node, dtn::core::NODE_UNAVAILABLE);
00137                                                 }
00138                                                 break;
00139                                         }
00140 
00141                                         default:
00142                                                 break;
00143                                 }
00144 
00145                         } catch (const std::bad_cast&) {
00146 
00147                         }
00148                 }
00149 
00150                 void ConnectionManager::addConnection(const dtn::core::Node &n)
00151                 {
00152                         ibrcommon::MutexLock l(_node_lock);
00153                         _static_nodes.insert(n);
00154                         dtn::core::NodeEvent::raise(n, dtn::core::NODE_AVAILABLE);
00155                 }
00156 
00157                 void ConnectionManager::addConvergenceLayer(ConvergenceLayer *cl)
00158                 {
00159                         ibrcommon::MutexLock l(_cl_lock);
00160                         _cl.insert( cl );
00161                 }
00162 
00163                 void ConnectionManager::discovered(const dtn::core::Node &node)
00164                 {
00165                         // ignore messages of ourself
00166                         if (node.getEID() == dtn::core::BundleCore::local) return;
00167 
00168                         ibrcommon::MutexLock l(_node_lock);
00169 
00170                         // if this node was unknown before...
00171                         if (!isNeighbor(node))
00172                         {
00173                                 // announce the new node
00174                                 dtn::core::NodeEvent::raise(node, dtn::core::NODE_AVAILABLE);
00175                         }
00176 
00177                         _discovered_nodes.erase(node);
00178                         _discovered_nodes.insert(node);
00179                 }
00180 
00181                 void ConnectionManager::check_discovered()
00182                 {
00183                         ibrcommon::MutexLock l(_node_lock);
00184 
00185                         // search for outdated nodes
00186                         std::set<dtn::core::Node>::iterator iter = _discovered_nodes.begin();
00187 
00188                         while (iter != _discovered_nodes.end())
00189                         {
00190                                 dtn::core::Node n = (*iter);
00191 
00192                                 // node is outdated -> remove it
00193                                 _discovered_nodes.erase( iter++ );
00194 
00195                                 if ( !n.decrementTimeout(1) )
00196                                 {
00197                                         // if the node is unknown now ...
00198                                         if (!isNeighbor(n))
00199                                         {
00200                                                 // announce the unavailable event
00201                                                 dtn::core::NodeEvent::raise(n, dtn::core::NODE_UNAVAILABLE);
00202                                         }
00203                                 }
00204                                 else
00205                                 {
00206                                         _discovered_nodes.insert(n);
00207                                 }
00208                         }
00209                 }
00210 
00211                 void ConnectionManager::open(const dtn::core::Node &node)
00212                 {
00213                         ibrcommon::MutexLock l(_cl_lock);
00214 
00215                         // search for the right cl
00216                         for (std::set<ConvergenceLayer*>::iterator iter = _cl.begin(); iter != _cl.end(); iter++)
00217                         {
00218                                 ConvergenceLayer *cl = (*iter);
00219                                 if (node.has(cl->getDiscoveryProtocol()))
00220                                 {
00221                                         cl->open(node);
00222 
00223                                         // stop here, we queued the bundle already
00224                                         return;
00225                                 }
00226                         }
00227 
00228                         throw ConnectionNotAvailableException();
00229                 }
00230 
00231                 void ConnectionManager::queue(const dtn::core::Node &node, const ConvergenceLayer::Job &job)
00232                 {
00233                         ibrcommon::MutexLock l(_cl_lock);
00234 
00235                         // search for the right cl
00236                         for (std::set<ConvergenceLayer*>::iterator iter = _cl.begin(); iter != _cl.end(); iter++)
00237                         {
00238                                 ConvergenceLayer *cl = (*iter);
00239                                 if (node.has(cl->getDiscoveryProtocol()))
00240                                 {
00241                                         cl->queue(node, job);
00242 
00243                                         // stop here, we queued the bundle already
00244                                         return;
00245                                 }
00246                         }
00247 
00248                         throw ConnectionNotAvailableException();
00249                 }
00250 
00251                 void ConnectionManager::queue(const ConvergenceLayer::Job &job)
00252                 {
00253                         try {
00254                                 ibrcommon::MutexLock l(_node_lock);
00255                                 dtn::core::Node match(job._destination);
00256 
00257                                 if (IBRCOMMON_LOGGER_LEVEL >= 50)
00258                                 {
00259                                         IBRCOMMON_LOGGER_DEBUG(50) << "## static node list ##" << IBRCOMMON_LOGGER_ENDL;
00260                                         for (std::set<dtn::core::Node>::const_iterator iter = _static_nodes.begin(); iter != _static_nodes.end(); iter++)
00261                                         {
00262                                                 const dtn::core::Node &n = (*iter);
00263                                                 IBRCOMMON_LOGGER_DEBUG(50) << n.toString() << IBRCOMMON_LOGGER_ENDL;
00264                                         }
00265                                 }
00266 
00267                                 if (IBRCOMMON_LOGGER_LEVEL >= 50)
00268                                 {
00269                                         IBRCOMMON_LOGGER_DEBUG(50) << "## dynamic node list ##" << IBRCOMMON_LOGGER_ENDL;
00270                                         for (std::set<dtn::core::Node>::const_iterator iter = _discovered_nodes.begin(); iter != _discovered_nodes.end(); iter++)
00271                                         {
00272                                                 const dtn::core::Node &n = (*iter);
00273                                                 IBRCOMMON_LOGGER_DEBUG(50) << n.toString() << IBRCOMMON_LOGGER_ENDL;
00274                                         }
00275                                 }
00276 
00277                                 if (IBRCOMMON_LOGGER_LEVEL >= 50)
00278                                 {
00279                                         IBRCOMMON_LOGGER_DEBUG(50) << "## connected node list ##" << IBRCOMMON_LOGGER_ENDL;
00280                                         for (std::set<dtn::core::Node>::const_iterator iter = _connected_nodes.begin(); iter != _connected_nodes.end(); iter++)
00281                                         {
00282                                                 const dtn::core::Node &n = (*iter);
00283                                                 IBRCOMMON_LOGGER_DEBUG(50) << n.toString() << IBRCOMMON_LOGGER_ENDL;
00284                                         }
00285                                 }
00286 
00287                                 IBRCOMMON_LOGGER_DEBUG(50) << "match for " << match.toString() << IBRCOMMON_LOGGER_ENDL;
00288 
00289                                 try {
00290                                         // queue to a static node
00291                                         std::set<dtn::core::Node>::const_iterator iter = _static_nodes.find(match);
00292 
00293                                         if (iter != _static_nodes.end())
00294                                         {
00295                                                 throw (*iter);
00296                                         }
00297                                 } catch (const std::exception&) { }
00298 
00299                                 try {
00300                                         // queue to a dynamic discovered node
00301                                         std::set<dtn::core::Node>::const_iterator iter = _discovered_nodes.find(match);
00302 
00303                                         if (iter != _discovered_nodes.end())
00304                                         {
00305                                                 throw (*iter);
00306                                         }
00307                                 } catch (const std::exception&) { }
00308 
00309                                 try {
00310                                         // queue to a connected node
00311                                         std::set<dtn::core::Node>::const_iterator iter = _connected_nodes.find(match);
00312 
00313                                         if (iter != _connected_nodes.end())
00314                                         {
00315                                                 throw (*iter);
00316                                         }
00317                                 } catch (const std::exception&) { }
00318                         } catch (const dtn::core::Node &next) {
00319                                 IBRCOMMON_LOGGER_DEBUG(50) << "next hop: " << next.toString() << IBRCOMMON_LOGGER_ENDL;
00320                                 queue(next, job);
00321                                 return;
00322                         }
00323 
00324                         throw NeighborNotAvailableException("No active connection to this neighbor available!");
00325                 }
00326 
00327                 void ConnectionManager::queue(const dtn::data::EID &eid, const dtn::data::BundleID &b)
00328                 {
00329                         queue( ConvergenceLayer::Job(eid, b) );
00330                 }
00331 
00332                 const std::set<dtn::core::Node> ConnectionManager::getNeighbors()
00333                 {
00334                         ibrcommon::MutexLock l(_node_lock);
00335 
00336                         std::set<dtn::core::Node> _nodes;
00337 
00338                         for (std::set<dtn::core::Node>::const_iterator iter = _static_nodes.begin(); iter != _static_nodes.end(); iter++)
00339                         {
00340                                 _nodes.insert( *iter );
00341                         }
00342 
00343                         for (std::set<dtn::core::Node>::const_iterator iter = _discovered_nodes.begin(); iter != _discovered_nodes.end(); iter++)
00344                         {
00345                                 _nodes.insert( *iter );
00346                         }
00347 
00348                         for (std::set<dtn::core::Node>::const_iterator iter = _connected_nodes.begin(); iter != _connected_nodes.end(); iter++)
00349                         {
00350                                 _nodes.insert( *iter );
00351                         }
00352 
00353                         return _nodes;
00354                 }
00355 
00356 
00357                 bool ConnectionManager::isNeighbor(const dtn::core::Node &node)
00358                 {
00359                         // search for the node in all sets
00360                         if (_static_nodes.find(node) != _static_nodes.end())
00361                         {
00362                                 return true;
00363                         }
00364 
00365                         if (_discovered_nodes.find(node) != _discovered_nodes.end())
00366                         {
00367                                 return true;
00368                         }
00369 
00370                         if (_connected_nodes.find(node) != _connected_nodes.end())
00371                         {
00372                                 return true;
00373                         }
00374 
00375                         return false;
00376                 }
00377 
00378                 const std::string ConnectionManager::getName() const
00379                 {
00380                         return "ConnectionManager";
00381                 }
00382         }
00383 }