Index: source/ariba/overlay/BaseOverlay.cpp
===================================================================
--- source/ariba/overlay/BaseOverlay.cpp	(revision 5284)
+++ source/ariba/overlay/BaseOverlay.cpp	(revision 5316)
@@ -245,6 +245,6 @@
 BaseOverlay::BaseOverlay() :
 	bc(NULL), overlayInterface(NULL), nodeId(NodeID::UNSPECIFIED),
-	spovnetId(SpoVNetID::UNSPECIFIED), initiatorLink(LinkID::UNSPECIFIED),
-	state(BaseOverlayStateInvalid), sideport(&SideportListener::DEFAULT) {
+	spovnetId(SpoVNetID::UNSPECIFIED), state(BaseOverlayStateInvalid),
+	sideport(&SideportListener::DEFAULT), started(false) {
 }
 
@@ -268,4 +268,7 @@
 	Timer::setInterval( 500 );
 	Timer::start();
+
+	started = true;
+	state = BaseOverlayStateInvalid;
 }
 
@@ -285,4 +288,11 @@
 	bc->unregisterMessageReceiver( this );
 	bc->unregisterEventListener( this );
+
+	started = false;
+	state = BaseOverlayStateInvalid;
+}
+
+bool BaseOverlay::isStarted(){
+	return started;
 }
 
@@ -292,16 +302,40 @@
 		const EndpointDescriptor& bootstrapEp) {
 
-	ovl.visShowNodeBubble ( ovlId, nodeId, "joining..." );
+	if(id != spovnetId){
+		logging_error("attempt to join against invalid spovnet, call initiate first");
+		return;
+	}
+
+
+	//ovl.visShowNodeBubble ( ovlId, nodeId, "joining..." );
 	logging_info( "Starting to join spovnet " << id.toString() <<
 			" with nodeid " << nodeId.toString());
 
-	// contact the spovnet initiator and request to join. if the join is granted we will
-	// receive further information on the structure of the overlay that is used in the spovnet
-	// but first, we have to establish a link to the initiator...
-	spovnetId = id;
-	state = BaseOverlayStateJoinInitiated;
-
-	initiatorLink = bc->establishLink( bootstrapEp );
-	logging_info("join process initiated for " << id.toString() << "...");
+	if(bootstrapEp == EndpointDescriptor::UNSPECIFIED && state == BaseOverlayStateInvalid){
+
+		// bootstrap against ourselfs
+		logging_debug("joining spovnet locally");
+
+		overlayInterface->joinOverlay();
+		state = BaseOverlayStateCompleted;
+		BOOST_FOREACH( NodeListener* i, nodeListeners )
+			i->onJoinCompleted( spovnetId );
+
+		//ovl.visChangeNodeIcon ( ovlId, nodeId, OvlVis::ICON_ID_CAMERA );
+		//ovl.visChangeNodeColor( ovlId, nodeId, OvlVis::NODE_COLORS_GREEN );
+
+		logging_debug("starting overlay bootstrap module");
+		overlayBootstrap.start(this, spovnetId, nodeId);
+		overlayBootstrap.publish(bc->getEndpointDescriptor());
+
+	} else {
+
+		// bootstrap against another node
+		logging_debug("joining spovnet remotely against " << bootstrapEp.toString());
+
+		const LinkID& lnk = bc->establishLink( bootstrapEp );
+		bootstrapLinks.push_back(lnk);
+		logging_info("join process initiated for " << id.toString() << "...");
+	}
 }
 
@@ -310,4 +344,8 @@
 	logging_info( "Leaving spovnet " << spovnetId );
 	bool ret = ( state != this->BaseOverlayStateInvalid );
+
+	logging_debug("stopping overlay bootstrap module");
+	overlayBootstrap.stop();
+	overlayBootstrap.revoke();
 
 	logging_debug( "Dropping all auto-links" );
@@ -329,18 +367,11 @@
 		overlayInterface->leaveOverlay();
 
-	// leave spovnet
-	if( state != BaseOverlayStateInitiator ) {
-		// then, leave the spovnet baseoverlay
-		OverlayMsg overMsg( OverlayMsg::typeBye, nodeId );
-		bc->sendMessage( initiatorLink, &overMsg );
-
-		// drop the link and set to correct state
-		bc->dropLink( initiatorLink );
-		initiatorLink = LinkID::UNSPECIFIED;
-	}
+	// drop still open bootstrap links
+	BOOST_FOREACH( LinkID lnk, bootstrapLinks )
+		bc->dropLink( lnk );
 
 	// change to inalid state
 	state = BaseOverlayStateInvalid;
-	ovl.visShutdown( ovlId, nodeId, string("") );
+	//ovl.visShutdown( ovlId, nodeId, string("") );
 
 	// inform all registered services of the event
@@ -362,5 +393,4 @@
 
 	spovnetId = id;
-	state = BaseOverlayStateInitiator;
 
 	overlayInterface = OverlayFactory::create( *this, param, nodeId, this );
