Index: source/ariba/overlay/BaseOverlay.cpp
===================================================================
--- source/ariba/overlay/BaseOverlay.cpp	(revision 3374)
+++ source/ariba/overlay/BaseOverlay.cpp	(revision 3690)
@@ -1,3 +1,3 @@
-// [Licence]
+// [License]
 // The Ariba-Underlay Copyright
 //
@@ -35,5 +35,5 @@
 // official policies, either expressed or implied, of the Institute of
 // Telematics.
-// [Licence]
+// [License]
 
 #include "BaseOverlay.h"
@@ -43,4 +43,9 @@
 #include "ariba/CommunicationListener.h"
 #include "ariba/SideportListener.h"
+
+#include "ariba/overlay/messages/OverlayMsg.h"
+#include "ariba/overlay/messages/JoinRequest.h"
+#include "ariba/overlay/messages/JoinReply.h"
+#include "ariba/overlay/messages/LinkRequest.h"
 
 namespace ariba {
@@ -175,10 +180,8 @@
 void BaseOverlay::createSpoVNet(const SpoVNetID& id, const OverlayParameterSet& param, const SecurityParameterSet& sec, const QoSParameterSet& qos){
 
-	//
-	// set the state that we are an initiator,
-	// this way incoming messages are handled correctly
-	//
-
-	logging_info( "creating spovnet " + id.toString() << " with nodeid " << nodeId.toString() );
+	// set the state that we are an initiator, this way incoming messages are
+	// handled correctly
+	logging_info( "creating spovnet " + id.toString() <<
+			" with nodeid " << nodeId.toString() );
 
 	spovnetId = id;
@@ -192,12 +195,8 @@
 	}
 
-	//
 	// bootstrap against ourselfs
-	//
-
 	overlayInterface->joinOverlay();
-	BOOST_FOREACH( NodeListener* i, nodeListeners ){
+	BOOST_FOREACH( NodeListener* i, nodeListeners )
 		i->onJoinCompleted( spovnetId );
-	}
 
 	ovl.visChangeNodeIcon ( ovlId, nodeId, OvlVis::ICON_ID_CAMERA );
@@ -205,21 +204,8 @@
 }
 
