• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

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 dtn::data::EID(node.getURI()) == 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                                                 // if this node is still available (discovered or static)
00130                                                 if (isNeighbor(connection.node))
00131                                                 {
00132                                                         // remove the node from the connected list
00133                                                         _connected_nodes.erase(connection.node);
00134 
00135                                                         // remove the node from the discovered list
00136                                                         _discovered_nodes.erase(connection.node);
00137 
00138                                                         // if the node is unknown now ...
00139                                                         if (!isNeighbor(connection.node))
00140                                                         {
00141                                                                 // announce the unavailable event
00142                                                                 dtn::core::NodeEvent::raise(connection.node, dtn::core::NODE_UNAVAILABLE);
00143                                                         }
00144                                                 }
00145                                                 break;
00146                                         }
00147 
00148                                         default:
00149                                                 break;
00150                                 }
00151 
00152                         } catch (const std::bad_cast&) {
00153 
00154                         }
00155                 }
00156 
00157                 void ConnectionManager::addConnection(const dtn::core::Node &n)
00158                 {
00159                         ibrcommon::MutexLock l(_node_lock);
00160                         _static_nodes.insert(n);
00161                         dtn::core::NodeEvent::raise(n, dtn::core::NODE_AVAILABLE);
00162                 }
00163 
00164                 void ConnectionManager::addConvergenceLayer(ConvergenceLayer *cl)
00165                 {
00166                         ibrcommon::MutexLock l(_cl_lock);
00167                         _cl.insert( cl );
00168                 }
00169 
00170                 void ConnectionManager::discovered(const dtn::core::Node &node)
00171                 {
00172                         // ignore messages of ourself
00173                         if (EID(node.getURI()) == dtn::core::BundleCore::local) return;
00174 
00175                         ibrcommon::MutexLock l(_node_lock);
00176 
00177                         // if this node was unknown before...
00178                         if (!isNeighbor(node))
00179                         {
00180                                 // announce the new node
00181                                 dtn::core::NodeEvent::raise(node, dtn::core::NODE_AVAILABLE);
00182                         }
00183 
00184                         _discovered_nodes.erase(node);
00185                         _discovered_nodes.insert(node);
00186                 }
00187 
00188                 void ConnectionManager::check_discovered()
00189                 {
00190                         ibrcommon::MutexLock l(_node_lock);
00191 
00192                         // search for outdated nodes
00193                         std::set<dtn::core::Node>::iterator iter = _discovered_nodes.begin();
00194 
00195                         while (iter != _discovered_nodes.end())
00196                         {
00197                                 dtn::core::Node n = (*iter);
00198 
00199                                 // node is outdated -> remove it
00200                                 _discovered_nodes.erase( iter++ );
00201 
00202                                 if ( !n.decrementTimeout(1) )
00203                                 {
00204                                         // remove the connected node
00205                                         _connected_nodes.erase(n);
00206 
00207                                         // announce the unavailable event
00208                                         dtn::core::NodeEvent::raise(n, dtn::core::NODE_UNAVAILABLE);
00209                                 }
00210                                 else
00211                                 {
00212                                         _discovered_nodes.insert(n);
00213                                 }
00214                         }
00215                 }
00216 
00217                 void ConnectionManager::open(const dtn::core::Node &node)
00218                 {
00219                         if ((node.getProtocol() == Node::CONN_UNDEFINED) || (node.getProtocol() == Node::CONN_UNSUPPORTED))
00220                                 throw ConnectionNotAvailableException();
00221 
00222                         ibrcommon::MutexLock l(_cl_lock);
00223 
00224                         // search for the right cl
00225                         for (std::set<ConvergenceLayer*>::iterator iter = _cl.begin(); iter != _cl.end(); iter++)
00226                         {
00227                                 ConvergenceLayer *cl = (*iter);
00228                                 if (node.getProtocol() == cl->getDiscoveryProtocol())
00229                                 {
00230                                         cl->open(node);
00231 
00232                                         // stop here, we queued the bundle already
00233                                         return;
00234                                 }
00235                         }
00236 
00237                         throw ConnectionNotAvailableException();
00238                 }
00239 
00240                 void ConnectionManager::queue(const dtn::core::Node &node, const ConvergenceLayer::Job &job)
00241                 {
00242                         if ((node.getProtocol() == Node::CONN_UNDEFINED) || (node.getProtocol() == Node::CONN_UNSUPPORTED))
00243                                 throw ConnectionNotAvailableException();
00244 
00245                         ibrcommon::MutexLock l(_cl_lock);
00246 
00247                         // search for the right cl
00248                         for (std::set<ConvergenceLayer*>::iterator iter = _cl.begin(); iter != _cl.end(); iter++)
00249                         {
00250                                 ConvergenceLayer *cl = (*iter);
00251                                 if (node.getProtocol() == cl->getDiscoveryProtocol())
00252                                 {
00253                                         cl->queue(node, job);
00254 
00255                                         // stop here, we queued the bundle already
00256                                         return;
00257                                 }
00258                         }
00259 
00260                         throw ConnectionNotAvailableException();
00261                 }
00262 
00263                 void ConnectionManager::queue(const ConvergenceLayer::Job &job)
00264                 {
00265                         try {
00266                                 ibrcommon::MutexLock l(_node_lock);
00267 
00268                                 // create a match rank list
00269                                 std::list<dtn::core::Node> match_rank;
00270 
00271                                 // we prefer TCP as primary connection type
00272                                 match_rank.push_back(dtn::core::Node(job._destination, Node::CONN_TCPIP));
00273 
00274                                 // use UDP as seconds connection type
00275                                 match_rank.push_back(dtn::core::Node(job._destination, Node::CONN_UDPIP));
00276 
00277                                 // use Bluetooth as fourth connection type
00278                                 match_rank.push_back(dtn::core::Node(job._destination, Node::CONN_BLUETOOTH));
00279 
00280                                 // use ZigBee as fifth connection type
00281                                 match_rank.push_back(dtn::core::Node(job._destination, Node::CONN_ZIGBEE));
00282 
00283                                 // use HTTP as sixth connection type
00284                                 match_rank.push_back(dtn::core::Node(job._destination, Node::CONN_HTTP));
00285 
00286                                 if (IBRCOMMON_LOGGER_LEVEL >= 50)
00287                                 {
00288                                         IBRCOMMON_LOGGER_DEBUG(50) << "## static node list ##" << IBRCOMMON_LOGGER_ENDL;
00289                                         for (std::set<dtn::core::Node>::const_iterator iter = _static_nodes.begin(); iter != _static_nodes.end(); iter++)
00290                                         {
00291                                                 const dtn::core::Node &n = (*iter);
00292                                                 IBRCOMMON_LOGGER_DEBUG(50) << n.toString() << IBRCOMMON_LOGGER_ENDL;
00293                                         }
00294                                 }
00295 
00296                                 if (IBRCOMMON_LOGGER_LEVEL >= 50)
00297                                 {
00298                                         IBRCOMMON_LOGGER_DEBUG(50) << "## dynamic node list ##" << IBRCOMMON_LOGGER_ENDL;
00299                                         for (std::set<dtn::core::Node>::const_iterator iter = _discovered_nodes.begin(); iter != _discovered_nodes.end(); iter++)
00300                                         {
00301                                                 const dtn::core::Node &n = (*iter);
00302                                                 IBRCOMMON_LOGGER_DEBUG(50) << n.toString() << IBRCOMMON_LOGGER_ENDL;
00303                                         }
00304                                 }
00305 
00306                                 if (IBRCOMMON_LOGGER_LEVEL >= 50)
00307                                 {
00308                                         IBRCOMMON_LOGGER_DEBUG(50) << "## connected node list ##" << IBRCOMMON_LOGGER_ENDL;
00309                                         for (std::set<dtn::core::Node>::const_iterator iter = _connected_nodes.begin(); iter != _connected_nodes.end(); iter++)
00310                                         {
00311                                                 const dtn::core::Node &n = (*iter);
00312                                                 IBRCOMMON_LOGGER_DEBUG(50) << n.toString() << IBRCOMMON_LOGGER_ENDL;
00313                                         }
00314                                 }
00315 
00316                                 // iterate through all matches in the rank list
00317                                 for (std::list<dtn::core::Node>::const_iterator imatch = match_rank.begin(); imatch != match_rank.end(); imatch++)
00318                                 {
00319                                         const dtn::core::Node &match = (*imatch);
00320                                         IBRCOMMON_LOGGER_DEBUG(50) << "match for " << match.toString() << IBRCOMMON_LOGGER_ENDL;
00321 
00322                                         try {
00323                                                 // queue to a static node
00324                                                 std::set<dtn::core::Node>::const_iterator iter = _static_nodes.find(match);
00325 
00326                                                 if (iter != _static_nodes.end())
00327                                                 {
00328                                                         throw (*iter);
00329                                                 }
00330                                         } catch (const std::exception&) { }
00331 
00332                                         try {
00333                                                 // queue to a dynamic discovered node
00334                                                 std::set<dtn::core::Node>::const_iterator iter = _discovered_nodes.find(match);
00335 
00336                                                 if (iter != _discovered_nodes.end())
00337                                                 {
00338                                                         throw (*iter);
00339                                                 }
00340                                         } catch (const std::exception&) { }
00341 
00342                                         try {
00343                                                 // queue to a connected node
00344                                                 std::set<dtn::core::Node>::const_iterator iter = _connected_nodes.find(match);
00345 
00346                                                 if (iter != _connected_nodes.end())
00347                                                 {
00348                                                         throw (*iter);
00349                                                 }
00350                                         } catch (const std::exception&) { }
00351                                 }
00352                         } catch (const dtn::core::Node next) {
00353                                 IBRCOMMON_LOGGER_DEBUG(50) << "next hop: " << next.toString() << IBRCOMMON_LOGGER_ENDL;
00354                                 queue(next, job);
00355                                 return;
00356                         }
00357 
00358                         throw NeighborNotAvailableException("No active connection to this neighbor available!");
00359                 }
00360 
00361                 void ConnectionManager::queue(const dtn::data::EID &eid, const dtn::data::BundleID &b)
00362                 {
00363                         queue( ConvergenceLayer::Job(eid, b) );
00364                 }
00365 
00366                 const std::set<dtn::core::Node> ConnectionManager::getNeighbors()
00367                 {
00368                         ibrcommon::MutexLock l(_node_lock);
00369 
00370                         std::set<dtn::core::Node> _nodes;
00371 
00372                         for (std::set<dtn::core::Node>::const_iterator iter = _static_nodes.begin(); iter != _static_nodes.end(); iter++)
00373                         {
00374                                 _nodes.insert( *iter );
00375                         }
00376 
00377                         for (std::set<dtn::core::Node>::const_iterator iter = _discovered_nodes.begin(); iter != _discovered_nodes.end(); iter++)
00378                         {
00379                                 _nodes.insert( *iter );
00380                         }
00381 
00382                         for (std::set<dtn::core::Node>::const_iterator iter = _connected_nodes.begin(); iter != _connected_nodes.end(); iter++)
00383                         {
00384                                 _nodes.insert( *iter );
00385                         }
00386 
00387                         return _nodes;
00388                 }
00389 
00390 
00391                 bool ConnectionManager::isNeighbor(const dtn::core::Node &node)
00392                 {
00393                         // search for the node in all sets
00394                         if (_static_nodes.find(node) != _static_nodes.end())
00395                         {
00396                                 return true;
00397                         }
00398 
00399                         if (_discovered_nodes.find(node) != _discovered_nodes.end())
00400                         {
00401                                 return true;
00402                         }
00403 
00404                         if (_connected_nodes.find(node) != _connected_nodes.end())
00405                         {
00406                                 return true;
00407                         }
00408 
00409                         return false;
00410                 }
00411 
00412                 const std::string ConnectionManager::getName() const
00413                 {
00414                         return "ConnectionManager";
00415                 }
00416         }
00417 }

Generated on Wed Mar 30 2011 11:11:49 for IBR-DTNSuite by  doxygen 1.7.1