Index: /configure.ac
===================================================================
--- /configure.ac	(revision 6584)
+++ /configure.ac	(revision 6760)
@@ -53,4 +53,5 @@
 sample/Makefile
 sample/pingpong/Makefile
+sample/testdht/Makefile
 docu/Makefile
 docu/doxygen/Makefile
Index: /sample/Makefile.am
===================================================================
--- /sample/Makefile.am	(revision 6584)
+++ /sample/Makefile.am	(revision 6760)
@@ -1,1 +1,1 @@
-SUBDIRS = pingpong
+SUBDIRS = pingpong testdht
Index: /sample/testdht/DHTTest.cpp
===================================================================
--- /sample/testdht/DHTTest.cpp	(revision 6760)
+++ /sample/testdht/DHTTest.cpp	(revision 6760)
@@ -0,0 +1,204 @@
+#include "DHTTest.h"
+#include "ariba/utility/configuration/Configuration.h"
+
+using ariba::utility::Configuration;
+using namespace ariba;
+
+namespace ariba {
+namespace application {
+namespace dhttest {
+
+// logging
+use_logging_cpp( DHTTest );
+
+// the service that the dhttest wants to use
+ServiceID DHTTest::DHTTEST_SERVICEID = ServiceID( 111 );
+
+// construction
+DHTTest::DHTTest() {
+	Timer::setInterval( 10000 );
+}
+
+// destruction
+DHTTest::~DHTTest() {
+}
+
+// implementation of the startup interface
+void DHTTest::startup() {
+
+	logging_info( "starting up DHTTest service ... " );
+
+	// create ariba module
+	logging_debug( "creating ariba underlay module ... " );
+	ariba = new AribaModule();
+
+	Name spovnetName("dhttest");
+	Name nodeName = Name::UNSPECIFIED;
+	this->name = string("<dhttest>");
+
+	// get settings from configuration object
+	if( Configuration::haveConfig() ){
+		Configuration& config = Configuration::instance();
+
+		// get node name
+		if (config.exists("node.name"))
+			nodeName = config.read<string> ("node.name");
+
+		// configure ariba module
+		if (config.exists("ariba.endpoints"))
+			ariba->setProperty("endpoints", config.read<string>("ariba.endpoints"));
+		if (config.exists("ariba.bootstrap.hints"))
+			ariba->setProperty("bootstrap.hints", config.read<string>("ariba.bootstrap.hints"));
+		if (config.exists("dhttest.name"))
+			name = config.read<string>("dhttest.name");
+
+		// configure test parameteres
+		if (config.exists("dhttest.key"))
+			key = config.read<string>("dhttest.key");
+		if (config.exists("dhttest.data"))
+			data = config.read<string>("dhttest.data");
+
+	} // if( Configuration::haveConfig() )
+
+	// start ariba module
+	ariba->start();
+
+	// create node and join
+	node = new Node( *ariba, nodeName );
+
+	// bind communication and node listener
+	node->bind( this );                              /*NodeListener*/
+	//node->bind( this, DHTTest::DHTTEST_SERVICEID); /*CommunicationListener*/
+
+	// start node module
+	node->start();
+
+	// when initiating, you can define the overlay type, default is Chord [CHORD_OVERLAY]
+	SpoVNetProperties params;
+	//params.setBaseOverlayType( SpoVNetProperties::ONE_HOP_OVERLAY ); // alternative: OneHop
+
+	// initiate the spovnet
+	logging_info("initiating spovnet");
+	node->initiate(spovnetName, params);
+
+	// join the spovnet
+	logging_info("joining spovnet");
+	node->join(spovnetName);
+
+	// dht test started up...
+	logging_info( "dhttest starting up with"
+			<< " [spovnetid " << node->getSpoVNetId().toString() << "]"
+			<< " and [nodeid " << node->getNodeId().toString() << "]" );
+}
+
+// implementation of the startup interface
+void DHTTest::shutdown() {
+
+	logging_info( "dhttest service starting shutdown sequence ..." );
+
+	// stop timer
+	Timer::stop();
+
+	// leave spovnet
+	node->leave();
+
+	// unbind communication and node listener
+	node->unbind( this );                               /*NodeListener*/
+	//node->unbind( this, DHTTest::DHTTEST_SERVICEID ); /*CommunicationListener*/
+
+	// stop the ariba module
+	ariba->stop();
+
+	// delete node and ariba module
+	delete node;
+	delete ariba;
+
+	// now we are completely shut down
+	logging_info( "dhttest service shut down" );
+}
+
+// timer event
+void DHTTest::eventFunction() {
+
+	switch(counter) {
+	case 1:
+		logging_info( "Putting '" << key << "'->'" << data << "' in the dht.");
+
+		node->put(stod(key), stod(data), 3600);
+		break;
+	default:
+		logging_info( "Trying to get '" << key << "' from the DHT. This is try number " << counter-1 <<".");
+
+		node->get(stod(key), DHTTEST_SERVICEID);
+		break;
+	}
+
+	counter++;
+
+}
+
+void DHTTest::onJoinCompleted( const SpoVNetID& vid ) {
+	logging_info( "dhttest node join completed, spovnetid=" << vid.toString() );
+
+	// key is set -> this node will be testing
+	if(!key.empty()) {
+		counter = 0;
+
+		// start the timer to ping every second
+		Timer::start();
+	}
+
+}
+
+void DHTTest::onJoinFailed( const SpoVNetID& vid ) {
+	logging_error("dhttest node join failed, spovnetid=" << vid.toString() );
+}
+
+void DHTTest::onLeaveCompleted( const SpoVNetID& vid ){
+	logging_info("dhttest node leave completed, spovnetid=" << vid.toString() );
+}
+
+void DHTTest::onLeaveFailed( const SpoVNetID& vid ){
+	logging_error("dhttest node leave failed, spovnetid=" << vid.toString() );
+}
+
+
+bool DHTTest::onLinkRequest(const NodeID& remote, const DataMessage& msg) {
+	logging_info( "node " << remote.toString() << " wants to build up a link with us ... allowing" );
+	return true;
+}
+
+void DHTTest::onLinkUp(const LinkID& lnk, const NodeID& remote){
+	logging_info( "received link-up event for link " << lnk.toString()
+			<< " and node " << remote.toString() );
+}
+
+void DHTTest::onLinkDown(const LinkID& lnk, const NodeID& remote){
+	logging_info( "received link-down event for link " << lnk.toString()
+			<< " and node " << remote.toString() );
+}
+
+void DHTTest::onLinkChanged(const LinkID& lnk, const NodeID& remote){
+	logging_info( "link-changed event for link " << lnk.toString()
+			<< " and node " << remote.toString() );
+}
+
+void DHTTest::onLinkFail(const LinkID& lnk, const NodeID& remote){
+	logging_info( "received link-failed event for link " << lnk.toString()
+			<< " and node " << remote.toString() );
+}
+
+void DHTTest::onKeyValue( const Data& key, const vector<Data>& value ) {
+	logging_info( "----> Received DHT answer for '" << dtos(key) << "'.");
+	// TODO: implement
+}
+
+Data DHTTest::stod(string s) {
+	return Data((uint8_t*)s.data(), s.length()*8).clone();
+}
+
+string DHTTest::dtos(Data d) {
+	return string((char*)d.getBuffer(), d.getLength()/8);
+}
+
+}}} // namespace ariba, application, dhttest
Index: /sample/testdht/DHTTest.h
===================================================================
--- /sample/testdht/DHTTest.h	(revision 6760)
+++ /sample/testdht/DHTTest.h	(revision 6760)
@@ -0,0 +1,84 @@
+#ifndef __PINGPONG_H_
+#define __PINGPONG_H_
+
+#include "ariba/ariba.h"
+#include "ariba/utility/system/StartupInterface.h"
+#include "ariba/utility/system/Timer.h"
+
+#include <vector>
+
+using namespace ariba;
+using ariba::utility::StartupInterface;
+using ariba::utility::Timer;
+
+namespace ariba {
+namespace application {
+namespace dhttest {
+
+using namespace std;
+
+/*
+ * DHTTest main class
+ */
+class DHTTest: public NodeListener,
+	public CommunicationListener,
+	public StartupInterface,
+	public Timer {
+
+	use_logging_h(DHTTest);
+
+public:
+	DHTTest();
+	virtual ~DHTTest();
+
+protected:
+	// communication listener interface
+	virtual bool onLinkRequest(const NodeID& remote, const DataMessage& msg =
+			DataMessage::UNSPECIFIED);
+	virtual void onLinkUp(const LinkID& lnk, const NodeID& remote);
+	virtual void onLinkDown(const LinkID& lnk, const NodeID& remote);
+	virtual void onLinkChanged(const LinkID& lnk, const NodeID& remote);
+	virtual void onLinkFail(const LinkID& lnk, const NodeID& remote);
+
+	// the dht message handler (for answers to get() requests)
+	virtual void onKeyValue( const Data& key, const vector<Data>& value );
+
+	// node listener interface
+	virtual void onJoinCompleted(const SpoVNetID& vid);
+	virtual void onJoinFailed(const SpoVNetID& vid);
+	virtual void onLeaveCompleted(const SpoVNetID& vid);
+	virtual void onLeaveFailed(const SpoVNetID& vid);
+
+	// startup wrapper interface
+	virtual void startup();
+	virtual void shutdown();
+
+	// timer events
+	virtual void eventFunction();
+
+	// helper functions to convert from string to Data and visa versa
+	Data stod(string s);
+	string dtos(Data d);
+
+private:
+	// the ariba module and a node
+	AribaModule* ariba;
+	Node* node;
+	string name;
+
+	// this is for the specific dht test
+	string key;
+	string data;
+	int counter;
+
+	// the dht test service id
+	static ServiceID DHTTEST_SERVICEID;
+
+};
+
+// needed for simulation support
+ARIBA_SIMULATION_SERVICE(DHTTest);
+
+}}} // namespace ariba, application, pingpong
+
+#endif // __DHTTEST_H_
Index: /sample/testdht/Makefile.am
===================================================================
--- /sample/testdht/Makefile.am	(revision 6760)
+++ /sample/testdht/Makefile.am	(revision 6760)
@@ -0,0 +1,60 @@
+# sources ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+if OMNET
+lib_LTLIBRARIES = libtestdht.la
+else
+bin_PROGRAMS 	= testdht
+endif
+
+# compiler flags ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+AM_CPPFLAGS     = -DLINUX -D_LINUX -I../../source -D_REENTRANT
+AM_CPPFLAGS    += $(BOOST_CPPFLAGS)
+
+if DEBUG
+AM_CPPFLAGS    += -ggdb -DDEBUG -D_DEBUG -O0
+endif
+
+if PROFILING
+AM_CPPFLAGS    += -pg
+endif
+
+if OMNET
+AM_CPPFLAGS    += -fPIC -DUNDERLAY_OMNET
+endif
+
+# linker flags ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+AM_LDFLAGS      = -L../../source/ariba -lariba
+
+if PROFILING
+AM_LDFLAGS     += -pg
+endif
+
+if OMNET
+AM_LDFLAGS     += -shared -rdynamic
+endif
+
+# sources ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+if OMNET
+
+libtestdht_la_SOURCES = \
+  DHTTest.cpp \
+  DHTTest.h \
+  PingPongMessage.cpp \
+  PingPongMessage.h
+
+else
+
+#needed to fix autotools bug
+testdht_CPPFLAGS = $(AM_CPPFLAGS)
+
+testdht_SOURCES = \
+  PingPongMessage.cpp \
+  PingPongMessage.h \
+  DHTTest.cpp \
+  DHTTest.h \
+  main.cpp
+
+endif
Index: /sample/testdht/PingPongMessage.cpp
===================================================================
--- /sample/testdht/PingPongMessage.cpp	(revision 6760)
+++ /sample/testdht/PingPongMessage.cpp	(revision 6760)
@@ -0,0 +1,26 @@
+#include "PingPongMessage.h"
+
+namespace ariba {
+namespace application {
+namespace pingpong {
+
+vsznDefault(PingPongMessage);
+
+PingPongMessage::PingPongMessage() : id(0) {
+}
+
+PingPongMessage::PingPongMessage(uint8_t _id, string name) : id(_id),name(name) {
+}
+
+PingPongMessage::~PingPongMessage(){
+}
+
+string PingPongMessage::info(){
+	return "ping pong message id " + ariba::utility::Helper::ultos(id);
+}
+
+uint8_t PingPongMessage::getid(){
+	return id;
+}
+
+}}} // namespace ariba, appplication, pingpong
Index: /sample/testdht/PingPongMessage.h
===================================================================
--- /sample/testdht/PingPongMessage.h	(revision 6760)
+++ /sample/testdht/PingPongMessage.h	(revision 6760)
@@ -0,0 +1,40 @@
+#ifndef PINGPONGMESSAGES_H_
+#define PINGPONGMESSAGES_H_
+
+#include <string>
+#include "ariba/ariba.h"
+
+using namespace ariba;
+using std::string;
+
+namespace ariba {
+namespace application {
+namespace pingpong {
+
+using_serialization;
+
+class PingPongMessage : public Message {
+	VSERIALIZEABLE;
+public:
+	PingPongMessage();
+	PingPongMessage( uint8_t _id, string name = string("<ping>") );
+	virtual ~PingPongMessage();
+
+	string info();
+	uint8_t getid();
+
+	inline string getName() const {
+		return name;
+	}
+private:
+	uint8_t id;
+	string name;
+};
+
+}}} // namespace ariba, appplication , pingpong
+
+sznBeginDefault( ariba::application::pingpong::PingPongMessage, X ) {
+	X && id && T(name);
+} sznEnd();
+
+#endif /* PINGPONGMESSAGES_H_ */
Index: /sample/testdht/main.cpp
===================================================================
--- /sample/testdht/main.cpp	(revision 6760)
+++ /sample/testdht/main.cpp	(revision 6760)
@@ -0,0 +1,28 @@
+#include <string>
+#include "ariba/utility/system/StartupWrapper.h"
+#include "DHTTest.h"
+
+using std::string;
+using ariba::utility::StartupWrapper;
+using ariba::application::dhttest::DHTTest;
+
+int main( int argc, char** argv ) {
+
+	// get config file
+	string config = "./settings.cnf";
+	if (argc >= 2) config = argv[1];
+
+	StartupWrapper::initConfig( config );
+	StartupWrapper::startSystem();
+
+	// this will do the main functionality and block
+	DHTTest test;
+	StartupWrapper::startup(&test);
+
+	// --> we will run blocking until <enter> is hit
+
+	StartupWrapper::shutdown(&test);
+	StartupWrapper::stopSystem();
+
+	return 0;
+}
Index: /source/ariba/overlay/BaseOverlay.cpp
===================================================================
--- /source/ariba/overlay/BaseOverlay.cpp	(revision 6584)
+++ /source/ariba/overlay/BaseOverlay.cpp	(revision 6760)
@@ -1892,10 +1892,9 @@
 	stabilizeRelays();
 	stabilizeLinks();
+	stabilizeDHT();
 }
 
 
 // ----------------------------------------------------------------------------
-
-
 
 /// stabilize DHT state
@@ -2006,5 +2005,5 @@
 	// calculate hash
 	NodeID dest = NodeID::sha1(key.getBuffer(), key.getLength() / 8);
-	OverlayMsg msg(OverlayMsg::typeDHTRemove);
+	OverlayMsg msg(OverlayMsg::typeDHTGet);
 	DHTMessage dhtmsg(key);
 	msg.setDestinationNode(dest);
@@ -2014,4 +2013,3 @@
 }
 
-
 }} // namespace ariba, overlay
