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