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 );
Index: source/ariba/overlay/BaseOverlay.h
===================================================================
--- source/ariba/overlay/BaseOverlay.h	(revision 5738)
+++ source/ariba/overlay/BaseOverlay.h	(revision 5743)
@@ -160,4 +160,10 @@
 	bool isStarted();
 
+	/// Tries to establish a direct or overlay link
+	const LinkID establishLink(const EndpointDescriptor& ep,
+		const NodeID& node, const ServiceID& service,
+		const NodeID& remoteRelay = NodeID::UNSPECIFIED,
+		const LinkID& linkid = LinkID::UNSPECIFIED);
+
 	/**
 	 * Starts a link establishment procedure to the specfied node
@@ -169,13 +175,6 @@
 	 */
 	const LinkID establishLink(const NodeID& node, const ServiceID& service,
+		const NodeID& remoteRelay = NodeID::UNSPECIFIED,
 		const LinkID& linkid = LinkID::UNSPECIFIED);
-
-	/**
-	 * Starts a link establishment procedure to the specified
-	 * endpoint and to the specified service. Concurrently it tries to
-	 * establish a relay link over the overlay using the nodeid
-	 */
-	const LinkID establishLink(const EndpointDescriptor& ep, const NodeID& nodeid,
-		const ServiceID& service, const LinkID& linkid = LinkID::UNSPECIFIED);
 
 	/**
@@ -183,5 +182,5 @@
 	 * endpoint and to the specified service
 	 */