-const LinkID BaseOverlay::establishLink(const NodeID& node, const ServiceID& service){
-
-	// TODO: if this is not a onehop overlay the operation will go asynchronously
-	const EndpointDescriptor& endpoint = overlayInterface->resolveNode( node );
-	if( endpoint == EndpointDescriptor::UNSPECIFIED ){
-		logging_error( "could not resolve node to endpoint. unable to establish link" );
-		return LinkID::UNSPECIFIED;
-	}
-
-	logging_debug( "baseoverlay called to establish link between node " <<
-			node.toString() << " on endpoint " << endpoint.toString() <<
-			" for service " << service.toString() );
-
-	return establishLink( endpoint, service );
-}
-
-const LinkID BaseOverlay::establishLink(const EndpointDescriptor& ep, const ServiceID& service){
+
+/// establishes a link between two arbitrary nodes
+const LinkID BaseOverlay::establishLink( const NodeID& node,
+		const ServiceID& service, const LinkID& link_id ) {
 
 	if( !communicationListeners.contains( service ) ){
@@ -228,5 +214,45 @@
 	}
 
-	const LinkID link = bc->establishLink( ep );
+	// copy link id
+	LinkID linkid = link_id;
+
+	// create link id if necessary
+	if (linkid.isUnspecified()) linkid = LinkID::create();
+
+	// debug message
+	logging_debug( "BaseOverlay called to establish link between node " <<
+			node.toString() << " for service " << service.toString() );
+
+	// create link request message with own link id
+	OverlayMsg overlay_msg( OverlayMsg::OverlayMessageTypeLinkRequest, service, nodeId );
+	uint32_t nonce = (uint32_t)(rand() ^ (rand() << 16) ^ time(NULL));
+	LinkRequest link_request_msg( nonce, &bc->getEndpointDescriptor() );
+	overlay_msg.encapsulate( &link_request_msg );
+	pendingLinks.insert( make_pair(nonce, linkid) );
+
+	// debug message
+	logging_debug( "BaseOverlay routes LinkRequest message to node " << node.toString() );
+
+	// route message to overlay node
+	overlayInterface->routeMessage( node, &overlay_msg );
+
+	CommunicationListener* receiver = communicationListeners.get( service );
+	assert( receiver != NULL );
+
+	LinkItem item (linkid, NodeID::UNSPECIFIED, service, receiver);
+	linkMapping.insert( make_pair(linkid, item) );
+
+	return linkid;
+}
+
+const LinkID BaseOverlay::establishLink( const EndpointDescriptor& ep,
+		const ServiceID& service, const LinkID& linkid  ){
+
+	if( !communicationListeners.contains( service ) ){
+		logging_error( "no registered listener on serviceid " << service.toString() );
+		return LinkID::UNSPECIFIED;
+	}
+
+	const LinkID link = bc->establishLink( ep, linkid );
 
 	CommunicationListener* receiver = communicationListeners.get( service );
@@ -260,5 +286,5 @@
 seqnum_t BaseOverlay::sendMessage(const Message* message, const LinkID& link ){
 
-	logging_debug( "baseoverlay is sending message on link " << link.toString() );
+	logging_debug( "baseoverlay is sending data message on link " << link.toString() );
 
 	LinkMapping::iterator i = linkMapping.find( link );
@@ -268,5 +294,6 @@
 	}
 
-	OverlayMsg overmsg( OverlayMsg::OverlayMessageTypeData, i->second.service, nodeId );
+	OverlayMsg overmsg(
+		OverlayMsg::OverlayMessageTypeData,	i->second.service, nodeId );
 	overmsg.encapsulate( const_cast<Message*>(message) );
 
@@ -342,4 +369,5 @@
 	return overlayInterface->resolveNode( node );
 }
+
 
 bool BaseOverlay::bind(CommunicationListener* listener, const ServiceID& sid){
@@ -567,8 +595,12 @@
 }
 
+
 bool BaseOverlay::receiveMessage(const Message* message,
-	const LinkID& link, const NodeID& /*the nodeid is invalid in this case! removed var to prevent errors*/ ){
-
-	OverlayMsg* overlayMsg = ((Message*)message)->decapsulate<OverlayMsg>();
+	const LinkID& link, const NodeID&
+	/*the nodeid is invalid in this case! removed var to prevent errors*/ ){
+
+	// decapsulate overlay message
+	logging_debug( "go msg " << message->toString());
+	OverlayMsg* overlayMsg = const_cast<Message*>(message)->decapsulate<OverlayMsg>();
 	if( overlayMsg == NULL ) return false;
 
@@ -577,12 +609,9 @@
 	if( item != linkMapping.end() ) item->second.markused();
 
-	//
-	// handle user date that we forward to the
-	// appropriate service using the service id
-	// in the message. as we don't know the class
-	// of message that the service handles, we
-	// forward it as a pure Message*
-	//
-
+	/* ************************************************************************
+	/* handle user date that we forward to the appropriate service using the
+	 * service id in the message. as we don't know the class of message that
+	 * the service handles, we forward it as a pure Message
+	 */
 	if( overlayMsg->isType(OverlayMsg::OverlayMessageTypeData) ) {
 
@@ -601,8 +630,7 @@
 	} // if( overlayMsg->isType(OverlayMsg::OverlayMessageTypeData) )
 
-	//
-	// handle spovnet instance join requests
-	//
-
+	/* ************************************************************************
+	/* Handle spovnet instance join requests
+	 */
 	else if( overlayMsg->isType(OverlayMsg::OverlayMessageTypeJoinRequest) &&
 						state == BaseOverlayStateInitiator){
@@ -614,9 +642,6 @@
 					 joinReq->getSpoVNetID().toString() );
 
-		//
-		// make sure that the node actually wants to join
-		// the correct spovnet id that we administrate
-		//
-
+		/* make sure that the node actually wants to join
+		 * the correct spovnet id that we administrate */
 		if( joinReq->getSpoVNetID() != spovnetId ){
 			logging_error( "received join request for spovnet we don't handle " <<
@@ -641,10 +666,6 @@
 		joiningNodes.push_back( overlayMsg->getSourceNode() );
 
-		//
-		// send back our spovnetid, default overlay parameters,
-		// join allow result, and ourself as the endpoint
-		// to bootstrap the overlay against
-		//
-
+		// send back our spovnetid, default overlay parameters, join allow
+		// result, and ourself as the end-point to bootstrap the overlay against
 		OverlayMsg retmsg( OverlayMsg::OverlayMessageTypeJoinReply, nodeId );
 		JoinReply replyMsg( spovnetId, OverlayParameterSet::DEFAULT,
@@ -656,23 +677,21 @@
 		return true;
 
-	} // else if( overlayMsg->isType(OverlayMsg::OverlayMessageTypeJoinRequest) && state == BaseOverlayStateInitiator)
-
-	//
-	// handle replies to spovnet instance join requests
-	//
-
+	} // else if( overlayMsg->isType(OverlayMsg::OverlayMessageTypeJoinRequest)
+	  //          && state == BaseOverlayStateInitiator)
+
+	/* ************************************************************************
+	 * handle replies to spovnet instance join requests
+	 */
 	else if( overlayMsg->isType(OverlayMsg::OverlayMessageTypeJoinReply) &&
 						state == BaseOverlayStateJoinInitiated){
 
-		logging_debug( "baseoverlay received message of type OverlayMessageTypeJoinReply" );
+		logging_debug(
+			"baseoverlay received message of type OverlayMessageTypeJoinReply");
 
 		JoinReply* replyMsg = overlayMsg->decapsulate<JoinReply>();
 		logging_info( "received spovnet join reply" );
 
-		//
-		// make sure that we actually wanted to get
-		// into the spovnet whose id is in the message
-		//
-
+		// ensure that we actually wanted to get into the spovnet whose id is
+		// in the message
 		if( replyMsg->getSpoVNetID() != spovnetId ){
 			logging_error( "received spovnet join reply for spovnet " <<
@@ -681,15 +700,10 @@
 					spovnetId.toString() );
 
-			// state does not change here, maybe
-			// the reply does come in later
+			// state does not change here, maybe the reply does come in later
 			return false;
 		}
 
-		//
-		// if we did not get access to the spovnet
-		// notify of the failure and
+		// if we did not get access to the spovnet notify of the failure and
 		// close the link to the initiator
-		//
-
 		if( ! replyMsg->getJoinAllowed() ){
 
@@ -708,13 +722,11 @@
 		}
 
-		logging_info( "join request has been accepted for spovnet " << spovnetId.toString() );
-
-		//
-		// if we did get access to the spovnet
-		// we try to create the overlay structure
-		// as given in the reply message
-		//
-
-		overlayInterface = OverlayFactory::create( *this, replyMsg->getParam(), nodeId, this );
+		logging_info( "join request has been accepted for spovnet " <<
+				spovnetId.toString() );
+
+		// if we did get access to the spovnet we try to create the overlay
+		// structure as given in the reply message
+		overlayInterface = OverlayFactory::create( *this,
+				replyMsg->getParam(), nodeId, this );
 
 		if( overlayInterface == NULL ){
@@ -726,19 +738,14 @@
 
 			// inform all registered services of the event
-			BOOST_FOREACH( NodeListener* i, nodeListeners ){
+			BOOST_FOREACH( NodeListener* i, nodeListeners )
 				i->onJoinFailed( spovnetId );
-			}
 
 			return true;
 		}
 
-		//
-		// now start the join process for the overlay.
-		// the join process for the spovnet baseoverlay
-		// is now complete. we use the endpoint for
-		// overlay structure bootstrapping that the
-		// initiator provided in his reply message
-		//
-
+		/* now start the join process for the overlay. the join process for the
+		 * spovnet baseoverlay is now complete. we use the endpoint for overlay
+		 * structure bootstrapping that the initiator provided in his reply
+		 * message */
 		state = BaseOverlayStateCompleted;
 		ovl.visChangeNodeColor( ovlId, nodeId, OvlVis::NODE_COLORS_GREEN);
@@ -757,22 +764,19 @@
 
 
-	//
-	// handle update messages for link establishment
-	//
-
+	/* ************************************************************************
+     * handle update messages for link establishment
+     */
 	else if( overlayMsg->isType(OverlayMsg::OverlayMessageTypeUpdate) ){
 
-		logging_debug( "baseoverlay received message of type OverlayMessageTypeUpdate" );
+		logging_debug(
+			"baseoverlay received message of type OverlayMessageTypeUpdate"
+		);
 
 		const NodeID& sourcenode = overlayMsg->getSourceNode();
 		const ServiceID& service = overlayMsg->getService();
 
-		//
-		// we should have a linkmapping for the link, otherwise
-		// we ignore update messages
-		//
-
+		// linkmapping for the link available? no-> ignore
 		LinkMapping::iterator i = linkMapping.find( link );
-		if( i == linkMapping.end() ){
+		if( i == linkMapping.end() ) {
 			logging_warn( "received overlay update message for link " <<
 					link.toString() << " for which we have no mapping" );
@@ -780,17 +784,12 @@
 		}
 
-		//
 		// update our link mapping information for this link
-		//
-
-		bool changed = ( i->second.node != sourcenode ) || ( i->second.service != service );
-
+		bool changed =
+			( i->second.node != sourcenode ) ||
+			( i->second.service != service );
 		i->second.node = sourcenode;
 		i->second.service = service;
 
-		//
 		// if our link information changed, we send out an update, too
-		//
-
 		if( changed ){
 			OverlayMsg overMsg( OverlayMsg::OverlayMessageTypeUpdate, i->second.service, nodeId );
@@ -798,9 +797,6 @@
 		}
 
-		//
 		// set the correct listener service for the linkitem
 		// now we can tell the registered service of the linkup event
-		//
-
 		if( !communicationListeners.contains( service ) ){
 			logging_warn( "linkup event for service that has not been registered" );
@@ -810,5 +806,6 @@
 		CommunicationListener* iface = communicationListeners.get( service );
 		if( iface == NULL || iface == &CommunicationListener::DEFAULT ){
-			logging_warn( "linkup event for service that has been registered with a NULL interface" );
+			logging_warn( "linkup event for service that has been registered "
+				"with a NULL interface" );
 			return true;
 		}
@@ -817,8 +814,5 @@
 		i->second.markused();
 
-		//
 		// ask the service whether it wants to accept this link
-		//
-
 		if( iface->onLinkRequest(sourcenode) ){
 
@@ -838,21 +832,17 @@
 	} // else if( overlayMsg->isType(OverlayMsg::OverlayMessageTypeUpdate) )
 
-	//
-	// bye messages to say goodbye
-	//
-
-	else if( overlayMsg->isType(OverlayMsg::OverlayMessageTypeBye)){
-
-		logging_debug( "baseoverlay received message of type OverlayMessageTypeBye" );
-
-		logging_debug( "received bye message from " <<
+	/* ************************************************************************
+	 * handle bye messages
+	 */
+	else if( overlayMsg->isType(OverlayMsg::OverlayMessageTypeBye) ) {
+
+		logging_debug( "BaseOverlay received message of type OverlayMessageTypeBye" );
+		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 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 ){
 
@@ -869,10 +859,8 @@
 
 		} 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
+			// 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() );
-
 		}
 
@@ -881,8 +869,48 @@
 	} // else if( overlayMsg->isType(OverlayMsg::OverlayMessageTypeBye))
 
-	//
-	// something wrong ...
-	//
-
+	/* ************************************************************************
+	 * handle link request forwarded through the overlay
+	 */
+	else if( overlayMsg->isType(OverlayMsg::OverlayMessageTypeLinkRequest)) {
+		LinkRequest* linkReq = overlayMsg->decapsulate<LinkRequest>();
+		const ServiceID& service = overlayMsg->getService();
+		if (linkReq->isReply()) {
+
+			// find link
+			PendingLinkMap::iterator i = pendingLinks.find( linkReq->getNonce() );
+			if ( i == pendingLinks.end() ) {
+				logging_error( "Nonce not found in link request" );
+				return true;
+			}
+
+			// debug message
+			logging_debug( "LinkRequest reply received. Establishing link "
+				<< i->second << " to " << (linkReq->getEndpoint()->toString())
+				<< " for service " << service.toString()
+				<< " with nonce " << linkReq->getNonce()
+			);
+
+			// establishing link
+			bc->establishLink( *linkReq->getEndpoint(), i->second );
+		} else {
+			OverlayMsg overlay_msg( OverlayMsg::OverlayMessageTypeLinkRequest, service, nodeId );
+			LinkRequest link_request_msg(
+					linkReq->getNonce(), &bc->getEndpointDescriptor(), true );
+			overlay_msg.encapsulate( &link_request_msg );
+
+			// debug message
+			logging_debug( "Sending LinkRequest reply for link with nonce " <<
+					linkReq->getNonce()	);
+
+			// route message back over overlay
+			overlayInterface->routeMessage(
+				overlayMsg->getSourceNode(), &overlay_msg
+			);
+		}
+	} // if( overlayMsg->isType(OverlayMsg::OverlayMessageTypeLinkRequest))
+
+	/* ************************************************************************
+	 * unknown message type ... error!
+	 */
 	else {
 
@@ -1008,5 +1036,5 @@
 	}
 
-	BOOST_FOREACH( const LinkID lnk, oldlinks ){
+	BOOST_FOREACH( const LinkID lnk, oldlinks ) {
 		logging_debug( "auto-link " << lnk.toString() << " timed out and is getting dropped" );
 		dropLink( lnk );
