Index: source/ariba/overlay/BaseOverlay.cpp
===================================================================
--- source/ariba/overlay/BaseOverlay.cpp	(revision 5738)
+++ source/ariba/overlay/BaseOverlay.cpp	(revision 5743)
@@ -74,4 +74,28 @@
 }
 
+/// erases a link descriptor
+void BaseOverlay::eraseDescriptor( const LinkID& link, bool communication ) {
+	for ( vector<LinkDescriptor*>::iterator i = links.begin(); i!= links.end(); i++) {
+		LinkDescriptor* ld = *i;
+		if ((communication ? ld->communicationId : ld->overlayId) == link) {
+			delete ld;
+			links.erase(i);
+			break;
+		}
+	}
+}
+
+/// adds a link descriptor
+LinkDescriptor* BaseOverlay::addDescriptor( const LinkID& link ) {
+	LinkDescriptor* desc = getDescriptor( link );
+	if ( desc == NULL ) {
+		desc = new LinkDescriptor();
+		desc->overlayId = link;
+		links.push_back(desc);
+	}
+	return desc;
+}
+
+/// returns a auto-link descriptor
 LinkDescriptor* BaseOverlay::getAutoDescriptor( const NodeID& node, const ServiceID& service ) {
 	BOOST_FOREACH( LinkDescriptor* lp, links )
@@ -84,52 +108,17 @@
 }
 
