source: source/ariba/overlay/BaseOverlay.cpp@ 5780

Last change on this file since 5780 was 5779, checked in by mies, 15 years ago
File size: 51.2 KB
Line 
1// [License]
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// [License]
38
39#include "BaseOverlay.h"
40
41#include <sstream>
42#include <iostream>
43#include <string>
44#include <boost/foreach.hpp>
45
46#include "ariba/NodeListener.h"
47#include "ariba/CommunicationListener.h"
48#include "ariba/SideportListener.h"
49
50#include "ariba/overlay/LinkDescriptor.h"
51#include "ariba/overlay/messages/OverlayMsg.h"
52#include "ariba/overlay/messages/JoinRequest.h"
53#include "ariba/overlay/messages/JoinReply.h"
54#include "ariba/overlay/messages/LinkRequest.h"
55#include "ariba/overlay/messages/RelayMessage.h"
56
57#include "ariba/utility/misc/OvlVis.h"
58
59namespace ariba {
60namespace overlay {
61
62LinkDescriptor* BaseOverlay::getDescriptor( const LinkID& link, bool communication ) {
63 BOOST_FOREACH( LinkDescriptor* lp, links )
64 if ((communication ? lp->communicationId : lp->overlayId) == link)
65 return lp;
66 return NULL;
67}
68
69const LinkDescriptor* BaseOverlay::getDescriptor( const LinkID& link, bool communication ) const {
70 BOOST_FOREACH( const LinkDescriptor* lp, links )
71 if ((communication ? lp->communicationId : lp->overlayId) == link)
72 return lp;
73 return NULL;
74}
75
76/// erases a link descriptor
77void BaseOverlay::eraseDescriptor( const LinkID& link, bool communication ) {
78 for ( vector<LinkDescriptor*>::iterator i = links.begin(); i!= links.end(); i++) {
79 LinkDescriptor* ld = *i;
80 if ((communication ? ld->communicationId : ld->overlayId) == link) {
81 delete ld;
82 links.erase(i);
83 break;
84 }
85 }
86}
87
88/// adds a link descriptor
89LinkDescriptor* BaseOverlay::addDescriptor( const LinkID& link ) {
90 LinkDescriptor* desc = getDescriptor( link );
91 if ( desc == NULL ) {
92 desc = new LinkDescriptor();
93 desc->overlayId = link;
94 links.push_back(desc);
95 }
96 return desc;
97}
98
99/// returns a auto-link descriptor
100LinkDescriptor* BaseOverlay::getAutoDescriptor( const NodeID& node, const ServiceID& service ) {
101 BOOST_FOREACH( LinkDescriptor* lp, links )
102 if (lp->autolink && lp->remoteNode == node && lp->service == service && lp->up)
103 return lp;
104 BOOST_FOREACH( LinkDescriptor* lp, links )
105 if (lp->autolink && lp->remoteNode == node && lp->service == service )
106 return lp;
107 return NULL;
108}
109
110/// returns a direct local link relay descriptor for the given remote node
111LinkDescriptor* BaseOverlay::getRelayDescriptor( const NodeID& id ) {
112
113 // get used next hop towards node
114 LinkDescriptor* rld = NULL;
115 NodeID relayNode = NodeID::UNSPECIFIED;
116 LinkID rlid = overlayInterface->getNextLinkId(id);
117 if ( relayNode.isUnspecified() && !rlid.isUnspecified() && rld == NULL ) {
118 // get descriptor of first hop
119 rld = getDescriptor(rlid);
120 if (rld!=NULL) {
121 // is first hop a relay path use local relay
122 if ( rld->relay ) relayNode = rld->localRelay;
123
124 // no-> a proper relay node has been found
125 else relayNode = rld->remoteNode;
126 }
127 }
128
129 // if first relay is unknown choose a arbitrary direct node as relay
130 if ( relayNode.isUnspecified() ) {
131 for (size_t i=0; i<links.size(); i++)
132 if (links[i]->up &&
133 links[i]->communicationUp &&
134 !links[i]->relay &&
135 links[i]->keepAliveMissed <= 1 &&
136 links[i]->service == OverlayInterface::OVERLAY_SERVICE_ID) {
137 relayNode = links[i]->remoteNode;
138 break;
139 }
140 }
141
142 // no local relay found-> damn!
143 if (relayNode.isUnspecified()) return NULL;
144
145 // get descriptor
146 BOOST_FOREACH( LinkDescriptor* lp, links )
147 if (lp->remoteNode == relayNode &&
148 lp->service == OverlayInterface::OVERLAY_SERVICE_ID &&
149 lp->relay == false &&
150 lp->up) {
151
152// std::cout << "using relay node: " << lp->remoteNode.toString() << std::endl;
153 return lp;
154 }
155
156 return NULL;
157}
158
159/// returns the link descriptor that is actually used for sending a message over the overöay
160LinkDescriptor* BaseOverlay::getSendDescriptor( const NodeID& nodeid, bool follow ) {
161 for (size_t i=0; i<links.size(); i++)
162 if ( !links[i]->relay &&
163 links[i]->up &&
164 links[i]->communicationUp &&
165 links[i]->keepAliveMissed <= 1 &&
166 links[i]->remoteNode == nodeid &&
167 links[i]->service == OverlayInterface::OVERLAY_SERVICE_ID) {
168 return links[i];
169 }
170 LinkDescriptor* ld = getDescriptor(overlayInterface->getNextLinkId(nodeid));
171 if (ld != NULL && ld->relay && follow)
172 return getSendDescriptor(ld->localRelay, false);
173 return NULL;
174}
175
176NodeID BaseOverlay::getRelayNode( const NodeID& remoteNode ) {
177 LinkDescriptor* rld = getRelayDescriptor(remoteNode);
178 return rld!=NULL ? rld->remoteNode : NodeID::UNSPECIFIED;
179}
180
181/// routes a message over the overlay or directly sends it when a link is open
182seqnum_t BaseOverlay::sendOverlay( Message* message, const NodeID& nodeid, const NodeID& remoteRelay ) {
183 /// send message directly to a neighbor
184 for (size_t i=0; i<links.size(); i++)
185 if ( !links[i]->relay &&
186 links[i]->up &&
187 links[i]->communicationUp &&
188 links[i]->keepAliveMissed <= 1 &&
189 links[i]->remoteNode == nodeid &&
190 links[i]->service == OverlayInterface::OVERLAY_SERVICE_ID) {
191
192 // mark as relay and send message
193 links[i]->markAsRelay();
194 return sendMessage( message, links[i] );
195 }
196
197 /// send relayed message over the overlay
198 if (!remoteRelay.isUnspecified()) {
199 // create a information relay message to inform the relay about
200 OverlayMsg overlay_msg(
201 OverlayMsg::typeRelay, OverlayInterface::OVERLAY_SERVICE_ID, nodeId);
202 RelayMessage relayMsg( RelayMessage::typeInform, remoteRelay, nodeid, LinkID::UNSPECIFIED );
203 relayMsg.encapsulate( message );
204 overlay_msg.encapsulate( &relayMsg );
205
206 // get local relay link
207 LinkDescriptor* rld = getRelayDescriptor(nodeid);
208
209 // local relay available? send to local relay!
210 if (rld!=NULL) {
211 rld->markAsRelay();
212 sendMessage(&overlay_msg, rld);
213 } else
214 overlayInterface->routeMessage(remoteRelay, &overlay_msg);
215
216 // finished
217 return 0;
218 }
219
220 // common case: send message over the overlay
221 overlayInterface->routeMessage(nodeid, message);
222 return 0;
223}
224
225/// forwards a message over relays/directly using link descriptor
226seqnum_t BaseOverlay::sendMessage( Message* message, const LinkDescriptor* ld ) {
227
228 // directly send message
229 if ( !ld->communicationId.isUnspecified() && ld->communicationUp ) {
230 logging_debug("Send: Sending message via Base Communication");
231 return bc->sendMessage( ld->communicationId, message );
232 }
233
234 // relay message
235 else if ( ld->relay ) {
236
237 // sending a relayed message
238 logging_debug("Send: Relaying message to node "
239 << ld->remoteNode.toString()
240 << " using relay " << ld->localRelay
241 );
242
243 // create a information relay message to inform the relay about
244 OverlayMsg overlay_msg( OverlayMsg::typeRelay, ld->service, nodeId );
245 RelayMessage relayMsg( RelayMessage::typeInform, ld->remoteRelay, ld->remoteNode, ld->remoteLinkId );
246 relayMsg.encapsulate( message );
247 overlay_msg.encapsulate( &relayMsg );
248
249 // route message to relay node in order to inform it!
250 logging_debug("sendMessage: Sending message over relayed link with" << ld );
251 sendOverlay( &overlay_msg, ld->localRelay );
252 return 0;
253 }
254
255 // error
256 else {
257 logging_error( "Could not send message descriptor=" << ld );
258 return -1;
259 }
260 return -1;
261}
262
263/// creates a link descriptor, apply relay semantics if possible
264LinkDescriptor* BaseOverlay::createLinkDescriptor(
265 const NodeID remoteNode, const ServiceID service, const LinkID link_id ) {
266
267 // find listener
268 if( !communicationListeners.contains( service ) ) {
269 logging_error( "No listener found for service " << service.toString() );
270 return NULL;
271 }
272 CommunicationListener* listener = communicationListeners.get( service );
273 assert( listener != NULL );
274
275 // copy link id
276 LinkID linkid = link_id;
277
278 // create link id if necessary
279 if ( linkid.isUnspecified() )
280 linkid = LinkID::create();
281
282 // create relay link descriptor
283 NodeID relayNode = getRelayNode(remoteNode);
284
285 // add descriptor
286 LinkDescriptor* ld = addDescriptor( linkid );
287 ld->overlayId = linkid;
288 ld->service = service;
289 ld->listener = listener;
290 ld->remoteNode = remoteNode;
291
292 // set relay node if available
293 ld->relay = !relayNode.isUnspecified();
294 ld->localRelay = relayNode;
295
296 if (!ld->relay)
297 logging_error("No relay found!");
298
299 // debug output
300 logging_debug( "Created link descriptor: " << ld );
301
302 return ld;
303}
304
305
306// ----------------------------------------------------------------------------
307
308use_logging_cpp(BaseOverlay);
309
310// ----------------------------------------------------------------------------
311
312BaseOverlay::BaseOverlay() :
313 bc(NULL), overlayInterface(NULL), nodeId(NodeID::UNSPECIFIED),
314 spovnetId(SpoVNetID::UNSPECIFIED), state(BaseOverlayStateInvalid),
315 sideport(&SideportListener::DEFAULT), started(false), counter(0) {
316}
317
318BaseOverlay::~BaseOverlay() {
319}
320
321// ----------------------------------------------------------------------------
322
323void BaseOverlay::start( BaseCommunication& _basecomm, const NodeID& _nodeid ) {
324 logging_info("Starting...");
325
326 // set parameters
327 bc = &_basecomm;
328 nodeId = _nodeid;
329
330 // register at base communication
331 bc->registerMessageReceiver( this );
332 bc->registerEventListener( this );
333
334 // timer for auto link management
335 Timer::setInterval( 1000 );
336 Timer::start();
337
338 started = true;
339 state = BaseOverlayStateInvalid;
340}
341
342void BaseOverlay::stop() {
343 logging_info("Stopping...");
344
345 // stop timer
346 Timer::stop();
347
348 // delete oberlay interface
349 if(overlayInterface != NULL) {
350 delete overlayInterface;
351 overlayInterface = NULL;
352 }
353
354 // unregister at base communication
355 bc->unregisterMessageReceiver( this );
356 bc->unregisterEventListener( this );
357
358 started = false;
359 state = BaseOverlayStateInvalid;
360}
361
362bool BaseOverlay::isStarted(){
363 return started;
364}
365
366// ----------------------------------------------------------------------------
367
368void BaseOverlay::joinSpoVNet(const SpoVNetID& id,
369 const EndpointDescriptor& bootstrapEp) {
370
371 if(id != spovnetId){
372 logging_error("attempt to join against invalid spovnet, call initiate first");
373 return;
374 }
375
376
377 //ovl.visShowNodeBubble ( ovlId, nodeId, "joining..." );
378 logging_info( "Starting to join spovnet " << id.toString() <<
379 " with nodeid " << nodeId.toString());
380
381 if(bootstrapEp.isUnspecified() && state == BaseOverlayStateInvalid){
382
383 // bootstrap against ourselfs
384 logging_debug("joining spovnet locally");
385
386 overlayInterface->joinOverlay();
387 state = BaseOverlayStateCompleted;
388 BOOST_FOREACH( NodeListener* i, nodeListeners )
389 i->onJoinCompleted( spovnetId );
390
391 //ovl.visChangeNodeIcon ( ovlId, nodeId, OvlVis::ICON_ID_CAMERA );
392 //ovl.visChangeNodeColor( ovlId, nodeId, OvlVis::NODE_COLORS_GREEN );
393
394 logging_debug("starting overlay bootstrap module");
395 overlayBootstrap.start(this, spovnetId, nodeId);
396 overlayBootstrap.publish(bc->getEndpointDescriptor());
397
398 } else {
399
400 // bootstrap against another node
401 logging_debug("joining spovnet remotely against " << bootstrapEp.toString());
402
403 const LinkID& lnk = bc->establishLink( bootstrapEp );
404 bootstrapLinks.push_back(lnk);
405 logging_info("join process initiated for " << id.toString() << "...");
406 }
407}
408
409void BaseOverlay::leaveSpoVNet() {
410
411 logging_info( "Leaving spovnet " << spovnetId );
412 bool ret = ( state != this->BaseOverlayStateInvalid );
413
414 logging_debug("stopping overlay bootstrap module");
415 overlayBootstrap.stop();
416 overlayBootstrap.revoke();
417
418 logging_debug( "Dropping all auto-links" );
419
420 // gather all service links
421 vector<LinkID> servicelinks;
422 BOOST_FOREACH( LinkDescriptor* ld, links ) {
423 if( ld->service != OverlayInterface::OVERLAY_SERVICE_ID )
424 servicelinks.push_back( ld->overlayId );
425 }
426
427 // drop all service links
428 BOOST_FOREACH( LinkID lnk, servicelinks )
429 dropLink( lnk );
430
431 // let the node leave the spovnet overlay interface
432 logging_debug( "Leaving overlay" );
433 if( overlayInterface != NULL )
434 overlayInterface->leaveOverlay();
435
436 // drop still open bootstrap links
437 BOOST_FOREACH( LinkID lnk, bootstrapLinks )
438 bc->dropLink( lnk );
439
440 // change to inalid state
441 state = BaseOverlayStateInvalid;
442 //ovl.visShutdown( ovlId, nodeId, string("") );
443
444 // inform all registered services of the event
445 BOOST_FOREACH( NodeListener* i, nodeListeners ) {
446 if( ret ) i->onLeaveCompleted( spovnetId );
447 else i->onLeaveFailed( spovnetId );
448 }
449}
450
451void BaseOverlay::createSpoVNet(const SpoVNetID& id,
452 const OverlayParameterSet& param,
453 const SecurityParameterSet& sec,
454 const QoSParameterSet& qos) {
455
456 // set the state that we are an initiator, this way incoming messages are
457 // handled correctly
458 logging_info( "creating spovnet " + id.toString() <<
459 " with nodeid " << nodeId.toString() );
460
461 spovnetId = id;
462
463 overlayInterface = OverlayFactory::create( *this, param, nodeId, this );
464 if( overlayInterface == NULL ) {
465 logging_fatal( "overlay structure not supported" );
466 state = BaseOverlayStateInvalid;
467
468 BOOST_FOREACH( NodeListener* i, nodeListeners )
469 i->onJoinFailed( spovnetId );
470
471 return;
472 }
473}
474
475// ----------------------------------------------------------------------------
476
477const LinkID BaseOverlay::establishLink(
478 const EndpointDescriptor& ep, const NodeID& nodeid,
479 const ServiceID& service, const NodeID& remoteRelay, const LinkID& linkid ) {
480
481 LinkID link_id = linkid;
482
483 // establish link via overlay
484 if (!nodeid.isUnspecified())
485 link_id = establishLink( nodeid, service, remoteRelay, link_id );
486
487 // establish link directly if only ep is known
488 if (nodeid.isUnspecified())
489 establishDirectLink( ep, service, link_id );
490
491 return link_id;
492}
493
494/// call base communication's establish link and add link mapping
495const LinkID BaseOverlay::establishDirectLink( const EndpointDescriptor& ep,
496 const ServiceID& service, const LinkID& linkid ) {
497
498 // create a new link id if necessary
499 LinkID link_id = linkid;
500 if (link_id.isUnspecified()) link_id = LinkID::create();
501
502 /// find a service listener
503 if( !communicationListeners.contains( service ) ) {
504 logging_error( "No listener registered for service id=" << service.toString() );
505 return LinkID::UNSPECIFIED;
506 }
507 CommunicationListener* listener = communicationListeners.get( service );
508 assert( listener != NULL );
509
510 /// establish link and add mapping
511 logging_info("Establishing direct link " << link_id.toString()
512 << " using " << ep.toString());
513
514 // create descriptor
515 LinkDescriptor* ld = addDescriptor( link_id );
516 ld->overlayId = link_id;
517 ld->communicationId = link_id;
518 ld->listener = listener;
519 ld->service = service;
520 bc->establishLink( ep, link_id );
521
522 return link_id;
523}
524
525/// establishes a link between two arbitrary nodes
526const LinkID BaseOverlay::establishLink( const NodeID& node,
527 const ServiceID& service, const NodeID& remoteRelay, const LinkID& link_id ) {
528
529 // do not establish a link to myself!
530 if (node == nodeId) return LinkID::UNSPECIFIED;
531
532 // create a link descriptor
533 LinkDescriptor* ld = createLinkDescriptor( node, service, link_id );
534 ld->remoteRelay = remoteRelay;
535
536 // create link request message with own link id
537 uint32_t nonce = (uint32_t)(rand() ^ (rand() << 16) ^ time(NULL));
538 LinkRequest link_request_msg(
539 nonce, &bc->getEndpointDescriptor(), false,
540 ld->overlayId, ld->localRelay );
541 OverlayMsg overlay_msg( OverlayMsg::typeLinkRequest, service, nodeId );
542 overlay_msg.encapsulate( &link_request_msg );
543 pendingLinks.insert( make_pair(nonce, ld->overlayId) );
544
545 // debug message
546 logging_debug(
547 "Sending link request with"
548 << " link id=" << ld->overlayId
549 << " node id=" << ld->remoteNode.toString()
550 << " service id=" << ld->service.toString()
551 << " local relay id=" << ld->localRelay.toString()
552 << " nonce= " << nonce
553 );
554
555 // sending message through new link
556 sendMessage( &overlay_msg, ld );
557
558 return ld->overlayId;
559}
560
561/// drops an established link
562void BaseOverlay::dropLink(const LinkID& link) {
563 logging_debug( "Dropping link (initiated locally):" << link.toString() );
564
565 // find the link item to drop
566 LinkDescriptor* ld = getDescriptor(link);
567 if( ld == NULL ) {
568 logging_warn( "Can't drop link, link is unknown!");
569 return;
570 }
571
572 // delete all queued messages
573 if( ld->messageQueue.size() > 0 ) {
574 logging_warn( "Dropping link " << ld->overlayId.toString() << " that has "
575 << ld->messageQueue.size() << " waiting messages" );
576 ld->flushQueue();
577 }
578
579 // inform sideport and listener
580 ld->listener->onLinkDown( ld->overlayId, ld->remoteNode );
581 sideport->onLinkDown(ld->overlayId, this->nodeId, ld->remoteNode, this->spovnetId );
582
583 // do not drop relay links
584 if (!ld->usedAsRelay) {
585 // drop the link in base communication
586 if (ld->communicationUp) bc->dropLink( ld->communicationId );
587
588 // erase descriptor
589 eraseDescriptor( ld->overlayId );
590 } else
591 ld->dropWhenRelaysLeft = true;
592}
593
594// ----------------------------------------------------------------------------
595
596/// internal send message, always use this functions to send messages over links
597seqnum_t BaseOverlay::sendMessage( const Message* message, const LinkID& link ) {
598 logging_debug( "Sending data message on link " << link.toString() );
599
600 // get the mapping for this link
601 LinkDescriptor* ld = getDescriptor(link);
602 if( ld == NULL ) {
603 logging_error("Could not send message. "
604 << "Link not found id=" << link.toString());
605 return -1;
606 }
607
608 // check if the link is up yet, if its an auto link queue message
609 if( !ld->up ) {
610 ld->markAsUsed();
611 if( ld->autolink ) {
612 logging_info("Auto-link " << link.toString() << " not up, queue message");
613 Data data = data_serialize( message );
614 const_cast<Message*>(message)->dropPayload();
615 ld->messageQueue.push_back( new Message(data) );
616 } else {
617 logging_error("Link " << link.toString() << " not up, drop message");
618 }
619 return -1;
620 }
621
622 // compile overlay message (has service and node id)
623 OverlayMsg overmsg( OverlayMsg::typeData, ld->service, nodeId );
624 overmsg.encapsulate( const_cast<Message*>(message) );
625
626 // send message over relay/direct/overlay
627 return sendMessage( &overmsg, ld );
628}
629
630seqnum_t BaseOverlay::sendMessage(const Message* message,
631 const NodeID& node, const ServiceID& service) {
632
633 // find link for node and service
634 LinkDescriptor* ld = getAutoDescriptor( node, service );
635
636 // if we found no link, create an auto link
637 if( ld == NULL ) {
638
639 // debug output
640 logging_info( "No link to send message to node "
641 << node.toString() << " found for service "
642 << service.toString() << ". Creating auto link ..."
643 );
644
645 // this will call onlinkup on us, if everything worked we now have a mapping
646 LinkID link = LinkID::create();
647
648 // call base overlay to create a link
649 link = establishLink( node, service, NodeID::UNSPECIFIED, link );
650 ld = getDescriptor( link );
651 if( ld == NULL ) {
652 logging_error( "Failed to establish auto-link.");
653 return -1;
654 }
655 ld->autolink = true;
656
657 logging_debug( "Auto-link establishment in progress to node "
658 << node.toString() << " with link id=" << link.toString() );
659 }
660 assert(ld != NULL);
661
662 // mark the link as used, as we now send a message through it
663 ld->markAsUsed();
664
665 // send / queue message
666 return sendMessage( message, ld->overlayId );
667}
668
669// ----------------------------------------------------------------------------
670
671const EndpointDescriptor& BaseOverlay::getEndpointDescriptor(
672 const LinkID& link) const {
673
674 // return own end-point descriptor
675 if( link == LinkID::UNSPECIFIED )
676 return bc->getEndpointDescriptor();
677
678 // find link descriptor. not found -> return unspecified
679 const LinkDescriptor* ld = getDescriptor(link);
680 if (ld==NULL) return EndpointDescriptor::UNSPECIFIED();
681
682 // return endpoint-descriptor from base communication
683 return bc->getEndpointDescriptor( ld->communicationId );
684}
685
686const EndpointDescriptor& BaseOverlay::getEndpointDescriptor(
687 const NodeID& node) const {
688
689 // return own end-point descriptor
690 if( node == nodeId || node == NodeID::UNSPECIFIED )
691 return bc->getEndpointDescriptor();
692
693 // no joined and request remote descriptor? -> fail!
694 if( overlayInterface == NULL ) {
695 logging_error( "overlay interface not set, cannot resolve endpoint" );
696 return EndpointDescriptor::UNSPECIFIED();
697 }
698
699 // resolve end-point descriptor from the base-overlay routing table
700 return overlayInterface->resolveNode( node );
701}
702
703// ----------------------------------------------------------------------------
704
705bool BaseOverlay::registerSidePort(SideportListener* _sideport) {
706 sideport = _sideport;
707 _sideport->configure( this );
708}
709
710bool BaseOverlay::unregisterSidePort(SideportListener* _sideport) {
711 sideport = &SideportListener::DEFAULT;
712}
713
714// ----------------------------------------------------------------------------
715
716bool BaseOverlay::bind(CommunicationListener* listener, const ServiceID& sid) {
717 logging_debug( "binding communication listener " << listener
718 << " on serviceid " << sid.toString() );
719
720 if( communicationListeners.contains( sid ) ) {
721 logging_error( "some listener already registered for service id "
722 << sid.toString() );
723 return false;
724 }
725
726 communicationListeners.registerItem( listener, sid );
727 return true;
728}
729
730
731bool BaseOverlay::unbind(CommunicationListener* listener, const ServiceID& sid) {
732 logging_debug( "unbinding listener " << listener << " from serviceid " << sid.toString() );
733
734 if( !communicationListeners.contains( sid ) ) {
735 logging_warn( "cannot unbind listener. no listener registered on service id " << sid.toString() );
736 return false;
737 }
738
739 if( communicationListeners.get(sid) != listener ) {
740 logging_warn( "listener bound to service id " << sid.toString()
741 << " is different than listener trying to unbind" );
742 return false;
743 }
744
745 communicationListeners.unregisterItem( sid );
746 return true;
747}
748
749// ----------------------------------------------------------------------------
750
751bool BaseOverlay::bind(NodeListener* listener) {
752 logging_debug( "Binding node listener " << listener );
753
754 // already bound? yes-> warning
755 NodeListenerVector::iterator i =
756 find( nodeListeners.begin(), nodeListeners.end(), listener );
757 if( i != nodeListeners.end() ) {
758 logging_warn("Node listener " << listener << " is already bound!" );
759 return false;
760 }
761
762 // no-> add
763 nodeListeners.push_back( listener );
764 return true;
765}
766
767bool BaseOverlay::unbind(NodeListener* listener) {
768 logging_debug( "Unbinding node listener " << listener );
769
770 // already unbound? yes-> warning
771 NodeListenerVector::iterator i = find( nodeListeners.begin(), nodeListeners.end(), listener );
772 if( i == nodeListeners.end() ) {
773 logging_warn( "Node listener " << listener << " is not bound!" );
774 return false;
775 }
776
777 // no-> remove
778 nodeListeners.erase( i );
779 return true;
780}
781
782// ----------------------------------------------------------------------------
783
784void BaseOverlay::onLinkUp(const LinkID& id,
785 const address_v* local, const address_v* remote) {
786 logging_debug( "Link up with base communication link id=" << id );
787
788 // get descriptor for link
789 LinkDescriptor* ld = getDescriptor(id, true);
790
791 // handle bootstrap link we initiated
792 if( std::find(bootstrapLinks.begin(), bootstrapLinks.end(), id) != bootstrapLinks.end() ){
793 logging_info(
794 "Join has been initiated by me and the link is now up. " <<
795 "Sending out join request for SpoVNet " << spovnetId.toString()
796 );
797
798 // send join request message
799 OverlayMsg overlayMsg( OverlayMsg::typeJoinRequest, nodeId );
800 JoinRequest joinRequest( spovnetId, nodeId );
801 overlayMsg.encapsulate( &joinRequest );
802 bc->sendMessage( id, &overlayMsg );
803 return;
804 }
805
806 // no link found? -> link establishment from remote, add one!
807 if (ld == NULL) {
808 ld = addDescriptor( id );
809 logging_debug( "onLinkUp (remote request) descriptor: " << ld );
810
811 // update descriptor
812 ld->fromRemote = true;
813 ld->communicationId = id;
814 ld->communicationUp = true;
815 ld->markAsUsed();
816
817 // in this case, do not inform listener, since service it unknown
818 // -> wait for update message!
819
820 // link mapping found? -> send update message with node-id and service id
821 } else {
822 logging_debug( "onLinkUp descriptor (initiated locally):" << ld );
823
824 // note: necessary to validate the link on the remote side!
825 logging_debug( "Sending out update" <<
826 " for service " << ld->service.toString() <<
827 " with local node id " << nodeId.toString() <<
828 " on link " << ld->overlayId.toString() );
829
830 // update descriptor
831 ld->markAsUsed();
832 ld->communicationUp = true;
833
834 // if link is a relayed link ->convert to direct link
835 if (ld->relay && !ld->remoteLinkId.isUnspecified() ) {
836 logging_info( "Converting to direct link: " << ld );
837 ld->up = true;
838 ld->relay = false;
839 ld->localRelay = NodeID::UNSPECIFIED;
840 OverlayMsg overMsg( OverlayMsg::typeDirectLink, ld->service, nodeId );
841 overMsg.setRelayLink( ld->remoteLinkId );
842 bc->sendMessage( ld->communicationId, &overMsg );
843 }
844
845 // compile and send update message
846 OverlayMsg overlayMsg( OverlayMsg::typeUpdate, ld->service, nodeId );
847 overlayMsg.setAutoLink( ld->autolink );
848 bc->sendMessage( ld->communicationId, &overlayMsg );
849 }
850}
851
852void BaseOverlay::onLinkDown(const LinkID& id,
853 const address_v* local, const address_v* remote) {
854
855 // erase bootstrap links
856 vector<LinkID>::iterator it = std::find( bootstrapLinks.begin(), bootstrapLinks.end(), id );
857 if( it != bootstrapLinks.end() ) bootstrapLinks.erase( it );
858
859 // get descriptor for link
860 LinkDescriptor* ld = getDescriptor(id, true);
861 if ( ld == NULL ) return; // not found? ->ignore!
862 logging_info( "onLinkDown descriptor: " << ld );
863
864 // inform listeners about link down
865 ld->communicationUp = false;
866 ld->listener->onLinkDown( ld->overlayId, ld->remoteNode );
867 sideport->onLinkDown( id, this->nodeId, ld->remoteNode, this->spovnetId );
868
869 // delete all queued messages (auto links)
870 if( ld->messageQueue.size() > 0 ) {
871 logging_warn( "Dropping link " << id.toString() << " that has "
872 << ld->messageQueue.size() << " waiting messages" );
873 ld->flushQueue();
874 }
875
876 // erase mapping
877 eraseDescriptor(ld->overlayId);
878}
879
880void BaseOverlay::onLinkChanged(const LinkID& id,
881 const address_v* oldlocal, const address_v* newlocal,
882 const address_v* oldremote, const address_v* newremote) {
883
884 // get descriptor for link
885 LinkDescriptor* ld = getDescriptor(id, true);
886 if ( ld == NULL ) return; // not found? ->ignore!
887 logging_debug( "onLinkChanged descriptor: " << ld );
888
889 // inform listeners
890 ld->listener->onLinkChanged( ld->overlayId, ld->remoteNode );
891 sideport->onLinkChanged( id, this->nodeId, ld->remoteNode, this->spovnetId );
892
893 // autolinks: refresh timestamp
894 ld->markAsUsed();
895}
896
897void BaseOverlay::onLinkFail(const LinkID& id,
898 const address_v* local, const address_v* remote) {
899 logging_debug( "Link fail with base communication link id=" << id );
900
901 // erase bootstrap links
902 vector<LinkID>::iterator it = std::find( bootstrapLinks.begin(), bootstrapLinks.end(), id );
903 if( it != bootstrapLinks.end() ) bootstrapLinks.erase( it );
904
905 // get descriptor for link
906 LinkDescriptor* ld = getDescriptor(id, true);
907 if ( ld == NULL ) return; // not found? ->ignore!
908 logging_debug( "Link failed id=" << ld->overlayId.toString() );
909
910 // inform listeners
911 ld->listener->onLinkFail( ld->overlayId, ld->remoteNode );
912 sideport->onLinkFail( id, this->nodeId, ld->remoteNode, this->spovnetId );
913
914 // autolinks: refresh timestamp
915 ld->markAsUsed();
916}
917
918void BaseOverlay::onLinkQoSChanged(const LinkID& id, const address_v* local,
919 const address_v* remote, const QoSParameterSet& qos) {
920 logging_debug( "Link quality changed with base communication link id=" << id );
921
922 // get descriptor for link
923 LinkDescriptor* ld = getDescriptor(id, true);
924 if ( ld == NULL ) return; // not found? ->ignore!
925 logging_debug( "Link quality changed id=" << ld->overlayId.toString() );
926
927 // autolinks: refresh timestamp
928 ld->markAsUsed();
929}
930
931bool BaseOverlay::onLinkRequest( const LinkID& id, const address_v* local,
932 const address_v* remote ) {
933 logging_debug("Accepting link request from " << remote->to_string() );
934 return true;
935}
936
937/// handles a message from base communication
938bool BaseOverlay::receiveMessage(const Message* message,
939 const LinkID& link, const NodeID& ) {
940 // get descriptor for link
941 LinkDescriptor* ld = getDescriptor( link, true );
942
943 // link known?
944 if (ld == NULL) { // no-> handle with unspecified params
945 logging_debug("Received message from base communication, link descriptor unknown" );
946 return handleMessage( message, LinkID::UNSPECIFIED, link, NodeID::UNSPECIFIED );
947 } else { // yes -> handle with overlay link id
948 logging_debug("Received message from base communication, link id=" << ld->overlayId.toString() );
949 return handleMessage( message, ld->overlayId, link, NodeID::UNSPECIFIED );
950 }
951}
952
953// ----------------------------------------------------------------------------
954
955/// handles a message from an overlay
956void BaseOverlay::incomingRouteMessage( Message* msg, const LinkID& link, const NodeID& source ) {
957 logging_debug("Received message from overlay -- "
958 << " link id=" << link.toString()
959 << " node id=" << source.toString() );
960 handleMessage( msg, link, LinkID::UNSPECIFIED, source );
961}
962
963// ----------------------------------------------------------------------------
964
965/// handles an incoming message
966bool BaseOverlay::handleMessage( const Message* message,
967 const LinkID& boLink, const LinkID& bcLink, const NodeID& remoteNode ) {
968 logging_debug( "Handling message: " << message->toString());
969
970 bool ret = false;
971
972 // decapsulate overlay message
973 OverlayMsg* overlayMsg =
974 const_cast<Message*>(message)->decapsulate<OverlayMsg>();
975 if( overlayMsg == NULL ) return false;
976
977 // mark the link as in action
978 LinkDescriptor* ld = getDescriptor(boLink);
979 if (ld == NULL) ld = getDescriptor(bcLink, true);
980 if (ld != NULL) {
981 ld->markAsUsed();
982 ld->markAlive();
983 }
984
985 switch ( overlayMsg->getType() ) {
986 // ---------------------------------------------------------------------
987 // Handle spovnet instance join requests
988 // ---------------------------------------------------------------------
989 case OverlayMsg::typeJoinRequest: {
990
991 // decapsulate message
992 JoinRequest* joinReq = overlayMsg->decapsulate<JoinRequest>();
993 logging_info( "Received join request for spovnet " <<
994 joinReq->getSpoVNetID().toString() );
995
996 // check spovnet id
997 if( joinReq->getSpoVNetID() != spovnetId ) {
998 logging_error(
999 "Received join request for spovnet we don't handle " <<
1000 joinReq->getSpoVNetID().toString() );
1001 ret = false;
1002 break;
1003 }
1004
1005 // TODO: here you can implement mechanisms to deny joining of a node
1006 bool allow = true;
1007 logging_info( "Sending join reply for spovnet " <<
1008 spovnetId.toString() << " to node " <<
1009 overlayMsg->getSourceNode().toString() <<
1010 ". Result: " << (allow ? "allowed" : "denied") );
1011 joiningNodes.push_back( overlayMsg->getSourceNode() );
1012
1013 // return overlay parameters
1014 assert( overlayInterface != NULL );
1015 logging_debug( "Using bootstrap end-point "
1016 << getEndpointDescriptor().toString() )
1017 OverlayParameterSet parameters = overlayInterface->getParameters();
1018 OverlayMsg retmsg( OverlayMsg::typeJoinReply, nodeId );
1019 JoinReply replyMsg( spovnetId, parameters,
1020 allow, getEndpointDescriptor() );
1021 retmsg.encapsulate(&replyMsg);
1022 bc->sendMessage( bcLink, &retmsg );
1023 ret = true;
1024 break;
1025 }
1026
1027 // ---------------------------------------------------------------------
1028 // handle replies to spovnet instance join requests
1029 // ---------------------------------------------------------------------
1030 case OverlayMsg::typeJoinReply: {
1031
1032 // decapsulate message
1033 logging_debug("received join reply message");
1034 JoinReply* replyMsg = overlayMsg->decapsulate<JoinReply>();
1035
1036 // correct spovnet?
1037 if( replyMsg->getSpoVNetID() != spovnetId ) { // no-> fail
1038 logging_error( "Received SpoVNet join reply for " <<
1039 replyMsg->getSpoVNetID().toString() <<
1040 " != " << spovnetId.toString() );
1041 ret = false;
1042 delete replyMsg;
1043 break;
1044 }
1045
1046 // access granted? no -> fail
1047 if( !replyMsg->getJoinAllowed() ) {
1048 logging_error( "Our join request has been denied" );
1049
1050 // drop initiator link
1051 if(bcLink != LinkID::UNSPECIFIED){
1052 bc->dropLink( bcLink );
1053
1054 vector<LinkID>::iterator it = std::find(
1055 bootstrapLinks.begin(), bootstrapLinks.end(), bcLink);
1056 if( it != bootstrapLinks.end() )
1057 bootstrapLinks.erase(it);
1058 }
1059
1060 // inform all registered services of the event
1061 BOOST_FOREACH( NodeListener* i, nodeListeners )
1062 i->onJoinFailed( spovnetId );
1063
1064 ret = true;
1065 delete replyMsg;
1066 break;
1067 }
1068
1069 // access has been granted -> continue!
1070 logging_info("Join request has been accepted for spovnet " <<
1071 spovnetId.toString() );
1072
1073 logging_debug( "Using bootstrap end-point "
1074 << replyMsg->getBootstrapEndpoint().toString() );
1075
1076 //
1077 // create overlay structure from spovnet parameter set
1078 // if we have not boostrapped yet against some other node
1079 //
1080
1081 if( overlayInterface == NULL ){
1082
1083 logging_debug("first-time bootstrapping");
1084
1085 overlayInterface = OverlayFactory::create(
1086 *this, replyMsg->getParam(), nodeId, this );
1087
1088 // overlay structure supported? no-> fail!
1089 if( overlayInterface == NULL ) {
1090 logging_error( "overlay structure not supported" );
1091
1092 if(bcLink != LinkID::UNSPECIFIED){
1093 bc->dropLink( bcLink );
1094
1095 vector<LinkID>::iterator it = std::find(
1096 bootstrapLinks.begin(), bootstrapLinks.end(), bcLink);
1097 if( it != bootstrapLinks.end() )
1098 bootstrapLinks.erase(it);
1099 }
1100
1101 // inform all registered services of the event
1102 BOOST_FOREACH( NodeListener* i, nodeListeners )
1103 i->onJoinFailed( spovnetId );
1104
1105 delete replyMsg;
1106 ret = true;
1107 break;
1108 }
1109
1110 // everything ok-> join the overlay!
1111 state = BaseOverlayStateCompleted;
1112 overlayInterface->createOverlay();
1113
1114 overlayInterface->joinOverlay( replyMsg->getBootstrapEndpoint() );
1115
1116 // update ovlvis
1117 //ovl.visChangeNodeColor( ovlId, nodeId, OvlVis::NODE_COLORS_GREEN);
1118
1119 // inform all registered services of the event
1120 BOOST_FOREACH( NodeListener* i, nodeListeners )
1121 i->onJoinCompleted( spovnetId );
1122
1123 delete replyMsg;
1124
1125 } else {
1126
1127 // this is not the first bootstrap, just join the additional node
1128 logging_debug("not first-time bootstrapping");
1129 overlayInterface->joinOverlay( replyMsg->getBootstrapEndpoint() );
1130
1131 delete replyMsg;
1132
1133 } // if( overlayInterface == NULL )
1134
1135 ret = true;
1136 break;
1137 }
1138
1139 // ---------------------------------------------------------------------
1140 // handle data forward messages
1141 // ---------------------------------------------------------------------
1142 case OverlayMsg::typeData: {
1143
1144 // get service
1145 const ServiceID& service = overlayMsg->getService();
1146 logging_debug( "received data for service " << service.toString() );
1147
1148 // find listener
1149 CommunicationListener* listener =
1150 communicationListeners.get( service );
1151 if( listener == NULL ) {
1152 ret = true;
1153 break;
1154 }
1155
1156 // delegate data message
1157 listener->onMessage( overlayMsg,
1158 overlayMsg->getSourceNode(), ld==NULL ? LinkID::UNSPECIFIED : ld->overlayId );
1159
1160 ret = true;
1161 break;
1162 }
1163
1164 // ---------------------------------------------------------------------
1165 // handle update messages for link establishment
1166 // ---------------------------------------------------------------------
1167 case OverlayMsg::typeUpdate: {
1168 // get info
1169 const NodeID& sourcenode = overlayMsg->getSourceNode();
1170 const ServiceID& service = overlayMsg->getService();
1171
1172 // no link descriptor available -> error!
1173 if( ld == NULL ) {
1174 logging_warn( "received overlay update message for link for "
1175 << "which we have no mapping" );
1176 ret = false;
1177 break;
1178 }
1179 logging_debug("Received type update message on link " << ld );
1180
1181 // update our link mapping information for this link
1182 bool changed =
1183 ( ld->remoteNode != sourcenode ) || ( ld->service != service );
1184 ld->remoteNode = sourcenode;
1185 ld->service = service;
1186 ld->autolink = overlayMsg->isAutoLink();
1187
1188 // if our link information changed, we send out an update, too
1189 if( changed ) {
1190 OverlayMsg overMsg( OverlayMsg::typeUpdate, ld->service, nodeId );
1191 overMsg.setAutoLink(ld->autolink);
1192 bc->sendMessage( ld->communicationId, &overMsg );
1193 }
1194
1195 // service registered? no-> error!
1196 if( !communicationListeners.contains( service ) ) {
1197 logging_warn( "Link up: event listener has not been registered" );
1198 ret = false;
1199 break;
1200 }
1201
1202 // default or no service registered?
1203 CommunicationListener* listener = communicationListeners.get( service );
1204 if( listener == NULL || listener == &CommunicationListener::DEFAULT ) {
1205 logging_warn("Link up: event listener is default or null!" );
1206 ret = true;
1207 break;
1208 }
1209
1210 // update descriptor
1211 ld->listener = listener;
1212 ld->markAsUsed();
1213 ld->markAlive();
1214
1215 // ask the service whether it wants to accept this link
1216 if( !listener->onLinkRequest(sourcenode) ) {
1217
1218 logging_debug("Link id=" << ld->overlayId.toString() <<
1219 " has been denied by service " << service.toString() << ", dropping link");
1220
1221 // prevent onLinkDown calls to the service
1222 ld->listener = &CommunicationListener::DEFAULT;
1223
1224 // drop the link
1225 dropLink( ld->overlayId );
1226 ret = true;
1227 break;
1228 }
1229
1230 // set link up
1231 ld->up = true;
1232 logging_debug(
1233 "Link " << ld->overlayId.toString()
1234 << " has been accepted by service " << service.toString()
1235 << " and is now up"
1236 );
1237
1238 // auto links: link has been accepted -> send queued messages
1239 if( ld->messageQueue.size() > 0 ) {
1240 logging_info( "sending out queued messages on link " <<
1241 ld->overlayId.toString() );
1242 BOOST_FOREACH( Message* msg, ld->messageQueue ) {
1243 sendMessage( msg, ld->overlayId );
1244 delete msg;
1245 }
1246 ld->messageQueue.clear();
1247 }
1248
1249 // call the notification functions
1250 listener->onLinkUp( ld->overlayId, sourcenode );
1251 sideport->onLinkUp( ld->overlayId, nodeId, sourcenode, this->spovnetId );
1252
1253 ret = true;
1254 break;
1255 }
1256
1257 // ---------------------------------------------------------------------
1258 // handle link request forwarded through the overlay
1259 // ---------------------------------------------------------------------
1260 case OverlayMsg::typeLinkRequest: {
1261
1262 logging_debug( "received link request on link" );
1263
1264 // decapsulate message
1265 LinkRequest* linkReq = overlayMsg->decapsulate<LinkRequest>();
1266 const ServiceID& service = overlayMsg->getService();
1267
1268 // is request reply?
1269 if ( linkReq->isReply() ) {
1270
1271 // find link
1272 PendingLinkMap::iterator i = pendingLinks.find( linkReq->getNonce() );
1273 if ( i == pendingLinks.end() ) {
1274 logging_error( "Nonce not found in link request" );
1275 ret = true;
1276 break;
1277 }
1278
1279 // debug message
1280 logging_debug( "Link request reply received. Establishing link "
1281 << i->second << " to " << (linkReq->getEndpoint()->toString())
1282 << " for service " << service.toString()
1283 << " with nonce " << linkReq->getNonce()
1284 << " using relay " << linkReq->getRelay().toString()
1285 << " and remote link id=" << linkReq->getRemoteLinkId()
1286 );
1287
1288 // get descriptor
1289 LinkDescriptor* ldn = getDescriptor(i->second);
1290 if (ldn==NULL) {
1291 delete linkReq;
1292 ret = true;
1293 break;
1294 }
1295
1296 // check if link request reply has a relay node ...
1297 if (!linkReq->getRelay().isUnspecified()) { // yes->
1298 ldn->up = true;
1299 ldn->relay = true;
1300 if (ldn->localRelay.isUnspecified()) {
1301 logging_error("On LinkRequest reply: local relay is unspecifed on link " << ldn );
1302 showLinkState();
1303 }
1304 ldn->remoteRelay = linkReq->getRelay();
1305 ldn->remoteLinkId = linkReq->getRemoteLinkId();
1306 ldn->remoteNode = overlayMsg->getSourceNode();
1307
1308 ldn->markAlive();
1309
1310 // compile and send update message
1311 OverlayMsg _overlayMsg( OverlayMsg::typeUpdate, ldn->service, nodeId );
1312 _overlayMsg.setAutoLink(ldn->autolink);
1313 sendMessage( &_overlayMsg, ldn );
1314
1315 // auto links: link has been accepted -> send queued messages
1316 if( ldn->messageQueue.size() > 0 ) {
1317 logging_info( "Sending out queued messages on link " <<
1318 ldn->overlayId.toString() );
1319 BOOST_FOREACH( Message* msg, ldn->messageQueue ) {
1320 sendMessage( msg, ldn->overlayId );
1321 delete msg;
1322 }
1323 ldn->messageQueue.clear();
1324 }
1325
1326 ldn->listener->onLinkUp( ldn->overlayId, ldn->remoteNode );
1327
1328 // try to establish a direct link
1329 ldn->communicationId =
1330 bc->establishLink( *linkReq->getEndpoint(), i->second );
1331 }
1332
1333 // no relay node-> use overlay routing
1334 else {
1335 ldn->up = true;
1336
1337 // establish direct link
1338 ldn->communicationId =
1339 bc->establishLink( *linkReq->getEndpoint(), i->second );
1340 }
1341 } else {
1342 logging_debug( "Link request received from node id="
1343 << overlayMsg->getSourceNode() );
1344
1345 // create link descriptor
1346 LinkDescriptor* ldn =
1347 createLinkDescriptor(overlayMsg->getSourceNode(),
1348 overlayMsg->getService(), LinkID::UNSPECIFIED );
1349 assert(!ldn->overlayId.isUnspecified());
1350
1351 // create reply message
1352 OverlayMsg overlay_msg( OverlayMsg::typeLinkRequest, service, nodeId );
1353 LinkRequest link_request_msg(
1354 linkReq->getNonce(),
1355 &bc->getEndpointDescriptor(),
1356 true, ldn->overlayId, ldn->localRelay
1357 );
1358 overlay_msg.encapsulate( &link_request_msg );
1359
1360 // debug message
1361 logging_debug( "Sending LinkRequest reply for link with nonce " <<
1362 linkReq->getNonce() );
1363
1364 // if this is a relay link-> update information & inform listeners
1365 if (!linkReq->getRelay().isUnspecified()) {
1366 // set flags
1367 ldn->up = true;
1368 ldn->relay = true;
1369 if (ldn->localRelay.isUnspecified()) {
1370 logging_error("On LinkRequest request: local relay is unspecifed on link " << ldn );
1371 showLinkState();
1372 }
1373 ldn->remoteRelay = linkReq->getRelay();
1374 ldn->remoteNode = overlayMsg->getSourceNode();
1375 ldn->remoteLinkId = linkReq->getRemoteLinkId();
1376 ldn->listener->onLinkUp( ldn->overlayId, ldn->remoteNode );
1377 }
1378
1379 // route message back over overlay
1380 sendMessage( &overlay_msg, ldn );
1381 }
1382 delete linkReq;
1383 ret = true;
1384 break;
1385 }
1386
1387 // ---------------------------------------------------------------------
1388 // handle relay message to forward messages
1389 // ---------------------------------------------------------------------
1390 case OverlayMsg::typeRelay: {
1391
1392 logging_debug( "received relay request on link" );
1393
1394 // decapsulate message
1395 RelayMessage* relayMsg = overlayMsg->decapsulate<RelayMessage>();
1396
1397 // mark incoming link as relay
1398 if (ld!=NULL) ld->markAsRelay();
1399
1400 // am I the destination of this message? yes->
1401 if (relayMsg->getDestNode() == nodeId ) {
1402 // deliver relay message locally!
1403 logging_debug("Relay message reached destination. Handling the message.");
1404 handleMessage( relayMsg, relayMsg->getDestLink(), LinkID::UNSPECIFIED, remoteNode );
1405 ret = true;
1406 break;
1407 }
1408
1409 // is relay message informative?
1410 switch (relayMsg->getType()) {
1411
1412 // handle relay notification
1413 case RelayMessage::typeInform: {
1414 logging_info("Received relay information message with"
1415 << " relay " << relayMsg->getRelayNode()
1416 << " destination " << relayMsg->getDestNode() );
1417
1418 // create route message
1419 OverlayMsg _overMsg( *overlayMsg );
1420 relayMsg->setType( RelayMessage::typeRoute );
1421 _overMsg.encapsulate( relayMsg );
1422
1423 // forward message
1424 if (relayMsg->getRelayNode() == nodeId || relayMsg->getRelayNode().isUnspecified()) {
1425 logging_info("Routing relay message to " << relayMsg->getDestNode().toString() );
1426 sendOverlay( &_overMsg, relayMsg->getDestNode() );
1427 } else {
1428 logging_info("Routing relay message to " << relayMsg->getRelayNode().toString() );
1429 sendOverlay( &_overMsg, relayMsg->getRelayNode() );
1430 }
1431 ret = true;
1432 break;
1433 }
1434
1435 // handle relay routing
1436 case RelayMessage::typeRoute: {
1437 logging_info("Received relay route message with"
1438 << " relay " << relayMsg->getRelayNode()
1439 << " destination " << relayMsg->getDestNode() );
1440
1441 // am I the relay for this message? yes->
1442 if (relayMsg->getRelayNode() == nodeId ) {
1443 logging_debug("I'm the relay for this message. Sending to destination.");
1444 OverlayMsg _overMsg( *overlayMsg );
1445 _overMsg.encapsulate(relayMsg);
1446
1447 /// this must be handled by using relay link!
1448 sendOverlay(&_overMsg, relayMsg->getDestNode());
1449 ret = true;
1450 break;
1451 }
1452
1453 // error: I'm not a relay or destination!
1454 logging_error("This node is neither relay nor destination. Dropping Message!");
1455 ret = true;
1456 break;
1457 }
1458 default: {
1459 logging_error("RelayMessage Unknown!");
1460 ret = true;
1461 break;
1462 }
1463 }
1464 delete relayMsg;
1465 break;
1466 }
1467
1468 // ---------------------------------------------------------------------
1469 // handle keep-alive messages
1470 // ---------------------------------------------------------------------
1471 case OverlayMsg::typeKeepAlive: {
1472 logging_debug( "received keep-alive on link" );
1473 if ( ld != NULL ) {
1474 logging_info("Keep-Alive for "<< ld->overlayId);
1475 ld->markAlive();
1476 }
1477 break;
1478 }
1479
1480 // ---------------------------------------------------------------------
1481 // handle direct link replacement messages
1482 // ---------------------------------------------------------------------
1483 case OverlayMsg::typeDirectLink: {
1484
1485 logging_debug( "Received direct link replacement request" );
1486
1487 LinkDescriptor* rld = getDescriptor( overlayMsg->getRelayLink() );
1488 if (rld == NULL || ld == NULL) {
1489 logging_error("Direct link replacement: Link "
1490 << overlayMsg->getRelayLink() << "not found error." );
1491 break;
1492 }
1493 logging_info( "Received direct link convert notification for " << rld );
1494
1495 // set communcation link id and set it up
1496 rld->communicationId = ld->communicationId;
1497
1498 // this is neccessary since this link was a relay link before!
1499 rld->communicationUp = true;
1500
1501 // this is not a relay link anymore!
1502 rld->relay = false;
1503 rld->localRelay = NodeID::UNSPECIFIED;
1504 rld->remoteRelay = NodeID::UNSPECIFIED;
1505
1506 // mark used and alive!
1507 rld->markAsUsed();
1508 rld->markAlive();
1509
1510 // erase the original descriptor
1511 eraseDescriptor(ld->overlayId);
1512 break;
1513 }
1514
1515 // ---------------------------------------------------------------------
1516 // handle unknown message type
1517 // ---------------------------------------------------------------------
1518 default: {
1519 logging_error( "received message in invalid state! don't know " <<
1520 "what to do with this message of type " <<
1521 overlayMsg->getType() );
1522 ret = false;
1523 break;
1524 }
1525 } /* switch */
1526
1527 delete overlayMsg;
1528 return ret;
1529}
1530
1531// ----------------------------------------------------------------------------
1532
1533void BaseOverlay::broadcastMessage(Message* message, const ServiceID& service) {
1534
1535 logging_debug( "broadcasting message to all known nodes " <<
1536 "in the overlay from service " + service.toString() );
1537
1538 OverlayInterface::NodeList nodes = overlayInterface->getKnownNodes(true);
1539 OverlayInterface::NodeList::iterator i = nodes.begin();
1540 for(; i != nodes.end(); i++ ) {
1541 if( *i == nodeId) continue; // don't send to ourselfs
1542 sendMessage( message, *i, service );
1543 }
1544}
1545
1546vector<NodeID> BaseOverlay::getOverlayNeighbors(bool deep) const {
1547 // the known nodes _can_ also include our node, so we remove ourself
1548 vector<NodeID> nodes = overlayInterface->getKnownNodes(deep);
1549
1550 vector<NodeID>::iterator i = find( nodes.begin(), nodes.end(), this->nodeId );
1551 if( i != nodes.end() ) nodes.erase( i );
1552
1553 return nodes;
1554}
1555
1556const NodeID& BaseOverlay::getNodeID(const LinkID& lid) const {
1557 if( lid == LinkID::UNSPECIFIED ) return nodeId;
1558 const LinkDescriptor* ld = getDescriptor(lid);
1559 if( ld == NULL ) return NodeID::UNSPECIFIED;
1560 else return ld->remoteNode;
1561}
1562
1563vector<LinkID> BaseOverlay::getLinkIDs( const NodeID& nid ) const {
1564 vector<LinkID> linkvector;
1565 BOOST_FOREACH( LinkDescriptor* ld, links ) {
1566 if( ld->remoteNode == nid || nid == NodeID::UNSPECIFIED ) {
1567 linkvector.push_back( ld->overlayId );
1568 }
1569 }
1570 return linkvector;
1571}
1572
1573
1574void BaseOverlay::onNodeJoin(const NodeID& node) {
1575 JoiningNodes::iterator i = std::find( joiningNodes.begin(), joiningNodes.end(), node );
1576 if( i == joiningNodes.end() ) return;
1577
1578 logging_info( "node has successfully joined baseoverlay and overlay structure "
1579 << node.toString() );
1580
1581 joiningNodes.erase( i );
1582}
1583
1584void BaseOverlay::eventFunction() {
1585
1586 // send keep-alive messages over established links
1587 BOOST_FOREACH( LinkDescriptor* ld, links ) {
1588 if (!ld->up) continue;
1589 OverlayMsg overMsg( OverlayMsg::typeKeepAlive,
1590 OverlayInterface::OVERLAY_SERVICE_ID, nodeId );
1591 sendMessage( &overMsg, ld );
1592 }
1593
1594 // iterate over all links and check for time boundaries
1595 vector<LinkDescriptor*> oldlinks;
1596 time_t now = time(NULL);
1597 BOOST_FOREACH( LinkDescriptor* ld, links ) {
1598 // remote used as relay flag
1599 if ( ld->usedAsRelay && difftime( now, ld->timeUsedAsRelay ) > 10)
1600 ld->usedAsRelay = false;
1601
1602 // keep alives and not up? yes-> link connection request is stale!
1603 if ( !ld->up && difftime( now, ld->keepAliveTime ) >= 2 ) {
1604
1605 // increase counter
1606 ld->keepAliveMissed++;
1607
1608 // missed more than four keep-alive messages (10 sec)? -> drop link
1609 if (ld->keepAliveMissed > 8) {
1610 logging_info( "Link connection request is stale, closing: " << ld );
1611 oldlinks.push_back( ld );
1612 continue;
1613 }
1614 }
1615
1616 if (!ld->up) continue;
1617
1618 // drop links that are dropped and not used as relay
1619 if (ld->dropWhenRelaysLeft && !ld->usedAsRelay && !ld->autolink) {
1620 oldlinks.push_back( ld );
1621 continue;
1622 }
1623
1624 // auto-link time exceeded?
1625 if ( ld->autolink && difftime( now, ld->lastuse ) > 30 ) {
1626 oldlinks.push_back( ld );
1627 continue;
1628 }
1629
1630 // keep alives missed? yes->
1631 if ( difftime( now, ld->keepAliveTime ) > 2 ) {
1632
1633 // increase counter
1634 ld->keepAliveMissed++;
1635
1636 // missed more than four keep-alive messages (4 sec)? -> drop link
1637 if (ld->keepAliveMissed >= 8) {
1638 logging_info( "Link is stale, closing: " << ld );
1639 oldlinks.push_back( ld );
1640 continue;
1641 }
1642 }
1643 }
1644
1645 // drop links
1646 BOOST_FOREACH( const LinkDescriptor* ld, oldlinks ) {
1647/*
1648 vector<LinkID>::iterator it = std::find(
1649 bootstrapLinks.begin(), bootstrapLinks.end(), ld->communicationId);
1650
1651 if (!ld->communicationId.isUnspecified() && it != bootstrapLinks.end() ){
1652 logging_info( "Not dropping initiator link: " << ld );
1653 continue;
1654 }
1655*/
1656 logging_info( "Link timed out. Dropping " << ld );
1657 dropLink( ld->overlayId );
1658 }
1659
1660 // show link state
1661 counter++;
1662 if (counter>=4) showLinkState();
1663 if (counter>=4 || counter<0) counter = 0;
1664}
1665
1666void BaseOverlay::showLinkState() {
1667 int i=0;
1668 logging_info("--- link state -------------------------------");
1669 BOOST_FOREACH( LinkDescriptor* ld, links ) {
1670 logging_info("link " << i << ": " << ld);
1671 i++;
1672 }
1673 logging_info("----------------------------------------------");
1674}
1675
1676}} // namespace ariba, overlay
Note: See TracBrowser for help on using the repository browser.