Index: source/ariba/overlay/BaseOverlay.cpp
===================================================================
--- source/ariba/overlay/BaseOverlay.cpp	(revision 10653)
+++ source/ariba/overlay/BaseOverlay.cpp	(revision 12060)
@@ -57,11 +57,23 @@
 #include "ariba/utility/visual/DddVis.h"
 #include "ariba/utility/visual/ServerVis.h"
+#include <ariba/utility/misc/sha1.h>
 
 namespace ariba {
 namespace overlay {
+
+using namespace std;
+using ariba::transport::system_priority;
 
 #define visualInstance 		ariba::utility::DddVis::instance()
 #define visualIdOverlay 	ariba::utility::ServerVis::NETWORK_ID_BASE_OVERLAY
 #define visualIdBase		ariba::utility::ServerVis::NETWORK_ID_BASE_COMMUNICATION
+
+
+// time constants (in seconds)
+#define KEEP_ALIVE_TIME         60                      // send keep-alive message after link is not used for #s  
+
+#define LINK_ESTABLISH_TIME_OUT 10                      // timeout: link requested but not up
+#define KEEP_ALIVE_TIME_OUT     KEEP_ALIVE_TIME + LINK_ESTABLISH_TIME_OUT     // timeout: no data received on this link (incl. keep-alive messages)
+#define AUTO_LINK_TIME_OUT      KEEP_ALIVE_TIME_OUT                    // timeout: auto link not used for #s
 
 
@@ -85,5 +97,5 @@
 
 LinkDescriptor* BaseOverlay::getDescriptor( const LinkID& link, bool communication ) {
-	BOOST_FOREACH( LinkDescriptor* lp, links )
+	foreach( LinkDescriptor* lp, links )
 				if ((communication ? lp->communicationId : lp->overlayId) == link)
 					return lp;
@@ -92,5 +104,5 @@
 
 const LinkDescriptor* BaseOverlay::getDescriptor( const LinkID& link, bool communication ) const {
-	BOOST_FOREACH( const LinkDescriptor* lp, links )
+	foreach( const LinkDescriptor* lp, links )
 				if ((communication ? lp->communicationId : lp->overlayId) == link)
 					return lp;
@@ -122,13 +134,23 @@
 
 /// returns a auto-link descriptor
-LinkDescriptor* BaseOverlay::getAutoDescriptor( const NodeID& node, const ServiceID& service ) {
+LinkDescriptor* BaseOverlay::getAutoDescriptor( const NodeID& node, const ServiceID& service )
+{
 	// search for a descriptor that is already up
-	BOOST_FOREACH( LinkDescriptor* lp, links )
-				if (lp->autolink && lp->remoteNode == node && lp->service == service && lp->up && lp->keepAliveMissed == 0)
-					return lp;
+	foreach( LinkDescriptor* lp, links )
+    {
+        if (lp->autolink && lp->remoteNode == node && lp->service == service && isLinkVital(lp) )
+            return lp;
+    }
+	
 	// if not found, search for one that is about to come up...
-	BOOST_FOREACH( LinkDescriptor* lp, links )
-	if (lp->autolink && lp->remoteNode == node && lp->service == service && lp->keepAliveMissed == 0 )
-		return lp;
+	foreach( LinkDescriptor* lp, links )
+	{
+	    time_t now = time(NULL);
+	    
+        if (lp->autolink && lp->remoteNode == node && lp->service == service
+                && difftime( now, lp->keepAliveReceived ) <= LINK_ESTABLISH_TIME_OUT )
+            return lp;
+	}
+	
 	return NULL;
 }
@@ -136,35 +158,47 @@
 /// stabilizes link information
 void BaseOverlay::stabilizeLinks() {
-	// send keep-alive messages over established links
-	BOOST_FOREACH( LinkDescriptor* ld, links ) {
+    time_t now = time(NULL);
+    
+    // send keep-alive messages over established links
+	foreach( LinkDescriptor* ld, links )
+    {
 		if (!ld->up) continue;
-		OverlayMsg msg( OverlayMsg::typeLinkAlive,
-				OverlayInterface::OVERLAY_SERVICE_ID, nodeId, ld->remoteNode );
-		if (ld->relayed) msg.setRouteRecord(true);
-		send_link( &msg, ld->overlayId );
+		
+		if ( difftime( now, ld->keepAliveSent ) >= KEEP_ALIVE_TIME )
+		{
+		    logging_debug("[BaseOverlay] Sending KeepAlive over "
+		            << ld->to_string()
+		            << " after "
+		            << difftime( now, ld->keepAliveSent )
+		            << "s");
+		    
+            OverlayMsg msg( OverlayMsg::typeKeepAlive,
+                    OverlayInterface::OVERLAY_SERVICE_ID, nodeId, ld->remoteNode );
+            msg.setRouteRecord(true);
+            ld->keepAliveSent = now;
+            send_link( &msg, ld->overlayId, system_priority::OVERLAY );
+		}
 	}
 
 	// iterate over all links and check for time boundaries
 	vector<LinkDescriptor*> oldlinks;
-	time_t now = time(NULL);
-	BOOST_FOREACH( LinkDescriptor* ld, links ) {
-
-		// keep alives and not up? yes-> link connection request is stale!
-		if ( !ld->up && difftime( now, ld->keepAliveTime ) >= 2 ) {
-
-			// increase counter
-			ld->keepAliveMissed++;
-
-			// missed more than four keep-alive messages (10 sec)? -> drop link
-			if (ld->keepAliveMissed > 4) {
-				logging_info( "Link connection request is stale, closing: " << ld );
-				oldlinks.push_back( ld );
-				continue;
-			}
+	foreach( LinkDescriptor* ld, links ) {
+
+		// link connection request stale?
+		if ( !ld->up && difftime( now, ld->keepAliveReceived ) >= LINK_ESTABLISH_TIME_OUT )  // NOTE: keepAliveReceived == now, on connection request
+		{
+            logging_info( "Link connection request is stale, closing: " << ld );
+            ld->failed = true;
+            oldlinks.push_back( ld );
+            continue;
 		}
 
 		if (!ld->up) continue;
 
+		
+		
+		
 		// check if link is relayed and retry connecting directly
+		// TODO Mario: What happens here?  --> There are 3 attempts to replace a relayed link with a direct one. see: handleLinkReply
 		if ( ld->relayed && !ld->communicationUp && ld->retryCounter > 0) {
 			ld->retryCounter--;
@@ -173,5 +207,5 @@
 
 		// remote used as relay flag
-		if ( ld->relaying && difftime( now, ld->timeRelaying ) > 10)
+		if ( ld->relaying && difftime( now, ld->timeRelaying ) > KEEP_ALIVE_TIME_OUT)  // TODO is this a reasonable timeout ??
 			ld->relaying = false;
 
@@ -183,5 +217,5 @@
 
 		// auto-link time exceeded?
-		if ( ld->autolink && difftime( now, ld->lastuse ) > 30 ) {
+		if ( ld->autolink && difftime( now, ld->lastuse ) > AUTO_LINK_TIME_OUT ) {
 			oldlinks.push_back( ld );
 			continue;
@@ -189,20 +223,15 @@
 
 		// keep alives missed? yes->
-		if ( difftime( now, ld->keepAliveTime ) > 4 ) {
-
-			// increase counter
-			ld->keepAliveMissed++;
-
-			// missed more than four keep-alive messages (4 sec)? -> drop link
-			if (ld->keepAliveMissed >= 2) {
-				logging_info( "Link is stale, closing: " << ld );
-				oldlinks.push_back( ld );
-				continue;
-			}
+		if ( difftime( now, ld->keepAliveReceived ) >= KEEP_ALIVE_TIME_OUT )
+		{
+            logging_info( "Link is stale, closing: " << ld );
+            ld->failed = true;
+            oldlinks.push_back( ld );
+            continue;
 		}
 	}
 
 	// drop links
-	BOOST_FOREACH( LinkDescriptor* ld, oldlinks ) {
+	foreach( LinkDescriptor* ld, oldlinks ) {
 		logging_info( "Link timed out. Dropping " << ld );
 		ld->relaying = false;
@@ -210,8 +239,17 @@
 	}
 
-	// show link state
-	counter++;
-	if (counter>=4) showLinks();
-	if (counter>=4 || counter<0) counter = 0;
+	
+	
+	
+	// show link state  (debug output)
+	if (counter>=10 || counter<0)
+    {
+	    showLinks();
+	    counter = 0;
+    }
+	else
+	{
+	    counter++;
+	}
 }
 
@@ -230,8 +268,8 @@
 
 		int i=0;
-		BOOST_FOREACH( LinkDescriptor* ld, links ) {
-			if (!ld->isVital() || ld->service != OverlayInterface::OVERLAY_SERVICE_ID) continue;
+		foreach( LinkDescriptor* ld, links ) {
+			if (!isLinkVital(ld) || ld->service != OverlayInterface::OVERLAY_SERVICE_ID) continue;
 			bool found = false;
-			BOOST_FOREACH(NodeID& id, nodes)
+			foreach(NodeID& id, nodes)
 			if (id  == ld->remoteNode) found = true;
 			if (found) continue;
@@ -261,8 +299,15 @@
 	int i=0;
 	logging_info("--- link state -------------------------------");
-	BOOST_FOREACH( LinkDescriptor* ld, links ) {
+	foreach( LinkDescriptor* ld, links ) {
 		string epd = "";
-		if (ld->isDirectVital())
-			epd = getEndpointDescriptor(ld->remoteNode).toString();
+		if (isLinkDirectVital(ld))
+		{
+//			epd = getEndpointDescriptor(ld->remoteNode).toString();
+		    
+		    epd = "Connection: ";
+		    epd += bc->get_local_endpoint_of_link(ld->communicationId)->to_string();
+		    epd += " <---> ";
+		    epd += bc->get_remote_endpoint_of_link(ld->communicationId)->to_string();
+		}
 
 		logging_info("LINK_STATE: " << i << ": " << ld << " " << epd);
@@ -289,11 +334,38 @@
 // internal message delivery ---------------------------------------------------
 
+
+seqnum_t BaseOverlay::send_overlaymessage_down( OverlayMsg* message, const LinkID& bc_link, uint8_t priority )
+{
+    // set priority
+    message->setPriority(priority);
+    
+    // wrap old OverlayMsg into reboost message
+    reboost::message_t wrapped_message = message->wrap_up_for_sending();
+    
+    // send down to BaseCommunication
+    try
+    {
+        // * send *
+        return bc->sendMessage(bc_link, wrapped_message, priority, false);
+    }
+    catch ( communication::communication_message_not_sent& e )
+    {
+        ostringstream out;
+        out << "Communication message not sent: " << e.what();
+        throw message_not_sent(out.str());
+    }
+    
+    throw logic_error("This should never happen!");
+}
+
+
 /// routes a message to its destination node
-void BaseOverlay::route( OverlayMsg* message ) {
-
+void BaseOverlay::route( OverlayMsg* message, const NodeID& last_hop )
+{
 	// exceeded time-to-live? yes-> drop message
-	if (message->getNumHops() > message->getTimeToLive()) {
-		logging_warn("Message exceeded TTL. Dropping message and relay routes"
-				"for recovery.");
+	if (message->getNumHops() > message->getTimeToLive())
+	{
+		logging_warn("Message exceeded TTL. Dropping message and relay routes "
+            << "for recovery. Hop count: " << (int) message->getNumHops());
 		removeRelayNode(message->getDestinationNode());
 		return;
@@ -301,132 +373,279 @@
 
 	// no-> forward message
-	else {
+	else
+	{
 		// destinastion myself? yes-> handle message
-		if (message->getDestinationNode() == nodeId) {
-			logging_warn("Usually I should not route messages to myself!");
-			Message msg;
-			msg.encapsulate(message);
-			handleMessage( &msg, NULL );
-		} else {
-			// no->send message to next hop
-			send( message, message->getDestinationNode() );
-		}
-	}
+		if (message->getDestinationNode() == nodeId)
+		{
+			logging_warn("Usually I should not route messages to myself. And I won't!");
+		}
+
+		// no->send message to next hop
+		else
+		{
+		    try
+		    {
+                /* (deep) packet inspection to determine priority */
+                // BRANCH: typeData  -->  send with low priority
+                if ( message->getType() == OverlayMsg::typeData )
+                {
+                    // TODO think about implementing explicit routing queue (with active queue management??)
+                    send( message,
+                          message->getDestinationNode(),
+                          message->getPriority(),
+                          last_hop );
+                }
+                // BRANCH: internal message  -->  send with higher priority
+                else
+                {
+                    send( message,
+                          message->getDestinationNode(),
+                          system_priority::HIGH,
+                          last_hop );
+                }
+		    }
+		    catch ( message_not_sent& e )
+		    {
+		        logging_warn("Unable to route message of type "
+		                << message->getType()
+		                << " to "
+		                << message->getDestinationNode()
+		                << ". Reason: "
+		                << e.what());
+		        
+		        // inform sender
+                if ( message->getType() != OverlayMsg::typeMessageLost )
+                {
+                    report_lost_message(message);
+                }
+		    }
+		}
+	}
+}
+
+void BaseOverlay::report_lost_message( const OverlayMsg* message )
+{
+    OverlayMsg reply(OverlayMsg::typeMessageLost);
+    reply.setSeqNum(message->getSeqNum());
+    
+    /**
+     * MessageLost-Message
+     * 
+     * - Type of lost message
+     * - Hop count of lost message
+     * - Source-LinkID  of lost message
+     */
+    reboost::shared_buffer_t b(sizeof(uint8_t)*2);
+    b.mutable_data()[0] = message->getType();
+    b.mutable_data()[1] = message->getNumHops();
+    reply.append_buffer(b);
+    reply.append_buffer(message->getSourceLink().serialize());
+    
+    try
+    {
+        send_node(&reply, message->getSourceNode(),
+                system_priority::OVERLAY,
+                OverlayInterface::OVERLAY_SERVICE_ID);
+    }
+    catch ( message_not_sent& e )
+    {
+        logging_warn("Tried to inform another node that we could'n route their message. But we were not able to send this error-message, too.");
+    }
 }
 
 /// sends a message to another node, delivers it to the base overlay class
-seqnum_t BaseOverlay::send( OverlayMsg* message, const NodeID& destination ) {
+seqnum_t BaseOverlay::send( OverlayMsg* message,
+        const NodeID& destination,
+        uint8_t priority,
+        const NodeID& last_hop ) throw(message_not_sent)
+{
 	LinkDescriptor* next_link = NULL;
 
 	// drop messages to unspecified destinations
-	if (destination.isUnspecified()) return -1;
-
-	// send messages to myself -> handle message and drop warning!
-	if (destination == nodeId) {
-		logging_warn("Sent message to myself. Handling message.")
-		Message msg;
-		msg.encapsulate(message);
-		handleMessage( &msg, NULL );
-		return -1;
+	if (destination.isUnspecified())
+	    throw message_not_sent("No destination specified. Drop!");
+
+	// send messages to myself -> drop!
+    // TODO maybe this is not what we want. why not just deliver this message?
+    //   There is a similar check in the route function, there it should be okay.
+	if (destination == nodeId)
+	{
+	    logging_warn("Sent message to myself. Drop!");
+	    
+	    throw message_not_sent("Sent message to myself. Drop!");
 	}
 
 	// use relay path?
-	if (message->isRelayed()) {
+	if (message->isRelayed())
+	{
 		next_link = getRelayLinkTo( destination );
-		if (next_link != NULL) {
+		
+		if (next_link != NULL)
+		{
 			next_link->setRelaying();
-			return bc->sendMessage(next_link->communicationId, message);
-		} else {
-			logging_warn("Could not send message. No relay hop found to "
-					<< destination << " -- trying to route over overlay paths ...")
-//			logging_error("ERROR: " << debugInformation() );
-		//			return -1;
-		}
-	}
-
+
+			// * send message over relayed link *
+			return send_overlaymessage_down(message, next_link->communicationId, priority);
+		}
+		else
+		{
+			logging_warn("No relay hop found to " << destination
+			        << " -- trying to route over overlay paths ...")
+		}
+	}
+
+	
 	// last resort -> route over overlay path
 	LinkID next_id = overlayInterface->getNextLinkId( destination );
-	if (next_id.isUnspecified()) {
-		logging_warn("Could not send message. No next hop found to " <<
-				destination );
-		logging_error("ERROR: " << debugInformation() );
-		return -1;
-	}
-
-	// get link descriptor, up and running? yes-> send message
+	if ( next_id.isUnspecified() )
+	{		
+        // apperently we're the closest node --> try second best node
+        //   NOTE: This is helpful if our routing table is not up-to-date, but 
+        //   may lead to circles. So we have to be careful.
+        std::vector<const LinkID*> next_ids = 
+            overlayInterface->getSortedLinkIdsTowardsNode( destination );
+            
+        for ( int i = 0; i < next_ids.size(); i++ )
+        {
+            const LinkID& link = *next_ids[i];
+            
+            if ( ! link.isUnspecified() )
+            {
+                next_id = link;
+                
+                break;
+            }
+        }
+     
+        // still no next hop found. drop.
+        if ( next_id.isUnspecified() )
+        {
+            logging_warn("Could not send message. No next hop found to " <<
+                destination );
+            logging_error("ERROR: " << debugInformation() );
+            
+            throw message_not_sent("No next hop found.");
+        }
+	}
+
+	
+	/* get link descriptor, do some checks and send message */
 	next_link = getDescriptor(next_id);
-	if (next_link != NULL && next_link->up) {
-		// send message over relayed link
-		return send(message, next_link);
-	}
-
-	// no-> error, dropping message
-	else {
-		logging_warn("Could not send message. Link not known or up");
-		logging_error("ERROR: " << debugInformation() );
-		return -1;
-	}
-
-	// not reached-> fail
-	return -1;
-}
+    
+    // check pointer
+    if ( next_link == NULL )
+    {
+        // NOTE: this shuldn't happen
+        throw message_not_sent("Could not send message. Link not known.");
+    }
+    
+    // avoid circles
+    if ( next_link->remoteNode == last_hop )
+    {
+        // XXX logging_debug
+        logging_info("Possible next hop would create a circle: "
+            << next_link->remoteNode);
+        
+        throw message_not_sent("Could not send message. Possible next hop would create a circle.");
+    }
+    
+    // check if link is up
+	if ( ! next_link->up)
+	{
+        logging_warn("Could not send message. Link not up");
+        logging_error("ERROR: " << debugInformation() );
+        
+        throw message_not_sent("Could not send message. Link not up");
+	}
+
+	// * send message over overlay link *
+	return send(message, next_link, priority);
+}
+
 
 /// send a message using a link descriptor, delivers it to the base overlay class
-seqnum_t BaseOverlay::send( OverlayMsg* message, LinkDescriptor* ldr, bool ignore_down ) {
+seqnum_t BaseOverlay::send( OverlayMsg* message,
+        LinkDescriptor* ldr,
+        uint8_t priority ) throw(message_not_sent)
+{
 	// check if null
-	if (ldr == NULL) {
-		logging_error("Can not send message to " << message->getDestinationAddress());
-		return -1;
+	if (ldr == NULL)
+	{
+        ostringstream out;
+        out << "Can not send message to " << message->getDestinationAddress();
+        throw message_not_sent(out.str());
 	}
 
 	// check if up
-	if (!ldr->up && !ignore_down) {
-		logging_error("Can not send message. Link not up:" << ldr );
+	if ( !ldr->up )
+	{
 		logging_error("DEBUG_INFO: " << debugInformation() );
-		return -1;
-	}
-	LinkDescriptor* ld = NULL;
-
-	// handle relayed link
-	if (ldr->relayed) {
+
+        ostringstream out;
+        out << "Can not send message. Link not up:" << ldr->to_string();
+        throw message_not_sent(out.str());
+	}
+	
+	LinkDescriptor* next_hop_ld = NULL;
+
+	// BRANCH: relayed link
+	if (ldr->relayed)
+	{
 		logging_debug("Resolving direct link for relayed link to "
 				<< ldr->remoteNode);
-		ld = getRelayLinkTo( ldr->remoteNode );
-		if (ld==NULL) {
-			logging_error("No relay path found to link " << ldr );
+		
+		next_hop_ld = getRelayLinkTo( ldr->remoteNode );
+		
+		if (next_hop_ld==NULL)
+		{
 			logging_error("DEBUG_INFO: " << debugInformation() );
-			return -1;
-		}
-		ld->setRelaying();
+			
+	        ostringstream out;
+	        out << "No relay path found to link: " << ldr;
+	        throw message_not_sent(out.str());
+		}
+		
+		next_hop_ld->setRelaying();
 		message->setRelayed(true);
-	} else
-		ld = ldr;
-
-	// handle direct link
-	if (ld->communicationUp) {
-		logging_debug("send(): Sending message over direct link.");
-		return bc->sendMessage( ld->communicationId, message );
-	} else {
-		logging_error("send(): Could not send message. "
-				"Not a relayed link and direct link is not up.");
-		return -1;
-	}
-	return -1;
+	}
+	// BRANCH: direct link
+	else
+	{
+		next_hop_ld = ldr;
+	}
+
+	
+	// check next hop-link
+	if ( ! next_hop_ld->communicationUp)
+	{
+	    throw message_not_sent( "send(): Could not send message."
+	            " Not a relayed link and direct link is not up." );
+	}
+
+	// send over next link
+    logging_debug("send(): Sending message over direct link.");
+    return send_overlaymessage_down(message, next_hop_ld->communicationId, priority);
+
 }
 
 seqnum_t BaseOverlay::send_node( OverlayMsg* message, const NodeID& remote,
-		const ServiceID& service) {
+        uint8_t priority, const ServiceID& service) throw(message_not_sent)
+{
 	message->setSourceNode(nodeId);
 	message->setDestinationNode(remote);
 	message->setService(service);
-	return send( message, remote );
-}
-
-seqnum_t BaseOverlay::send_link( OverlayMsg* message, const LinkID& link,bool ignore_down ) {
+	return send( message, remote, priority );
+}
+
+void BaseOverlay::send_link( OverlayMsg* message,
+        const LinkID& link,
+        uint8_t priority ) throw(message_not_sent)
+{
 	LinkDescriptor* ld = getDescriptor(link);
-	if (ld==NULL) {
-		logging_error("Cannot find descriptor to link id=" << link.toString());
-		return -1;
-	}
+	if (ld==NULL)
+	{
+	    throw message_not_sent("Cannot find descriptor to link id=" + link.toString());
+	}
+	
 	message->setSourceNode(nodeId);
 	message->setDestinationNode(ld->remoteNode);
@@ -437,5 +656,17 @@
 	message->setService(ld->service);
 	message->setRelayed(ld->relayed);
-	return send( message, ld, ignore_down );
+    
+    
+    try
+    {
+        // * send message *
+        send( message, ld, priority );
+    }
+    catch ( message_not_sent& e )
+    {
+        // drop failed link
+        ld->failed = true;
+        dropLink(ld->overlayId);
+    }
 }
 
@@ -451,6 +682,7 @@
 		// relay link still used and alive?
 		if (ld==NULL
-				|| !ld->isDirectVital()
-				|| difftime(route.used, time(NULL)) > 8) {
+				|| !isLinkDirectVital(ld)
+				|| difftime(route.used, time(NULL)) > KEEP_ALIVE_TIME_OUT)  // TODO this was set to 8 before.. Is the new timeout better?
+		{
 			logging_info("Forgetting relay information to node "
 					<< route.node.toString() );
@@ -488,5 +720,5 @@
 	if (message->isRelayed()) {
 		// try to find source node
-		BOOST_FOREACH( relay_route& route, relay_routes ) {
+		foreach( relay_route& route, relay_routes ) {
 			// relay route found? yes->
 			if ( route.node == message->getDestinationNode() ) {
@@ -504,5 +736,5 @@
 
 		// try to find source node
-		BOOST_FOREACH( relay_route& route, relay_routes ) {
+		foreach( relay_route& route, relay_routes ) {
 
 			// relay route found? yes->
@@ -516,8 +748,8 @@
 				if (route.hops > message->getNumHops()
 						|| rld == NULL
-						|| !rld->isDirectVital()) {
+						|| !isLinkDirectVital(ld)) {
 					logging_info("Updating relay information to node "
 							<< route.node.toString()
-							<< " reducing to " << message->getNumHops() << " hops.");
+							<< " reducing to " << (int) message->getNumHops() << " hops.");
 					route.hops = message->getNumHops();
 					route.link = ld->overlayId;
@@ -542,8 +774,8 @@
 LinkDescriptor* BaseOverlay::getRelayLinkTo( const NodeID& remote ) {
 	// try to find source node
-	BOOST_FOREACH( relay_route& route, relay_routes ) {
+	foreach( relay_route& route, relay_routes ) {
 		if (route.node == remote ) {
 			LinkDescriptor* ld = getDescriptor( route.link );
-			if (ld==NULL || !ld->isDirectVital()) return NULL; else {
+			if (ld==NULL || !isLinkDirectVital(ld)) return NULL; else {
 				route.used = time(NULL);
 				return ld;
@@ -575,9 +807,9 @@
 // ----------------------------------------------------------------------------
 
-void BaseOverlay::start( BaseCommunication& _basecomm, const NodeID& _nodeid ) {
+void BaseOverlay::start( BaseCommunication* _basecomm, const NodeID& _nodeid ) {
 	logging_info("Starting...");
 
 	// set parameters
-	bc = &_basecomm;
+	bc = _basecomm;
 	nodeId = _nodeid;
 
@@ -587,5 +819,6 @@
 
 	// timer for auto link management
-	Timer::setInterval( 1000 );
+	Timer::setInterval( 1000 ); // XXX
+//	Timer::setInterval( 10000 );
 	Timer::start();
 
@@ -641,5 +874,5 @@
 		overlayInterface->joinOverlay();
 		state = BaseOverlayStateCompleted;
-		BOOST_FOREACH( NodeListener* i, nodeListeners )
+		foreach( NodeListener* i, nodeListeners )
 			i->onJoinCompleted( spovnetId );
 
@@ -682,5 +915,6 @@
 	// gather all service links
 	vector<LinkID> servicelinks;
-	BOOST_FOREACH( LinkDescriptor* ld, links ) {
+	foreach( LinkDescriptor* ld, links )
+	{
 		if( ld->service != OverlayInterface::OVERLAY_SERVICE_ID )
 			servicelinks.push_back( ld->overlayId );
@@ -688,15 +922,23 @@
 
 	// drop all service links
-	BOOST_FOREACH( LinkID lnk, servicelinks )
-	dropLink( lnk );
+	foreach( LinkID lnk, servicelinks )
+	{
+	    logging_debug("Dropping service link " << lnk.toString());
+	    dropLink( lnk );
+	}
 
 	// let the node leave the spovnet overlay interface
 	logging_debug( "Leaving overlay" );
 	if( overlayInterface != NULL )
+	{
 		overlayInterface->leaveOverlay();
+	}
 
 	// drop still open bootstrap links
-	BOOST_FOREACH( LinkID lnk, bootstrapLinks )
-	bc->dropLink( lnk );
+	foreach( LinkID lnk, bootstrapLinks )
+	{
+	    logging_debug("Dropping bootstrap link " << lnk.toString());
+	    bc->dropLink( lnk );
+	}
 
 	// change to inalid state
@@ -708,5 +950,6 @@
 
 	// inform all registered services of the event
-	BOOST_FOREACH( NodeListener* i, nodeListeners ) {
+	foreach( NodeListener* i, nodeListeners )
+	{
 		if( ret ) i->onLeaveCompleted( spovnetId );
 		else i->onLeaveFailed( spovnetId );
@@ -731,5 +974,5 @@
 		state = BaseOverlayStateInvalid;
 
-		BOOST_FOREACH( NodeListener* i, nodeListeners )
+		foreach( NodeListener* i, nodeListeners )
 		i->onJoinFailed( spovnetId );
 
@@ -783,7 +1026,11 @@
 		const ServiceID& service ) {
 
+    // TODO What if we already have a Link to this node and this service id?
+    
 	// do not establish a link to myself!
-	if (remote == nodeId) return LinkID::UNSPECIFIED;
-
+	if (remote == nodeId) return 
+	        LinkID::UNSPECIFIED;
+
+	
 	// create a link descriptor
 	LinkDescriptor* ld = addDescriptor();
@@ -792,4 +1039,8 @@
 	ld->service = service;
 	ld->listener = getListener(ld->service);
+    
+    // initialize sequence numbers
+    ld->last_sent_seqnum = SequenceNumber::createRandomSeqNum_Short();
+    logging_debug("Creating new link with initial SeqNum: " << ld->last_sent_seqnum);
 
 	// create link request message
@@ -800,4 +1051,7 @@
 	msg.setRelayed(true);
 	msg.setRegisterRelay(true);
+//	msg.setRouteRecord(true);
+    
+    msg.setSeqNum(ld->last_sent_seqnum);
 
 	// debug message
@@ -809,17 +1063,71 @@
 	);
 
+	
 	// sending message to node
-	send_node( &msg, ld->remoteNode, ld->service );
-
+	try
+	{
+	    // * send *
+	    seqnum_t seq = send_node( &msg, ld->remoteNode, system_priority::OVERLAY, ld->service );
+	}
+	catch ( message_not_sent& e )
+	{
+	    logging_warn("Link request not sent: " << e.what());
+	    
+	    // Message not sent. Cancel link request.
+	    SystemQueue::instance().scheduleCall(
+	            boost::bind(
+	                    &BaseOverlay::__onLinkEstablishmentFailed,
+	                    this,
+	                    ld->overlayId)
+	        );
+	}
+	
 	return ld->overlayId;
 }
 
+/// NOTE: "id" is an Overlay-LinkID
+void BaseOverlay::__onLinkEstablishmentFailed(const LinkID& id)
+{
+    // TODO This code redundant. But also it's not easy to aggregate in one function.
+    
+    // get descriptor for link
+    LinkDescriptor* ld = getDescriptor(id, false);
+    if ( ld == NULL ) return; // not found? ->ignore!
+
+    logging_debug( "__onLinkEstablishmentFaild: " << ld );
+
+    // removing relay link information
+    removeRelayLink(ld->overlayId);
+
+    // inform listeners about link down
+    ld->communicationUp = false;
+    if (!ld->service.isUnspecified())
+    {
+        CommunicationListener* lst = getListener(ld->service);
+        if(lst != NULL) lst->onLinkFail( ld->overlayId, ld->remoteNode );
+        sideport->onLinkFail( id, this->nodeId, ld->remoteNode, this->spovnetId );
+    }
+
+    // delete all queued messages (auto links)
+    if( ld->messageQueue.size() > 0 ) {
+        logging_warn( "Dropping link " << id.toString() << " that has "
+                << ld->messageQueue.size() << " waiting messages" );
+        ld->flushQueue();
+    }
+
+    // erase mapping
+    eraseDescriptor(ld->overlayId);
+}
+
+
 /// drops an established link
-void BaseOverlay::dropLink(const LinkID& link) {
-	logging_info( "Dropping link (initiated locally):" << link.toString() );
+void BaseOverlay::dropLink(const LinkID& link)
+{
+	logging_info( "Dropping link: " << link.toString() );
 
 	// find the link item to drop
 	LinkDescriptor* ld = getDescriptor(link);
-	if( ld == NULL ) {
+	if( ld == NULL )
+	{
 		logging_warn( "Can't drop link, link is unknown!");
 		return;
@@ -827,25 +1135,73 @@
 
 	// delete all queued messages
-	if( ld->messageQueue.size() > 0 ) {
+	if( ld->messageQueue.size() > 0 )
+	{
 		logging_warn( "Dropping link " << ld->overlayId.toString() << " that has "
 				<< ld->messageQueue.size() << " waiting messages" );
 		ld->flushQueue();
 	}
-
-	// inform sideport and listener
-	if(ld->listener != NULL)
-		ld->listener->onLinkDown( ld->overlayId, ld->remoteNode );
-	sideport->onLinkDown(ld->overlayId, this->nodeId, ld->remoteNode, this->spovnetId );
-
-	// do not drop relay links
-	if (!ld->relaying) {
-		// drop the link in base communication
-		if (ld->communicationUp) bc->dropLink( ld->communicationId );
-
-		// erase descriptor
-		eraseDescriptor( ld->overlayId );
-	} else {
-		ld->dropAfterRelaying = true;
-	}
+	
+	    
+	// inform application and remote note (but only once)
+	//   NOTE: If we initiated the drop, this function is called twice, but on 
+	//   the second call, there is noting to do.
+	if ( ld->up && ! ld->failed )
+	{
+        // inform sideport and listener
+        if(ld->listener != NULL)
+        {
+            ld->listener->onLinkDown( ld->overlayId, ld->remoteNode );
+        }
+        sideport->onLinkDown(ld->overlayId, this->nodeId, ld->remoteNode, this->spovnetId );
+	
+        // send link-close to remote node
+        logging_info("Sending LinkClose message to remote node.");
+        OverlayMsg close_msg(OverlayMsg::typeLinkClose);
+        send_link(&close_msg, link, system_priority::OVERLAY);
+    
+        // deactivate link
+        ld->up = false;
+//         ld->closing = true;
+	}
+	
+	else if ( ld->failed )
+    {
+        // inform listener
+        if( ld->listener != NULL )
+        {
+            ld->listener->onLinkFail( ld->overlayId, ld->remoteNode );
+        }
+        
+        ld->up = false;
+        __removeDroppedLink(ld->overlayId);
+    }
+}
+
+/// called from typeLinkClose-handler
+void BaseOverlay::__removeDroppedLink(const LinkID& link)
+{
+    // find the link item to drop
+    LinkDescriptor* ld = getDescriptor(link);
+    if( ld == NULL )
+    {
+        return;
+    }
+
+    // do not drop relay links
+    if (!ld->relaying)
+    {
+        // drop the link in base communication
+        if (ld->communicationUp)
+        {
+            bc->dropLink( ld->communicationId );
+        }
+
+        // erase descriptor
+        eraseDescriptor( ld->overlayId );
+    }
+    else
+    {
+        ld->dropAfterRelaying = true;
+    }
 }
 
@@ -853,40 +1209,86 @@
 
 /// internal send message, always use this functions to send messages over links
-seqnum_t BaseOverlay::sendMessage( const Message* message, const LinkID& link ) {
+const SequenceNumber& BaseOverlay::sendMessage( reboost::message_t message,
+        const LinkID& link,
+        uint8_t priority ) throw(message_not_sent)
+{
 	logging_debug( "Sending data message on link " << link.toString() );
 
 	// get the mapping for this link
 	LinkDescriptor* ld = getDescriptor(link);
-	if( ld == NULL ) {
-		logging_error("Could not send message. "
-				<< "Link not found id=" << link.toString());
-		return -1;
+	if( ld == NULL )
+	{
+	    throw message_not_sent("Could not send message. Link not found id=" + link.toString());
 	}
 
 	// check if the link is up yet, if its an auto link queue message
-	if( !ld->up ) {
+	if( !ld->up )
+	{
 		ld->setAutoUsed();
-		if( ld->autolink ) {
+		if( ld->autolink )
+		{
 			logging_info("Auto-link " << link.toString() << " not up, queue message");
-			Data data = data_serialize( message );
-			const_cast<Message*>(message)->dropPayload();
-			ld->messageQueue.push_back( new Message(data) );
-		} else {
-			logging_error("Link " << link.toString() << " not up, drop message");
-		}
-		return -1;
-	}
-
-	// compile overlay message (has service and node id)
-	OverlayMsg overmsg( OverlayMsg::typeData );
-	overmsg.encapsulate( const_cast<Message*>(message) );
-
-	// send message over relay/direct/overlay
-	return send_link( &overmsg, ld->overlayId );
-}
-
-
-seqnum_t BaseOverlay::sendMessage(const Message* message,
-		const NodeID& node, const ServiceID& service) {
+			
+			// queue message
+	        LinkDescriptor::message_queue_entry msg;
+	        msg.message = message;
+	        msg.priority = priority;
+
+			ld->messageQueue.push_back( msg );
+			
+			return SequenceNumber::DISABLED;  // TODO what to return if message is queued?
+		}
+		else
+		{
+		    throw message_not_sent("Link " + link.toString() + " not up, drop message");
+		}
+	}
+	
+	// TODO AKTUELL: sequence numbers
+	// TODO seqnum on fast path ?
+	ld->last_sent_seqnum.increment();
+	
+	/* choose fast-path for direct links; normal overlay-path otherwise */
+	// BRANCH: direct link
+	if ( ld->communicationUp && !ld->relayed )
+	{
+	    // * send down to BaseCommunication *
+	    try
+	    {
+	        bc->sendMessage(ld->communicationId, message, priority, true);
+        }
+        catch ( communication::communication_message_not_sent& e )
+        {
+            ostringstream out;
+            out << "Communication message on fast-path not sent: " << e.what();
+            throw message_not_sent(out.str());
+        }
+	}
+
+	// BRANCH: use (slow) overlay-path
+	else
+	{
+        // compile overlay message (has service and node id)
+        OverlayMsg overmsg( OverlayMsg::typeData );
+        overmsg.set_payload_message(message);
+        
+        // set SeqNum
+        if ( ld->transmit_seqnums )
+        {
+            overmsg.setSeqNum(ld->last_sent_seqnum);
+        }
+        logging_debug("Sending Message with SeqNum: " << overmsg.getSeqNum());
+    
+        // send message over relay/direct/overlay
+        send_link( &overmsg, ld->overlayId, priority );
+	}
+	
+	// return seqnum
+ 	return ld->last_sent_seqnum;
+}
+
+
+const SequenceNumber& BaseOverlay::sendMessage(reboost::message_t message,
+		const NodeID& node, uint8_t priority, const ServiceID& service) {
 
 	// find link for node and service
@@ -907,5 +1309,5 @@
 		if( ld == NULL ) {
 			logging_error( "Failed to establish auto-link.");
-			return -1;
+            throw message_not_sent("Failed to establish auto-link.");
 		}
 		ld->autolink = true;
@@ -920,10 +1322,10 @@
 
 	// send / queue message
-	return sendMessage( message, ld->overlayId );
-}
-
-
-NodeID BaseOverlay::sendMessageCloserToNodeID(const Message* message,
-        const NodeID& address, const ServiceID& service) {
+	return sendMessage( message, ld->overlayId, priority );
+}
+
+
+NodeID BaseOverlay::sendMessageCloserToNodeID(reboost::message_t message,
+        const NodeID& address, uint8_t priority, const ServiceID& service) {
     
     if ( overlayInterface->isClosestNodeTo(address) )
@@ -936,8 +1338,8 @@
     if ( closest_node != NodeID::UNSPECIFIED )
     {
-        seqnum_t seqnum = sendMessage(message, closest_node, service);
+        sendMessage(message, closest_node, priority, service);
     }
     
-    return closest_node;  // XXX return seqnum ?? tuple? closest_node via (non const) reference?
+    return closest_node;  // return seqnum ?? tuple? closest_node via (non const) reference?
 }
 // ----------------------------------------------------------------------------
@@ -978,5 +1380,5 @@
 
 	// see if we can find the node in our own table
-	BOOST_FOREACH(const LinkDescriptor* ld, links){
+	foreach(const LinkDescriptor* ld, links){
 		if(ld->remoteNode != node) continue;
 		if(!ld->communicationUp) continue;
@@ -1079,5 +1481,6 @@
 
 void BaseOverlay::onLinkUp(const LinkID& id,
-		const address_v* local, const address_v* remote) {
+        const addressing2::EndpointPtr local, const addressing2::EndpointPtr remote)
+{
 	logging_debug( "Link up with base communication link id=" << id );
 
@@ -1085,8 +1488,9 @@
 	LinkDescriptor* ld = getDescriptor(id, true);
 
-	// handle bootstrap link we initiated
+	// BRANCH: 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. " <<
+				"LinkID: " << id.toString() <<
 				"Sending out join request for SpoVNet " << spovnetId.toString()
 		);
@@ -1096,10 +1500,12 @@
 				OverlayInterface::OVERLAY_SERVICE_ID, nodeId );
 		JoinRequest joinRequest( spovnetId, nodeId );
-		overlayMsg.encapsulate( &joinRequest );
-		bc->sendMessage( id, &overlayMsg );
+		overlayMsg.append_buffer(joinRequest.serialize_into_shared_buffer());
+
+		send_overlaymessage_down(&overlayMsg, id, system_priority::OVERLAY);
+		
 		return;
 	}
 
-	// no link found? -> link establishment from remote, add one!
+	// BRANCH: link establishment from remote, add one!
 	if (ld == NULL) {
 		ld = addDescriptor( id );
@@ -1115,7 +1521,9 @@
 		// in this case, do not inform listener, since service it unknown
 		// -> wait for update message!
-
-		// link mapping found? -> send update message with node-id and service id
-	} else {
+	}
+	
+	// BRANCH: We requested this link in the first place
+	else
+	{
 		logging_info( "onLinkUp descriptor (initiated locally):" << ld );
 
@@ -1126,14 +1534,34 @@
 		ld->fromRemote = false;
 
-		// if link is a relayed link->convert to direct link
-		if (ld->relayed) {
-			logging_info( "Converting to direct link: " << ld );
+		// BRANCH: this was a relayed link before --> convert to direct link
+		//   TODO do we really have to send a message here?
+		if (ld->relayed)
+		{
 			ld->up = true;
 			ld->relayed = false;
+			logging_info( "Converting to direct link: " << ld );
+			
+			// send message
 			OverlayMsg overMsg( OverlayMsg::typeLinkDirect );
 			overMsg.setSourceLink( ld->overlayId );
 			overMsg.setDestinationLink( ld->remoteLink );
-			send_link( &overMsg, ld->overlayId );
-		} else {
+			send_link( &overMsg, ld->overlayId, system_priority::OVERLAY );
+			
+		    // inform listener
+		    if( ld->listener != NULL)
+		        ld->listener->onLinkChanged( ld->overlayId, ld->remoteNode );
+		}
+		
+
+        /* NOTE: Chord is opening direct-links in it's setup routine which are
+         *   neither set to "relayed" nor to "up". To activate these links a
+         *   typeLinkUpdate must be sent.
+         *   
+         * This branch is would also be taken when we had a working link before 
+         *   (ld->up == true). I'm not sure if this case does actually happen 
+         *   and whether it's tested.
+         */
+		else
+		{
 			// note: necessary to validate the link on the remote side!
 			logging_info( "Sending out update" <<
@@ -1144,7 +1572,15 @@
 			// compile and send update message
 			OverlayMsg overlayMsg( OverlayMsg::typeLinkUpdate );
-			overlayMsg.setSourceLink(ld->overlayId);
 			overlayMsg.setAutoLink( ld->autolink );
-			send_link( &overlayMsg, ld->overlayId, true );
+		    overlayMsg.setSourceNode(nodeId);
+		    overlayMsg.setDestinationNode(ld->remoteNode);
+		    overlayMsg.setSourceLink(ld->overlayId);
+		    overlayMsg.setDestinationLink(ld->remoteLink);
+		    overlayMsg.setService(ld->service);
+		    overlayMsg.setRelayed(false);
+
+		    // TODO ld->communicationId = id ??
+		    
+		    send_overlaymessage_down(&overlayMsg, id, system_priority::OVERLAY);
 		}
 	}
@@ -1152,6 +1588,7 @@
 
 void BaseOverlay::onLinkDown(const LinkID& id,
-		const address_v* local, const address_v* remote) {
-
+        const addressing2::EndpointPtr local,
+        const addressing2::EndpointPtr remote)
+{
 	// erase bootstrap links
 	vector<LinkID>::iterator it = std::find( bootstrapLinks.begin(), bootstrapLinks.end(), id );
@@ -1185,61 +1622,111 @@
 }
 
+
+void BaseOverlay::onLinkFail(const LinkID& id,
+        const addressing2::EndpointPtr local,
+        const addressing2::EndpointPtr 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
+//	LinkDescriptor* ld = getDescriptor(id, true);
+//	if ( ld == NULL ) return; // not found? ->ignore!
+//	logging_debug( "Link failed id=" << ld->overlayId.toString() );
+//
+//	// inform listeners
+//	ld->listener->onLinkFail( ld->overlayId, ld->remoteNode );
+//	sideport->onLinkFail( id, this->nodeId, ld->remoteNode, this->spovnetId );
+	
+	logging_debug( "  ... calling onLinkDown ..." );
+	onLinkDown(id, local, remote);
+}
+
+
 void BaseOverlay::onLinkChanged(const LinkID& id,
-		const address_v* oldlocal, const address_v* newlocal,
-		const address_v* oldremote, const address_v* newremote) {
-
-	// get descriptor for link
-	LinkDescriptor* ld = getDescriptor(id, true);
-	if ( ld == NULL ) return; // not found? ->ignore!
-	logging_debug( "onLinkChanged descriptor: " << ld );
-
-	// inform listeners
-	ld->listener->onLinkChanged( ld->overlayId, ld->remoteNode );
-	sideport->onLinkChanged( id, this->nodeId, ld->remoteNode, this->spovnetId );
-
-	// autolinks: refresh timestamp
-	ld->setAutoUsed();
-}
-
-void BaseOverlay::onLinkFail(const LinkID& id,
-		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
-	LinkDescriptor* ld = getDescriptor(id, true);
-	if ( ld == NULL ) return; // not found? ->ignore!
-	logging_debug( "Link failed id=" << ld->overlayId.toString() );
-
-	// inform listeners
-	ld->listener->onLinkFail( ld->overlayId, ld->remoteNode );
-	sideport->onLinkFail( id, this->nodeId, ld->remoteNode, this->spovnetId );
-}
-
-void BaseOverlay::onLinkQoSChanged(const LinkID& id, const address_v* local,
-		const address_v* remote, const QoSParameterSet& qos) {
-	logging_debug( "Link quality changed with base communication link id=" << id );
-
-	// get descriptor for link
-	LinkDescriptor* ld = getDescriptor(id, true);
-	if ( ld == NULL ) return; // not found? ->ignore!
-	logging_debug( "Link quality changed id=" << ld->overlayId.toString() );
-}
-
-bool BaseOverlay::onLinkRequest( const LinkID& id, const address_v* local,
-		const address_v* remote ) {
+        const addressing2::EndpointPtr oldlocal,  const addressing2::EndpointPtr newlocal,
+        const addressing2::EndpointPtr oldremote, const addressing2::EndpointPtr newremote)
+{
+    // get descriptor for link
+    LinkDescriptor* ld = getDescriptor(id, true);
+    if ( ld == NULL ) return; // not found? ->ignore!
+    logging_debug( "onLinkChanged descriptor: " << ld );
+
+    // inform listeners
+    ld->listener->onLinkChanged( ld->overlayId, ld->remoteNode );
+    sideport->onLinkChanged( id, this->nodeId, ld->remoteNode, this->spovnetId );
+
+    // autolinks: refresh timestamp
+    ld->setAutoUsed();
+}
+
+//void BaseOverlay::onLinkQoSChanged(const LinkID& id,
+//        const addressing2::EndpointPtr local, const addressing2::EndpointPtr remote,
+//        const QoSParameterSet& qos)
+//{
+//	logging_debug( "Link quality changed with base communication link id=" << id );
+//
+//	// get descriptor for link
+//	LinkDescriptor* ld = getDescriptor(id, true);
+//	if ( ld == NULL ) return; // not found? ->ignore!
+//	logging_debug( "Link quality changed id=" << ld->overlayId.toString() );
+//}
+
+bool BaseOverlay::onLinkRequest(const LinkID& id,
+        const addressing2::EndpointPtr local,
+        const addressing2::EndpointPtr remote)
+{
 	logging_debug("Accepting link request from " << remote->to_string() );
+	
+	// TODO ask application..?
+	
 	return true;
 }
 
+
+
+
 /// handles a message from base communication
-bool BaseOverlay::receiveMessage(const Message* message,
-		const LinkID& link, const NodeID& ) {
+bool BaseOverlay::receiveMessage( reboost::shared_buffer_t message,
+		const LinkID& link,
+		const NodeID&,
+		bool bypass_overlay )
+{
 	// get descriptor for link
 	LinkDescriptor* ld = getDescriptor( link, true );
-	return handleMessage( message, ld, link );
+
+	
+	/* choose fastpath for direct links; normal overlay-path otherwise */	
+	if ( bypass_overlay && ld )
+	{
+        // message received --> link is alive
+        ld->keepAliveReceived = time(NULL);
+        // hop count on this link
+        ld->hops = 0;
+
+        
+        // hand over to CommunicationListener (aka Application) 
+	    CommunicationListener* lst = getListener(ld->service);
+	    if ( lst != NULL )
+	    {
+	        lst->onMessage(
+	                message,
+	                ld->remoteNode,
+	                ld->overlayId,
+                    SequenceNumber::DISABLED,
+	                NULL );
+	        
+	        return true;
+	    }
+
+	    return false;
+	}
+	else
+	{
+	    return handleMessage( message, ld, link );	    
+	}
 }
 
@@ -1247,17 +1734,19 @@
 
 /// Handle spovnet instance join requests
-bool BaseOverlay::handleJoinRequest( OverlayMsg* overlayMsg, const LinkID& bcLink ) {
-
+bool BaseOverlay::handleJoinRequest( reboost::shared_buffer_t message, const NodeID& source, const LinkID& bcLink )
+{
 	// decapsulate message
-	JoinRequest* joinReq = overlayMsg->decapsulate<JoinRequest>();
+	JoinRequest joinReq;
+	joinReq.deserialize_from_shared_buffer(message);
+	
 	logging_info( "Received join request for spovnet " <<
-			joinReq->getSpoVNetID().toString() );
+			joinReq.getSpoVNetID().toString() );
 
 	// check spovnet id
-	if( joinReq->getSpoVNetID() != spovnetId ) {
+	if( joinReq.getSpoVNetID() != spovnetId ) {
 		logging_error(
 				"Received join request for spovnet we don't handle " <<
-				joinReq->getSpoVNetID().toString() );
-		delete joinReq;
+				joinReq.getSpoVNetID().toString() );
+
 		return false;
 	}
@@ -1267,7 +1756,7 @@
 	logging_info( "Sending join reply for spovnet " <<
 			spovnetId.toString() << " to node " <<
-			overlayMsg->getSourceNode().toString() <<
+			source.toString() <<
 			". Result: " << (allow ? "allowed" : "denied") );
-	joiningNodes.push_back( overlayMsg->getSourceNode() );
+	joiningNodes.push_back( source );
 
 	// return overlay parameters
@@ -1276,32 +1765,44 @@
 			<< getEndpointDescriptor().toString() )
 	OverlayParameterSet parameters = overlayInterface->getParameters();
+	
+	
+	// create JoinReplay Message
 	OverlayMsg retmsg( OverlayMsg::typeJoinReply,
 			OverlayInterface::OVERLAY_SERVICE_ID, nodeId );
-	JoinReply replyMsg( spovnetId, parameters,
-			allow, getEndpointDescriptor() );
-	retmsg.encapsulate(&replyMsg);
-	bc->sendMessage( bcLink, &retmsg );
-
-	delete joinReq;
+	JoinReply replyMsg( spovnetId, parameters, allow );
+	retmsg.append_buffer(replyMsg.serialize_into_shared_buffer());
+
+	// XXX This is unlovely clash between the old message system and the new one,
+	// but a.t.m. we can't migrate everything to the new system at once..
+	// ---> Consider the EndpointDescriptor as part of the JoinReply..
+	retmsg.append_buffer(getEndpointDescriptor().serialize());
+	
+	// * send *
+	send_overlaymessage_down(&retmsg, bcLink, system_priority::OVERLAY);
+
 	return true;
 }
 
 /// Handle replies to spovnet instance join requests
-bool BaseOverlay::handleJoinReply( OverlayMsg* overlayMsg, const LinkID& bcLink ) {
+bool BaseOverlay::handleJoinReply( reboost::shared_buffer_t message, const LinkID& bcLink )
+{
 	// decapsulate message
 	logging_debug("received join reply message");
-	JoinReply* replyMsg = overlayMsg->decapsulate<JoinReply>();
+	JoinReply replyMsg;
+	EndpointDescriptor endpoints;
+	reboost::shared_buffer_t buff = replyMsg.deserialize_from_shared_buffer(message);
+	buff = endpoints.deserialize(buff);
 
 	// correct spovnet?
-	if( replyMsg->getSpoVNetID() != spovnetId ) { // no-> fail
+	if( replyMsg.getSpoVNetID() != spovnetId ) { // no-> fail
 		logging_error( "Received SpoVNet join reply for " <<
-				replyMsg->getSpoVNetID().toString() <<
+				replyMsg.getSpoVNetID().toString() <<
 				" != " << spovnetId.toString() );
-		delete replyMsg;
+
 		return false;
 	}
 
 	// access granted? no -> fail
-	if( !replyMsg->getJoinAllowed() ) {
+	if( !replyMsg.getJoinAllowed() ) {
 		logging_error( "Our join request has been denied" );
 
@@ -1317,8 +1818,7 @@
 
 		// inform all registered services of the event
-		BOOST_FOREACH( NodeListener* i, nodeListeners )
+		foreach( NodeListener* i, nodeListeners )
 		i->onJoinFailed( spovnetId );
 
-		delete replyMsg;
 		return true;
 	}
@@ -1329,5 +1829,5 @@
 
 	logging_debug( "Using bootstrap end-point "
-			<< replyMsg->getBootstrapEndpoint().toString() );
+			<< endpoints.toString() );
 
 	// create overlay structure from spovnet parameter set
@@ -1338,5 +1838,5 @@
 
 		overlayInterface = OverlayFactory::create(
-				*this, replyMsg->getParam(), nodeId, this );
+				*this, replyMsg.getParam(), nodeId, this );
 
 		// overlay structure supported? no-> fail!
@@ -1354,8 +1854,7 @@
 
 			// inform all registered services of the event
-			BOOST_FOREACH( NodeListener* i, nodeListeners )
+			foreach( NodeListener* i, nodeListeners )
 			i->onJoinFailed( spovnetId );
 
-			delete replyMsg;
 			return true;
 		}
@@ -1365,6 +1864,6 @@
 		overlayInterface->createOverlay();
 
-		overlayInterface->joinOverlay( replyMsg->getBootstrapEndpoint() );
-		overlayBootstrap.recordJoin( replyMsg->getBootstrapEndpoint() );
+		overlayInterface->joinOverlay( endpoints );
+		overlayBootstrap.recordJoin( endpoints );
 
 		// update ovlvis
@@ -1372,18 +1871,13 @@
 
 		// inform all registered services of the event
-		BOOST_FOREACH( NodeListener* i, nodeListeners )
-		i->onJoinCompleted( spovnetId );
-
-		delete replyMsg;
-
-	} else {
-
+		foreach( NodeListener* i, nodeListeners )
+		    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() );
-		overlayBootstrap.recordJoin( replyMsg->getBootstrapEndpoint() );
-
-		delete replyMsg;
-
+		overlayInterface->joinOverlay( endpoints );
+		overlayBootstrap.recordJoin( endpoints );
 	} // if( overlayInterface == NULL )
 
@@ -1392,7 +1886,9 @@
 
 
-bool BaseOverlay::handleData( OverlayMsg* overlayMsg, LinkDescriptor* ld ) {
+bool BaseOverlay::handleData( reboost::shared_buffer_t message, OverlayMsg* overlayMsg, LinkDescriptor* ld )
+{
 	// get service
-	const ServiceID& service = overlayMsg->getService();
+	const ServiceID& service = ld->service; //overlayMsg->getService();
+
 	logging_debug( "Received data for service " << service.toString()
 			<< " on link " << overlayMsg->getDestinationLink().toString() );
@@ -1402,7 +1898,11 @@
 	if(lst != NULL){
 		lst->onMessage(
-				overlayMsg,
-				overlayMsg->getSourceNode(),
-				overlayMsg->getDestinationLink()
+				message,
+//				overlayMsg->getSourceNode(),
+//				overlayMsg->getDestinationLink(),
+				ld->remoteNode,
+				ld->overlayId,
+                overlayMsg->getSeqNum(),
+				overlayMsg
 		);
 	}
@@ -1411,4 +1911,105 @@
 }
 
+bool BaseOverlay::handleLostMessage( reboost::shared_buffer_t message, OverlayMsg* msg )
+{
+    /**
+     * Deserialize MessageLost-Message
+     * 
+     * - Type of lost message
+     * - Hop count of lost message
+     * - Source-LinkID  of lost message
+     */
+    const uint8_t* buff = message(0, sizeof(uint8_t)*2).data();
+    uint8_t type = buff[0];
+    uint8_t hops = buff[1];
+    LinkID linkid;
+    linkid.deserialize(message(sizeof(uint8_t)*2));
+    
+    logging_warn("Node " << msg->getSourceNode()
+            << " informed us, that our message of type " << (int) type
+            << " is lost after traveling " << (int) hops << " hops."
+            << " (LinkID: " << linkid.toString());
+
+    
+    // TODO switch-case ?
+    
+    // BRANCH: LinkRequest --> link request failed
+    if ( type == OverlayMsg::typeLinkRequest )
+    {
+        __onLinkEstablishmentFailed(linkid);
+    }
+    
+    // BRANCH: Data --> link disrupted. Drop link.
+    //   (We could use something more advanced here. e.g. At least send a 
+    //    keep-alive message and wait for a keep-alive reply.)
+    if ( type == OverlayMsg::typeData )
+    {
+        LinkDescriptor* link_desc = getDescriptor(linkid);
+        
+        if ( link_desc )
+        {
+            link_desc->failed = true;
+        }
+        
+        dropLink(linkid);
+    }
+    
+    // BRANCH: ping lost
+    if ( type == OverlayMsg::typePing )
+    {
+        CommunicationListener* lst = getListener(msg->getService());
+        if( lst != NULL )
+        {
+            lst->onPingLost(msg->getSourceNode());
+        }
+    }
+    
+    return true;
+}
+
+bool BaseOverlay::handlePing( OverlayMsg* overlayMsg, LinkDescriptor* ld )
+{
+    // TODO AKTUELL: implement interfaces: Node::ping(node); BaseOverlay::ping(node)
+    
+    bool send_pong = false;
+    
+    // inform application and ask permission to send a pong message
+    CommunicationListener* lst = getListener(overlayMsg->getService());
+    if( lst != NULL )
+    {
+        send_pong = lst->onPing(overlayMsg->getSourceNode());
+    }
+    
+    // send pong message if allowed
+    if ( send_pong )
+    {
+        OverlayMsg pong_msg(OverlayMsg::typePong);
+        pong_msg.setSeqNum(overlayMsg->getSeqNum());
+        
+        // send message
+        try
+        {
+            send_node( &pong_msg, 
+                overlayMsg->getSourceNode(), 
+                system_priority::OVERLAY,
+                overlayMsg->getService() );
+        }
+        catch ( message_not_sent& e )
+        {
+            logging_info("Could not send Pong-Message to node: " << 
+                overlayMsg->getSourceNode());
+        }
+    }
+}
+
+bool BaseOverlay::handlePong( OverlayMsg* overlayMsg, LinkDescriptor* ld )
+{
+    // inform application
+    CommunicationListener* lst = getListener(overlayMsg->getService());
+    if( lst != NULL )
+    {
+        lst->onPong(overlayMsg->getSourceNode());
+    }
+}
 
 bool BaseOverlay::handleLinkUpdate( OverlayMsg* overlayMsg, LinkDescriptor* ld ) {
@@ -1439,5 +2040,5 @@
 		overlayMsg->setSourceLink(ld->overlayId);
 		overlayMsg->setService(ld->service);
-		send( overlayMsg, ld );
+		send( overlayMsg, ld, system_priority::OVERLAY );
 	}
 
@@ -1481,8 +2082,8 @@
 	if( ld->messageQueue.size() > 0 ) {
 		logging_info( "Sending out queued messages on link " << ld );
-		BOOST_FOREACH( Message* msg, ld->messageQueue ) {
-			sendMessage( msg, ld->overlayId );
-			delete msg;
-		}
+        foreach( LinkDescriptor::message_queue_entry msg, ld->messageQueue )
+        {
+            sendMessage( msg.message, ld->overlayId, msg.priority );
+        }
 		ld->messageQueue.clear();
 	}
@@ -1497,5 +2098,4 @@
 /// handle a link request and reply
 bool BaseOverlay::handleLinkRequest( OverlayMsg* overlayMsg, LinkDescriptor* ld ) {
-	logging_info( "Link request received from node id=" << overlayMsg->getSourceNode() );
 
 	//TODO: Check if a request has already been sent using getSourceLink() ...
@@ -1514,16 +2114,33 @@
 	ldn->remoteNode = overlayMsg->getSourceNode();
 	ldn->remoteLink = overlayMsg->getSourceLink();
-
+	ldn->hops = overlayMsg->getNumHops();
+	
+    // initialize sequence numbers
+    ldn->last_sent_seqnum = SequenceNumber::createRandomSeqNum_Short();
+    logging_debug("Creating new link with initial SeqNum: " << ldn->last_sent_seqnum);
+    
+    
 	// update time-stamps
 	ldn->setAlive();
 	ldn->setAutoUsed();
 
+	logging_info( "Link request received from node id="
+	        << overlayMsg->getSourceNode()
+	        << " LINK: "
+	        << ldn);
+	
 	// create reply message and send back!
 	overlayMsg->swapRoles(); // swap source/destination
 	overlayMsg->setType(OverlayMsg::typeLinkReply);
 	overlayMsg->setSourceLink(ldn->overlayId);
-	overlayMsg->setSourceEndpoint( bc->getEndpointDescriptor() );
 	overlayMsg->setRelayed(true);
-	send( overlayMsg, ld ); // send back to link
+//	overlayMsg->setRouteRecord(true);
+    overlayMsg->setSeqNum(ld->last_sent_seqnum);
+	
+	// TODO aktuell do the same thing in the typeLinkRequest-Message, too. But be careful with race conditions!!
+	// append our endpoints (for creation of a direct link)
+	overlayMsg->set_payload_message(bc->getEndpointDescriptor().serialize());
+	
+	send( overlayMsg, ld, system_priority::OVERLAY ); // send back to link
 
 	// inform listener
@@ -1534,6 +2151,13 @@
 }
 
-bool BaseOverlay::handleLinkReply( OverlayMsg* overlayMsg, LinkDescriptor* ld ) {
-
+bool BaseOverlay::handleLinkReply(
+        OverlayMsg* overlayMsg,
+        reboost::shared_buffer_t sub_message,
+        LinkDescriptor* ld )
+{
+    // deserialize EndpointDescriptor
+    EndpointDescriptor endpoints;
+    endpoints.deserialize(sub_message);
+    
 	// find link request
 	LinkDescriptor* ldn = getDescriptor(overlayMsg->getDestinationLink());
@@ -1554,9 +2178,10 @@
 
 	// debug message
-	logging_debug( "Link request reply received. Establishing link"
+	logging_info( "Link request reply received. Establishing link"
 			<< " for service " << overlayMsg->getService().toString()
 			<< " with local id=" << overlayMsg->getDestinationLink()
 			<< " and remote link id=" << overlayMsg->getSourceLink()
-			<< " to " << overlayMsg->getSourceEndpoint().toString()
+			<< " to " << endpoints.toString()
+			<< " hop count: " << overlayMsg->getRouteRecord().size()
 	);
 
@@ -1577,7 +2202,7 @@
 		logging_info( "Sending out queued messages on link " <<
 				ldn->overlayId.toString() );
-		BOOST_FOREACH( Message* msg, ldn->messageQueue ) {
-			sendMessage( msg, ldn->overlayId );
-			delete msg;
+		foreach( LinkDescriptor::message_queue_entry msg, ldn->messageQueue )
+		{
+			sendMessage( msg.message, ldn->overlayId, msg.priority );
 		}
 		ldn->messageQueue.clear();
@@ -1589,5 +2214,5 @@
 	// try to replace relay link with direct link
 	ldn->retryCounter = 3;
-	ldn->endpoint = overlayMsg->getSourceEndpoint();
+	ldn->endpoint = endpoints;
 	ldn->communicationId =	bc->establishLink( ldn->endpoint );
 
@@ -1596,15 +2221,42 @@
 
 /// handle a keep-alive message for a link
-bool BaseOverlay::handleLinkAlive( OverlayMsg* overlayMsg, LinkDescriptor* ld ) {
+bool BaseOverlay::handleLinkAlive( OverlayMsg* overlayMsg, LinkDescriptor* ld )
+{
 	LinkDescriptor* rld = getDescriptor(overlayMsg->getDestinationLink());
-	if ( rld != NULL ) {
-		logging_debug("Keep-Alive for " <<
-				overlayMsg->getDestinationLink() );
+	
+	if ( rld != NULL )
+	{
+		logging_debug("Keep-Alive for " << overlayMsg->getDestinationLink() );
 		if (overlayMsg->isRouteRecord())
+		{
 			rld->routeRecord = overlayMsg->getRouteRecord();
+		}
+		
+		// set alive
 		rld->setAlive();
+		
+		
+		/* answer keep alive */
+		if ( overlayMsg->getType() == OverlayMsg::typeKeepAlive )
+		{
+            time_t now = time(NULL);
+            logging_debug("[BaseOverlay] Answering KeepAlive over "
+                    << ld->to_string()
+                    << " after "
+                    << difftime( now, ld->keepAliveSent )
+                    << "s");
+            
+            OverlayMsg msg( OverlayMsg::typeKeepAliveReply,
+                    OverlayInterface::OVERLAY_SERVICE_ID, nodeId, ld->remoteNode );
+            msg.setRouteRecord(true);
+            ld->keepAliveSent = now;
+            send_link( &msg, ld->overlayId, system_priority::OVERLAY );
+		}
+
 		return true;
-	} else {
-		logging_error("Keep-Alive for "
+	}
+	else
+	{
+		logging_error("No Keep-Alive for "
 				<< overlayMsg->getDestinationLink() << ": link unknown." );
 		return false;
@@ -1636,17 +2288,28 @@
 	// erase the original descriptor
 	eraseDescriptor(ld->overlayId);
+	
+    // inform listener
+    if( rld->listener != NULL)
+        rld->listener->onLinkChanged( rld->overlayId, rld->remoteNode );
+	
 	return true;
 }
 
 /// handles an incoming message
-bool BaseOverlay::handleMessage( const Message* message, LinkDescriptor* ld,
-		const LinkID bcLink ) {
-	logging_debug( "Handling message: " << message->toString());
-
+bool BaseOverlay::handleMessage( reboost::shared_buffer_t message, LinkDescriptor* ld,
+		const LinkID bcLink )
+{
 	// decapsulate overlay message
-	OverlayMsg* overlayMsg =
-			const_cast<Message*>(message)->decapsulate<OverlayMsg>();
-	if( overlayMsg == NULL ) return false;
-
+	OverlayMsg* overlayMsg = new OverlayMsg();
+	reboost::shared_buffer_t sub_buff = overlayMsg->deserialize_from_shared_buffer(message);
+
+// 	// XXX debug
+// 	logging_info( "Received overlay message."
+// 	        << " Hops: " << (int) overlayMsg->getNumHops()
+// 	        << " Type: " << (int) overlayMsg->getType()
+// 	        << " Payload size: " << sub_buff.size()
+//             << " SeqNum: " << overlayMsg->getSeqNum() );
+	
+	
 	// increase number of hops
 	overlayMsg->increaseNumHops();
@@ -1660,6 +2323,7 @@
 	// handle signaling messages (do not route!)
 	if (overlayMsg->getType()>=OverlayMsg::typeSignalingStart &&
-			overlayMsg->getType()<=OverlayMsg::typeSignalingEnd ) {
-		overlayInterface->onMessage(overlayMsg, NodeID::UNSPECIFIED, LinkID::UNSPECIFIED);
+			overlayMsg->getType()<=OverlayMsg::typeSignalingEnd )
+	{
+		overlayInterface->onMessage(overlayMsg, sub_buff, NodeID::UNSPECIFIED, LinkID::UNSPECIFIED);
 		delete overlayMsg;
 		return true;
@@ -1673,42 +2337,110 @@
 				<< " to " << overlayMsg->getDestinationNode()
 		);
-		route( overlayMsg );
+		
+//		// XXX testing AKTUELL
+//        logging_info("MARIO: Routing message "
+//                << " from " << overlayMsg->getSourceNode()
+//                << " to " << overlayMsg->getDestinationNode() );
+//        logging_info( "Type: " << overlayMsg->getType() << " Payload size: " << sub_buff.size());
+		overlayMsg->append_buffer(sub_buff);
+		
+		route( overlayMsg, ld->remoteNode );
 		delete overlayMsg;
 		return true;
 	}
 
-	// handle base overlay message
+	
+	/* handle base overlay message */
 	bool ret = false; // return value
-	switch ( overlayMsg->getType() ) {
-
-	// data transport messages
-	case OverlayMsg::typeData:
-		ret = handleData(overlayMsg, ld); 			break;
-
-		// overlay setup messages
-	case OverlayMsg::typeJoinRequest:
-		ret = handleJoinRequest(overlayMsg, bcLink ); 	break;
-	case OverlayMsg::typeJoinReply:
-		ret = handleJoinReply(overlayMsg, bcLink ); 	break;
-
-		// link specific messages
-	case OverlayMsg::typeLinkRequest:
-		ret = handleLinkRequest(overlayMsg, ld ); 	break;
-	case OverlayMsg::typeLinkReply:
-		ret = handleLinkReply(overlayMsg, ld ); 	break;
-	case OverlayMsg::typeLinkUpdate:
-		ret = handleLinkUpdate(overlayMsg, ld );  	break;
-	case OverlayMsg::typeLinkAlive:
-		ret = handleLinkAlive(overlayMsg, ld );   	break;
-	case OverlayMsg::typeLinkDirect:
-		ret = handleLinkDirect(overlayMsg, ld );  	break;
-
-		// handle unknown message type
-	default: {
-		logging_error( "received message in invalid state! don't know " <<
-				"what to do with this message of type " << overlayMsg->getType() );
-		ret = false;
-		break;
-	}
+	try
+	{
+        switch ( overlayMsg->getType() ) 
+        {
+            // data transport messages
+            case OverlayMsg::typeData:
+            {
+                // NOTE: On relayed links, Â»ldÂ« does not point to our link, but on the relay link. 
+                LinkDescriptor* end_to_end_ld = getDescriptor(overlayMsg->getDestinationLink());
+                
+                if ( ! end_to_end_ld )
+                {
+                    logging_warn("Error: Data-Message claims to belong to a link we don't know.");
+                    
+                    ret = false;
+                }
+                else
+                {
+                    // message received --> link is alive
+                    end_to_end_ld->keepAliveReceived = time(NULL);
+                    // hop count on this link
+                    end_to_end_ld->hops = overlayMsg->getNumHops();
+                    
+                    // * call handler *
+                    ret = handleData(sub_buff, overlayMsg, end_to_end_ld);
+                }
+                
+                break;
+            }
+            case OverlayMsg::typeMessageLost:
+                ret = handleLostMessage(sub_buff, overlayMsg);
+                
+                break;
+        
+                // overlay setup messages
+            case OverlayMsg::typeJoinRequest:
+                ret = handleJoinRequest(sub_buff, overlayMsg->getSourceNode(), bcLink ); 	break;
+            case OverlayMsg::typeJoinReply:
+                ret = handleJoinReply(sub_buff, bcLink ); 	break;
+        
+                // link specific messages
+            case OverlayMsg::typeLinkRequest:
+                ret = handleLinkRequest(overlayMsg, ld ); 	break;
+            case OverlayMsg::typeLinkReply:
+                ret = handleLinkReply(overlayMsg, sub_buff, ld ); 	break;
+            case OverlayMsg::typeLinkUpdate:
+                ret = handleLinkUpdate(overlayMsg, ld );  	break;
+            case OverlayMsg::typeKeepAlive:
+            case OverlayMsg::typeKeepAliveReply:
+                ret = handleLinkAlive(overlayMsg, ld );   	break;
+            case OverlayMsg::typeLinkDirect:
+                ret = handleLinkDirect(overlayMsg, ld );  	break;
+                
+            case OverlayMsg::typeLinkClose:
+            {
+                dropLink(overlayMsg->getDestinationLink());
+                __removeDroppedLink(overlayMsg->getDestinationLink());
+                
+                break;
+            }
+            
+            /// ping over overlay path (or similar)
+            case OverlayMsg::typePing:
+            {
+                ret = handlePing(overlayMsg, ld);
+                break;
+            }
+            case OverlayMsg::typePong:
+            {
+                ret = handlePong(overlayMsg, ld);
+                break;
+            }
+            
+                // handle unknown message type
+            default:
+            {
+                logging_error( "received message in invalid state! don't know " <<
+                        "what to do with this message of type " << overlayMsg->getType() );
+                ret = false;
+                break;
+            }
+        }
+	}
+	catch ( reboost::illegal_sub_buffer& e )
+	{
+	    logging_error( "Failed to create sub-buffer while reading message: Â»"
+	            << e.what()
+	            << "Â« Message too short? ");
+	    
+	    assert(false); // XXX
 	}
 
@@ -1720,11 +2452,8 @@
 // ----------------------------------------------------------------------------
 
-void BaseOverlay::broadcastMessage(Message* message, const ServiceID& service) {
+void BaseOverlay::broadcastMessage(reboost::message_t message, const ServiceID& service, uint8_t priority) {
 
 	logging_debug( "broadcasting message to all known nodes " <<
 			"in the overlay from service " + service.toString() );
-
-	if(message == NULL) return;
-	message->setReleasePayload(false);
 
 	OverlayInterface::NodeList nodes = overlayInterface->getKnownNodes(true);
@@ -1732,6 +2461,6 @@
 		NodeID& id = nodes.at(i);
 		if(id == this->nodeId) continue; // don't send to ourselfs
-		if(i+1 == nodes.size()) message->setReleasePayload(true); // release payload on last send
-		sendMessage( message, id, service );
+
+		sendMessage( message, id, priority, service );
 	}
 }
@@ -1755,5 +2484,5 @@
 vector<LinkID> BaseOverlay::getLinkIDs( const NodeID& nid ) const {
 	vector<LinkID> linkvector;
-	BOOST_FOREACH( LinkDescriptor* ld, links ) {
+	foreach( LinkDescriptor* ld, links ) {
 		if( ld->remoteNode == nid || nid == NodeID::UNSPECIFIED ) {
 			linkvector.push_back( ld->overlayId );
@@ -1779,4 +2508,43 @@
 	updateVisual();
 }
+
+
+
+/* link status */
+bool BaseOverlay::isLinkDirect(const ariba::LinkID& lnk) const
+{
+    const LinkDescriptor* ld = getDescriptor(lnk);
+    
+    if (!ld)
+        return false;
+    
+    return ld->communicationUp && !ld->relayed;
+}
+
+int BaseOverlay::getHopCount(const ariba::LinkID& lnk) const
+{
+    const LinkDescriptor* ld = getDescriptor(lnk);
+    
+    if (!ld)
+        return -1;
+    
+    return ld->hops;    
+}
+
+
+bool BaseOverlay::isLinkVital(const LinkDescriptor* link) const
+{
+    time_t now = time(NULL);
+
+    return link->up && difftime( now, link->keepAliveReceived ) <= KEEP_ALIVE_TIME_OUT; // TODO is this too long for a "vital" link..? 
+}
+
+bool BaseOverlay::isLinkDirectVital(const LinkDescriptor* link) const
+{
+    return isLinkVital(link) && link->communicationUp && !link->relayed;
+}
+
+/* [link status] */
+
 
 void BaseOverlay::updateVisual(){
@@ -1878,6 +2646,6 @@
 	static set<NodeID> linkset;
 	set<NodeID> remotenodes;
-	BOOST_FOREACH( LinkDescriptor* ld, links ) {
-		if (!ld->isVital() || ld->service != OverlayInterface::OVERLAY_SERVICE_ID)
+	foreach( LinkDescriptor* ld, links ) {
+		if (!isLinkVital(ld) || ld->service != OverlayInterface::OVERLAY_SERVICE_ID)
 			continue;
 
@@ -1895,5 +2663,5 @@
 	do{
 		changed = false;
-		BOOST_FOREACH(NodeID n, linkset){
+		foreach(NodeID n, linkset){
 			if(remotenodes.find(n) == remotenodes.end()){
 				visualInstance.visDisconnect(visualIdBase, this->nodeId, n, "");
@@ -1908,5 +2676,5 @@
 	do{
 		changed = false;
-		BOOST_FOREACH(NodeID n, remotenodes){
+		foreach(NodeID n, remotenodes){
 			if(linkset.find(n) == linkset.end()){
 				visualInstance.visConnect(visualIdBase, this->nodeId, n, "");
@@ -1933,5 +2701,5 @@
 	// dump link state
 	s << "--- link state -------------------------------" << endl;
-	BOOST_FOREACH( LinkDescriptor* ld, links ) {
+	foreach( LinkDescriptor* ld, links ) {
 		s << "link " << i << ": " << ld << endl;
 		i++;
