|  | 1 | // [Licence] | 
|---|
|  | 2 | // The Ariba-Underlay Copyright | 
|---|
|  | 3 | // | 
|---|
|  | 4 | // Copyright (c) 2008-2009, Institute of Telematics, UniversitÀt Karlsruhe (TH) | 
|---|
|  | 5 | // | 
|---|
|  | 6 | // Institute of Telematics | 
|---|
|  | 7 | // UniversitÀt Karlsruhe (TH) | 
|---|
|  | 8 | // Zirkel 2, 76128 Karlsruhe | 
|---|
|  | 9 | // Germany | 
|---|
|  | 10 | // | 
|---|
|  | 11 | // Redistribution and use in source and binary forms, with or without | 
|---|
|  | 12 | // modification, are permitted provided that the following conditions are | 
|---|
|  | 13 | // met: | 
|---|
|  | 14 | // | 
|---|
|  | 15 | // 1. Redistributions of source code must retain the above copyright | 
|---|
|  | 16 | // notice, this list of conditions and the following disclaimer. | 
|---|
|  | 17 | // 2. Redistributions in binary form must reproduce the above copyright | 
|---|
|  | 18 | // notice, this list of conditions and the following disclaimer in the | 
|---|
|  | 19 | // documentation and/or other materials provided with the distribution. | 
|---|
|  | 20 | // | 
|---|
|  | 21 | // THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND | 
|---|
|  | 22 | // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
|---|
|  | 23 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 
|---|
|  | 24 | // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR | 
|---|
|  | 25 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 
|---|
|  | 26 | // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 
|---|
|  | 27 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 
|---|
|  | 28 | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | 
|---|
|  | 29 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 
|---|
|  | 30 | // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 
|---|
|  | 31 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
|---|
|  | 32 | // | 
|---|
|  | 33 | // The views and conclusions contained in the software and documentation | 
|---|
|  | 34 | // are those of the authors and should not be interpreted as representing | 
|---|
|  | 35 | // official policies, either expressed or implied, of the Institute of | 
|---|
|  | 36 | // Telematics. | 
|---|
|  | 37 | // [Licence] | 
|---|
|  | 38 |  | 
|---|
|  | 39 | #include "BaseOverlay.h" | 
|---|
|  | 40 |  | 
|---|
|  | 41 | #include "ariba/utility/misc/OvlVis.h" | 
|---|
|  | 42 | #include "ariba/NodeListener.h" | 
|---|
|  | 43 | #include "ariba/CommunicationListener.h" | 
|---|
|  | 44 |  | 
|---|
|  | 45 | namespace ariba { | 
|---|
|  | 46 | namespace overlay { | 
|---|
|  | 47 |  | 
|---|
|  | 48 | use_logging_cpp(BaseOverlay); | 
|---|
|  | 49 |  | 
|---|
|  | 50 | BaseOverlay::BaseOverlay() | 
|---|
|  | 51 | : bc(NULL), overlayInterface(NULL), | 
|---|
|  | 52 | nodeId(NodeID::UNSPECIFIED), spovnetId(SpoVNetID::UNSPECIFIED), | 
|---|
|  | 53 | initiatorLink(LinkID::UNSPECIFIED), state(BaseOverlayStateInvalid){ | 
|---|
|  | 54 | } | 
|---|
|  | 55 |  | 
|---|
|  | 56 | BaseOverlay::~BaseOverlay(){ | 
|---|
|  | 57 | } | 
|---|
|  | 58 |  | 
|---|
|  | 59 | void BaseOverlay::start( BaseCommunication& _basecomm, const NodeID& _nodeid ){ | 
|---|
|  | 60 |  | 
|---|
|  | 61 | bc = &_basecomm; | 
|---|
|  | 62 | nodeId = _nodeid; | 
|---|
|  | 63 |  | 
|---|
|  | 64 | logging_info("creating base overlay"); | 
|---|
|  | 65 |  | 
|---|
|  | 66 | bc->registerMessageReceiver( this ); | 
|---|
|  | 67 | bc->registerEventListener( this ); | 
|---|
|  | 68 |  | 
|---|
|  | 69 | ovl.visCreate( ovlId, nodeId, string(""), string("") ); | 
|---|
|  | 70 | ovl.visChangeNodeColor(ovlId, nodeId, OvlVis::NODE_COLORS_GREY); | 
|---|
|  | 71 |  | 
|---|
|  | 72 | //      if (Identifier(Configuration::instance().read<unsigned long>("BASE_nodeid")) == | 
|---|
|  | 73 | //          Identifier(Configuration::instance().read<unsigned long>("SOURCE"))) { | 
|---|
|  | 74 | //              ovl.visChangeNodeIcon(ovlId, nodeId, OvlVis::ICON_ID_CAMERA); | 
|---|
|  | 75 | //      } else if (Identifier(Configuration::instance().read<unsigned long>("BASE_nodeid")) == | 
|---|
|  | 76 | //          Identifier(Configuration::instance().read<unsigned long>("MR_A"))) { | 
|---|
|  | 77 | //              ovl.visChangeNodeIcon(ovlId, nodeId, OvlVis::ICON_ID_CHARACTER_A); | 
|---|
|  | 78 | //      } else if (Identifier(Configuration::instance().read<unsigned long>("BASE_nodeid")) == | 
|---|
|  | 79 | //          Identifier(Configuration::instance().read<unsigned long>("MR_W"))) { | 
|---|
|  | 80 | //              ovl.visChangeNodeIcon(ovlId, nodeId, OvlVis::ICON_ID_CHARACTER_W); | 
|---|
|  | 81 | //      } | 
|---|
|  | 82 |  | 
|---|
|  | 83 | // timer for auto link management | 
|---|
|  | 84 | Timer::setInterval( 5000 ); | 
|---|
|  | 85 | Timer::start(); | 
|---|
|  | 86 | } | 
|---|
|  | 87 |  | 
|---|
|  | 88 | void BaseOverlay::stop() { | 
|---|
|  | 89 |  | 
|---|
|  | 90 | logging_info("deleting base overlay"); | 
|---|
|  | 91 |  | 
|---|
|  | 92 | Timer::stop(); | 
|---|
|  | 93 | bc->unregisterMessageReceiver( this ); | 
|---|
|  | 94 | bc->unregisterEventListener( this ); | 
|---|
|  | 95 | } | 
|---|
|  | 96 |  | 
|---|
|  | 97 | void BaseOverlay::joinSpoVNet(const SpoVNetID& id, const EndpointDescriptor& bootstrapEp){ | 
|---|
|  | 98 |  | 
|---|
|  | 99 | ovl.visShowNodeBubble ( ovlId, nodeId, "joining..." ); | 
|---|
|  | 100 | logging_info( "starting to join spovnet " << id.toString() << "..."); | 
|---|
|  | 101 |  | 
|---|
|  | 102 | // | 
|---|
|  | 103 | // contact the spovnet initiator and request | 
|---|
|  | 104 | // to join. if the join is granted we will | 
|---|
|  | 105 | // receive further information on the structure | 
|---|
|  | 106 | // of the overlay that is used in the spovnet | 
|---|
|  | 107 | // | 
|---|
|  | 108 | // but first, we have to establish a link to the initiator... | 
|---|
|  | 109 | // | 
|---|
|  | 110 |  | 
|---|
|  | 111 | spovnetId = id; | 
|---|
|  | 112 | state = BaseOverlayStateJoinInitiated; | 
|---|
|  | 113 |  | 
|---|
|  | 114 | initiatorLink = bc->establishLink( bootstrapEp ); | 
|---|
|  | 115 | logging_info("join process initiated for " << id.toString() << "..."); | 
|---|
|  | 116 | } | 
|---|
|  | 117 |  | 
|---|
|  | 118 | void BaseOverlay::leaveSpoVNet(){ | 
|---|
|  | 119 |  | 
|---|
|  | 120 | logging_info( "leaving spovnet " << spovnetId ); | 
|---|
|  | 121 | bool ret = ( state != this->BaseOverlayStateInvalid ); | 
|---|
|  | 122 |  | 
|---|
|  | 123 | logging_debug( "dropping all auto-links ..." ); | 
|---|
|  | 124 |  | 
|---|
|  | 125 | // now we start leaving the spovnet: fist delete all links | 
|---|
|  | 126 | // that we still have in the baseoverlay initiated by | 
|---|
|  | 127 | // some services, the leave the actual overlay structure, | 
|---|
|  | 128 | // then leave the spovnet | 
|---|
|  | 129 |  | 
|---|
|  | 130 | // --> drop all service links | 
|---|
|  | 131 |  | 
|---|
|  | 132 | vector<LinkID> servicelinks; | 
|---|
|  | 133 | BOOST_FOREACH( LinkPair item, linkMapping ){ | 
|---|
|  | 134 | if( item.second.service != OverlayInterface::OVERLAY_SERVICE_ID ) | 
|---|
|  | 135 | servicelinks.push_back( item.first ); | 
|---|
|  | 136 | } | 
|---|
|  | 137 | BOOST_FOREACH( LinkID lnk, servicelinks ){ | 
|---|
|  | 138 | // the dropLink function will remove | 
|---|
|  | 139 | // the item from the linkMapping | 
|---|
|  | 140 | dropLink( lnk ); | 
|---|
|  | 141 | } | 
|---|
|  | 142 |  | 
|---|
|  | 143 | // --> leave overlay structure | 
|---|
|  | 144 |  | 
|---|
|  | 145 | logging_debug( "leaving overlay" ); | 
|---|
|  | 146 | // first, leave the overlay interface | 
|---|
|  | 147 | overlayInterface->leaveOverlay(); | 
|---|
|  | 148 |  | 
|---|
|  | 149 | // --> leave spovnet | 
|---|
|  | 150 |  | 
|---|
|  | 151 | if( state != BaseOverlayStateInitiator ){ | 
|---|
|  | 152 |  | 
|---|
|  | 153 | // then, leave the spovnet baseoverlay | 
|---|
|  | 154 | OverlayMsg overMsg( OverlayMsg::OverlayMessageTypeBye, nodeId ); | 
|---|
|  | 155 | bc->sendMessage( initiatorLink, &overMsg ); | 
|---|
|  | 156 |  | 
|---|
|  | 157 | // drop the link and set to correct state | 
|---|
|  | 158 | bc->dropLink( initiatorLink ); | 
|---|
|  | 159 | initiatorLink = LinkID::UNSPECIFIED; | 
|---|
|  | 160 | } | 
|---|
|  | 161 |  | 
|---|
|  | 162 | state = BaseOverlayStateInvalid; | 
|---|
|  | 163 | ovl.visShutdown( ovlId, nodeId, string("") ); | 
|---|
|  | 164 |  | 
|---|
|  | 165 | // inform all registered services of the event | 
|---|
|  | 166 | BOOST_FOREACH( NodeListener* i, nodeListeners ){ | 
|---|
|  | 167 | if( ret ) i->onLeaveCompleted( spovnetId ); | 
|---|
|  | 168 | else      i->onLeaveFailed( spovnetId ); | 
|---|
|  | 169 | } | 
|---|
|  | 170 | } | 
|---|
|  | 171 |  | 
|---|
|  | 172 | void BaseOverlay::createSpoVNet(const SpoVNetID& id, const OverlayParameterSet& param, const SecurityParameterSet& sec, const QoSParameterSet& qos){ | 
|---|
|  | 173 |  | 
|---|
|  | 174 | // | 
|---|
|  | 175 | // set the state that we are an initiator, | 
|---|
|  | 176 | // this way incoming messages are handled correctly | 
|---|
|  | 177 | // | 
|---|
|  | 178 |  | 
|---|
|  | 179 | logging_info("creating spovnet " + id.toString()); | 
|---|
|  | 180 |  | 
|---|
|  | 181 | spovnetId = id; | 
|---|
|  | 182 | state = BaseOverlayStateInitiator; | 
|---|
|  | 183 |  | 
|---|
|  | 184 | overlayInterface = OverlayFactory::create( *this, param, nodeId, this ); | 
|---|
|  | 185 | if( overlayInterface == NULL ){ | 
|---|
|  | 186 | logging_fatal( "overlay structure not supported" ); | 
|---|
|  | 187 | state = BaseOverlayStateInvalid; | 
|---|
|  | 188 | return; | 
|---|
|  | 189 | } | 
|---|
|  | 190 |  | 
|---|
|  | 191 | // | 
|---|
|  | 192 | // bootstrap against ourselfs | 
|---|
|  | 193 | // | 
|---|
|  | 194 |  | 
|---|
|  | 195 | overlayInterface->joinOverlay(); | 
|---|
|  | 196 | BOOST_FOREACH( NodeListener* i, nodeListeners ){ | 
|---|
|  | 197 | i->onJoinCompleted( spovnetId ); | 
|---|
|  | 198 | } | 
|---|
|  | 199 |  | 
|---|
|  | 200 | ovl.visChangeNodeIcon ( ovlId, nodeId, OvlVis::ICON_ID_CAMERA ); | 
|---|
|  | 201 | ovl.visChangeNodeColor( ovlId, nodeId, OvlVis::NODE_COLORS_GREEN); | 
|---|
|  | 202 | } | 
|---|
|  | 203 |  | 
|---|
|  | 204 | const LinkID BaseOverlay::establishLink(const NodeID& node, const ServiceID& service){ | 
|---|
|  | 205 |  | 
|---|
|  | 206 | // TODO: if this is not a onehop overlay the operation will go asynchronously | 
|---|
|  | 207 | const EndpointDescriptor& endpoint = overlayInterface->resolveNode( node ); | 
|---|
|  | 208 | if( endpoint == EndpointDescriptor::UNSPECIFIED ){ | 
|---|
|  | 209 | logging_error( "could not resolve node to endpoint. unable to establish link" ); | 
|---|
|  | 210 | return LinkID::UNSPECIFIED; | 
|---|
|  | 211 | } | 
|---|
|  | 212 |  | 
|---|
|  | 213 | logging_debug( "baseoverlay called to establish link between node " << | 
|---|
|  | 214 | node.toString() << " on endpoint " << endpoint.toString() << | 
|---|
|  | 215 | " for service " << service.toString() ); | 
|---|
|  | 216 |  | 
|---|
|  | 217 | return establishLink( endpoint, service ); | 
|---|
|  | 218 | } | 
|---|
|  | 219 |  | 
|---|
|  | 220 | const LinkID BaseOverlay::establishLink(const EndpointDescriptor& ep, const ServiceID& service){ | 
|---|
|  | 221 |  | 
|---|
|  | 222 | if( !communicationListeners.contains( service ) ){ | 
|---|
|  | 223 | logging_error( "no registered listener on serviceid " << service.toString() ); | 
|---|
|  | 224 | return LinkID::UNSPECIFIED; | 
|---|
|  | 225 | } | 
|---|
|  | 226 |  | 
|---|
|  | 227 | const LinkID link = bc->establishLink( ep ); | 
|---|
|  | 228 |  | 
|---|
|  | 229 | CommunicationListener* receiver = communicationListeners.get( service ); | 
|---|
|  | 230 | LinkItem item (link, NodeID::UNSPECIFIED, service, receiver); | 
|---|
|  | 231 | linkMapping.insert( make_pair(link, item) ); | 
|---|
|  | 232 |  | 
|---|
|  | 233 | return link; | 
|---|
|  | 234 | } | 
|---|
|  | 235 |  | 
|---|
|  | 236 | void BaseOverlay::dropLink(const LinkID& link){ | 
|---|
|  | 237 |  | 
|---|
|  | 238 | logging_debug( "baseoverlay dropping link " << link.toString() ); | 
|---|
|  | 239 | LinkMapping::iterator i = linkMapping.find( link ); | 
|---|
|  | 240 |  | 
|---|
|  | 241 | if( i == linkMapping.end() ){ | 
|---|
|  | 242 | logging_warn( "can't drop link, mapping unknown " << link.toString() ); | 
|---|
|  | 243 | return; | 
|---|
|  | 244 | } | 
|---|
|  | 245 |  | 
|---|
|  | 246 | linkMapping.erase( i ); | 
|---|
|  | 247 |  | 
|---|
|  | 248 | LinkItem item = i->second; | 
|---|
|  | 249 | bc->dropLink( link ); | 
|---|
|  | 250 |  | 
|---|
|  | 251 | if( item.interface != NULL ) | 
|---|
|  | 252 | item.interface->onLinkDown( link, item.node ); | 
|---|
|  | 253 | } | 
|---|
|  | 254 |  | 
|---|
|  | 255 | seqnum_t BaseOverlay::sendMessage(const Message* message, const LinkID& link ){ | 
|---|
|  | 256 |  | 
|---|
|  | 257 | logging_debug( "baseoverlay is sending message on link " << link.toString() ); | 
|---|
|  | 258 |  | 
|---|
|  | 259 | LinkMapping::iterator i = linkMapping.find( link ); | 
|---|
|  | 260 | if( i == linkMapping.end() ){ | 
|---|
|  | 261 | logging_error( "could not send message. link not found " << link.toString() ); | 
|---|
|  | 262 | return -1; | 
|---|
|  | 263 | } | 
|---|
|  | 264 |  | 
|---|
|  | 265 | OverlayMsg overmsg( OverlayMsg::OverlayMessageTypeData, i->second.service, nodeId ); | 
|---|
|  | 266 | overmsg.encapsulate( const_cast<Message*>(message) ); | 
|---|
|  | 267 |  | 
|---|
|  | 268 | i->second.markused(); | 
|---|
|  | 269 | return bc->sendMessage( link, &overmsg ); | 
|---|
|  | 270 | } | 
|---|
|  | 271 |  | 
|---|
|  | 272 | seqnum_t BaseOverlay::sendMessage(const Message* message, const NodeID& node, const ServiceID& service){ | 
|---|
|  | 273 |  | 
|---|
|  | 274 | LinkID link = LinkID::UNSPECIFIED; | 
|---|
|  | 275 |  | 
|---|
|  | 276 | LinkMapping::iterator i = linkMapping.begin(); | 
|---|
|  | 277 | LinkMapping::iterator iend = linkMapping.end(); | 
|---|
|  | 278 |  | 
|---|
|  | 279 | for( ; i != iend; i++ ){ | 
|---|
|  | 280 | if( i->second.node == node && i->second.service == service ){ | 
|---|
|  | 281 | link = i->second.link; | 
|---|
|  | 282 | break; | 
|---|
|  | 283 | } | 
|---|
|  | 284 | } | 
|---|
|  | 285 |  | 
|---|
|  | 286 | if( link == LinkID::UNSPECIFIED ){ | 
|---|
|  | 287 |  | 
|---|
|  | 288 | logging_info( "no link could be found to send message to node " << | 
|---|
|  | 289 | node.toString() << " for service " << service.toString() << | 
|---|
|  | 290 | ". creating auto link ..."); | 
|---|
|  | 291 |  | 
|---|
|  | 292 | link = establishLink( node, service ); | 
|---|
|  | 293 | LinkMapping::iterator i = linkMapping.find( link ); | 
|---|
|  | 294 |  | 
|---|
|  | 295 | if( i == linkMapping.end() || link == LinkID::UNSPECIFIED ){ | 
|---|
|  | 296 | logging_error( "failed to establish auto link to node " << node.toString() << | 
|---|
|  | 297 | " for service " << service.toString() ); | 
|---|
|  | 298 | return -1; | 
|---|
|  | 299 | } | 
|---|
|  | 300 |  | 
|---|
|  | 301 | i->second.autolink = true; | 
|---|
|  | 302 |  | 
|---|
|  | 303 | logging_debug( "establishing autolink in progress to node " | 
|---|
|  | 304 | << node.toString() << " with new link-id " << link.toString() ); | 
|---|
|  | 305 |  | 
|---|
|  | 306 | } // if( link != LinkID::UNSPECIFIED ) | 
|---|
|  | 307 |  | 
|---|
|  | 308 | assert( link != LinkID::UNSPECIFIED ); | 
|---|
|  | 309 |  | 
|---|
|  | 310 | // mark the link as used, as we | 
|---|
|  | 311 | // now send a message through it | 
|---|
|  | 312 | i->second.markused(); | 
|---|
|  | 313 |  | 
|---|
|  | 314 | // send the message through the new link. the link may not be functional, | 
|---|
|  | 315 | // but for us there is a link-id so we can send messages through it. if | 
|---|
|  | 316 | // the link is not yet up and the message needs to be cached, this is the | 
|---|
|  | 317 | // task of the BaseCommunication, it will cache and send it later. | 
|---|
|  | 318 | return sendMessage( message, link ); | 
|---|
|  | 319 | } | 
|---|
|  | 320 |  | 
|---|
|  | 321 | const EndpointDescriptor& BaseOverlay::getEndpointDescriptor(const LinkID& link) const { | 
|---|
|  | 322 |  | 
|---|
|  | 323 | return bc->getEndpointDescriptor( link ); | 
|---|
|  | 324 | } | 
|---|
|  | 325 |  | 
|---|
|  | 326 | const EndpointDescriptor& BaseOverlay::getEndpointDescriptor(const NodeID& node) const { | 
|---|
|  | 327 |  | 
|---|
|  | 328 | if( node == nodeId || node == NodeID::UNSPECIFIED ) | 
|---|
|  | 329 | return bc->getEndpointDescriptor(); | 
|---|
|  | 330 |  | 
|---|
|  | 331 | if( overlayInterface == NULL ){ | 
|---|
|  | 332 | logging_error( "overlay interface not set, cannot resolve endpoint" ); | 
|---|
|  | 333 | return EndpointDescriptor::UNSPECIFIED; | 
|---|
|  | 334 | } | 
|---|
|  | 335 |  | 
|---|
|  | 336 | // TODO: if this is not a onehop overlay the operation will go asynchronously | 
|---|
|  | 337 | return overlayInterface->resolveNode( node ); | 
|---|
|  | 338 | } | 
|---|
|  | 339 |  | 
|---|
|  | 340 | bool BaseOverlay::bind(CommunicationListener* listener, const ServiceID& sid){ | 
|---|
|  | 341 | logging_debug( "binding communication listener " << listener | 
|---|
|  | 342 | << " on serviceid " << sid.toString() ); | 
|---|
|  | 343 |  | 
|---|
|  | 344 | if( communicationListeners.contains( sid ) ){ | 
|---|
|  | 345 | logging_error( "some listener already registered for service id " | 
|---|
|  | 346 | << sid.toString() ); | 
|---|
|  | 347 | return false; | 
|---|
|  | 348 | } | 
|---|
|  | 349 |  | 
|---|
|  | 350 | communicationListeners.registerItem( listener, sid ); | 
|---|
|  | 351 | return true; | 
|---|
|  | 352 | } | 
|---|
|  | 353 |  | 
|---|
|  | 354 | bool BaseOverlay::unbind(CommunicationListener* listener, const ServiceID& sid){ | 
|---|
|  | 355 | logging_debug( "unbinding listener " << listener | 
|---|
|  | 356 | << " from serviceid " << sid.toString() ); | 
|---|
|  | 357 |  | 
|---|
|  | 358 | if( !communicationListeners.contains( sid ) ){ | 
|---|
|  | 359 | logging_warn( "cannot unbind listener. no listener registered on service id " << sid.toString() ); | 
|---|
|  | 360 | return false; | 
|---|
|  | 361 | } | 
|---|
|  | 362 |  | 
|---|
|  | 363 | if( communicationListeners.get(sid) != listener ){ | 
|---|
|  | 364 | logging_warn( "listener bound to service id " << sid.toString() | 
|---|
|  | 365 | << " is different than listener trying to unbind" ); | 
|---|
|  | 366 | return false; | 
|---|
|  | 367 | } | 
|---|
|  | 368 |  | 
|---|
|  | 369 | communicationListeners.unregisterItem( sid ); | 
|---|
|  | 370 | return true; | 
|---|
|  | 371 | } | 
|---|
|  | 372 |  | 
|---|
|  | 373 | bool BaseOverlay::bind(NodeListener* listener){ | 
|---|
|  | 374 | logging_debug( "binding node listener " << listener ); | 
|---|
|  | 375 |  | 
|---|
|  | 376 | NodeListenerVector::iterator i = find( nodeListeners.begin(), nodeListeners.end(), listener ); | 
|---|
|  | 377 | if( i != nodeListeners.end() ){ | 
|---|
|  | 378 | logging_warn( "node listener " << listener << " is already bound, cannot bind" ); | 
|---|
|  | 379 | return false; | 
|---|
|  | 380 | } | 
|---|
|  | 381 |  | 
|---|
|  | 382 | nodeListeners.push_back( listener ); | 
|---|
|  | 383 | return true; | 
|---|
|  | 384 | } | 
|---|
|  | 385 |  | 
|---|
|  | 386 | bool BaseOverlay::unbind(NodeListener* listener){ | 
|---|
|  | 387 | logging_debug( "unbinding node listener " << listener ); | 
|---|
|  | 388 |  | 
|---|
|  | 389 | NodeListenerVector::iterator i = find( nodeListeners.begin(), nodeListeners.end(), listener ); | 
|---|
|  | 390 | if( i == nodeListeners.end() ){ | 
|---|
|  | 391 | logging_warn( "node listener " << listener << " is not bound, cannot unbind" ); | 
|---|
|  | 392 | return false; | 
|---|
|  | 393 | } | 
|---|
|  | 394 |  | 
|---|
|  | 395 | nodeListeners.erase( i ); | 
|---|
|  | 396 | return true; | 
|---|
|  | 397 | } | 
|---|
|  | 398 |  | 
|---|
|  | 399 | void BaseOverlay::onLinkUp(const LinkID& id, const NetworkLocator* local, const NetworkLocator* remote){ | 
|---|
|  | 400 |  | 
|---|
|  | 401 | logging_debug( "base overlay received linkup event " + id.toString() ); | 
|---|
|  | 402 | // TODO: updateOvlVis( getNodeID(id) ); | 
|---|
|  | 403 |  | 
|---|
|  | 404 | // | 
|---|
|  | 405 | // if we get up a link while we are in the | 
|---|
|  | 406 | // join phase and this is the link that | 
|---|
|  | 407 | // we have initiated towards the spovnet owner | 
|---|
|  | 408 | // continue the join process by sending | 
|---|
|  | 409 | // a join request message through the link | 
|---|
|  | 410 | // | 
|---|
|  | 411 |  | 
|---|
|  | 412 | if( state == BaseOverlayStateJoinInitiated && id == initiatorLink){ | 
|---|
|  | 413 |  | 
|---|
|  | 414 | logging_info( "join has been initiated by me and the link is now up. " << | 
|---|
|  | 415 | "sending out join request for spovnet " << | 
|---|
|  | 416 | spovnetId.toString() ); | 
|---|
|  | 417 |  | 
|---|
|  | 418 | OverlayMsg overMsg( OverlayMsg::OverlayMessageTypeJoinRequest, nodeId ); | 
|---|
|  | 419 | JoinRequest joinmsg( spovnetId, nodeId ); | 
|---|
|  | 420 | overMsg.encapsulate( &joinmsg ); | 
|---|
|  | 421 |  | 
|---|
|  | 422 | state = BaseOverlayStateJoinInitiated; // state remains in JoinInitiated | 
|---|
|  | 423 | bc->sendMessage( id, &overMsg ); | 
|---|
|  | 424 |  | 
|---|
|  | 425 | return; | 
|---|
|  | 426 |  | 
|---|
|  | 427 | } // if( state == BaseOverlayStateJoinInitiated && id == initiatorLink) | 
|---|
|  | 428 |  | 
|---|
|  | 429 | // | 
|---|
|  | 430 | // otherwise this is a link initiated by a service | 
|---|
|  | 431 | // then we exchange update messages to exchange the | 
|---|
|  | 432 | // service id and node id for the link. in this case | 
|---|
|  | 433 | // we should have a link mapping for this link. if | 
|---|
|  | 434 | // we have no link mapping this link was initiated by | 
|---|
|  | 435 | // the remote side. | 
|---|
|  | 436 | // | 
|---|
|  | 437 |  | 
|---|
|  | 438 | LinkMapping::iterator i = linkMapping.find( id ); | 
|---|
|  | 439 |  | 
|---|
|  | 440 | if( i == linkMapping.end() ){ | 
|---|
|  | 441 |  | 
|---|
|  | 442 | LinkItem item (id, NodeID::UNSPECIFIED, ServiceID::UNSPECIFIED, NULL ); | 
|---|
|  | 443 | linkMapping.insert( make_pair(id, item) ); | 
|---|
|  | 444 |  | 
|---|
|  | 445 | } else { | 
|---|
|  | 446 |  | 
|---|
|  | 447 | logging_debug( "sending out OverlayMessageTypeUpdate" << | 
|---|
|  | 448 | " for service " << i->second.service.toString() << | 
|---|
|  | 449 | " with local node id " << nodeId.toString() << | 
|---|
|  | 450 | " on link " << id.toString() ); | 
|---|
|  | 451 |  | 
|---|
|  | 452 | OverlayMsg overMsg( | 
|---|
|  | 453 | OverlayMsg::OverlayMessageTypeUpdate, | 
|---|
|  | 454 | i->second.service, | 
|---|
|  | 455 | nodeId | 
|---|
|  | 456 | ); | 
|---|
|  | 457 |  | 
|---|
|  | 458 | bc->sendMessage( id, &overMsg ); | 
|---|
|  | 459 | i->second.markused(); | 
|---|
|  | 460 |  | 
|---|
|  | 461 | } // if( i == linkMapping.end() ) | 
|---|
|  | 462 |  | 
|---|
|  | 463 | // the link is only valid for the service when we receive | 
|---|
|  | 464 | // the OverlayMessageTypeUpdate from the remote node and | 
|---|
|  | 465 | // have the nodeid and serviceid for the link! | 
|---|
|  | 466 | } | 
|---|
|  | 467 |  | 
|---|
|  | 468 | void BaseOverlay::onLinkDown(const LinkID& id, const NetworkLocator* local, const NetworkLocator* remote){ | 
|---|
|  | 469 |  | 
|---|
|  | 470 | logging_debug( "link went down " << id.toString() ); | 
|---|
|  | 471 |  | 
|---|
|  | 472 | // | 
|---|
|  | 473 | // tell the service that the link went | 
|---|
|  | 474 | // down and remove the mapping | 
|---|
|  | 475 | // | 
|---|
|  | 476 |  | 
|---|
|  | 477 | LinkMapping::iterator i = linkMapping.find( id ); | 
|---|
|  | 478 | if( i == linkMapping.end() ) { | 
|---|
|  | 479 | // this can also be one of the baseoverlay links that | 
|---|
|  | 480 | // no mapping is stored for. therefore we issue no warning. | 
|---|
|  | 481 | // it can also be a link that has been dropped and the | 
|---|
|  | 482 | // mapping is already deleted in the dropLink function. | 
|---|
|  | 483 | // also, the service notification is issued then in dropLink | 
|---|
|  | 484 | return; | 
|---|
|  | 485 | } | 
|---|
|  | 486 |  | 
|---|
|  | 487 | if( i->second.interface != NULL ) | 
|---|
|  | 488 | i->second.interface->onLinkDown( id, i->second.node ); | 
|---|
|  | 489 |  | 
|---|
|  | 490 | linkMapping.erase( i ); | 
|---|
|  | 491 | } | 
|---|
|  | 492 |  | 
|---|
|  | 493 | void BaseOverlay::onLinkChanged(const LinkID& id, const NetworkLocator* oldlocal, const NetworkLocator* newlocal, const NetworkLocator* oldremote, const NetworkLocator* newremote){ | 
|---|
|  | 494 |  | 
|---|
|  | 495 | logging_debug( "link changed " << id.toString() ); | 
|---|
|  | 496 |  | 
|---|
|  | 497 | // | 
|---|
|  | 498 | // tell the service that the link changed | 
|---|
|  | 499 | // | 
|---|
|  | 500 |  | 
|---|
|  | 501 | LinkMapping::iterator i = linkMapping.find( id ); | 
|---|
|  | 502 | if( i == linkMapping.end() ) return; | 
|---|
|  | 503 |  | 
|---|
|  | 504 | if( i->second.interface != NULL ) | 
|---|
|  | 505 | i->second.interface->onLinkChanged( id, i->second.node ); | 
|---|
|  | 506 |  | 
|---|
|  | 507 | i->second.markused(); | 
|---|
|  | 508 | } | 
|---|
|  | 509 |  | 
|---|
|  | 510 | void BaseOverlay::onLinkFail(const LinkID& id, const NetworkLocator* local, const NetworkLocator* remote){ | 
|---|
|  | 511 |  | 
|---|
|  | 512 | logging_debug( "link failed " << id.toString() ); | 
|---|
|  | 513 |  | 
|---|
|  | 514 | // | 
|---|
|  | 515 | // tell the service that the link failed | 
|---|
|  | 516 | // | 
|---|
|  | 517 |  | 
|---|
|  | 518 | LinkMapping::iterator i = linkMapping.find( id ); | 
|---|
|  | 519 | if( i == linkMapping.end() ) return; | 
|---|
|  | 520 |  | 
|---|
|  | 521 | if( i->second.interface != NULL ) | 
|---|
|  | 522 | i->second.interface->onLinkFail( id, i->second.node ); | 
|---|
|  | 523 |  | 
|---|
|  | 524 | i->second.markused(); | 
|---|
|  | 525 | } | 
|---|
|  | 526 |  | 
|---|
|  | 527 | void BaseOverlay::onLinkQoSChanged(const LinkID& id, const NetworkLocator* local, const NetworkLocator* remote, const QoSParameterSet& qos) { | 
|---|
|  | 528 |  | 
|---|
|  | 529 | logging_debug( "link qos changed " << id.toString() ); | 
|---|
|  | 530 |  | 
|---|
|  | 531 | // | 
|---|
|  | 532 | // tell the service that the link qos has changed | 
|---|
|  | 533 | // | 
|---|
|  | 534 |  | 
|---|
|  | 535 | LinkMapping::iterator i = linkMapping.find( id ); | 
|---|
|  | 536 | if( i == linkMapping.end() ) return; | 
|---|
|  | 537 |  | 
|---|
|  | 538 | // TODO: convert QoSParameterSet to the LinkProperties properties | 
|---|
|  | 539 | if( i->second.interface != NULL ) | 
|---|
|  | 540 | i->second.interface->onLinkQoSChanged( id, i->second.node, LinkProperties::DEFAULT ); | 
|---|
|  | 541 |  | 
|---|
|  | 542 | i->second.markused(); | 
|---|
|  | 543 | } | 
|---|
|  | 544 |  | 
|---|
|  | 545 | bool BaseOverlay::receiveMessage(const Message* message, | 
|---|
|  | 546 | const LinkID& link, const NodeID& /*the nodeid is invalid in this case! removed var to prevent errors*/ ){ | 
|---|
|  | 547 |  | 
|---|
|  | 548 | OverlayMsg* overlayMsg = ((Message*)message)->decapsulate<OverlayMsg>(); | 
|---|
|  | 549 | if( overlayMsg == NULL ) return false; | 
|---|
|  | 550 |  | 
|---|
|  | 551 | // mark the link as in action | 
|---|
|  | 552 | LinkMapping::iterator item = linkMapping.find( link ); | 
|---|
|  | 553 | if( item != linkMapping.end() ) item->second.markused(); | 
|---|
|  | 554 |  | 
|---|
|  | 555 | // | 
|---|
|  | 556 | // handle user date that we forward to the | 
|---|
|  | 557 | // appropriate service using the service id | 
|---|
|  | 558 | // in the message. as we don't know the class | 
|---|
|  | 559 | // of message that the service handles, we | 
|---|
|  | 560 | // forward it as a pure Message* | 
|---|
|  | 561 | // | 
|---|
|  | 562 |  | 
|---|
|  | 563 | if( overlayMsg->isType(OverlayMsg::OverlayMessageTypeData) ) { | 
|---|
|  | 564 |  | 
|---|
|  | 565 | logging_debug( "baseoverlay received message of type OverlayMessageTypeData" ); | 
|---|
|  | 566 |  | 
|---|
|  | 567 | const ServiceID& service = overlayMsg->getService(); | 
|---|
|  | 568 | CommunicationListener* serviceListener = communicationListeners.get( service ); | 
|---|
|  | 569 |  | 
|---|
|  | 570 | logging_debug( "received data for service " << service.toString() ); | 
|---|
|  | 571 |  | 
|---|
|  | 572 | if( serviceListener != NULL ) | 
|---|
|  | 573 | serviceListener->onMessage( overlayMsg, overlayMsg->getSourceNode(), link ); | 
|---|
|  | 574 |  | 
|---|
|  | 575 | return true; | 
|---|
|  | 576 |  | 
|---|
|  | 577 | } // if( overlayMsg->isType(OverlayMsg::OverlayMessageTypeData) ) | 
|---|
|  | 578 |  | 
|---|
|  | 579 | // | 
|---|
|  | 580 | // handle spovnet instance join requests | 
|---|
|  | 581 | // | 
|---|
|  | 582 |  | 
|---|
|  | 583 | else if( overlayMsg->isType(OverlayMsg::OverlayMessageTypeJoinRequest) && | 
|---|
|  | 584 | state == BaseOverlayStateInitiator){ | 
|---|
|  | 585 |  | 
|---|
|  | 586 | logging_debug( "baseoverlay received message of type OverlayMessageTypeJoinRequest" ); | 
|---|
|  | 587 |  | 
|---|
|  | 588 | JoinRequest* joinReq = overlayMsg->decapsulate<JoinRequest>(); | 
|---|
|  | 589 | logging_info( "received join request for spovnet " << | 
|---|
|  | 590 | joinReq->getSpoVNetID().toString() ); | 
|---|
|  | 591 |  | 
|---|
|  | 592 | // | 
|---|
|  | 593 | // make sure that the node actually wants to join | 
|---|
|  | 594 | // the correct spovnet id that we administrate | 
|---|
|  | 595 | // | 
|---|
|  | 596 |  | 
|---|
|  | 597 | if( joinReq->getSpoVNetID() != spovnetId ){ | 
|---|
|  | 598 | logging_error( "received join request for spovnet we don't handle " << | 
|---|
|  | 599 | joinReq->getSpoVNetID().toString() ); | 
|---|
|  | 600 | return false; | 
|---|
|  | 601 | } | 
|---|
|  | 602 |  | 
|---|
|  | 603 | // | 
|---|
|  | 604 | // only if all services allow the node to join it is allowed | 
|---|
|  | 605 | // using the isJoinAllowed interface security policies can be | 
|---|
|  | 606 | // implemented by higher layer services | 
|---|
|  | 607 | // | 
|---|
|  | 608 |  | 
|---|
|  | 609 | // TODO: here you can implement mechanisms to deny joining of a node | 
|---|
|  | 610 | bool allow = true; | 
|---|
|  | 611 |  | 
|---|
|  | 612 | logging_info( "sending back join reply for spovnet " << | 
|---|
|  | 613 | spovnetId.toString() << " to node " << | 
|---|
|  | 614 | overlayMsg->getSourceNode().toString() << | 
|---|
|  | 615 | ". result: " << (allow ? "allowed" : "denied") ); | 
|---|
|  | 616 |  | 
|---|
|  | 617 | joiningNodes.push_back( overlayMsg->getSourceNode() ); | 
|---|
|  | 618 |  | 
|---|
|  | 619 | // | 
|---|
|  | 620 | // send back our spovnetid, default overlay parameters, | 
|---|
|  | 621 | // join allow result, and ourself as the endpoint | 
|---|
|  | 622 | // to bootstrap the overlay against | 
|---|
|  | 623 | // | 
|---|
|  | 624 |  | 
|---|
|  | 625 | OverlayMsg retmsg( OverlayMsg::OverlayMessageTypeJoinReply, nodeId ); | 
|---|
|  | 626 | JoinReply replyMsg( spovnetId, OverlayParameterSet::DEFAULT, | 
|---|
|  | 627 | allow, getEndpointDescriptor() ); | 
|---|
|  | 628 |  | 
|---|
|  | 629 | retmsg.encapsulate(&replyMsg); | 
|---|
|  | 630 | bc->sendMessage( link, &retmsg ); | 
|---|
|  | 631 |  | 
|---|
|  | 632 | return true; | 
|---|
|  | 633 |  | 
|---|
|  | 634 | } // else if( overlayMsg->isType(OverlayMsg::OverlayMessageTypeJoinRequest) && state == BaseOverlayStateInitiator) | 
|---|
|  | 635 |  | 
|---|
|  | 636 | // | 
|---|
|  | 637 | // handle replies to spovnet instance join requests | 
|---|
|  | 638 | // | 
|---|
|  | 639 |  | 
|---|
|  | 640 | else if( overlayMsg->isType(OverlayMsg::OverlayMessageTypeJoinReply) && | 
|---|
|  | 641 | state == BaseOverlayStateJoinInitiated){ | 
|---|
|  | 642 |  | 
|---|
|  | 643 | logging_debug( "baseoverlay received message of type OverlayMessageTypeJoinReply" ); | 
|---|
|  | 644 |  | 
|---|
|  | 645 | JoinReply* replyMsg = overlayMsg->decapsulate<JoinReply>(); | 
|---|
|  | 646 | logging_info( "received spovnet join reply" ); | 
|---|
|  | 647 |  | 
|---|
|  | 648 | // | 
|---|
|  | 649 | // make sure that we actually wanted to get | 
|---|
|  | 650 | // into the spovnet whose id is in the message | 
|---|
|  | 651 | // | 
|---|
|  | 652 |  | 
|---|
|  | 653 | if( replyMsg->getSpoVNetID() != spovnetId ){ | 
|---|
|  | 654 | logging_error( "received spovnet join reply for spovnet " << | 
|---|
|  | 655 | replyMsg->getSpoVNetID().toString() << | 
|---|
|  | 656 | " but we wanted to join spovnet " << | 
|---|
|  | 657 | spovnetId.toString() ); | 
|---|
|  | 658 |  | 
|---|
|  | 659 | // state does not change here, maybe | 
|---|
|  | 660 | // the reply does come in later | 
|---|
|  | 661 | return false; | 
|---|
|  | 662 | } | 
|---|
|  | 663 |  | 
|---|
|  | 664 | // | 
|---|
|  | 665 | // if we did not get access to the spovnet | 
|---|
|  | 666 | // notify of the failure and | 
|---|
|  | 667 | // close the link to the initiator | 
|---|
|  | 668 | // | 
|---|
|  | 669 |  | 
|---|
|  | 670 | if( ! replyMsg->getJoinAllowed() ){ | 
|---|
|  | 671 |  | 
|---|
|  | 672 | logging_error( "our join request has been denied" ); | 
|---|
|  | 673 |  | 
|---|
|  | 674 | bc->dropLink( initiatorLink ); | 
|---|
|  | 675 | initiatorLink = LinkID::UNSPECIFIED; | 
|---|
|  | 676 | state = BaseOverlayStateInvalid; | 
|---|
|  | 677 |  | 
|---|
|  | 678 | // inform all registered services of the event | 
|---|
|  | 679 | BOOST_FOREACH( NodeListener* i, nodeListeners ){ | 
|---|
|  | 680 | i->onJoinFailed( spovnetId ); | 
|---|
|  | 681 | } | 
|---|
|  | 682 |  | 
|---|
|  | 683 | return true; | 
|---|
|  | 684 | } | 
|---|
|  | 685 |  | 
|---|
|  | 686 | logging_info( "join request has been accepted for spovnet " << spovnetId.toString() ); | 
|---|
|  | 687 |  | 
|---|
|  | 688 | // | 
|---|
|  | 689 | // if we did get access to the spovnet | 
|---|
|  | 690 | // we try to create the overlay structure | 
|---|
|  | 691 | // as given in the reply message | 
|---|
|  | 692 | // | 
|---|
|  | 693 |  | 
|---|
|  | 694 | overlayInterface = OverlayFactory::create( *this, replyMsg->getParam(), nodeId, this ); | 
|---|
|  | 695 |  | 
|---|
|  | 696 | if( overlayInterface == NULL ){ | 
|---|
|  | 697 | logging_error( "overlay structure not supported" ); | 
|---|
|  | 698 |  | 
|---|
|  | 699 | bc->dropLink( initiatorLink ); | 
|---|
|  | 700 | initiatorLink = LinkID::UNSPECIFIED; | 
|---|
|  | 701 | state = BaseOverlayStateInvalid; | 
|---|
|  | 702 |  | 
|---|
|  | 703 | // inform all registered services of the event | 
|---|
|  | 704 | BOOST_FOREACH( NodeListener* i, nodeListeners ){ | 
|---|
|  | 705 | i->onJoinFailed( spovnetId ); | 
|---|
|  | 706 | } | 
|---|
|  | 707 |  | 
|---|
|  | 708 | return true; | 
|---|
|  | 709 | } | 
|---|
|  | 710 |  | 
|---|
|  | 711 | // | 
|---|
|  | 712 | // now start the join process for the overlay. | 
|---|
|  | 713 | // the join process for the spovnet baseoverlay | 
|---|
|  | 714 | // is now complete. we use the endpoint for | 
|---|
|  | 715 | // overlay structure bootstrapping that the | 
|---|
|  | 716 | // initiator provided in his reply message | 
|---|
|  | 717 | // | 
|---|
|  | 718 |  | 
|---|
|  | 719 | state = BaseOverlayStateCompleted; | 
|---|
|  | 720 | ovl.visChangeNodeColor( ovlId, nodeId, OvlVis::NODE_COLORS_GREEN); | 
|---|
|  | 721 |  | 
|---|
|  | 722 | overlayInterface->createOverlay(); | 
|---|
|  | 723 | overlayInterface->joinOverlay( replyMsg->getBootstrapEndpoint() ); | 
|---|
|  | 724 |  | 
|---|
|  | 725 | // inform all registered services of the event | 
|---|
|  | 726 | BOOST_FOREACH( NodeListener* i, nodeListeners ){ | 
|---|
|  | 727 | i->onJoinCompleted( spovnetId ); | 
|---|
|  | 728 | } | 
|---|
|  | 729 |  | 
|---|
|  | 730 | return true; | 
|---|
|  | 731 |  | 
|---|
|  | 732 | } // else if( overlayMsg->isType(OverlayMsg::OverlayMessageTypeJoinReply) && state == BaseOverlayStateJoinInitiated) | 
|---|
|  | 733 |  | 
|---|
|  | 734 |  | 
|---|
|  | 735 | // | 
|---|
|  | 736 | // handle update messages for link establishment | 
|---|
|  | 737 | // | 
|---|
|  | 738 |  | 
|---|
|  | 739 | else if( overlayMsg->isType(OverlayMsg::OverlayMessageTypeUpdate) ){ | 
|---|
|  | 740 |  | 
|---|
|  | 741 | logging_debug( "baseoverlay received message of type OverlayMessageTypeUpdate" ); | 
|---|
|  | 742 |  | 
|---|
|  | 743 | const NodeID& sourcenode = overlayMsg->getSourceNode(); | 
|---|
|  | 744 | const ServiceID& service = overlayMsg->getService(); | 
|---|
|  | 745 |  | 
|---|
|  | 746 | // | 
|---|
|  | 747 | // we should have a linkmapping for the link, otherwise | 
|---|
|  | 748 | // we ignore update messages | 
|---|
|  | 749 | // | 
|---|
|  | 750 |  | 
|---|
|  | 751 | LinkMapping::iterator i = linkMapping.find( link ); | 
|---|
|  | 752 | if( i == linkMapping.end() ){ | 
|---|
|  | 753 | logging_warn( "received overlay update message for link " << | 
|---|
|  | 754 | link.toString() << " for which we have no mapping" ); | 
|---|
|  | 755 | return false; | 
|---|
|  | 756 | } | 
|---|
|  | 757 |  | 
|---|
|  | 758 | // | 
|---|
|  | 759 | // update our link mapping information for this link | 
|---|
|  | 760 | // | 
|---|
|  | 761 |  | 
|---|
|  | 762 | bool changed = ( i->second.node != sourcenode ) || ( i->second.service != service ); | 
|---|
|  | 763 |  | 
|---|
|  | 764 | i->second.node = sourcenode; | 
|---|
|  | 765 | i->second.service = service; | 
|---|
|  | 766 |  | 
|---|
|  | 767 | // | 
|---|
|  | 768 | // if our link information changed, we send out an update, too | 
|---|
|  | 769 | // | 
|---|
|  | 770 |  | 
|---|
|  | 771 | if( changed ){ | 
|---|
|  | 772 | OverlayMsg overMsg( OverlayMsg::OverlayMessageTypeUpdate, i->second.service, nodeId ); | 
|---|
|  | 773 | bc->sendMessage( link, &overMsg ); | 
|---|
|  | 774 | } | 
|---|
|  | 775 |  | 
|---|
|  | 776 | // | 
|---|
|  | 777 | // set the correct listener service for the linkitem | 
|---|
|  | 778 | // now we can tell the registered service of the linkup event | 
|---|
|  | 779 | // | 
|---|
|  | 780 |  | 
|---|
|  | 781 | if( !communicationListeners.contains( service ) ){ | 
|---|
|  | 782 | logging_warn( "linkup event for service that has not been registered" ); | 
|---|
|  | 783 | return false; | 
|---|
|  | 784 | } | 
|---|
|  | 785 |  | 
|---|
|  | 786 | CommunicationListener* iface = communicationListeners.get( service ); | 
|---|
|  | 787 | if( iface == NULL ){ | 
|---|
|  | 788 | logging_warn( "linkup event for service that has been registered with a NULL interface" ); | 
|---|
|  | 789 | return true; | 
|---|
|  | 790 | } | 
|---|
|  | 791 |  | 
|---|
|  | 792 | i->second.interface = iface; | 
|---|
|  | 793 | iface->onLinkUp( link, sourcenode ); | 
|---|
|  | 794 | i->second.markused(); | 
|---|
|  | 795 |  | 
|---|
|  | 796 | return true ; | 
|---|
|  | 797 |  | 
|---|
|  | 798 | } // else if( overlayMsg->isType(OverlayMsg::OverlayMessageTypeUpdate) ) | 
|---|
|  | 799 |  | 
|---|
|  | 800 | // | 
|---|
|  | 801 | // bye messages to say goodbye | 
|---|
|  | 802 | // | 
|---|
|  | 803 |  | 
|---|
|  | 804 | else if( overlayMsg->isType(OverlayMsg::OverlayMessageTypeBye)){ | 
|---|
|  | 805 |  | 
|---|
|  | 806 | logging_debug( "baseoverlay received message of type OverlayMessageTypeBye" ); | 
|---|
|  | 807 |  | 
|---|
|  | 808 | logging_debug( "received bye message from " << | 
|---|
|  | 809 | overlayMsg->getSourceNode().toString() ); | 
|---|
|  | 810 |  | 
|---|
|  | 811 | // | 
|---|
|  | 812 | // if we are the initiator and receive a bye from a node | 
|---|
|  | 813 | // the node just left. if we are a node and receive a bye | 
|---|
|  | 814 | // from the initiator, we have to close, too. | 
|---|
|  | 815 | // | 
|---|
|  | 816 |  | 
|---|
|  | 817 | if( overlayMsg->getSourceNode() == spovnetInitiator ){ | 
|---|
|  | 818 |  | 
|---|
|  | 819 | bc->dropLink( initiatorLink ); | 
|---|
|  | 820 | initiatorLink = LinkID::UNSPECIFIED; | 
|---|
|  | 821 | state = BaseOverlayStateInvalid; | 
|---|
|  | 822 |  | 
|---|
|  | 823 | logging_fatal( "initiator ended spovnet" ); | 
|---|
|  | 824 |  | 
|---|
|  | 825 | // inform all registered services of the event | 
|---|
|  | 826 | BOOST_FOREACH( NodeListener* i, nodeListeners ){ | 
|---|
|  | 827 | i->onLeaveFailed( spovnetId ); | 
|---|
|  | 828 | } | 
|---|
|  | 829 |  | 
|---|
|  | 830 | } else { | 
|---|
|  | 831 |  | 
|---|
|  | 832 | // a node that said goodbye and we are the initiator | 
|---|
|  | 833 | // don't have to do much here, as the node also | 
|---|
|  | 834 | // will go out of the overlay structure | 
|---|
|  | 835 | logging_info( "node left " << overlayMsg->getSourceNode() ); | 
|---|
|  | 836 |  | 
|---|
|  | 837 | } | 
|---|
|  | 838 |  | 
|---|
|  | 839 | return true; | 
|---|
|  | 840 |  | 
|---|
|  | 841 | } // else if( overlayMsg->isType(OverlayMsg::OverlayMessageTypeBye)) | 
|---|
|  | 842 |  | 
|---|
|  | 843 | // | 
|---|
|  | 844 | // something wrong ... | 
|---|
|  | 845 | // | 
|---|
|  | 846 |  | 
|---|
|  | 847 | else { | 
|---|
|  | 848 |  | 
|---|
|  | 849 | logging_error( "received message in invalid state! don't know " << | 
|---|
|  | 850 | "what to do with this message of type " << | 
|---|
|  | 851 | overlayMsg->getType() ); | 
|---|
|  | 852 | return false; | 
|---|
|  | 853 |  | 
|---|
|  | 854 | } // else | 
|---|
|  | 855 |  | 
|---|
|  | 856 | return false; | 
|---|
|  | 857 | } | 
|---|
|  | 858 |  | 
|---|
|  | 859 | void BaseOverlay::broadcastMessage(Message* message, const ServiceID& service){ | 
|---|
|  | 860 |  | 
|---|
|  | 861 | logging_debug( "broadcasting message to all known nodes " << | 
|---|
|  | 862 | "in the overlay from service " + service.toString() ); | 
|---|
|  | 863 |  | 
|---|
|  | 864 | OverlayInterface::NodeList nodes = overlayInterface->getKnownNodes(); | 
|---|
|  | 865 |  | 
|---|
|  | 866 | OverlayInterface::NodeList::iterator i = nodes.begin(); | 
|---|
|  | 867 | OverlayInterface::NodeList::iterator iend = nodes.end(); | 
|---|
|  | 868 |  | 
|---|
|  | 869 | for( ; i != iend; i++ ){ | 
|---|
|  | 870 | if( *i == nodeId) continue; // don't send to ourselfs | 
|---|
|  | 871 | sendMessage( message, *i, service ); | 
|---|
|  | 872 | } | 
|---|
|  | 873 | } | 
|---|
|  | 874 |  | 
|---|
|  | 875 | vector<NodeID> BaseOverlay::getOverlayNeighbors() const { | 
|---|
|  | 876 | // the known nodes _can_ also include our | 
|---|
|  | 877 | // node, so we remove ourselfs | 
|---|
|  | 878 |  | 
|---|
|  | 879 | vector<NodeID> nodes = overlayInterface->getKnownNodes(); | 
|---|
|  | 880 | vector<NodeID>::iterator i = find( nodes.begin(), nodes.end(), this->nodeId ); | 
|---|
|  | 881 | if( i != nodes.end() ) nodes.erase( i ); | 
|---|
|  | 882 |  | 
|---|
|  | 883 | return nodes; | 
|---|
|  | 884 | } | 
|---|
|  | 885 |  | 
|---|
|  | 886 | void BaseOverlay::updateOvlVis( const NodeID& n ) { | 
|---|
|  | 887 | NodeID node = n; | 
|---|
|  | 888 | /*      void visShowNodeBubble ( | 
|---|
|  | 889 | NETWORK_ID network, | 
|---|
|  | 890 | NodeID& node, | 
|---|
|  | 891 | string label | 
|---|
|  | 892 | ); | 
|---|
|  | 893 | */ | 
|---|
|  | 894 | using namespace std; | 
|---|
|  | 895 |  | 
|---|
|  | 896 | if (node == nodeId || node.isUnspecified()) return; | 
|---|
|  | 897 |  | 
|---|
|  | 898 | // min/max | 
|---|
|  | 899 | if ( node < min || min.isUnspecified() ) min = node; | 
|---|
|  | 900 | if ( node > max || max.isUnspecified() ) max = node; | 
|---|
|  | 901 |  | 
|---|
|  | 902 | // successor | 
|---|
|  | 903 | if ( succ.isUnspecified() || (node > nodeId && (succ < nodeId || (node-nodeId) < (succ-nodeId))) ) { | 
|---|
|  | 904 | if (!succ.isUnspecified() && node != succ) | 
|---|
|  | 905 | ovl.visDisconnect(ovlId, nodeId, succ, string("")); | 
|---|
|  | 906 | succ = node; | 
|---|
|  | 907 | ovl.visConnect(ovlId, nodeId, succ, string("")); | 
|---|
|  | 908 | } | 
|---|
|  | 909 |  | 
|---|
|  | 910 | // set successor (circle-wrap) | 
|---|
|  | 911 | if (succ.isUnspecified() && !min.isUnspecified()) { | 
|---|
|  | 912 | succ = min; | 
|---|
|  | 913 | ovl.visConnect(ovlId, nodeId, succ, string("")); | 
|---|
|  | 914 | } | 
|---|
|  | 915 | } | 
|---|
|  | 916 |  | 
|---|
|  | 917 | const NodeID& BaseOverlay::getNodeID(const LinkID& lid) const { | 
|---|
|  | 918 |  | 
|---|
|  | 919 | if( lid == LinkID::UNSPECIFIED ) return nodeId; | 
|---|
|  | 920 |  | 
|---|
|  | 921 | LinkMapping::const_iterator i = linkMapping.find( lid ); | 
|---|
|  | 922 | if( i == linkMapping.end() ) return NodeID::UNSPECIFIED; | 
|---|
|  | 923 | else return i->second.node; | 
|---|
|  | 924 | } | 
|---|
|  | 925 |  | 
|---|
|  | 926 | void BaseOverlay::incomingRouteMessage(Message* msg){ | 
|---|
|  | 927 | // gets handled as normal data message | 
|---|
|  | 928 | receiveMessage( msg, LinkID::UNSPECIFIED, NodeID::UNSPECIFIED ); | 
|---|
|  | 929 | } | 
|---|
|  | 930 |  | 
|---|
|  | 931 | void BaseOverlay::onNodeJoin(const NodeID& node){ | 
|---|
|  | 932 |  | 
|---|
|  | 933 | JoiningNodes::iterator i = std::find( joiningNodes.begin(), joiningNodes.end(), node ); | 
|---|
|  | 934 | if( i == joiningNodes.end() ) return; | 
|---|
|  | 935 |  | 
|---|
|  | 936 | logging_info( "node has successfully joined baseoverlay and overlay structure " | 
|---|
|  | 937 | << node.toString() ); | 
|---|
|  | 938 |  | 
|---|
|  | 939 | joiningNodes.erase( i ); | 
|---|
|  | 940 | } | 
|---|
|  | 941 |  | 
|---|
|  | 942 | void BaseOverlay::eventFunction(){ | 
|---|
|  | 943 |  | 
|---|
|  | 944 | list<LinkID> oldlinks; | 
|---|
|  | 945 | time_t now = time(NULL); | 
|---|
|  | 946 |  | 
|---|
|  | 947 | // first gather all the links from linkMapping that need droppin | 
|---|
|  | 948 | // don't directly drop, as the dropLink function affects the | 
|---|
|  | 949 | // linkMapping structure that we are traversing here. | 
|---|
|  | 950 | // drop links after a timeout of 30s | 
|---|
|  | 951 |  | 
|---|
|  | 952 | BOOST_FOREACH( LinkPair item, linkMapping ){ | 
|---|
|  | 953 | if( item.second.autolink && difftime(now, item.second.lastuse) > 30) | 
|---|
|  | 954 | oldlinks.push_back( item.first ); | 
|---|
|  | 955 | } | 
|---|
|  | 956 |  | 
|---|
|  | 957 | BOOST_FOREACH( const LinkID lnk, oldlinks ){ | 
|---|
|  | 958 | logging_debug( "auto-link " << lnk.toString() << " timed out and is getting dropped" ); | 
|---|
|  | 959 | dropLink( lnk ); | 
|---|
|  | 960 | } | 
|---|
|  | 961 | } | 
|---|
|  | 962 |  | 
|---|
|  | 963 | }} // namespace ariba, overlay | 
|---|