@@ -368,14 +398,10 @@
 		logging_fatal( "overlay structure not supported" );
 		state = BaseOverlayStateInvalid;
+
+		BOOST_FOREACH( NodeListener* i, nodeListeners )
+			i->onJoinFailed( spovnetId );
+
 		return;
 	}
-
-	// bootstrap against ourselfs
-	overlayInterface->joinOverlay();
-	BOOST_FOREACH( NodeListener* i, nodeListeners )
-		i->onJoinCompleted( spovnetId );
-
-	ovl.visChangeNodeIcon ( ovlId, nodeId, OvlVis::ICON_ID_CAMERA );
-	ovl.visChangeNodeColor( ovlId, nodeId, OvlVis::NODE_COLORS_GREEN );
 }
 
@@ -695,6 +721,6 @@
 	LinkDescriptor* ld = getDescriptor(id, true);
 
-	// handle initiator link
-	if(state == BaseOverlayStateJoinInitiated && id == initiatorLink) {
+	// handle bootstrap link we initiated
+	if( std::find(bootstrapLinks.begin(), bootstrapLinks.end(), id) != bootstrapLinks.end() ){
 		logging_info(
 			"Join has been initiated by me and the link is now up. " <<
@@ -759,4 +785,8 @@
 	const address_v* local, const address_v* remote) {
 
+	// erase bootstrap links
+	vector<LinkID>::iterator it = std::find( bootstrapLinks.begin(), bootstrapLinks.end(), id );
+	if( it != bootstrapLinks.end() ) bootstrapLinks.erase( it );
+
 	// get descriptor for link
 	LinkDescriptor* ld = getDescriptor(id, true);
@@ -800,4 +830,8 @@
 	const address_v* local, const address_v* remote) {
 	logging_debug( "Link fail with base communication link id=" << id );
+
+	// erase bootstrap links
+	vector<LinkID>::iterator it = std::find( bootstrapLinks.begin(), bootstrapLinks.end(), id );
+	if( it != bootstrapLinks.end() ) bootstrapLinks.erase( it );
 
 	// get descriptor for link
@@ -927,5 +961,4 @@
 			logging_debug("received join reply message");
 			JoinReply* replyMsg = overlayMsg->decapsulate<JoinReply>();
-			assert(state == BaseOverlayStateJoinInitiated);
 
 			// correct spovnet?
@@ -942,11 +975,18 @@
 
 				// drop initiator link
-				bc->dropLink( initiatorLink );
-				initiatorLink = LinkID::UNSPECIFIED;
-				state = BaseOverlayStateInvalid;
+
+				if(bcLink != LinkID::UNSPECIFIED){
+					bc->dropLink( bcLink );
+
+					vector<LinkID>::iterator it = std::find(
+							bootstrapLinks.begin(), bootstrapLinks.end(), bcLink);
+					if( it != bootstrapLinks.end() )
+						bootstrapLinks.erase(it);
+				}
 
 				// inform all registered services of the event
 				BOOST_FOREACH( NodeListener* i, nodeListeners )
 					i->onJoinFailed( spovnetId );
+
 				return true;
 			}
@@ -956,36 +996,59 @@
 					spovnetId.toString() );
 
+			logging_debug( "Using bootstrap end-point "
+				<< replyMsg->getBootstrapEndpoint().toString() );
+
+			//
 			// create overlay structure from spovnet parameter set
-			overlayInterface = OverlayFactory::create(
-				*this, replyMsg->getParam(), nodeId, this );
-
-			// overlay structure supported? no-> fail!
-			if( overlayInterface == NULL ) {
-				logging_error( "overlay structure not supported" );
-
-				bc->dropLink( initiatorLink );
-				initiatorLink = LinkID::UNSPECIFIED;
-				state = BaseOverlayStateInvalid;
+			// if we have not boostrapped yet against some other node
+			//
+
+			if( overlayInterface == NULL ){
+
+				logging_debug("first-time bootstrapping");
+
+				overlayInterface = OverlayFactory::create(
+					*this, replyMsg->getParam(), nodeId, this );
+
+				// overlay structure supported? no-> fail!
+				if( overlayInterface == NULL ) {
+					logging_error( "overlay structure not supported" );
+
+					if(bcLink != LinkID::UNSPECIFIED){
+						bc->dropLink( bcLink );
+
+						vector<LinkID>::iterator it = std::find(
+								bootstrapLinks.begin(), bootstrapLinks.end(), bcLink);
+						if( it != bootstrapLinks.end() )
+							bootstrapLinks.erase(it);
+					}
+
+					// inform all registered services of the event
+					BOOST_FOREACH( NodeListener* i, nodeListeners )
+					i->onJoinFailed( spovnetId );
+
+					return true;
+				}
+
+				// everything ok-> join the overlay!
+				state = BaseOverlayStateCompleted;
+				overlayInterface->createOverlay();
+
+				overlayInterface->joinOverlay( replyMsg->getBootstrapEndpoint() );
+
+				// update ovlvis
+				//ovl.visChangeNodeColor( ovlId, nodeId, OvlVis::NODE_COLORS_GREEN);
 
 				// inform all registered services of the event
 				BOOST_FOREACH( NodeListener* i, nodeListeners )
-				i->onJoinFailed( spovnetId );
-
-				return true;
-			}
-
-			// everything ok-> join the overlay!
-			state = BaseOverlayStateCompleted;
-			overlayInterface->createOverlay();
-			logging_debug( "Using bootstrap end-point "
-				<< replyMsg->getBootstrapEndpoint().toString() );
-			overlayInterface->joinOverlay( replyMsg->getBootstrapEndpoint() );
-
-			// update ovlvis
-			ovl.visChangeNodeColor( ovlId, nodeId, OvlVis::NODE_COLORS_GREEN);
-
-			// inform all registered services of the event
-			BOOST_FOREACH( NodeListener* i, nodeListeners )
-				i->onJoinCompleted( spovnetId );
+					i->onJoinCompleted( spovnetId );
+
+			} else {
+
+				// this is not the first bootstrap, just join the additional node
+				logging_debug("not first-time bootstrapping");
+				overlayInterface->joinOverlay( replyMsg->getBootstrapEndpoint() );
+
+			} // if( overlayInterface == NULL )
 
 			return true;
@@ -1103,41 +1166,9 @@
 
 		// ---------------------------------------------------------------------
-		// handle bye messages
-		// ---------------------------------------------------------------------
-		case OverlayMsg::typeBye: {
-			logging_debug( "received bye message from " <<
-					overlayMsg->getSourceNode().toString() );
-
-			/* if we are the initiator and receive a bye from a node
-			 * the node just left. if we are a node and receive a bye
-			 * from the initiator, we have to close, too.
-			 */
-			if( overlayMsg->getSourceNode() == spovnetInitiator ) {
-
-				bc->dropLink( initiatorLink );
-				initiatorLink = LinkID::UNSPECIFIED;
-				state = BaseOverlayStateInvalid;
-
-				logging_fatal( "initiator ended spovnet" );
-
-				// inform all registered services of the event
-				BOOST_FOREACH( NodeListener* i, nodeListeners )
-					i->onLeaveFailed( spovnetId );
-
-			} else {
-				// a node that said goodbye and we are the initiator don't have to
-				// do much here, as the node also will go out of the overlay
-				// structure
-				logging_info( "node left " << overlayMsg->getSourceNode() );
-			}
-
-			return true;
-
-		}
-
-		// ---------------------------------------------------------------------
 		// handle link request forwarded through the overlay
 		// ---------------------------------------------------------------------
 		case OverlayMsg::typeLinkRequest: {
+
+			logging_debug( "received link request on link" );
 
 			// decapsulate message
@@ -1261,4 +1292,6 @@
 		case OverlayMsg::typeRelay: {
 
+			logging_debug( "received relay request on link" );
+
 			// decapsulate message
 			RelayMessage* relayMsg = overlayMsg->decapsulate<RelayMessage>();
@@ -1347,4 +1380,7 @@
 		// ---------------------------------------------------------------------
 		case OverlayMsg::typeKeepAlive: {
+
+			logging_debug( "received keep-alive on link" );
+
 			if ( ld != NULL ) {
 				//logging_force("Keep-Alive for "<< ld->overlayId);
@@ -1358,4 +1394,7 @@
 		// ---------------------------------------------------------------------
 		case OverlayMsg::typeDirectLink: {
+
+			logging_debug( "received direct link replacement request" );
+
 			LinkDescriptor* rld = getDescriptor( overlayMsg->getRelayLink() );
 			logging_force( "Received direct link convert notification for " << rld );
@@ -1380,4 +1419,5 @@
 
 	} /* switch */
+
 	return false;
 }
@@ -1398,7 +1438,7 @@
 }
 
-vector<NodeID> BaseOverlay::getOverlayNeighbors() const {
+vector<NodeID> BaseOverlay::getOverlayNeighbors(bool deep) const {
 	// the known nodes _can_ also include our node, so we remove ourself
-	vector<NodeID> nodes = overlayInterface->getKnownNodes();
+	vector<NodeID> nodes = overlayInterface->getKnownNodes(deep);
 	vector<NodeID>::iterator i = find( nodes.begin(), nodes.end(), this->nodeId );
 	if( i != nodes.end() ) nodes.erase( i );
@@ -1499,5 +1539,9 @@
 	// drop links
 	BOOST_FOREACH( const LinkDescriptor* ld, oldlinks ) {
-		if (!ld->communicationId.isUnspecified() && ld->communicationId == initiatorLink) {
+
+		vector<LinkID>::iterator it = std::find(
+				bootstrapLinks.begin(), bootstrapLinks.end(), ld->communicationId);
+
+		if (!ld->communicationId.isUnspecified() && it != bootstrapLinks.end() ){
 			logging_force( "Not dropping initiator link: " << ld );
 			continue;