-void BaseOverlay::eraseDescriptor( const LinkID& link, bool communication ) {
-	for ( vector<LinkDescriptor*>::iterator i = links.begin(); i!= links.end(); i++) {
-		LinkDescriptor* ld = *i;
-		if ((communication ? ld->communicationId : ld->overlayId) == link) {
-			delete ld;
-			links.erase(i);
-			break;
-		}
-	}
-}
-
-LinkDescriptor* BaseOverlay::addDescriptor( const LinkID& link ) {
-	LinkDescriptor* desc = getDescriptor( link );
-	if ( desc == NULL ) {
-		desc = new LinkDescriptor();
-		desc->overlayId = link;
-		links.push_back(desc);
-	}
-	return desc;
-}
-
-/// returns a direct link relay descriptor to the given relay node
-LinkDescriptor* BaseOverlay::getRelayDescriptor( const NodeID& relayNode ) {
-	BOOST_FOREACH( LinkDescriptor* lp, links )
-		if (lp->remoteNode == relayNode &&
-		    lp->service == OverlayInterface::OVERLAY_SERVICE_ID &&
-		    lp->relay == false &&
-		    lp->up)
-			return lp;
-	return NULL;
-}
-
-/// find a proper relay node
-const NodeID BaseOverlay::findRelayNode( const NodeID id ) {
+/// returns a direct local link relay descriptor for the given remote node
+LinkDescriptor* BaseOverlay::getRelayDescriptor( const NodeID& id ) {
+
+	// get used next hop towards node
 	LinkDescriptor* rld = NULL;
 	NodeID relayNode = NodeID::UNSPECIFIED;
-
-	// get used next hop towards node
 	LinkID rlid = overlayInterface->getNextLinkId(id);
-	while ( relayNode.isUnspecified() && !rlid.isUnspecified() && rld == NULL ) {
-
+	if ( relayNode.isUnspecified() && !rlid.isUnspecified() && rld == NULL ) {
 		// get descriptor of first hop
 		rld = getDescriptor(rlid);
-		logging_info( rld );
-
-		// is first hop a relay path? yes-> try to find real link!
-		if ( rld->relay )
-			relayNode = getRelayDescriptor(rld->localRelay)->remoteNode;
+
+		// is first hop a relay path use local relay
+		if ( rld->relay ) relayNode = rld->localRelay;
 
 		// no-> a proper relay node has been found
@@ -150,59 +139,19 @@
 	}
 
-	// do not return myself or use the node as relay node
-	if (relayNode == nodeId)
-		return NodeID::UNSPECIFIED;
-	else {
-		logging_info( "Returning relay node " << relayNode.toString() );
-		return relayNode;
-	}
-}
-
-/// forwards a message over relays/directly using link descriptor
-seqnum_t BaseOverlay::sendMessage( Message* message, const LinkDescriptor* ld ) {
-
-	// directly send message
-	if ( !ld->communicationId.isUnspecified() && ld->communicationUp ) {
-		logging_debug("Send: Sending message via Base Communication");
-		return bc->sendMessage( ld->communicationId, message );
-	}
-
-	// relay message
-	else if ( ld->relay ) {
-
-		logging_debug("Send: Relaying message to node "
-			<< ld->remoteNode.toString()
-			<< " using relay " << ld->localRelay
-		);
-/*
-		// get local relay link descriptor and mark as used for relaying
-		LinkDescriptor* rld = getRelayDescriptor(ld->localRelay);
-		if (rld==NULL) {
-			logging_error("Send: Relay descriptor for relay " <<
-				ld->localRelay.toString() << " is unknown.");
-			return -1;
-		}
-		rld->markAsRelay();*/
-
-		// create a information relay message to inform the relay about
-		OverlayMsg overlay_msg( OverlayMsg::typeRelay, ld->service, nodeId );
-		RelayMessage relayMsg( RelayMessage::typeInform, ld->remoteRelay, ld->remoteNode, ld->remoteLinkId );
-		relayMsg.encapsulate( message );
-		overlay_msg.encapsulate( &relayMsg );
-
-		// route message to relay node in order to inform it!
-		logging_debug("sendMessage: Sending message over relayed link with" << ld );
-		sendOverlay( &overlay_msg, ld->localRelay );
-		return 0;
-	}
-
-	// error
-	else {
-		logging_error( "Could not send message descriptor=" << ld );
-		return -1;
-	}
-	return -1;
-}
-
+	// no local relay found-> damn!
+	if (relayNode.isUnspecified()) return NULL;
+
+	// get descriptor
+	BOOST_FOREACH( LinkDescriptor* lp, links )
+		if (lp->remoteNode == relayNode &&
+		    lp->service == OverlayInterface::OVERLAY_SERVICE_ID &&
+		    lp->relay == false &&
+		    lp->up)
+			return lp;
+
+	return NULL;
+}
+
+/// returns the link descriptor that is actually used for sending a message over the overÃ¶ay
 LinkDescriptor* BaseOverlay::getSendDescriptor( const NodeID& nodeid, bool follow ) {
 	for (size_t i=0; i<links.size(); i++)
@@ -221,6 +170,12 @@
 }
 
+NodeID BaseOverlay::getRelayNode( const NodeID& remoteNode ) {
+	LinkDescriptor* rld = getRelayDescriptor(remoteNode);
+	return rld!=NULL ? rld->remoteNode : NodeID::UNSPECIFIED;
+}
+
 /// routes a message over the overlay or directly sends it when a link is open
-seqnum_t BaseOverlay::sendOverlay( Message* message, const NodeID& nodeid ) {
+seqnum_t BaseOverlay::sendOverlay( Message* message, const NodeID& nodeid, const NodeID& remoteRelay  ) {
+	/// send message directly to a neighbor
 	for (size_t i=0; i<links.size(); i++)
 		if ( !links[i]->relay &&
@@ -230,10 +185,74 @@
 			links[i]->remoteNode == nodeid &&
 			links[i]->service == OverlayInterface::OVERLAY_SERVICE_ID) {
+
+			// mark as relay and send message
 			links[i]->markAsRelay();
 			return sendMessage( message, links[i] );
-			break;
-		}
+		}
+
+	/// send relayed message over the overlay
+	if (!remoteRelay.isUnspecified()) {
+		// create a information relay message to inform the relay about
+		OverlayMsg overlay_msg(
+			OverlayMsg::typeRelay, OverlayInterface::OVERLAY_SERVICE_ID, nodeId);
+		RelayMessage relayMsg( RelayMessage::typeInform, remoteRelay, nodeid, LinkID::UNSPECIFIED );
+		relayMsg.encapsulate( message );
+		overlay_msg.encapsulate( &relayMsg );
+
+		// get local relay link
+		LinkDescriptor* rld = getRelayDescriptor(nodeid);
+
+		// local relay available? send to local relay!
+		if (rld!=NULL) {
+			rld->markAsRelay();
+			sendMessage(&overlay_msg, rld);
+		} else
+			overlayInterface->routeMessage(remoteRelay, &overlay_msg);
+
+		// finished
+		return 0;
+	}
+
+	// common case: send message over the overlay
 	overlayInterface->routeMessage(nodeid, message);
 	return 0;
+}
+
+/// forwards a message over relays/directly using link descriptor
+seqnum_t BaseOverlay::sendMessage( Message* message, const LinkDescriptor* ld ) {
+
+	// directly send message
+	if ( !ld->communicationId.isUnspecified() && ld->communicationUp ) {
+		logging_debug("Send: Sending message via Base Communication");
+		return bc->sendMessage( ld->communicationId, message );
+	}
+
+	// relay message
+	else if ( ld->relay ) {
+
+		// sending a relayed message
+		logging_debug("Send: Relaying message to node "
+			<< ld->remoteNode.toString()
+			<< " using relay " << ld->localRelay
+		);
+
+		// create a information relay message to inform the relay about
+		OverlayMsg overlay_msg( OverlayMsg::typeRelay, ld->service, nodeId );
+		RelayMessage relayMsg( RelayMessage::typeInform, ld->remoteRelay, ld->remoteNode, ld->remoteLinkId );
+		relayMsg.encapsulate( message );
+		overlay_msg.encapsulate( &relayMsg );
+
+		// route message to relay node in order to inform it!
+		logging_debug("sendMessage: Sending message over relayed link with" << ld );
+		sendOverlay( &overlay_msg, ld->localRelay );
+		return 0;
+	}
+
+	// error
+	else {
+		logging_error( "Could not send message descriptor=" << ld );
+		return -1;
+	}
+	return -1;
 }
 
@@ -258,5 +277,6 @@
 
 	// create relay link descriptor
-	NodeID relayNode = findRelayNode(remoteNode);
+	LinkDescriptor* rld = getRelayDescriptor(remoteNode);
+	NodeID relayNode = rld != NULL ? rld->remoteNode : NodeID::UNSPECIFIED;
 
 	// add descriptor
@@ -454,5 +474,5 @@
 const LinkID BaseOverlay::establishLink(
 	const EndpointDescriptor& ep, const NodeID& nodeid,
-	const ServiceID& service, const LinkID& linkid ) {
+	const ServiceID& service, const NodeID& remoteRelay, const LinkID& linkid ) {
 
 	LinkID link_id = linkid;
@@ -460,9 +480,9 @@
 	// establish link via overlay
 	if (!nodeid.isUnspecified())
-		link_id = establishLink( nodeid, service, link_id );
+		link_id = establishLink( nodeid, service, remoteRelay, link_id );
 
 	// establish link directly if only ep is known
-//	if (nodeid.isUnspecified())
-		establishLink( ep, service, link_id );
+	if (nodeid.isUnspecified())
+		establishDirectLink( ep, service, link_id );
 
 	return link_id;
@@ -470,5 +490,5 @@
 
 /// call base communication's establish link and add link mapping
-const LinkID BaseOverlay::establishLink( const EndpointDescriptor& ep,
+const LinkID BaseOverlay::establishDirectLink( const EndpointDescriptor& ep,
 		const ServiceID& service, const LinkID& linkid ) {
 
@@ -502,5 +522,5 @@
 /// establishes a link between two arbitrary nodes
 const LinkID BaseOverlay::establishLink( const NodeID& node,
-		const ServiceID& service, const LinkID& link_id ) {
+		const ServiceID& service, const NodeID& remoteRelay, const LinkID& link_id ) {
 
 	// do not establish a link to myself!
@@ -509,4 +529,5 @@
 	// create a link descriptor
 	LinkDescriptor* ld = createLinkDescriptor( node, service, link_id );
+	ld->remoteRelay = remoteRelay;
 
 	// create link request message with own link id
@@ -809,5 +830,5 @@
 
 		// if link is a relayed link ->convert to direct link
-		if (ld->relay) {
+		if (ld->relay && !ld->remoteLinkId.isUnspecified() ) {
 			logging_info( "Converting to direct link: " << ld );
 			ld->up = true;
@@ -1025,5 +1046,4 @@
 
 				// drop initiator link
-
 				if(bcLink != LinkID::UNSPECIFIED){
 					bc->dropLink( bcLink );