-	const LinkID establishLink(const EndpointDescriptor& ep,
+	const LinkID establishDirectLink(const EndpointDescriptor& ep,
 		const ServiceID& service, const LinkID& linkid = LinkID::UNSPECIFIED);
 
@@ -412,16 +411,18 @@
 
 	/// returns a direct link relay descriptor to the given relay node
-	LinkDescriptor* getRelayDescriptor( const NodeID& relayNode );
-
-	/// find a proper relay node that is directly connected to this node
-	const NodeID findRelayNode( const NodeID id );
+	LinkDescriptor* getRelayDescriptor( const NodeID& remoteNode );
+
+	/// returns the local relay node to a given remote node
+	NodeID getRelayNode( const NodeID& remoteNode );
+
+	/// returns the direct link the message to a neighbor is send to
+	LinkDescriptor* getSendDescriptor( const NodeID& nodeid, bool follow = true );
+
+	/// routes a message over the overlay or directly sends it when a link is open
+	seqnum_t sendOverlay( Message* message, const NodeID& nodeid,
+		const NodeID& remoteRelay = NodeID::UNSPECIFIED );
 
 	/// forwards a message over relays/overlay/directly using link descriptor
 	seqnum_t sendMessage( Message* message, const LinkDescriptor* ld );
-
-	LinkDescriptor* getSendDescriptor( const NodeID& nodeid, bool follow = true );
-
-	/// routes a message over the overlay or directly sends it when a link is open
-	seqnum_t sendOverlay( Message* message, const NodeID& nodeid );
 
 	/// creates a link descriptor, applys relay semantics if possible
Index: source/ariba/overlay/modules/chord/Chord.cpp
===================================================================
--- source/ariba/overlay/modules/chord/Chord.cpp	(revision 5738)
+++ source/ariba/overlay/modules/chord/Chord.cpp	(revision 5743)
@@ -57,5 +57,5 @@
 
 	// create routing table
-	this->table = new chord_routing_table(_nodeid, 2);
+	this->table = new chord_routing_table(_nodeid, 4);
 	orphan_removal_counter = 0;
 	discovery_count = 0;
@@ -71,7 +71,8 @@
 
 /// helper: sets up a link using the base overlay
-LinkID Chord::setup(const EndpointDescriptor& endp, const NodeID& node) {
+LinkID Chord::setup(const EndpointDescriptor& endp, const NodeID& node, const NodeID& remoteRelay ) {
 	logging_debug("Request to setup link to " << endp.toString() );
 
+	// check if we already have a connection
 	for (int i=0; i<table->size(); i++)
 		if ((*table)[i]->id == node && !((*table)[i]->info.isUnspecified()))
@@ -89,5 +90,5 @@
 
 	// establish link via base overlay
-	return baseoverlay.establishLink(endp, node, OverlayInterface::OVERLAY_SERVICE_ID);
+	return baseoverlay.establishLink(endp, node, OverlayInterface::OVERLAY_SERVICE_ID, remoteRelay );
 }
 
@@ -105,4 +106,5 @@
 	Discovery dmsg;
 	dmsg.setSourceEndpoint(&baseoverlay.getEndpointDescriptor());
+	dmsg.setSourceRelay(baseoverlay.getRelayNode(destination));
 	dmsg.setFollowType(Discovery::normal);
 	dmsg.setTTL((uint8_t) ttl);
@@ -120,4 +122,5 @@
 		Discovery dmsg;
 		dmsg.setSourceEndpoint(&baseoverlay.getEndpointDescriptor());
+		dmsg.setSourceRelay(baseoverlay.getRelayNode(nodeid));
 		dmsg.setFollowType(Discovery::successor);
 		dmsg.setTTL((uint8_t)3);
@@ -130,4 +133,5 @@
 		Discovery dmsg;
 		dmsg.setSourceEndpoint(&baseoverlay.getEndpointDescriptor());
+		dmsg.setSourceRelay(baseoverlay.getRelayNode(nodeid));
 		dmsg.setFollowType(Discovery::predecessor);
 		dmsg.setTTL((uint8_t)3);
@@ -332,5 +336,5 @@
 		// check if source node can be added to routing table and setup link
 		if (m->getSource() != nodeid && table->is_insertable(m->getSource()))
-			setup(*dmsg->getSourceEndpoint(), m->getSource() );
+			setup(*dmsg->getSourceEndpoint(), m->getSource(), dmsg->getSourceRelay() );
 
 		// delegate discovery message
Index: source/ariba/overlay/modules/chord/Chord.h
===================================================================
--- source/ariba/overlay/modules/chord/Chord.h	(revision 5738)
+++ source/ariba/overlay/modules/chord/Chord.h	(revision 5743)
@@ -81,5 +81,7 @@
 
 	// helper: sets up a link using the "base overlay"
-	LinkID setup( const EndpointDescriptor& endp, const NodeID& node = NodeID::UNSPECIFIED );
+	LinkID setup( const EndpointDescriptor& endp,
+		const NodeID& node = NodeID::UNSPECIFIED,
+		const NodeID& remoteRelay = NodeID::UNSPECIFIED );
 
 	// helper: sends a message using the "base overlay"
Index: source/ariba/overlay/modules/chord/messages/Discovery.h
===================================================================
--- source/ariba/overlay/modules/chord/messages/Discovery.h	(revision 5738)
+++ source/ariba/overlay/modules/chord/messages/Discovery.h	(revision 5743)
@@ -70,4 +70,5 @@
 		this->follow_type = msg.follow_type;
 		this->ttl = msg.ttl;
+		this->source_relay = msg.source_relay;
 		this->source_endpoint = msg.source_endpoint;
 	}
@@ -99,8 +100,16 @@
 	}
 
+	inline void setSourceRelay( const NodeID& relay ) {
+		source_relay = relay;
+	}
+
+	inline const NodeID& getSourceRelay() const {
+		return source_relay;
+	}
 private:
 	uint8_t follow_type;
 	uint8_t ttl;
 	EndpointDescriptor source_endpoint;
+	NodeID source_relay;
 };
 
@@ -112,5 +121,5 @@
 
 	// serialize end-point
-	X && source_endpoint;
+	X && source_relay && source_endpoint;
 } sznEnd();
 
Index: source/ariba/overlay/modules/onehop/OneHop.cpp
===================================================================
--- source/ariba/overlay/modules/onehop/OneHop.cpp	(revision 5738)
+++ source/ariba/overlay/modules/onehop/OneHop.cpp	(revision 5743)
@@ -154,5 +154,5 @@
 	} else {
 		bootstrapLinks.push_back(
-				baseoverlay.establishLink( bootstrapEp,
+				baseoverlay.establishDirectLink( bootstrapEp,
 					OverlayInterface::OVERLAY_SERVICE_ID )
 					);
@@ -314,5 +314,5 @@
 
 			logging_debug( "building up link to node in overlay " << node.toString() );
-			const LinkID link = baseoverlay.establishLink( *((*i).second),
+			const LinkID link = baseoverlay.establishDirectLink( *((*i).second),
 							OverlayInterface::OVERLAY_SERVICE_ID );
 
