Index: /etc/pingpong/settings_initiator.cnf
===================================================================
--- /etc/pingpong/settings_initiator.cnf	(revision 5274)
+++ /etc/pingpong/settings_initiator.cnf	(revision 5284)
@@ -1,6 +1,5 @@
-#node.name = marty
 node.initiator = true
-#ariba.ip.addr =
-ariba.tcp.port = 5002
-#ariba.udp.port =
-#ariba.bootstrap.hints=pingpong{ip{127.0.0.1},tcp(ip,{5002})}
+ariba.endpoints = tcp{5002}
+#ariba.bootstrap.hints=pingpong{ip{127.0.0.1};tcp{5002}}
+pingpong.name = Marty
+
Index: /etc/pingpong/settings_node1.cnf
===================================================================
--- /etc/pingpong/settings_node1.cnf	(revision 5274)
+++ /etc/pingpong/settings_node1.cnf	(revision 5284)
@@ -1,7 +1,6 @@
 #node.name = docbrown
 node.initiator = false
-#ariba.ip.addr =
-ariba.tcp.port = 5003
-#ariba.udp.port =
-ariba.bootstrap.hints=pingpong{ip{127.0.0.1},tcp(ip,{5002})}
+ariba.endpoints = tcp{5003}
+ariba.bootstrap.hints=pingpong{ip{127.0.0.1};tcp{5002}}
+pingpong.name = Biff
 
Index: /etc/pingpong/settings_node2.cnf
===================================================================
--- /etc/pingpong/settings_node2.cnf	(revision 5274)
+++ /etc/pingpong/settings_node2.cnf	(revision 5284)
@@ -1,7 +1,5 @@
 #node.name = biff
 node.initiator = false
-#ariba.ip.addr =
-ariba.tcp.port = 5004
-#ariba.udp.port =
-ariba.bootstrap.hints=pingpong{ip{127.0.0.1},tcp(ip,{5002})}
-
+ariba.endpoints = tcp{5004}
+ariba.bootstrap.hints=pingpong{ip{127.0.0.1};tcp{5002}}
+pingpong.name = McFly
Index: /etc/pingpong/settings_node3.cnf
===================================================================
--- /etc/pingpong/settings_node3.cnf	(revision 5274)
+++ /etc/pingpong/settings_node3.cnf	(revision 5284)
@@ -1,7 +1,6 @@
 #node.name = biff
 node.initiator = false
-#ariba.ip.addr =
-ariba.tcp.port = 5005
-#ariba.udp.port =
-ariba.bootstrap.hints=pingpong{ip{127.0.0.1},tcp(ip,{5002})}
+ariba.endpoints = tcp{5005}
+ariba.bootstrap.hints=pingpong{ip{127.0.0.1};tcp{5002}}
+pingpong.name = DocBrown
 
Index: /etc/pingpong/settings_node4.cnf
===================================================================
--- /etc/pingpong/settings_node4.cnf	(revision 5274)
+++ /etc/pingpong/settings_node4.cnf	(revision 5284)
@@ -1,7 +1,5 @@
 #node.name = biff
 node.initiator = false
-#ariba.ip.addr =
-ariba.tcp.port = 5006
-#ariba.udp.port =
-ariba.bootstrap.hints=pingpong{ip{127.0.0.1},tcp(ip,{5002})}
-
+ariba.endpoints = tcp{5006}
+ariba.bootstrap.hints=pingpong{ip{127.0.0.1};tcp{5002}}
+pingpong.name = Sebastian
Index: /etc/pingpong/settings_node5.cnf
===================================================================
--- /etc/pingpong/settings_node5.cnf	(revision 5274)
+++ /etc/pingpong/settings_node5.cnf	(revision 5284)
@@ -1,7 +1,7 @@
 #node.name = biff
 node.initiator = false
-#ariba.ip.addr =
-ariba.tcp.port = 5007
-#ariba.udp.port =
-ariba.bootstrap.hints=pingpong{ip{127.0.0.1},tcp(ip,{5002})}
+ariba.endpoints = tcp{5007}
+ariba.bootstrap.hints=pingpong{ip{127.0.0.1};tcp{5002}}
+pingpong.name=DocBrown
 
+
Index: /sample/pingpong/PingPong.cpp
===================================================================
--- /sample/pingpong/PingPong.cpp	(revision 5274)
+++ /sample/pingpong/PingPong.cpp	(revision 5284)
@@ -49,14 +49,10 @@
 
 	// configure ariba module
-	if (config.exists("ariba.ip.addr")) ariba->setProperty("ip.addr",
-			config.read<string>("ariba.ip.addr"));
-	if (config.exists("ariba.tcp.port")) ariba->setProperty("tcp.port",
-			config.read<string>("ariba.tcp.port"));
-	if (config.exists("ariba.udp.port")) ariba->setProperty("udp.port",
-			config.read<string>("ariba.udp.port"));
-	if (config.exists("ariba.bootstrap.hints")) ariba->setProperty("bootstrap.hints",
-			config.read<string>("ariba.bootstrap.hints"));
-	if (config.exists("pingpong.name")) name =
-			config.read<string>("pingpong.name");
+	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("pingpong.name"))
+		name = config.read<string>("pingpong.name");
 
 	// start ariba module
Index: /source/ariba/AribaModule.cpp
===================================================================
--- /source/ariba/AribaModule.cpp	(revision 5274)
+++ /source/ariba/AribaModule.cpp	(revision 5284)
@@ -50,5 +50,4 @@
 #include "ariba/communication/BaseCommunication.h"
 #include "ariba/communication/EndpointDescriptor.h"
-#include "ariba/communication/modules/network/NetworkLocator.h"
 
 using namespace ariba::utility::Helper;
@@ -58,12 +57,8 @@
 namespace ariba {
 
+use_logging_cpp(AribaModule);
+
 AribaModule::AribaModule()
-	: base_comm(NULL), sideport_sniffer(NULL),
-		ip_addr(NULL), started(false) {
-
-	// init with default values
-
-	this->tcp_port = 41402;
-	this->udp_port = 41402;
+	: base_comm(NULL), sideport_sniffer(NULL), started(false) {
 }
 
@@ -101,4 +96,5 @@
 			Name name(type);
 			EndpointDescriptor* desc = EndpointDescriptor::fromString(data);
+			logging_debug("Added bootstap info for " << type << ": " << desc->toString() );
 			addBootstrapNode(name, desc);
 		}
@@ -132,5 +128,5 @@
 	}
 
-	//logging_debug( "added bootstrap info: " << getBootstrapHints() );
+	logging_debug( "Added bootstrap info: " << getBootstrapHints() );
 }
 
@@ -171,4 +167,5 @@
 	started = true;
 	base_comm = new BaseCommunication();
+	base_comm->setEndpoints(endpoints);
 }
 
@@ -192,12 +189,5 @@
 // @see Module.h
 void AribaModule::setProperty(string key, string value) {
-	if (key == "ip.addr") {
-		if (ip_addr != NULL) delete ip_addr;
-		communication::IPv4Locator* loc = new communication::IPv4Locator();
-		*loc = communication::IPv4Locator::fromString(value);
-		ip_addr = loc;
-	}
-	else if (key == "tcp.port") tcp_port = stoi(value);
-	else if (key == "udp.port") udp_port = stoi(value);
+	if (key == "endpoints") endpoints = value;
 	else if (key == "bootstrap.hints") addBootstrapHints(value);
 }
@@ -205,7 +195,5 @@
 // @see Module.h
 const string AribaModule::getProperty(string key) const {
-	if (key == "ip.addr") return ip_addr->toString();
-	else if (key == "tcp.port") return ultos(tcp_port);
-	else if (key == "udp.port") return ultos(udp_port);
+	if (key == "endpoints") return endpoints; // TODO: return local endpoints
 	else if (key == "bootstrap.hints") return getBootstrapHints();
 }
@@ -214,8 +202,6 @@
 const vector<string> AribaModule::getProperties() const {
 	vector<string> properties;
-	properties.push_back("ip.addr");
-	properties.push_back("tcp.port");
-	properties.push_back("udp.port");
-	properties.push_back("hints");
+	properties.push_back("endpoints");
+	properties.push_back("bootstrap.hints");
 	return properties;
 }
Index: /source/ariba/AribaModule.h
===================================================================
--- /source/ariba/AribaModule.h	(revision 5274)
+++ /source/ariba/AribaModule.h	(revision 5284)
@@ -42,4 +42,6 @@
 #include <string>
 #include <vector>
+#include "ariba/utility/logging/Logging.h"
+
 
 using std::vector;
@@ -58,10 +60,8 @@
 namespace ariba {
 
+// forward declaration
 namespace communication {
-class EndpointDescriptor;
-class NetworkLocator;
-}
-namespace communication {
-class BaseCommunication;
+	class EndpointDescriptor;
+	class BaseCommunication;
 }
 
@@ -86,4 +86,5 @@
 class AribaModule: public Module {
 	friend class Node;
+	use_logging_h(AribaModule);
 public:
 	/**
@@ -186,4 +187,5 @@
 	// members
 	string bootstrapFile; //< file with bootstrap information
+	string endpoints;
 	bool started; //< flag, if module has been started
 
@@ -196,8 +198,4 @@
 	communication::BaseCommunication* base_comm;
 	SideportListener* sideport_sniffer;
-
-	// TODO: use "abstract" representations here!
-	communication::NetworkLocator* ip_addr;
-	uint16_t tcp_port, udp_port;
 };
 
Index: /source/ariba/Makefile.am
===================================================================
--- /source/ariba/Makefile.am	(revision 5274)
+++ /source/ariba/Makefile.am	(revision 5284)
@@ -113,58 +113,59 @@
 # ------------> communication :: modules
 
-nobase_libariba_la_HEADERS += \
-  communication/modules/modules.h \
-  communication/modules/_namespace.h
+#nobase_libariba_la_HEADERS += \
+#  communication/modules/modules.h \
+#  communication/modules/_namespace.h
 
 # ------------> communication :: modules :: network
-libariba_la_SOURCES += \
-  communication/modules/network/NetworkLocator.cpp \
-  communication/modules/network/NetworkProtocol.cpp
-
-nobase_libariba_la_HEADERS += \
-  communication/modules/network/NetworkLocator.h \
-  communication/modules/network/NetworkProtocol.h
+
+#libariba_la_SOURCES += \
+#  communication/modules/network/NetworkLocator.cpp \
+#  communication/modules/network/NetworkProtocol.cpp
+
+#nobase_libariba_la_HEADERS += \
+#  communication/modules/network/NetworkLocator.h \
+#  communication/modules/network/NetworkProtocol.h
 
 # ------------> communication :: modules :: network :: ip
 
-libariba_la_SOURCES += \
-  communication/modules/network/ip/IPv4Locator.cpp \
-  communication/modules/network/ip/IPv4NetworkProtocol.cpp
-
-nobase_libariba_la_HEADERS += \
-  communication/modules/network/ip/IPv4Locator.h  \
-  communication/modules/network/ip/IPv4NetworkProtocol.h
+#libariba_la_SOURCES += \
+#  communication/modules/network/ip/IPv4Locator.cpp \
+#  communication/modules/network/ip/IPv4NetworkProtocol.cpp
+
+#nobase_libariba_la_HEADERS += \
+#  communication/modules/network/ip/IPv4Locator.h  \
+#  communication/modules/network/ip/IPv4NetworkProtocol.h
 
 # ------------> communication :: modules :: network :: omnet
 
-if OMNET
-libariba_la_SOURCES += \
-  communication/modules/network/omnet/OmnetNetworkProtocol.cpp
-
-nobase_libariba_la_HEADERS += \
-  communication/modules/network/omnet/OmnetNetworkProtocol.h
-endif
+#if OMNET
+#libariba_la_SOURCES += \
+#  communication/modules/network/omnet/OmnetNetworkProtocol.cpp
+
+#nobase_libariba_la_HEADERS += \
+#  communication/modules/network/omnet/OmnetNetworkProtocol.h
+#endif
 
 #------------> communication :: modules :: transport
 
-libariba_la_SOURCES += \
-  communication/modules/transport/TransportLocator.cpp \
-  communication/modules/transport/TransportProtocol.cpp
-
-nobase_libariba_la_HEADERS += \
-  communication/modules/transport/TransportLocator.h \
-  communication/modules/transport/TransportProtocol.h
+#libariba_la_SOURCES += \
+#  communication/modules/transport/TransportLocator.cpp \
+#  communication/modules/transport/TransportProtocol.cpp
+
+#nobase_libariba_la_HEADERS += \
+#  communication/modules/transport/TransportLocator.h \
+#  communication/modules/transport/TransportProtocol.h
 
 #------------> communication :: modules :: transport :: omnet
 
-if OMNET
-libariba_la_SOURCES += \
-  communication/modules/transport/omnet/AribaOmnetMessage_m.cc \
-  communication/modules/transport/omnet/AribaOmnetModule.cpp
-
-nobase_libariba_la_HEADERS += \
-  communication/modules/transport/omnet/AribaOmnetMessage_m.h \
-  communication/modules/transport/omnet/AribaOmnetModule.h
-endif
+#if OMNET
+#libariba_la_SOURCES += \
+#  communication/modules/transport/omnet/AribaOmnetMessage_m.cc \
+#  communication/modules/transport/omnet/AribaOmnetModule.cpp
+
+#nobase_libariba_la_HEADERS += \
+#  communication/modules/transport/omnet/AribaOmnetMessage_m.h \
+#  communication/modules/transport/omnet/AribaOmnetModule.h
+#endif
 
 #------------> communication :: modules :: transport :: protlib
@@ -172,71 +173,71 @@
 if OMNET
 else
-libariba_la_SOURCES += \
-  communication/modules/transport/protlib/timer_module.cpp \
-  communication/modules/transport/protlib/threadsafe_db.cpp \
-  communication/modules/transport/protlib/address.cpp \
-  communication/modules/transport/protlib/ie.cpp \
-  communication/modules/transport/protlib/tp_over_tcp.cpp \
-  communication/modules/transport/protlib/setuid.cpp \
-  communication/modules/transport/protlib/tp.cpp \
-  communication/modules/transport/protlib/connectionmap_uds.cpp \
-  communication/modules/transport/protlib/logfile.cpp \
-  communication/modules/transport/protlib/timer.cpp \
-  communication/modules/transport/protlib/connectionmap.cpp \
-  communication/modules/transport/protlib/fqueue.cpp \
-  communication/modules/transport/protlib/threads.cpp \
-  communication/modules/transport/protlib/messages.cpp \
-  communication/modules/transport/protlib/queuemanager.cpp \
-  communication/modules/transport/protlib/network_message.cpp \
-  communication/modules/transport/protlib/configuration.cpp \
-  communication/modules/transport/protlib/tp_over_uds.cpp \
-  communication/modules/transport/protlib/tp_over_udp.cpp \
-  communication/modules/transport/protlib/tp_over_tls_tcp.cpp \
-  communication/modules/transport/protlib/fastqueue.c \
-  communication/modules/transport/protlib/eclock_gettime.c \
-  communication/modules/transport/protlib/testqueue.c
-
-nobase_libariba_la_HEADERS += \
-  communication/modules/transport/protlib/tp_over_uds.h \
-  communication/modules/transport/protlib/threadsafe_db.h \
-  communication/modules/transport/protlib/configuration.h \
-  communication/modules/transport/protlib/ie.h \
-  communication/modules/transport/protlib/llhashers.h \
-  communication/modules/transport/protlib/fqueue.h \
-  communication/modules/transport/protlib/assocdata_uds.h \
-  communication/modules/transport/protlib/address.h \
-  communication/modules/transport/protlib/logfile.h \
-  communication/modules/transport/protlib/timer.h \
-  communication/modules/transport/protlib/queuemanager.h \
-  communication/modules/transport/protlib/messages.h \
-  communication/modules/transport/protlib/assocdata.h \
-  communication/modules/transport/protlib/protlib_types.h \
-  communication/modules/transport/protlib/tp_over_tcp.h \
-  communication/modules/transport/protlib/tp.h \
-  communication/modules/transport/protlib/threads.h \
-  communication/modules/transport/protlib/connectionmap.h \
-  communication/modules/transport/protlib/timer_module.h \
-  communication/modules/transport/protlib/fastqueue.h \
-  communication/modules/transport/protlib/tperror.h \
-  communication/modules/transport/protlib/tp_over_tls_tcp.h \
-  communication/modules/transport/protlib/network_message.h \
-  communication/modules/transport/protlib/tp_over_udp.h \
-  communication/modules/transport/protlib/setuid.h \
-  communication/modules/transport/protlib/cleanuphandler.h \
-  communication/modules/transport/protlib/connectionmap_uds.h
+#libariba_la_SOURCES += \
+#  communication/modules/transport/protlib/timer_module.cpp \
+#  communication/modules/transport/protlib/threadsafe_db.cpp \
+#  communication/modules/transport/protlib/address.cpp \
+#  communication/modules/transport/protlib/ie.cpp \
+#  communication/modules/transport/protlib/tp_over_tcp.cpp \
+#  communication/modules/transport/protlib/setuid.cpp \
+#  communication/modules/transport/protlib/tp.cpp \
+#  communication/modules/transport/protlib/connectionmap_uds.cpp \
+#  communication/modules/transport/protlib/logfile.cpp \
+#  communication/modules/transport/protlib/timer.cpp \
+#  communication/modules/transport/protlib/connectionmap.cpp \
+#  communication/modules/transport/protlib/fqueue.cpp \
+#  communication/modules/transport/protlib/threads.cpp \
+#  communication/modules/transport/protlib/messages.cpp \
+#  communication/modules/transport/protlib/queuemanager.cpp \
+#  communication/modules/transport/protlib/network_message.cpp \
+#  communication/modules/transport/protlib/configuration.cpp \
+#  communication/modules/transport/protlib/tp_over_uds.cpp \
+#  communication/modules/transport/protlib/tp_over_udp.cpp \
+#  communication/modules/transport/protlib/tp_over_tls_tcp.cpp \
+#  communication/modules/transport/protlib/fastqueue.c \
+#  communication/modules/transport/protlib/eclock_gettime.c \
+#  communication/modules/transport/protlib/testqueue.c
+
+#nobase_libariba_la_HEADERS += \
+#  communication/modules/transport/protlib/tp_over_uds.h \
+#  communication/modules/transport/protlib/threadsafe_db.h \
+#  communication/modules/transport/protlib/configuration.h \
+#  communication/modules/transport/protlib/ie.h \
+#  communication/modules/transport/protlib/llhashers.h \
+#  communication/modules/transport/protlib/fqueue.h \
+#  communication/modules/transport/protlib/assocdata_uds.h \
+#  communication/modules/transport/protlib/address.h \
+#  communication/modules/transport/protlib/logfile.h \
+#  communication/modules/transport/protlib/timer.h \
+#  communication/modules/transport/protlib/queuemanager.h \
+#  communication/modules/transport/protlib/messages.h \
+#  communication/modules/transport/protlib/assocdata.h \
+#  communication/modules/transport/protlib/protlib_types.h \
+#  communication/modules/transport/protlib/tp_over_tcp.h \
+#  communication/modules/transport/protlib/tp.h \
+#  communication/modules/transport/protlib/threads.h \
+#  communication/modules/transport/protlib/connectionmap.h \
+#  communication/modules/transport/protlib/timer_module.h \
+#  communication/modules/transport/protlib/fastqueue.h \
+#  communication/modules/transport/protlib/tperror.h \
+#  communication/modules/transport/protlib/tp_over_tls_tcp.h \
+#  communication/modules/transport/protlib/network_message.h \
+#  communication/modules/transport/protlib/tp_over_udp.h \
+#  communication/modules/transport/protlib/setuid.h \
+#  communication/modules/transport/protlib/cleanuphandler.h \
+#  communication/modules/transport/protlib/connectionmap_uds.h
 endif
 
 #------------> communication :: modules :: transport :: tcp
 
-if OMNET
-else
-libariba_la_SOURCES += \
-  communication/modules/transport/tcp/TCPTransport.cpp \
-  communication/modules/transport/tcp/TCPTransportLocator.cpp
-
-nobase_libariba_la_HEADERS += \
-  communication/modules/transport/tcp/TCPTransport.h \
-  communication/modules/transport/tcp/TCPTransportLocator.h
-endif
+#if OMNET
+#else
+#libariba_la_SOURCES += \
+#  communication/modules/transport/tcp/TCPTransport.cpp \
+#  communication/modules/transport/tcp/TCPTransportLocator.cpp
+
+#nobase_libariba_la_HEADERS += \
+#  communication/modules/transport/tcp/TCPTransport.h \
+#  communication/modules/transport/tcp/TCPTransportLocator.h
+#endif
 
 #------------> communication :: networkinfo
@@ -379,4 +380,93 @@
 nobase_libariba_la_HEADERS += \
   utility/measurement/PathloadMeasurement.h
+
+#------------> utility :: addressing
+
+libariba_la_SOURCES += \
+  utility/addressing/ip_address.cpp \
+  utility/addressing/tcpip_endpoint.cpp \
+  utility/addressing/rfcomm_endpoint.cpp \
+  utility/addressing/mac_address.cpp \
+  utility/addressing/port_address.cpp 
+
+nobase_libariba_la_HEADERS += \
+  utility/addressing/ip_address.hpp \
+  utility/addressing/test_addressing.hpp \
+  utility/addressing/tcpip_endpoint.hpp \
+  utility/addressing/endpoint_set.hpp \
+  utility/addressing/addressing.hpp \
+  utility/addressing/detail/compare_to_operators.hpp \
+  utility/addressing/detail/address_convenience.hpp \
+  utility/addressing/rfcomm_endpoint.hpp \
+  utility/addressing/mac_address.hpp \
+  utility/addressing/port_address.hpp \
+  utility/addressing/facades/to_string_v.hpp \
+  utility/addressing/facades/address_v.hpp \
+  utility/addressing/facades/vfacade.hpp \
+  utility/addressing/facades/comparable_v.hpp \
+  utility/addressing/facades/to_bytes_v.hpp
+
+#------------> utility :: transport
+
+libariba_la_SOURCES += \
+  utility/transport/tcpip/tcpip.cpp \
+  utility/transport/tcpip/protlib/timer_module.cpp \
+  utility/transport/tcpip/protlib/setuid.cpp \
+  utility/transport/tcpip/protlib/queuemanager.cpp \
+  utility/transport/tcpip/protlib/messages.cpp \
+  utility/transport/tcpip/protlib/fqueue.cpp \
+  utility/transport/tcpip/protlib/fastqueue.c \
+  utility/transport/tcpip/protlib/eclock_gettime.c \
+  utility/transport/tcpip/protlib/tp_over_udp.cpp \
+  utility/transport/tcpip/protlib/connectionmap_uds.cpp \
+  utility/transport/tcpip/protlib/network_message.cpp \
+  utility/transport/tcpip/protlib/threadsafe_db.cpp \
+  utility/transport/tcpip/protlib/timer.cpp \
+  utility/transport/tcpip/protlib/address.cpp \
+  utility/transport/tcpip/protlib/connectionmap.cpp \
+  utility/transport/tcpip/protlib/tp.cpp \
+  utility/transport/tcpip/protlib/tp_over_tcp.cpp \
+  utility/transport/tcpip/protlib/configuration.cpp \
+  utility/transport/tcpip/protlib/ie.cpp \
+  utility/transport/tcpip/protlib/threads.cpp \
+  utility/transport/tcpip/protlib/logfile.cpp \
+  utility/transport/transport_peer.cpp \
+  utility/transport/rfcomm/rfcomm.cpp \
+  utility/transport/asio/asio_io_service.cpp 
+
+nobase_libariba_la_HEADERS += \
+  utility/transport/test_transport.hpp \
+  utility/transport/tcpip/tcpip.hpp \
+  utility/transport/transport_peer.hpp \
+  utility/transport/transport_protocol.hpp \
+  utility/transport/rfcomm/rfcomm.hpp \
+  utility/transport/transport.hpp \
+  utility/transport/asio/bluetooth_endpoint.hpp \
+  utility/transport/asio/rfcomm.hpp \
+  utility/transport/transport_listener.hpp \
+  utility/transport/tcpip/protlib/threadsafe_db.h \
+  utility/transport/tcpip/protlib/configuration.h \
+  utility/transport/tcpip/protlib/ie.h \
+  utility/transport/tcpip/protlib/llhashers.h \
+  utility/transport/tcpip/protlib/fqueue.h \
+  utility/transport/tcpip/protlib/assocdata_uds.h \
+  utility/transport/tcpip/protlib/address.h \
+  utility/transport/tcpip/protlib/logfile.h \
+  utility/transport/tcpip/protlib/timer.h \
+  utility/transport/tcpip/protlib/queuemanager.h \
+  utility/transport/tcpip/protlib/messages.h \
+  utility/transport/tcpip/protlib/assocdata.h \
+  utility/transport/tcpip/protlib/protlib_types.h \
+  utility/transport/tcpip/protlib/tp_over_tcp.h \
+  utility/transport/tcpip/protlib/tp.h \
+  utility/transport/tcpip/protlib/threads.h \
+  utility/transport/tcpip/protlib/connectionmap.h \
+  utility/transport/tcpip/protlib/timer_module.h \
+  utility/transport/tcpip/protlib/fastqueue.h \
+  utility/transport/tcpip/protlib/tperror.h \
+  utility/transport/tcpip/protlib/network_message.h \
+  utility/transport/tcpip/protlib/setuid.h \
+  utility/transport/tcpip/protlib/cleanuphandler.h \
+  utility/transport/tcpip/protlib/connectionmap_uds.h
 
 #------------> utility :: messages
Index: /source/ariba/Node.cpp
===================================================================
--- /source/ariba/Node.cpp	(revision 5274)
+++ /source/ariba/Node.cpp	(revision 5284)
@@ -67,5 +67,5 @@
 		return;
 	}
-	ariba_mod.base_comm->start(ariba_mod.ip_addr, ariba_mod.tcp_port);
+	ariba_mod.base_comm->start();
 	base_overlay->start( *ariba_mod.base_comm, nodeId );
 	base_overlay->joinSpoVNet( spovnetId, *ep);
@@ -82,5 +82,5 @@
 	nodeId = generateNodeId(name);
 
-	ariba_mod.base_comm->start(ariba_mod.ip_addr, ariba_mod.tcp_port);
+	ariba_mod.base_comm->start();
 
 	base_overlay->start( *ariba_mod.base_comm, nodeId );
Index: /source/ariba/communication/BaseCommunication.cpp
===================================================================
--- /source/ariba/communication/BaseCommunication.cpp	(revision 5274)
+++ /source/ariba/communication/BaseCommunication.cpp	(revision 5284)
@@ -52,9 +52,13 @@
 namespace communication {
 
+#include "networkinfo/AddressDiscovery.hpp"
+
 use_logging_cpp(BaseCommunication);
-const BaseCommunication::LinkDescriptor BaseCommunication::LinkDescriptor::UNSPECIFIED;
-
-BaseCommunication::BaseCommunication()
-	: messageReceiver(NULL), network(NULL), transport(NULL), basecommStarted(false){
+const BaseCommunication::LinkDescriptor
+	BaseCommunication::LinkDescriptor::UNSPECIFIED;
+
+BaseCommunication::BaseCommunication() {
+	this->transport = NULL;
+	this->started = false;
 }
 
@@ -62,11 +66,10 @@
 }
 
-void BaseCommunication::start(const NetworkLocator* _locallocator, const uint16_t _listenport){
-
+void BaseCommunication::start() {
+	logging_info( "Starting up ..." );
 	currentSeqnum = 0;
-	listenport = _listenport;
-
-	logging_info( "starting up base communication and creating transports ..." );
-	logging_info( "using port " << listenport );
+
+	// creating transports
+	logging_info( "Creating transports ..." );
 
 #ifdef UNDERLAY_OMNET
@@ -77,90 +80,43 @@
 	network = new OmnetNetworkProtocol( module );
 #else
-	transport = new TCPTransport( listenport );
-	network = new IPv4NetworkProtocol();
+	transport = new transport_peer( localDescriptor.getEndpoints() );
 #endif
 
-	logging_debug( "searching for local locators ..." );
-
-	NetworkProtocol::NetworkLocatorSet locators = network->getAddresses();
-	NetworkProtocol::NetworkLocatorSet::iterator i = locators.begin();
-	NetworkProtocol::NetworkLocatorSet::iterator iend = locators.end();
-
-	//
-	// choose the first locator that is not localhost
-	//
-
-	bool foundLocator = false;
-
-	for( ; i != iend; i++){
-		logging_debug( "local locator found " << (*i)->toString() );
-		IPv4Locator* ipv4locator = dynamic_cast<IPv4Locator*>(*i);
-
-		// TODO: which locators are find to bind to?
-		// localhost is not too bad, works when testing locally
-		// with several instances. the manual override currently
-		// enables to use an arbitrary address, guess this is fine.
-		// so the manual override also can use ANY, LOCALHOST, BROADCAST
-
-		if( *ipv4locator != IPv4Locator::LOCALHOST &&
-		    *ipv4locator != IPv4Locator::ANY       &&
-		    *ipv4locator != IPv4Locator::BROADCAST  ){
-
-			ipv4locator->setPort(listenport);
-			localDescriptor.locator = ipv4locator;
-			localDescriptor.isUnspec = false;
-			logging_info( "binding to addr = " << ipv4locator->toString() );
-			foundLocator = true;
-			break;
-		}
-	} // for( ; i != iend; i++)
-
-
-	if( _locallocator != NULL ) {
-		if( localDescriptor.locator != NULL) delete localDescriptor.locator;
-		localDescriptor.locator = new IPv4Locator( IPv4Locator::fromString( _locallocator->toString()) );
-		localDescriptor.isUnspec = false;
-		logging_debug( "manual locator override, using locator=" <<
-					localDescriptor.locator->toString() );
-		foundLocator = true;
-	}
-
-	// if we found no local locator, exit using logging fatal
-	if( !foundLocator )
-		logging_fatal( "did not find a useable local locator!" );
-
-	transport->addMessageReceiver( this );
+	logging_info( "Searching for local locators ..." );
+	discoverEndpoints(localDescriptor.getEndpoints());
+	logging_info( "Done. Local endpoints = " << localDescriptor.toString() );
+
+	transport->register_listener( this );
 	transport->start();
 
 #ifndef UNDERLAY_OMNET
-	//
 	// bind to the network change detection
-	//
-
 	networkMonitor.registerNotification( this );
 #endif
 
-	//
 	// base comm startup done
-	//
-
-	basecommStarted = true;
-	logging_info( "base communication started up" );
+	started = true;
+	logging_info( "Started up." );
 }
 
 void BaseCommunication::stop() {
-
-	logging_info( "stopping base communication and transport ..." );
+	logging_info( "Stopping transports ..." );
 
 	transport->stop();
 	delete transport;
-	delete network;
-
-	basecommStarted = false;
-	logging_info( "base communication stopped" );
+	started = false;
+
+	logging_info( "Stopped." );
 }
 
 bool BaseCommunication::isStarted(){
-	return basecommStarted;
+	return started;
+}
+
+/// Sets the endpoints
+void BaseCommunication::setEndpoints( string& _endpoints ) {
+	localDescriptor.getEndpoints().assign(_endpoints);
+	logging_info("Setting local end-points: "
+		<< localDescriptor.getEndpoints().to_string());
 }
 
@@ -175,45 +131,23 @@
 
 	// debug
-	logging_debug( "request to establish link" );
-
-	//
-	// just use the first locator in the endp descriptors
-	//
-	if( descriptor.locator == NULL ){
-		logging_error( "invalid destination endpoint" );
-		return LinkID::UNSPECIFIED;
-	}
-
-	if( localDescriptor.locator == NULL ){
-		logging_error( "invalid local endpoint" );
-		return LinkID::UNSPECIFIED;
-	}
-
-	const NetworkLocator* remote = descriptor.locator;
-	const NetworkLocator* local =  localDescriptor.locator;
-
-	// create link identifier and link descriptor
-	if (linkid.isUnspecified()){
-		linkid = LinkID::create();
-		assert(!linkid.isUnspecified());
-	}
-
-	logging_debug( "creating new local descriptor entry with local link id " << linkid.toString() );
-	LinkDescriptor linkDescriptor( linkid, local, LinkID::UNSPECIFIED, remote, descriptor, false );
-	addLink( linkDescriptor );
-
-	//
-	// create a base msg with our link id and
-	// a request to open a link on the other side
-	//
-
-	logging_debug( "sending out base messages with request to open link to " << remote->toString() );
-	AribaBaseMsg baseMsg(
-			remote,
-			AribaBaseMsg::LINK_STATE_OPEN_REQUEST,
-			linkid,
-			LinkID::UNSPECIFIED );
-
-	transport->sendMessage(&baseMsg);
+	logging_debug( "Request to establish link" );
+
+	// create link identifier
+	if (linkid.isUnspecified())	linkid = LinkID::create();
+
+	// create link descriptor
+	logging_debug( "Creating new descriptor entry with local link id=" << linkid.toString() );
+	LinkDescriptor* ld = new LinkDescriptor();
+	ld->localLink = linkid;
+	addLink( ld );
+
+	// send a message to request new link to remote
+	logging_debug( "Send messages with request to open link to " << descriptor.toString() );
+	AribaBaseMsg baseMsg( AribaBaseMsg::typeLinkRequest, linkid );
+	baseMsg.getLocalDescriptor() = localDescriptor;
+
+	// serialize and send message
+	send( &baseMsg, descriptor );
+
 	return linkid;
 }
@@ -221,29 +155,24 @@
 void BaseCommunication::dropLink(const LinkID link) {
 
-	logging_debug( "starting to drop link " + link.toString() );
+	logging_debug( "Starting to drop link " + link.toString() );
 
 	// see if we have the link
-	LinkDescriptor& descriptor = queryLocalLink( link );
-	if( descriptor.isUnspecified() ){
-		logging_error( "don't know the link you want to drop "+ link.toString() );
+	LinkDescriptor& ld = queryLocalLink( link );
+	if( ld.isUnspecified() ) {
+		logging_error( "Don't know the link you want to drop "+ link.toString() );
 		return;
 	}
 
+	// tell the registered listeners
+	BOOST_FOREACH( CommunicationEvents* i, eventListener ) {
+		i->onLinkDown( link, ld.localLocator, ld.remoteLocator );
+	}
+
 	// create message to drop the link
-	logging_debug( "sending out link close request. for us, the link is closed now" );
-	AribaBaseMsg msg(
-		descriptor.remoteLocator,
-		AribaBaseMsg::LINK_STATE_CLOSE_REQUEST,
-		descriptor.localLink,
-		descriptor.remoteLink
-	);
+	logging_debug( "Sending out link close request. for us, the link is closed now" );
+	AribaBaseMsg msg( AribaBaseMsg::typeLinkClose, ld.localLink, ld.remoteLink );
 
 	// send message to drop the link
-	transport->sendMessage( &msg );
-
-	// tell the registered listeners
-	BOOST_FOREACH( CommunicationEvents* i, eventListener ){
-		i->onLinkDown( link, descriptor.localLocator, descriptor.remoteLocator );
-	}
+	send( &msg, ld );
 
 	// remove from map
@@ -253,36 +182,33 @@
 seqnum_t BaseCommunication::sendMessage( const LinkID lid, const Message* message) {
 
-	logging_debug( "sending out message to link " << lid.toString() );
+	logging_debug( "Sending out message to link " << lid.toString() );
 
 	// query local link info
-	LinkDescriptor& linkDesc = queryLocalLink(lid);
-	if( linkDesc.isUnspecified() ){
-		logging_error( "don't know the link with id " << lid.toString() );
+	LinkDescriptor& ld = queryLocalLink(lid);
+	if( ld.isUnspecified() ){
+		logging_error( "Don't know the link with id " << lid.toString() );
 		return -1;
 	}
 
+	// link not up-> error
+	if( !ld.up ) {
+		logging_error("Can not send on link " << lid.toString() << ": link not up");
+		return -1;
+	}
+
 	// create message
-	AribaBaseMsg msg(
-		linkDesc.remoteLocator,
-		AribaBaseMsg::LINK_STATE_DATA,
-		linkDesc.localLink,
-		linkDesc.remoteLink
-	);
+	AribaBaseMsg msg( AribaBaseMsg::typeData, ld.localLink, ld.remoteLink );
 
 	// encapsulate the payload message
 	msg.encapsulate( const_cast<Message*>(message) );
 
-	if( !linkDesc.linkup ){
-		logging_error("cant send message on link " << lid.toString() << ", link not up");
-		return -1;
-	}
-
 	// send message
-	transport->sendMessage( &msg );
+	send( &msg, ld );
+
+	// return sequence number
 	return ++currentSeqnum;
 }
 
 const EndpointDescriptor& BaseCommunication::getEndpointDescriptor(const LinkID link) const {
-
 	if( link == LinkID::UNSPECIFIED){
 		return localDescriptor;
@@ -294,14 +220,5 @@
 }
 
-void BaseCommunication::registerMessageReceiver(MessageReceiver* _receiver) {
-	messageReceiver = _receiver;
-}
-
-void BaseCommunication::unregisterMessageReceiver(MessageReceiver* _receiver) {
-	messageReceiver = NULL;
-}
-
 void BaseCommunication::registerEventListener(CommunicationEvents* _events){
-
 	if( eventListener.find( _events ) == eventListener.end() )
 		eventListener.insert( _events );
@@ -309,5 +226,4 @@
 
 void BaseCommunication::unregisterEventListener(CommunicationEvents* _events){
-
 	EventListenerSet::iterator i = eventListener.find( _events );
 	if( i != eventListener.end() )
@@ -315,257 +231,265 @@
 }
 
-
-bool BaseCommunication::receiveMessage(const Message* message, const LinkID& /*invalid*/, const NodeID& ){
-
-	//
-	// these messages arrive from the Transport module
-	// and are incoming network messages. Unpack the
-	// AribaBaseMsg and handle control packets,
-	// deliver data packets to the overlay
-	//
-
-	AribaBaseMsg* spovmsg = ((Message*)message)->decapsulate<AribaBaseMsg>();
-	logging_debug( "receiving base comm message of type " << spovmsg->getTypeString() );
-
-	//
-	// deliver data to the overlays. we just give the
-	// inner packet to every registered overlay ...
-	//
-
-	if( spovmsg->getType() == AribaBaseMsg::LINK_STATE_DATA ){
-
-		logging_debug( "received data message, forwarding to overlay" );
-
-		//
-		// put the linkid as address into the message
-		// and sent it to the receiver
-		//
-
-		if( messageReceiver != NULL ) {
-			messageReceiver->receiveMessage(
-				spovmsg,
-				spovmsg->getRemoteLink(),
-				NodeID::UNSPECIFIED
+SystemEventType TransportEvent("Transport");
+SystemEventType MessageDispatchEvent("MessageDispatchEvent", TransportEvent );
+
+class DispatchMsg {
+public:
+	address_v* local;
+	address_v* remote;
+	Message* message;
+};
+
+/// called when a system event is emitted by system queue
+void BaseCommunication::handleSystemEvent(const SystemEvent& event) {
+
+	// dispatch received messages
+	if ( event.getType() == MessageDispatchEvent ){
+		logging_debug( "Forwarding message receiver" );
+		DispatchMsg* dmsg = event.getData<DispatchMsg>();
+		Message* msg = dmsg->message;
+		receiveMessage(msg, dmsg->local, dmsg->remote);
+		msg->dropPayload();
+		delete dmsg;
+		delete msg;
+	}
+}
+
+/// called when a message is received form transport_peer
+void BaseCommunication::receive_message(transport_protocol* transport,
+	const address_vf local, const address_vf remote, const uint8_t* data,
+	size_t size) {
+
+//	logging_debug( "Dispatching message" );
+
+	// convert data
+	Data data_( const_cast<uint8_t*>(data), size * 8 );
+	DispatchMsg* dmsg = new DispatchMsg();
+
+	Message* msg = new Message(data_);
+	dmsg->local = local->clone();
+	dmsg->remote = remote->clone();
+	dmsg->message = msg;
+
+	SystemQueue::instance().scheduleEvent(
+		SystemEvent( this, MessageDispatchEvent, dmsg )
+	);
+}
+
+/// handles a message from the underlay transport
+void BaseCommunication::receiveMessage(const Message* message,
+	const address_v* local, const address_v* remote ){
+
+	/// decapsulate message
+	AribaBaseMsg* msg = ((Message*)message)->decapsulate<AribaBaseMsg>();
+	logging_debug( "Receiving message of type " << msg->getTypeString() );
+
+	// handle message
+	switch (msg->getType()) {
+
+		// ---------------------------------------------------------------------
+		// data message
+		// ---------------------------------------------------------------------
+		case AribaBaseMsg::typeData: {
+			logging_debug( "Received data message, forwarding to overlay" );
+			if( messageReceiver != NULL ) {
+				messageReceiver->receiveMessage(
+					msg, msg->getRemoteLink(), NodeID::UNSPECIFIED
+				);
+			}
+			break;
+		}
+
+		// ---------------------------------------------------------------------
+		// handle link request from remote
+		// ---------------------------------------------------------------------
+		case AribaBaseMsg::typeLinkRequest: {
+			logging_debug( "Received link open request" );
+
+			/// only answer the first request
+			if (!queryRemoteLink(msg->getLocalLink()).isUnspecified()) {
+				logging_debug("Link request already received. Ignore!");
+				break;
+			}
+
+			/// create link ids
+			LinkID localLink  = LinkID::create();
+			LinkID remoteLink = msg->getLocalLink();
+			logging_debug( "local=" << local->to_string()
+				<< " remote=" << remote->to_string()
 			);
+
+			// check if link creation is allowed by ALL listeners
+			bool allowlink = true;
+			BOOST_FOREACH( CommunicationEvents* i, eventListener ){
+				allowlink &= i->onLinkRequest( localLink, local, remote );
+			}
+
+			// not allowed-> warn
+			if( !allowlink ){
+				logging_warn( "Overlay denied creation of link" );
+				return;
+			}
+
+			// create descriptor
+			LinkDescriptor* ld = new LinkDescriptor();
+			ld->localLink = localLink;
+			ld->remoteLink = remoteLink;
+			ld->localLocator = local->clone();
+			ld->remoteLocator = remote->clone();
+			ld->remoteEndpoint = msg->getLocalDescriptor();
+
+			// add layer 1-3 addresses
+			ld->remoteEndpoint.getEndpoints().add(
+				ld->remoteLocator, endpoint_set::Layer1_3);
+			localDescriptor.getEndpoints().add(
+				local, endpoint_set::Layer1_3
+			);
+
+			// link is now up-> add it
+			ld->up = true;
+			addLink(ld);
+
+			// link is up!
+			logging_debug( "Link (initiated from remote) is up with "
+				<< "local(id=" << ld->localLink.toString() << ","
+				<< "locator=" << ld->localLocator->to_string() << ") "
+				<< "remote(id=" << ld->remoteLink.toString() << ", "
+				<< "locator=" << ld->remoteLocator->to_string() << ")"
+			);
+
+			// sending link request reply
+			logging_debug( "Sending link request reply with ids "
+				<< "local=" << localLink.toString() << ", "
+				<< "remote=" << remoteLink.toString() );
+			AribaBaseMsg reply( AribaBaseMsg::typeLinkReply, localLink, remoteLink );
+			reply.getLocalDescriptor() = localDescriptor;
+			reply.getRemoteDescriptor() = ld->remoteEndpoint;
+
+			send( &reply, *ld );
+
+			// inform listeners about new open link
+			BOOST_FOREACH( CommunicationEvents* i, eventListener ) {
+				i->onLinkUp( localLink, ld->localLocator, ld->remoteLocator);
+			}
+
+			// done
+			break;
 		}
 
-	} // LINK_STATE_DATA
-
-	//
-	// handle link open requests
-	//
-
-	else if( spovmsg->getType() == AribaBaseMsg::LINK_STATE_OPEN_REQUEST ){
-
-		logging_debug( "received link open request" );
-
-		//
-		// create a link context
-		//
-
-		//  in an incoming packet the localLink is from
-		// the sender perspective local and from our
-		// perspective remote
-
-		logging_debug( "creating local link" );
-
-		LinkID localLink  = LinkID::create();
-		LinkID remoteLink = spovmsg->getLocalLink();
-
-		if(localLink.isUnspecified()){
-			logging_error("local link is unspecified");
-			return false;
+		// ---------------------------------------------------------------------
+		// handle link request reply
+		// ---------------------------------------------------------------------
+		case AribaBaseMsg::typeLinkReply: {
+			logging_debug( "Received link open reply for a link we initiated" );
+
+			// this is a reply to a link open request, so we have already
+			// a link mapping and can now set the remote link to valid
+			LinkDescriptor& ld = queryLocalLink( msg->getRemoteLink() );
+
+			// no link found-> warn!
+			if (ld.isUnspecified()) {
+				logging_warn("Failed to find local link " << msg->getRemoteLink().toString());
+				return;
+			}
+
+			// set remote locator and link id
+			ld.remoteLink = msg->getLocalLink();
+			ld.remoteLocator = remote->clone();
+			localDescriptor.getEndpoints().add(
+				msg->getRemoteDescriptor().getEndpoints(),
+				endpoint_set::Layer1_3
+			);
+			ld.up = true;
+
+			logging_debug( "Link is now up with local id "
+				<< ld.localLink.toString() << " and remote id "
+				<< ld.remoteLink.toString() );
+
+
+			// inform lisneters about link up event
+			BOOST_FOREACH( CommunicationEvents* i, eventListener ){
+				i->onLinkUp( ld.localLink, ld.localLocator, ld.remoteLocator );
+			}
+
+			// done
+			break;
 		}
 
-		if(remoteLink.isUnspecified()){
-			logging_error("remote link is unspecified");
-			return false;
+		// ---------------------------------------------------------------------
+		// handle link close requests
+		// ---------------------------------------------------------------------
+		case AribaBaseMsg::typeLinkClose: {
+			// get remote link
+			const LinkID& localLink = msg->getRemoteLink();
+			logging_debug( "Received link close request for link " << localLink.toString() );
+
+			// searching for link, not found-> warn
+			LinkDescriptor& linkDesc = queryLocalLink( localLink );
+			if (linkDesc.isUnspecified()) {
+				logging_warn("Failed to find local link " << localLink.toString());
+				return;
+			}
+
+			// inform listeners
+			BOOST_FOREACH( CommunicationEvents* i, eventListener ){
+				i->onLinkDown( linkDesc.localLink,
+						linkDesc.localLocator, linkDesc.remoteLocator );
+			}
+
+			// remove the link descriptor
+			removeLink( localLink );
+
+			// done
+			break;
 		}
 
-		const NetworkLocator* localLocator  = dynamic_cast<const NetworkLocator*>(localDescriptor.locator);
-		const NetworkLocator* remoteLocator = dynamic_cast<const NetworkLocator*>(message->getSourceAddress());
-
-		logging_debug( "localLocator=" << localLocator->toString()
-				<< " remoteLocator=" << remoteLocator->toString());
-
-		// ask the registered listeners if this link
-		// creation is fine. we will only allow the
-		// link if all of them agree
-
-		bool allowlink = true;
-		BOOST_FOREACH( CommunicationEvents* i, eventListener ){
-			allowlink &= i->onLinkRequest( localLink, localLocator, remoteLocator );
+		// ---------------------------------------------------------------------
+		// handle link locator changes
+		// ---------------------------------------------------------------------
+		case AribaBaseMsg::typeLinkUpdate: {
+			const LinkID& localLink = msg->getRemoteLink();
+			logging_debug( "Received link update for link "
+				<< localLink.toString() );
+
+			// find the link description
+			LinkDescriptor& linkDesc = queryLocalLink( localLink );
+			if (linkDesc.isUnspecified()) {
+				logging_warn("Failed to update local link "
+					<< localLink.toString());
+				return;
+			}
+
+			// update the remote locator
+			const address_v* oldremote = linkDesc.remoteLocator;
+			linkDesc.remoteLocator = remote->clone();
+
+			// inform the listeners (local link has _not_ changed!)
+			BOOST_FOREACH( CommunicationEvents* i, eventListener ){
+				i->onLinkChanged(
+					linkDesc.localLink,	// linkid
+					linkDesc.localLocator,	// old local
+					linkDesc.localLocator,	// new local
+					oldremote,		// old remote
+					linkDesc.remoteLocator	// new remote
+				);
+			}
+
+			// done
+			break;
 		}
-
-		if( !allowlink ){
-			logging_warn( "overlay denied creation of link" );
-			return true;
-		}
-
-		//
-		// create and save the descriptor for the link
-		//
-
-		LinkDescriptor linkDescriptor(localLink, localLocator, remoteLink,
-					remoteLocator, EndpointDescriptor(remoteLocator), true);
-
-		logging_debug( "saving new link descriptor with " <<
-				"[local link " << localLink.toString() << "] " <<
-				"[local locator " << localLocator->toString() << "] " <<
-				"[remote link " << remoteLink.toString() << "] " <<
-				"[remote locator " << remoteLocator->toString() << "]" <<
-				"[link up true]" );
-
-		addLink( linkDescriptor );
-
-		//
-		// send out a link reply
-		//
-
-		logging_debug( "sending back link open reply for " <<
-					"[local link " << localLink.toString() << "] " <<
-					"[remote link " << remoteLink.toString() << "]" );
-
-		AribaBaseMsg reply(remoteLocator,
-				     AribaBaseMsg::LINK_STATE_OPEN_REPLY,
-				     localLink,
-				     remoteLink);
-
-		transport->sendMessage( &reply );
-
-		//
-		// the link is now open
-		//
-
-		BOOST_FOREACH( CommunicationEvents* i, eventListener ){
-			i->onLinkUp( localLink, localLocator, remoteLocator );
-		}
-
-	} // LINK_STATE_OPEN_REQUEST
-
-	//
-	// handle link open replies
-	//
-
-	else if( spovmsg->getType() == AribaBaseMsg::LINK_STATE_OPEN_REPLY ){
-
-		logging_debug( "received link open reply for a link we initiated" );
-
-		// this is a reply to a link open request, so we have already
-		// a link mapping and can now set the remote link to valid
-		LinkDescriptor& linkDesc = queryLocalLink( spovmsg->getRemoteLink() );
-
-		if (linkDesc.isUnspecified()) {
-			logging_warn("failed to find local link " << spovmsg->getRemoteLink().toString());
-			return false;
-		}
-
-		linkDesc.remoteLink = spovmsg->getLocalLink();
-		linkDesc.linkup = true;
-
-		logging_debug( "the link is now up with local link id " << linkDesc.localLink.toString() <<
-											" and remote link id " << linkDesc.remoteLink.toString() );
-
-		// notify the baseoverlay that the link is up, so
-		// it can exchange nodeids over this link. then we
-		// can send the queued messages, as both nodes have
-		// to know their nodeids first
-
-		BOOST_FOREACH( CommunicationEvents* i, eventListener ){
-			i->onLinkUp( linkDesc.localLink, linkDesc.localLocator, linkDesc.remoteLocator );
-		}
-
-	} // LINK_STATE_OPEN_REPLY
-
-	//
-	// handle link close requests
-	//
-
-	else if( spovmsg->getType() == AribaBaseMsg::LINK_STATE_CLOSE_REQUEST ){
-
-		const LinkID& localLink = spovmsg->getRemoteLink();
-		logging_debug( "received link close request for link " << localLink.toString() );
-
-		//
-		// the link is closed immediately, we
-		// don't need to send out a reply, so we
-		// delete the mapping and inform
-		//
-
-		LinkDescriptor& linkDesc = queryLocalLink( localLink );
-		if (linkDesc.isUnspecified()) {
-			logging_warn("Failed to find local link " << localLink.toString());
-			return false;
-		}
-
-		BOOST_FOREACH( CommunicationEvents* i, eventListener ){
-			i->onLinkDown( linkDesc.localLink, linkDesc.localLocator, linkDesc.remoteLocator );
-		}
-
-		//
-		// remove the link descriptor
-		//
-
-		removeLink( localLink );
-
-	} // LINK_STATE_CLOSE_REQUEST
-
-	//
-	// handle locator updates
-	//
-
-	else if( spovmsg->getType() == AribaBaseMsg::LINK_STATE_UPDATE ){
-
-		const LinkID& localLink = spovmsg->getRemoteLink();
-		logging_debug( "received link update for link " << localLink.toString() );
-
-		//
-		// find the link description
-		//
-
-		LinkDescriptor& linkDesc = queryLocalLink( localLink );
-		if (linkDesc.isUnspecified()) {
-			logging_warn("Failed to update local link " << localLink.toString());
-			return false;
-		}
-
-		//
-		// update the remote locator
-		//
-
-		const NetworkLocator* oldremote = linkDesc.remoteLocator;
-		linkDesc.remoteLocator = dynamic_cast<const NetworkLocator*>(message->getSourceAddress());
-
-		//
-		// inform the listeners (local link has _not_ changed!)
-		//
-
-		BOOST_FOREACH( CommunicationEvents* i, eventListener ){
-			i->onLinkChanged(
-				linkDesc.localLink,	// linkid
-				linkDesc.localLocator,	// old local
-				linkDesc.localLocator,	// new local
-				oldremote,		// old remote
-				linkDesc.remoteLocator	// new remote
-			);
-		}
-
-	} // LINK_STATE_UPDATE
-
-	return true;
-}
-
-void BaseCommunication::addLink( const LinkDescriptor& link ) {
+	}
+}
+
+/// add a newly allocated link to the set of links
+void BaseCommunication::addLink( LinkDescriptor* link ) {
 	linkSet.push_back( link );
 }
 
+/// remove a link from set
 void BaseCommunication::removeLink( const LinkID& localLink ) {
-
-	LinkSet::iterator i = linkSet.begin();
-	LinkSet::iterator iend = linkSet.end();
-
-	for( ; i != iend; i++){
-		if( (*i).localLink != localLink) continue;
-
+	for(LinkSet::iterator i=linkSet.begin(); i != linkSet.end(); i++){
+		if( (*i)->localLink != localLink) continue;
+		delete *i;
 		linkSet.erase( i );
 		break;
@@ -573,28 +497,28 @@
 }
 
+/// query a descriptor by local link id
 BaseCommunication::LinkDescriptor& BaseCommunication::queryLocalLink( const LinkID& link ) const {
 	for (int i=0; i<linkSet.size();i++)
-		if (linkSet[i].localLink == link) return (LinkDescriptor&)linkSet[i];
+		if (linkSet[i]->localLink == link) return (LinkDescriptor&)*linkSet[i];
 	return (LinkDescriptor&)LinkDescriptor::UNSPECIFIED;
 }
 
+/// query a descriptor by remote link id
 BaseCommunication::LinkDescriptor& BaseCommunication::queryRemoteLink( const LinkID& link ) const {
 	for (int i=0; i<linkSet.size();i++)
-		if (linkSet[i].remoteLink == link) return (LinkDescriptor&)linkSet[i];
+		if (linkSet[i]->remoteLink == link) return (LinkDescriptor&)*linkSet[i];
 	return (LinkDescriptor&)LinkDescriptor::UNSPECIFIED;
 }
 
-LinkIDs BaseCommunication::getLocalLinks( const EndpointDescriptor& ep ) const {
+LinkIDs BaseCommunication::getLocalLinks( const address_v* addr ) const {
 	LinkIDs ids;
-
 	for (int i=0; i<linkSet.size(); i++){
-		if( ep == EndpointDescriptor::UNSPECIFIED ){
-			ids.push_back( linkSet[i].localLink );
+		if( addr == NULL ){
+			ids.push_back( linkSet[i]->localLink );
 		} else {
-			if ( linkSet[i].remoteLocator == ep.locator )
-				ids.push_back( linkSet[i].localLink );
+			if ( *linkSet[i]->remoteLocator == *addr )
+				ids.push_back( linkSet[i]->localLink );
 		}
 	}
-
 	return ids;
 }
@@ -609,9 +533,8 @@
 #endif // UNDERLAY_OMNET
 
-	//
+/*- disabled!
+
 	// we only care about address changes, not about interface changes
 	// as address changes are triggered by interface changes, we are safe here
-	//
-
 	if( info.type != NetworkChangeInterface::EventTypeAddressNew &&
 		info.type != NetworkChangeInterface::EventTypeAddressDelete ) return;
@@ -619,8 +542,5 @@
 	logging_info( "base communication is handling network address changes" );
 
-	//
 	// get all now available addresses
-	//
-
 	NetworkInformation networkInformation;
 	AddressInformation addressInformation;
@@ -745,4 +665,17 @@
 		transport->sendMessage( &updateMsg );
 	}
+*/
+}
+
+/// sends a message to all end-points in the end-point descriptor
+void BaseCommunication::send(Message* message, const EndpointDescriptor& endpoint) {
+	Data data = data_serialize( message, DEFAULT_V );
+	transport->send( endpoint.getEndpoints(), data.getBuffer(), data.getLength() / 8);
+}
+
+/// sends a message to the remote locator inside the link descriptor
+void BaseCommunication::send(Message* message, const LinkDescriptor& desc) {
+	Data data = data_serialize( message, DEFAULT_V );
+	transport->send( desc.remoteLocator, data.getBuffer(), data.getLength() / 8);
 }
 
Index: /source/ariba/communication/BaseCommunication.h
===================================================================
--- /source/ariba/communication/BaseCommunication.h	(revision 5274)
+++ /source/ariba/communication/BaseCommunication.h	(revision 5284)
@@ -40,4 +40,5 @@
 #define BASECOMMUNICATION_H_
 
+// boost & std includes
 #include <ext/hash_map>
 #include <ext/hash_set>
@@ -49,65 +50,59 @@
 #include <boost/foreach.hpp>
 
+// utilities
 #include "ariba/utility/types.h"
 #include "ariba/utility/messages.h"
 #include "ariba/utility/logging/Logging.h"
 #include "ariba/utility/misc/Demultiplexer.hpp"
-
+#include "ariba/utility/system/SystemEventListener.h"
+
+// new transport and addressing
+#include "ariba/utility/addressing/addressing.hpp"
+#include "ariba/utility/transport/transport.hpp"
+
+// communication
 #include "ariba/communication/CommunicationEvents.h"
 #include "ariba/communication/EndpointDescriptor.h"
+#include "ariba/communication/messages/AribaBaseMsg.h"
+
+// network changes
 #include "ariba/communication/networkinfo/NetworkChangeInterface.h"
 #include "ariba/communication/networkinfo/NetworkChangeDetection.h"
 #include "ariba/communication/networkinfo/NetworkInformation.h"
 #include "ariba/communication/networkinfo/AddressInformation.h"
-#include "ariba/communication/messages/AribaBaseMsg.h"
-#include "ariba/communication/modules/transport/TransportProtocol.h"
-#include "ariba/communication/modules/network/NetworkProtocol.h"
-#include "ariba/communication/modules/network/NetworkLocator.h"
-
-#ifndef UNDERLAY_OMNET
-  #include "ariba/communication/modules/transport/tcp/TCPTransport.h"
-  #include "ariba/communication/modules/network/ip/IPv4NetworkProtocol.h"
-#endif
-
-using __gnu_cxx::hash_set;
-using __gnu_cxx::hash_map;
-
-using std::cout;
-using std::set;
-using std::map;
-using std::vector;
-using std::pair;
-using std::make_pair;
-using std::find;
-
-using ariba::communication::NetworkChangeDetection;
-using ariba::communication::NetworkChangeInterface;
-using ariba::communication::NetworkInterfaceList;
-using ariba::communication::NetworkInformation;
-using ariba::communication::AddressInformation;
-using ariba::communication::AddressList;
-using ariba::communication::AribaBaseMsg;
-using ariba::communication::CommunicationEvents;
-
-using ariba::utility::Demultiplexer;
-using ariba::utility::QoSParameterSet;
-using ariba::utility::SecurityParameterSet;
-using ariba::utility::Address;
-using ariba::utility::LinkID;
-using ariba::utility::LinkIDs;
-using ariba::utility::Message;
-using ariba::utility::MessageReceiver;
-using ariba::utility::seqnum_t;
-
-using ariba::communication::TransportProtocol;
-using ariba::communication::NetworkProtocol;
-using ariba::communication::NetworkLocator;
-#ifndef UNDERLAY_OMNET
-  using ariba::communication::IPv4NetworkProtocol;
-  using ariba::communication::TCPTransport;
-#endif
+
+// deprecated
+//#include "ariba/communication/modules/transport/TransportProtocol.h"
+//#include "ariba/communication/modules/network/NetworkProtocol.h"
+//#include "ariba/communication/modules/network/NetworkLocator.h"
+
+// disabled
+//#ifndef UNDERLAY_OMNET
+//  #include "ariba/communication/modules/transport/tcp/TCPTransport.h"
+//  #include "ariba/communication/modules/network/ip/IPv4NetworkProtocol.h"
+//#endif
+
+// deprecated
+//using ariba::communication::TransportProtocol;
+//using ariba::communication::NetworkProtocol;
+//using ariba::communication::NetworkLocator;
+
+// disabled
+//#ifndef UNDERLAY_OMNET
+//  using ariba::communication::IPv4NetworkProtocol;
+//  using ariba::communication::TCPTransport;
+//#endif
 
 namespace ariba {
 namespace communication {
+
+using namespace std;
+using namespace ariba::addressing;
+using namespace ariba::transport;
+using namespace ariba::utility;
+
+// use base ariba types (clarifies multiple definitions)
+using ariba::utility::Message;
+using ariba::utility::seqnum_t;
 
 /**
@@ -119,50 +114,34 @@
  * @author Sebastian Mies, Christoph Mayer
  */
-class BaseCommunication : public MessageReceiver, NetworkChangeInterface {
+class BaseCommunication: public NetworkChangeInterface,
+	public SystemEventListener, public transport_listener {
 	use_logging_h(BaseCommunication);
+
 public:
-
-	/**
-	 * Default ctor that just creates an empty
-	 * non functional base communication
-	 */
+	/// Default ctor that just creates an non-functional base communication
 	BaseCommunication();
 
-	/**
-	 * Default dtor that does nothing
-	 */
+	/// Default dtor that does nothing
 	virtual ~BaseCommunication();
 
-	/**
-	 * Startup the base communication, start modules etc.
-	 */
-	void start(const NetworkLocator* _locallocator, const uint16_t _listenport);
-
-	/**
-	 * stop the base communication, stop modules etc.
-	 */
+	/// Startup the base communication, start modules etc.
+	void start();
+
+	/// Stops the base communication, stop modules etc.
 	void stop();
 
-	/*
-	 * Check whether the base communication has been started up
-	 */
+	/// Sets the endpoints
+	void setEndpoints( string& endpoints );
+
+	/// Check whether the base communication has been started up
 	bool isStarted();
 
-
-	/**
-	 * Establishes a link to another end-point.
-	 */
-	const LinkID establishLink(
-		const EndpointDescriptor& descriptor,
-		const LinkID& linkid = LinkID::UNSPECIFIED,
-		const QoSParameterSet& qos = QoSParameterSet::DEFAULT,
-		const SecurityParameterSet& sec = SecurityParameterSet::DEFAULT
-	);
-
-	/**
-	 * Drops a link.
-	 *
-	 * @param The link id of the link that should be dropped
-	 */
+	/// Establishes a link to another end-point.
+	const LinkID establishLink(const EndpointDescriptor& descriptor,
+		const LinkID& linkid = LinkID::UNSPECIFIED, const QoSParameterSet& qos =
+				QoSParameterSet::DEFAULT, const SecurityParameterSet& sec =
+				SecurityParameterSet::DEFAULT);
+
+	/// Drops a link
 	void dropLink(const LinkID link);
 
@@ -182,5 +161,6 @@
 	 * @return The end-point descriptor of the link's end-point
 	 */
-	const EndpointDescriptor& getEndpointDescriptor( const LinkID link = LinkID::UNSPECIFIED ) const;
+	const EndpointDescriptor& getEndpointDescriptor(const LinkID link =
+			LinkID::UNSPECIFIED) const;
 
 	/**
@@ -190,5 +170,5 @@
 	 * @return List of LinkID
 	 */
-	LinkIDs getLocalLinks( const EndpointDescriptor& ep = EndpointDescriptor::UNSPECIFIED ) const;
+	LinkIDs getLocalLinks(const address_v* addr) const;
 
 	/**
@@ -197,5 +177,7 @@
 	 * @param _receiver The receiving side
 	 */
-	void registerMessageReceiver( MessageReceiver* _receiver );
+	void registerMessageReceiver(MessageReceiver* receiver) {
+		messageReceiver = receiver;
+	}
 
 	/**
@@ -204,28 +186,36 @@
 	 * @param _receiver The receiving side
 	 */
-	void unregisterMessageReceiver( MessageReceiver* _receiver );
-
-	void registerEventListener( CommunicationEvents* _events );
-	void unregisterEventListener( CommunicationEvents* _events );
+	void unregisterMessageReceiver(MessageReceiver* receiver) {
+		messageReceiver = NULL;
+	}
+
+	void registerEventListener(CommunicationEvents* _events);
+
+	void unregisterEventListener(CommunicationEvents* _events);
+
+public:
+
+	/// called when a system event is emitted by system queue
+	virtual void handleSystemEvent(const SystemEvent& event);
+
+	/// called when a message is received form transport_peer
+	virtual void receive_message(transport_protocol* transport,
+		const address_vf local, const address_vf remote, const uint8_t* data,
+		size_t size);
 
 protected:
 
-	/**
-	 * Called from the Transport when async items
-	 * from the SystemQueue are delivered
-	 */
-	virtual bool receiveMessage( const Message* message, const LinkID& link, const NodeID& node );
-
-	/**
-	 * Called when a network interface change happens
-	 */
-	virtual void onNetworkChange( const NetworkChangeInterface::NetworkChangeInfo& info );
+	/// handle received message from a transport module
+	void receiveMessage(const Message* message,
+		const address_v* local, const address_v* remote );
+
+	/// called when a network interface change happens
+	virtual void onNetworkChange(
+		const NetworkChangeInterface::NetworkChangeInfo& info);
 
 private:
-
-	/**
-	 * A link descriptor consisting of the
-	 * end-point descriptor and currently used locator and
-	 * message receiver
+	/**
+	 * A link descriptor consisting of the end-point descriptor and currently
+	 * used underlay address.
 	 */
 	class LinkDescriptor {
@@ -233,118 +223,80 @@
 		static const LinkDescriptor UNSPECIFIED;
 
+		/// default constructor
 		LinkDescriptor() :
-			localLink(LinkID::UNSPECIFIED),
-			localLocator(NULL),
-			remoteLink(LinkID::UNSPECIFIED),
-			remoteLocator(NULL),
-			remoteEndpoint(EndpointDescriptor::UNSPECIFIED),
-			linkup(false) {
+			localLink(LinkID::UNSPECIFIED), localLocator(NULL),
+			remoteLink(LinkID::UNSPECIFIED), remoteLocator(NULL),
+			remoteEndpoint(EndpointDescriptor::UNSPECIFIED), up(false) {
 		}
 
-		LinkDescriptor(const LinkID& _localLink, const NetworkLocator*& _localLocator,
-				const LinkID& _remoteLink, const NetworkLocator*& _remoteLocator,
-				const EndpointDescriptor& _remoteEndpoint, bool _linkup ) :
-			localLink(_localLink),
-			localLocator(_localLocator),
-			remoteLink(_remoteLink),
-			remoteLocator(_remoteLocator),
-			remoteEndpoint(_remoteEndpoint),
-			linkup(_linkup) {
+		~LinkDescriptor() {
+			if (localLocator!=NULL)  delete localLocator;
+			if (remoteLocator!=NULL) delete remoteLocator;
 		}
 
-		LinkDescriptor( const LinkDescriptor& desc ) :
-			localLink(desc.localLink),
-			localLocator(desc.localLocator),
-			remoteLink(desc.remoteLink),
-			remoteLocator(desc.remoteLocator),
-			remoteEndpoint(desc.remoteEndpoint),
-			linkup(desc.linkup) {
+		/// returns true if this is the UNSPECIFIED object
+		bool isUnspecified() const {
+			return this == &UNSPECIFIED;
 		}
 
-		bool isUnspecified() const {
-			return (this == &UNSPECIFIED);
-		}
-
-		LinkID 					localLink;
-		const NetworkLocator* 	localLocator;
-		LinkID 					remoteLink;
-		const NetworkLocator* 	remoteLocator;
-		EndpointDescriptor 		remoteEndpoint;
-
-		bool 					linkup;
+		/// link identifiers
+		LinkID localLink;
+		LinkID remoteLink;
+
+		/// used underlay addresses for the link
+		const address_v* localLocator;
+		const address_v* remoteLocator;
+
+		/// the remote end-point descriptor
+		EndpointDescriptor remoteEndpoint;
+
+		/// flag, whether this link is up
+		bool up;
 	};
 
-	/**
-	 * Link management: add a link
-	 */
-	void addLink( const LinkDescriptor& link );
-
-	/**
-	 * Link management: remove alink
-	 */
-	void removeLink( const LinkID& localLink );
-
-	/**
-	 * Link management: get link information using the local link
-	 */
-	LinkDescriptor& queryLocalLink( const LinkID& localLink ) const;
-
-	/**
-	 * Link management: get link information using the remote link
-	 */
-	LinkDescriptor& queryRemoteLink( const LinkID& remoteLink ) const;
-
-	/**
-	 * Link management: list of links
-	 */
-	typedef vector<LinkDescriptor> LinkSet;
-
-	/**
-	 * Link management: the set of currently managed links
-	 */
+	/// Link management: list of links
+	typedef vector<LinkDescriptor*> LinkSet;
+
+	/// Link management: the set of currently managed links
 	LinkSet linkSet;
 
-	/**
-	 * The message receiver
-	 */
-	MessageReceiver* messageReceiver;
-
-	/**
-	 * The local end-point descriptor
-	 */
+	/// Link management: add a link
+	void addLink( LinkDescriptor* link );
+
+	/// Link management: remove a link
+	void removeLink(const LinkID& localLink);
+
+	/// Link management: get link information using the local link
+	LinkDescriptor& queryLocalLink(const LinkID& localLink) const;
+
+	/// Link management: get link information using the remote link
+	LinkDescriptor& queryRemoteLink(const LinkID& remoteLink) const;
+
+	/// The local end-point descriptor
 	EndpointDescriptor localDescriptor;
 
-	/**
-	 * Network information and protocol
-	 */
-	NetworkProtocol* network;
-
-	/**
-	 * Transport information and protocol
-	 */
-	TransportProtocol* transport;
-
 #ifndef UNDERLAY_OMNET
-	/**
-	 * Detect changes in the routing/interface, etc.
-	 * stuff needed for mobility detection
-	 */
+	/// network change detector
 	NetworkChangeDetection networkMonitor;
 #endif
-
-	/**
-	 * The local listen port
-	 */
-	uint16_t listenport;
-
+	/// event listener
 	typedef set<CommunicationEvents*> EventListenerSet;
 	EventListenerSet eventListener;
 
+	/// sequence numbers
 	seqnum_t currentSeqnum;
 
-	/**
-	 * state of the base communication
-	 */
-	bool basecommStarted;
+	/// transport peer
+	transport_peer* transport;
+
+	/// the base overlay message receiver
+	MessageReceiver* messageReceiver;
+
+	/// convenience: send message to peer
+	void send( Message* message, const EndpointDescriptor& endpoint );
+	void send( Message* message, const LinkDescriptor& descriptor );
+
+	/// state of the base communication
+	bool started;
 
 };
@@ -352,3 +304,3 @@
 }} // namespace ariba, communication
 
-#endif /*BASECOMMUNICATION_H_*/
+#endif /* BASECOMMUNICATION_H_ */
Index: /source/ariba/communication/CommunicationEvents.cpp
===================================================================
--- /source/ariba/communication/CommunicationEvents.cpp	(revision 5274)
+++ /source/ariba/communication/CommunicationEvents.cpp	(revision 5284)
@@ -48,22 +48,28 @@
 }
 
-bool CommunicationEvents::onLinkRequest( const LinkID& id, const NetworkLocator* local, const NetworkLocator* remote ) {
+bool CommunicationEvents::onLinkRequest(const LinkID& id,
+	const address_v* local, const address_v* remote) {
 	return true;
 }
 
-void CommunicationEvents::onLinkUp( const LinkID& id, const NetworkLocator* local, const NetworkLocator* remote ) {
+void CommunicationEvents::onLinkUp(const LinkID& id, const address_v* local,
+	const address_v* remote) {
 }
 
-void CommunicationEvents::onLinkDown( const LinkID& id, const NetworkLocator* local, const NetworkLocator* remote ) {
+void CommunicationEvents::onLinkDown(const LinkID& id, const address_v* local,
+	const address_v* remote) {
 }
 
-
-void CommunicationEvents::onLinkChanged( const LinkID& id, const NetworkLocator* oldlocal, const NetworkLocator* newlocal, const NetworkLocator* oldremote, const NetworkLocator* newremote ) {
+void CommunicationEvents::onLinkChanged(const LinkID& id,
+	const address_v* oldlocal, const address_v* newlocal,
+	const address_v* oldremote, const address_v* newremote) {
 }
 
-void CommunicationEvents::onLinkFail( const LinkID& id, const NetworkLocator* local, const NetworkLocator* remote ){
+void CommunicationEvents::onLinkFail(const LinkID& id, const address_v* local,
+	const address_v* remote) {
 }
 
-void CommunicationEvents::onLinkQoSChanged( const LinkID& id, const NetworkLocator* local, const NetworkLocator* remote, const QoSParameterSet& qos ){
+void CommunicationEvents::onLinkQoSChanged(const LinkID& id,
+	const address_v* local, const address_v* remote, const QoSParameterSet& qos) {
 }
 
Index: /source/ariba/communication/CommunicationEvents.h
===================================================================
--- /source/ariba/communication/CommunicationEvents.h	(revision 5274)
+++ /source/ariba/communication/CommunicationEvents.h	(revision 5284)
@@ -41,16 +41,15 @@
 
 #include "ariba/utility/types/LinkID.h"
-#include "ariba/communication/modules/network/NetworkLocator.h"
 #include "ariba/utility/types/QoSParameterSet.h"
-
-using ariba::utility::LinkID;
-using ariba::utility::QoSParameterSet;
-using ariba::communication::NetworkLocator;
+#include "ariba/utility/addressing/addressing.hpp"
 
 namespace ariba {
 namespace communication {
 
+using ariba::utility::LinkID;
+using ariba::utility::QoSParameterSet;
+using namespace ariba::addressing;
+
 class CommunicationEvents {
-
 	friend class BaseCommunication;
 
@@ -69,5 +68,6 @@
 	 * @return True, if the link should be established
 	 */
-	virtual bool onLinkRequest( const LinkID& id, const NetworkLocator* local, const NetworkLocator* remote );
+	virtual bool onLinkRequest(const LinkID& id, const address_v* local,
+		const address_v* remote);
 
 	/**
@@ -77,5 +77,6 @@
 	 * @param id The link id of the established link
 	 */
-	virtual void onLinkUp( const LinkID& id, const NetworkLocator* local, const NetworkLocator* remote );
+	virtual void onLinkUp(const LinkID& id, const address_v* local,
+		const address_v* remote);
 
 	/**
@@ -84,5 +85,6 @@
 	 * @param id The link identifier of the dropped link
 	 */
-	virtual void onLinkDown( const LinkID& id, const NetworkLocator* local, const NetworkLocator* remote );
+	virtual void onLinkDown(const LinkID& id, const address_v* local,
+		const address_v* remote);
 
 	/**
@@ -94,9 +96,14 @@
 	 * @param id The link identifier of the changed link
 	 */
-	virtual void onLinkChanged( const LinkID& id, const NetworkLocator* oldlocal, const NetworkLocator* newlocal, const NetworkLocator* oldremote, const NetworkLocator* newremote );
+	virtual void onLinkChanged(const LinkID& id,
+		const address_v* oldlocal,  const address_v* newlocal,
+		const address_v* oldremote, const address_v* newremote
+	);
 
-	virtual void onLinkFail( const LinkID& id, const NetworkLocator* local, const NetworkLocator* remote );
+	virtual void onLinkFail(const LinkID& id, const address_v* local,
+		const address_v* remote);
 
-	virtual void onLinkQoSChanged( const LinkID& id, const NetworkLocator* local, const NetworkLocator* remote, const QoSParameterSet& qos );
+	virtual void onLinkQoSChanged(const LinkID& id, const address_v* local,
+		const address_v* remote, const QoSParameterSet& qos);
 };
 
Index: /source/ariba/communication/EndpointDescriptor.cpp
===================================================================
--- /source/ariba/communication/EndpointDescriptor.cpp	(revision 5274)
+++ /source/ariba/communication/EndpointDescriptor.cpp	(revision 5284)
@@ -48,113 +48,9 @@
 const EndpointDescriptor EndpointDescriptor::UNSPECIFIED;
 
-EndpointDescriptor::EndpointDescriptor() : locator( NULL ), isUnspec( true ){
-}
-
-EndpointDescriptor::EndpointDescriptor(const EndpointDescriptor& rh){
-	locator = (rh.locator != NULL) ? new IPv4Locator(*rh.locator) : NULL;
-	isUnspec = rh.isUnspec;
-}
-
-EndpointDescriptor::EndpointDescriptor(const Locator* _locator){
-	if( _locator == NULL ) return;
-
-	locator = new IPv4Locator(*dynamic_cast<IPv4Locator*>((Locator*)_locator));
-	isUnspec = false;
-}
-
-EndpointDescriptor::EndpointDescriptor(const string str) {
-	using namespace boost::xpressive;
-	using namespace ariba::utility::string_format;
-	using namespace ariba::utility::Helper;
-	using namespace std;
-
-	locator = NULL;
-	isUnspec = true;
-
-	smatch match;
-	if (regex_search(str, match, robjects)) {
-		regex_nav nav = match;
-		for (int i=0; i<nav.size(); i++) {
-			string type = nav[i][robject_id].str();
-			if (type=="ip") {
-				string ip = nav[i][robject_data].str();
-				ip = ip.substr(1,ip.size()-2);
-				this->locator = new IPv4Locator();
-				this->locator->setIP(ip);
-				this->isUnspec = false;
-			} else
-			if (type=="tcp") {
-				string port = nav[i][robject_data][rfields][1].str();
-				port = port.substr(1,port.size()-2);
-				this->locator->setPort(stoi(port));
-			}
-		}
-	}
-}
-
+/// destructor.
 EndpointDescriptor::~EndpointDescriptor() {
-}
-
-bool EndpointDescriptor::isUnspecified() const {
-	return isUnspec;
-}
-
-string EndpointDescriptor::toString() const {
-	if( locator == NULL ) return "<undefined locator>";
-	std::ostringstream o;
-	o << "ip{" << locator->getIP() << "}";
-	o << ",";
-	o << "tcp(ip,{" << locator->getPort() << "})";
-	return o.str();
-}
-
-EndpointDescriptor* EndpointDescriptor::fromString( string str ) {
-	return new EndpointDescriptor( str );
-}
-
-bool EndpointDescriptor::operator!=( const EndpointDescriptor& rh ) const {
-	return !operator==(rh);
-}
-
-bool EndpointDescriptor::operator==(const EndpointDescriptor& rh) const {
-
-	if( isUnspecified() && rh.isUnspecified() ) {
-
-		// both unspec bit set
-		return true;
-
-	} else if( (!isUnspecified()) && (!rh.isUnspecified()) ) {
-
-		//
-		// both are valid, check locators
-		//
-
-		if( locator == NULL && rh.locator == NULL ){
-
-			// both locators are invalid, ok true
-			return true;
-
-		} else if( locator == NULL ^ rh.locator == NULL ) {
-
-			// one locator is invalid, the other not, false
-			return false;
-
-		} else {
-
-			// both locators are valid, compare
-			assert( locator != NULL && rh.locator != NULL );
-			return ( locator->operator==(*rh.locator) );
-
-		}
-
-	} else {
-
-		// one is unspec, the other not
-		assert( isUnspecified() ^ rh.isUnspecified() );
-		return false;
-
-	}
 
 }
 
+
 }} // namespace ariba, communication
Index: /source/ariba/communication/EndpointDescriptor.h
===================================================================
--- /source/ariba/communication/EndpointDescriptor.h	(revision 5274)
+++ /source/ariba/communication/EndpointDescriptor.h	(revision 5284)
@@ -40,14 +40,22 @@
 #define ENDPOINTDESCRIPTOR_H_
 
+// deprecated
+//#include "ariba/communication/modules/network/ip/IPv4Locator.h"
+
+// deprecated
+//using ariba::utility::Locator;
+//using ariba::communication::IPv4Locator;
+
+// typical types
 #include "ariba/utility/types.h"
 #include "ariba/utility/serialization.h"
-#include "ariba/communication/modules/network/ip/IPv4Locator.h"
+
+// new addressing and transport
+#include "ariba/utility/addressing/addressing.hpp"
+#include "ariba/utility/transport/transport.hpp"
+
+// stdlibc++
 #include <string>
 #include <set>
-
-using std::string;
-using std::set;
-using ariba::utility::Locator;
-using ariba::communication::IPv4Locator;
 
 namespace ariba {
@@ -55,58 +63,90 @@
 
 using_serialization;
+using namespace std;
+using namespace ariba::addressing;
 
-class EndpointDescriptor : public VSerializeable {
-	VSERIALIZEABLE;
-
+class EndpointDescriptor: public VSerializeable { VSERIALIZEABLE
 	friend class BaseCommunication;
 
 public:
-	/**
-	 * The default constructor.
-	 */
-	EndpointDescriptor();
+	/// the unspecified endpoint descriptor
+	static const EndpointDescriptor UNSPECIFIED;
 
-	EndpointDescriptor(const EndpointDescriptor& rh);
-	EndpointDescriptor(const Locator* _locator);
-	EndpointDescriptor(const string str);
+	/// creates an empty endpoint descriptor with zero endpoints
+	EndpointDescriptor() : endpoints() {
+	}
 
-	/**
-	 * The destructor.
-	 */
+	/// destructor.
 	virtual ~EndpointDescriptor();
 
-	/**
-	 * An unspecified end-point
-	 */
-	static const EndpointDescriptor UNSPECIFIED;
+	/// copy constructor
+	EndpointDescriptor(const EndpointDescriptor& rh) :
+		endpoints(rh.endpoints) {
+	}
 
-	/**
-	 * Returns true, if the descriptor is unspecified.
-	 *
-	 * @return True, if the descriptor is unspecified.
-	 */
-	bool isUnspecified() const;
+	/// construct end-points from an endpoint set
+	EndpointDescriptor(const endpoint_set& endpoints ) :
+		endpoints(endpoints) {
+	}
 
-	virtual string toString() const;
-	static EndpointDescriptor* fromString( string str );
+	/// construct end-points from a string
+	EndpointDescriptor(const string& str) : endpoints(str) {
+	}
 
-	bool operator==( const EndpointDescriptor& rh ) const;
-	bool operator!=( const EndpointDescriptor& rh ) const;
+	/// convert end-points to string
+	string toString() const {
+		return endpoints.to_string();
+	}
+
+	/// returns true, if this object is the unspecified object
+	bool isUnspecified() const {
+		return this == &UNSPECIFIED;
+	}
+
+	/// create endpoint
+	static EndpointDescriptor* fromString(string str) {
+		return new EndpointDescriptor(str);
+	}
+
+	bool operator==(const EndpointDescriptor& rh) const {
+		if (rh.isUnspecified() && isUnspecified()) return true;
+		return false;
+	}
+
+	bool operator!=(const EndpointDescriptor& rh) const {
+		if (!rh.isUnspecified() && !isUnspecified()) return true;
+		return false;
+	}
+
+	EndpointDescriptor& operator=( const EndpointDescriptor& rhs) {
+		endpoints = rhs.endpoints;
+	}
+
+	/// returns the end-points of this descriptor
+	endpoint_set& getEndpoints() {
+		return endpoints;
+	}
+
+	/// returns the end-points of this descriptor
+	const endpoint_set& getEndpoints() const {
+		return endpoints;
+	}
 
 private:
-	bool isUnspec;
-	IPv4Locator* locator;
+	endpoint_set endpoints;
 };
 
 }} // namespace ariba, communication
 
-sznBeginDefault( ariba::communication::EndpointDescriptor, X ) {
-	uint8_t unspec = isUnspec;
-
-	X && unspec && VO(locator);
-
-	// when deserializing reset unspec flag
-	if (X.isDeserializer()) isUnspec = unspec;
-} sznEnd();
+sznBeginDefault( ariba::communication::EndpointDescriptor, X ){
+	// serialize endpoints
+	uint16_t len = endpoints.to_bytes_size();
+	X && len;
+	uint8_t* buffer = X.bytes( len );
+	if (buffer!=NULL) {
+		if (X.isDeserializer()) endpoints.assign(buffer,len);
+		else endpoints.to_bytes(buffer);
+	}
+}sznEnd();
 
 #endif /*ENDPOINTDESCRIPTOR_H_*/
Index: /source/ariba/communication/messages/AribaBaseMsg.cpp
===================================================================
--- /source/ariba/communication/messages/AribaBaseMsg.cpp	(revision 5274)
+++ /source/ariba/communication/messages/AribaBaseMsg.cpp	(revision 5284)
@@ -44,42 +44,28 @@
 vsznDefault(AribaBaseMsg);
 
-AribaBaseMsg::AribaBaseMsg(
-	const Address* address,
-	LINK_STATE _state,
-	const LinkID& _localLink,
-	const LinkID& _remoteLink )
-		: state( (uint8_t)_state ),
-		  localLink( _localLink ),
-		  remoteLink( _remoteLink ){
-
-	Message::setDestinationAddress( address );
+AribaBaseMsg::AribaBaseMsg( type_ _type,
+	const LinkID& localLink, const LinkID& remoteLink ) :
+	type((uint8_t)_type),
+	localLink(localLink),remoteLink(remoteLink) {
 }
 
-AribaBaseMsg::~AribaBaseMsg(){
+AribaBaseMsg::~AribaBaseMsg() {
 }
 
-const AribaBaseMsg::LINK_STATE AribaBaseMsg::getType(){
-	return (LINK_STATE)state;
-}
-
-const LinkID& AribaBaseMsg::getLocalLink(){
-	return localLink;
-}
-
-const LinkID& AribaBaseMsg::getRemoteLink(){
-	return remoteLink;
-}
-
-const string AribaBaseMsg::getTypeString(){
-
-	switch( getType() ){
-		case LINK_STATE_DATA: 			return "LINK_STATE_DATA";
-		case LINK_STATE_OPEN_REQUEST: 	return "LINK_STATE_OPEN_REQUEST";
-		case LINK_STATE_OPEN_REPLY: 	return "LINK_STATE_OPEN_REPLY";
-		case LINK_STATE_CLOSE_REQUEST: 	return "LINK_STATE_CLOSE_REQUEST";
-		case LINK_STATE_UPDATE:			return "LINK_STATE_UPDATE";
-		default:						"unknown";
+const string AribaBaseMsg::getTypeString() const {
+	switch (getType()) {
+		case typeData:
+			return "typeData";
+		case typeLinkRequest:
+			return "typeLinkRequest";
+		case typeLinkReply:
+			return "typeLinkReply";
+		case typeLinkClose:
+			return "typeLinkClose";
+		case typeLinkUpdate:
+			return "typeLinkUpdate";
+		default:
+			"unknown";
 	}
-
 	return "unknown";
 }
Index: /source/ariba/communication/messages/AribaBaseMsg.h
===================================================================
--- /source/ariba/communication/messages/AribaBaseMsg.h	(revision 5274)
+++ /source/ariba/communication/messages/AribaBaseMsg.h	(revision 5284)
@@ -48,4 +48,6 @@
 #include "ariba/utility/types/ServiceID.h"
 
+#include "../EndpointDescriptor.h"
+
 using std::string;
 using ariba::utility::Address;
@@ -62,31 +64,50 @@
 	VSERIALIZEABLE;
 public:
+	enum type_ {
+		typeData = 0,
+		typeLinkRequest = 1,
+		typeLinkReply = 2,
+		typeLinkClose = 3,
+		typeLinkUpdate = 4
+	};
 
-	typedef enum _LINK_STATE {
-		LINK_STATE_DATA          = 0,
-		LINK_STATE_OPEN_REQUEST  = 1,
-		LINK_STATE_OPEN_REPLY    = 2,
-		LINK_STATE_CLOSE_REQUEST = 3, // there is no close reply. send request and local link is closed
-		LINK_STATE_UPDATE        = 4,
-	} LINK_STATE;
-
-	AribaBaseMsg(
-			const Address* address    = NULL,
-			LINK_STATE _state         = LINK_STATE_DATA,
-			const LinkID& _localLink  = LinkID::UNSPECIFIED,
-			const LinkID& _remoteLink = LinkID::UNSPECIFIED );
+	AribaBaseMsg( type_ type = typeData,
+			const LinkID& localLink = LinkID::UNSPECIFIED,
+			const LinkID& remoteLink = LinkID::UNSPECIFIED );
 
 	virtual ~AribaBaseMsg();
 
-	const LINK_STATE getType();
-	const string getTypeString();
-	const LinkID& getLocalLink();
-	const LinkID& getRemoteLink();
+	const string getTypeString() const;
+
+	const type_ getType() const {
+		return (type_)type;
+	}
+
+	const LinkID& getLocalLink() const {
+		return localLink;
+	}
+
+	const LinkID& getRemoteLink() const {
+		return remoteLink;
+	}
+
+	EndpointDescriptor& getLocalDescriptor() {
+		return localDescriptor;
+	}
+
+	EndpointDescriptor& getRemoteDescriptor() {
+		return remoteDescriptor;
+	}
 
 private:
-	uint8_t state;		// the link message type
+	uint8_t type;		// the link message type
+
+	// remote and local link ids
 	LinkID localLink;	// the local link id
 	LinkID remoteLink;	// the remote link id
 
+	// remote and local endpoint descriptors
+	EndpointDescriptor localDescriptor;
+	EndpointDescriptor remoteDescriptor;
 };
 
@@ -94,5 +115,8 @@
 
 sznBeginDefault( ariba::communication::AribaBaseMsg, X ) {
-	X && state && &localLink && &remoteLink && Payload();
+	X && type && &localLink && &remoteLink;
+	if (type == typeLinkReply || type == typeLinkRequest)
+		X && localDescriptor && remoteDescriptor;
+	X && Payload();
 } sznEnd();
 
Index: /source/ariba/communication/networkinfo/AddressDiscovery.hpp
===================================================================
--- /source/ariba/communication/networkinfo/AddressDiscovery.hpp	(revision 5284)
+++ /source/ariba/communication/networkinfo/AddressDiscovery.hpp	(revision 5284)
@@ -0,0 +1,70 @@
+#ifndef ADDRESSDISCOVERY_HPP_
+#define ADDRESSDISCOVERY_HPP_
+
+#include "ariba/utility/addressing/addressing.hpp"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <ifaddrs.h>
+
+using namespace ariba::addressing;
+
+mac_address getMacFromIF( const char* name ) {
+	int s;
+	struct ifreq buffer;
+	s = socket(PF_INET, SOCK_DGRAM, 0);
+	memset(&buffer, 0x00, sizeof(buffer));
+	strcpy(buffer.ifr_name, name);
+	ioctl(s, SIOCGIFHWADDR, &buffer);
+	close(s);
+	mac_address addr;
+	addr.assign( (uint8_t*)buffer.ifr_hwaddr.sa_data, 6 );
+	return addr;
+}
+
+void discoverEndpoints( endpoint_set& endpoints ) {
+	struct ifaddrs* ifaceBuffer = NULL;
+	struct ifaddrs* tmpAddr     = NULL;
+	void*           tmpAddrPtr  = NULL;
+	char            straddr     [INET_ADDRSTRLEN];
+
+	int ret = getifaddrs( &ifaceBuffer );
+	if( ret != 0 ) return;
+
+	for( struct ifaddrs* i=ifaceBuffer; i != NULL; i=i->ifa_next ) {
+
+		// ignore devices that are disabled or have no ip
+		if(i == NULL) continue;
+		struct sockaddr* addr = i->ifa_addr;
+
+		// only look at IPv4, not IPv6 addresses
+		if (addr->sa_family == AF_INET) {
+			if (addr==NULL) continue;
+			tmpAddrPtr= &((struct sockaddr_in*)addr)->sin_addr;
+			inet_ntop( i->ifa_addr->sa_family, tmpAddrPtr, straddr, sizeof(straddr) );
+			ip_address ip = straddr;
+			if (ip.is_loopback()) continue;
+			address_vf vf = ip;
+			endpoints.add( vf );
+		} else
+		if (addr->sa_family == AF_INET6) {
+			if (addr==NULL) continue;
+			tmpAddrPtr= &((struct sockaddr_in6*)addr)->sin6_addr;
+			inet_ntop( i->ifa_addr->sa_family, tmpAddrPtr, straddr, sizeof(straddr) );
+			ip_address ip = straddr;
+			if (ip.is_loopback()) continue;
+			address_vf vf = ip;
+			endpoints.add( vf );
+		} else
+		if (i->ifa_name[0]=='p' && i->ifa_name[1]=='a' && i->ifa_name[2]=='n') {
+			mac_address mac = getMacFromIF(i->ifa_name);
+			address_vf vf = mac;
+			endpoints.add( vf );
+		}
+	}
+}
+
+#endif /* ADDRESSDISCOVERY_HPP_ */
Index: /source/ariba/communication/networkinfo/AddressInformation.cpp
===================================================================
--- /source/ariba/communication/networkinfo/AddressInformation.cpp	(revision 5274)
+++ /source/ariba/communication/networkinfo/AddressInformation.cpp	(revision 5284)
@@ -39,6 +39,13 @@
 #include "AddressInformation.h"
 
+#include <ifaddrs.h>
+
+#include <boost/asio/ip/address.hpp>
+#include <boost/asio/ip/address_v4.hpp>
+
 namespace ariba {
 namespace communication {
+
+using namespace ariba::addressing;
 
 AddressInformation::AddressInformation(){
@@ -52,32 +59,29 @@
 	AddressList retlist;
 
-	//
 	// gather transport addresses
-	//
-
 	struct ifaddrs* ifap;
 	getifaddrs( &ifap );
 
 	for( struct ifaddrs* p = ifap; p != NULL; p=p->ifa_next ){
+
+		// no name set? ->continue
 		if( interface.name.compare(string(p->ifa_name)) != 0 ) continue;
 
-		// TODO: currently only handle IPv4
+		// handle IPv4 entry
 		struct sockaddr* addr = p->ifa_addr;
-		if( addr->sa_family != AF_INET ) continue;
+		if( addr->sa_family == AF_INET ) {
+			// get address
+			const struct sockaddr_in& ipv4 = (const struct sockaddr_in&)*addr;
+			boost::asio::ip::address_v4::bytes_type bytes;
+			for( int i=0; i<4; i++ )
+				bytes[i] = (ipv4.sin_addr.s_addr >> (24-i*8)) & 0xff;
 
-		const struct sockaddr_in& ipv4 = (const struct sockaddr_in&)*addr;
-		boost::asio::ip::address_v4::bytes_type bytes;
-		for( int i=0; i<4; i++ )
-			bytes[i] = (ipv4.sin_addr.s_addr >> (24-i*8)) & 0xff;
-
-		boost::asio::ip::address boost_addr = boost::asio::ip::address_v4( bytes );
-		retlist.push_back( IPv4Locator::fromString(boost_addr.to_string()) );
+			// add ipv4 address
+			boost::asio::ip::address boost_addr = boost::asio::ip::address_v4( bytes );
+			retlist.push_back( vcapsule<address_v>( ip_address(boost_addr) ) );
+		}
 	}
 
 	freeifaddrs( ifap );
-
-	//
-	// TODO: gather further addresses like MAC etc.
-	//
 
 	return retlist;
Index: /source/ariba/communication/networkinfo/AddressInformation.h
===================================================================
--- /source/ariba/communication/networkinfo/AddressInformation.h	(revision 5274)
+++ /source/ariba/communication/networkinfo/AddressInformation.h	(revision 5284)
@@ -40,19 +40,17 @@
 #define __ADDRESS_INFORMATION_H
 
-#include <ifaddrs.h>
 #include <vector>
-#include <boost/asio/ip/address.hpp>
-#include <boost/asio/ip/address_v4.hpp>
+
 #include "ariba/communication/networkinfo/NetworkInterface.h"
-#include "ariba/communication/modules/network/ip/IPv4Locator.h"
-
-using std::vector;
-using ariba::communication::NetworkInterface;
-using ariba::communication::IPv4Locator;
+#include "ariba/utility/addressing/addressing.hpp"
 
 namespace ariba {
 namespace communication {
 
-typedef vector<IPv4Locator> AddressList; // TODO: make more general, not only ipv4
+using namespace std;
+using namespace ariba::addressing;
+
+/// a list of addresses
+typedef vector<address_v*> AddressList;
 
 class AddressInformation {
@@ -62,5 +60,4 @@
 
 	AddressList getAddresses(const NetworkInterface& interface);
-
 };
 
Index: /source/ariba/overlay/BaseOverlay.cpp
===================================================================
--- /source/ariba/overlay/BaseOverlay.cpp	(revision 5274)
+++ /source/ariba/overlay/BaseOverlay.cpp	(revision 5284)
@@ -185,5 +185,5 @@
 	// route message using overlay
 	else {
-		logging_error("Could not send message");
+		logging_error("Could not send message descriptor=" << ld );
 		logging_debug( "sendMessage: Routing message to node " << ld->remoteNode.toString() );
 		overlayInterface->routeMessage( ld->remoteNode, message );
@@ -689,5 +689,5 @@
 
 void BaseOverlay::onLinkUp(const LinkID& id,
-	const NetworkLocator* local, const NetworkLocator* remote) {
+	const address_v* local, const address_v* remote) {
 	logging_debug( "Link up with base communication link id=" << id );
 
@@ -740,4 +740,5 @@
 		// if link is a relayed link ->convert to direct link
 		if (ld->relay) {
+			logging_force( "Converting to direct link: " << ld );
 			ld->up = true;
 			ld->relay = false;
@@ -756,5 +757,5 @@
 
 void BaseOverlay::onLinkDown(const LinkID& id,
-	const NetworkLocator* local, const NetworkLocator* remote) {
+	const address_v* local, const address_v* remote) {
 
 	// get descriptor for link
@@ -780,6 +781,6 @@
 
 void BaseOverlay::onLinkChanged(const LinkID& id,
-	const NetworkLocator* oldlocal, const NetworkLocator* newlocal,
-	const NetworkLocator* oldremote, const NetworkLocator* newremote) {
+	const address_v* oldlocal, const address_v* newlocal,
+	const address_v* oldremote, const address_v* newremote) {
 
 	// get descriptor for link
@@ -797,5 +798,5 @@
 
 void BaseOverlay::onLinkFail(const LinkID& id,
-	const NetworkLocator* local, const NetworkLocator* remote) {
+	const address_v* local, const address_v* remote) {
 	logging_debug( "Link fail with base communication link id=" << id );
 
@@ -813,6 +814,6 @@
 }
 
-void BaseOverlay::onLinkQoSChanged(const LinkID& id, const NetworkLocator* local,
-	const NetworkLocator* remote, const QoSParameterSet& qos) {
+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 );
 
@@ -826,7 +827,7 @@
 }
 
-bool BaseOverlay::onLinkRequest( const LinkID& id, const NetworkLocator* local,
-	const NetworkLocator* remote ) {
-	logging_debug("Accepting link request from " << remote->toString() );
+bool BaseOverlay::onLinkRequest( const LinkID& id, const address_v* local,
+	const address_v* remote ) {
+	logging_debug("Accepting link request from " << remote->to_string() );
 	return true;
 }
@@ -1358,4 +1359,5 @@
 		case OverlayMsg::typeDirectLink: {
 			LinkDescriptor* rld = getDescriptor( overlayMsg->getRelayLink() );
+			logging_force( "Received direct link convert notification for " << rld );
 			rld->communicationId = ld->communicationId;
 			rld->communicationUp = true;
Index: /source/ariba/overlay/BaseOverlay.h
===================================================================
--- /source/ariba/overlay/BaseOverlay.h	(revision 5274)
+++ /source/ariba/overlay/BaseOverlay.h	(revision 5284)
@@ -118,4 +118,6 @@
 namespace overlay {
 
+using namespace ariba::addressing;
+
 class LinkDescriptor;
 
@@ -285,12 +287,12 @@
 	 * @see ariba::communication::CommunicationEvents.h
 	 */
-	virtual void onLinkUp(const LinkID& id, const NetworkLocator* local,
-		const NetworkLocator* remote);
-
-	/**
-	 * @see ariba::communication::CommunicationEvents.h
-	 */
-	virtual void onLinkDown(const LinkID& id, const NetworkLocator* local,
-		const NetworkLocator* remote);
+	virtual void onLinkUp(const LinkID& id, const address_v* local,
+		const address_v* remote);
+
+	/**
+	 * @see ariba::communication::CommunicationEvents.h
+	 */
+	virtual void onLinkDown(const LinkID& id, const address_v* local,
+		const address_v* remote);
 
 	/**
@@ -298,12 +300,12 @@
 	 */
 	virtual void onLinkChanged(const LinkID& id,
-		const NetworkLocator* oldlocal, const NetworkLocator* newlocal,
-		const NetworkLocator* oldremote, const NetworkLocator* newremote);
-
-	/**
-	 * @see ariba::communication::CommunicationEvents.h
-	 */
-	virtual void onLinkFail(const LinkID& id, const NetworkLocator* local,
-		const NetworkLocator* remote);
+		const address_v* oldlocal, const address_v* newlocal,
+		const address_v* oldremote, const address_v* newremote);
+
+	/**
+	 * @see ariba::communication::CommunicationEvents.h
+	 */
+	virtual void onLinkFail(const LinkID& id, const address_v* local,
+		const address_v* remote);
 
 	/**
@@ -311,5 +313,5 @@
 	 */
 	virtual void onLinkQoSChanged(const LinkID& id,
-		const NetworkLocator* local, const NetworkLocator* remote,
+		const address_v* local, const address_v* remote,
 		const QoSParameterSet& qos);
 
@@ -317,6 +319,6 @@
 	 * @see ariba::communication::CommunicationEvents.h
 	 */
-	virtual bool onLinkRequest(const LinkID& id, const NetworkLocator* local,
-		const NetworkLocator* remote);
+	virtual bool onLinkRequest(const LinkID& id, const address_v* local,
+		const address_v* remote);
 
 	/**
Index: /source/ariba/overlay/LinkDescriptor.h
===================================================================
--- /source/ariba/overlay/LinkDescriptor.h	(revision 5274)
+++ /source/ariba/overlay/LinkDescriptor.h	(revision 5284)
@@ -128,4 +128,5 @@
 		s << "serv=" << service.toString() << " ";
 		s << "overId=" << overlayId.toString().substr(0,6) << " ";
+		s << "commUp=" << communicationUp << " ";
 		s << "commId=" << communicationId.toString().substr(0,6) << " ";
 		s << "usedAsRel=" << usedAsRelay << " ";
Index: /source/ariba/utility/addressing/addressing.hpp
===================================================================
--- /source/ariba/utility/addressing/addressing.hpp	(revision 5284)
+++ /source/ariba/utility/addressing/addressing.hpp	(revision 5284)
@@ -0,0 +1,18 @@
+#ifndef ADDRESSING_HPP_
+#define ADDRESSING_HPP_
+
+/// @author Sebastian Mies <mies@tm.uka.de>
+
+#include "facades/to_bytes_v.hpp"
+#include "facades/to_string_v.hpp"
+#include "facades/comparable_v.hpp"
+#include "facades/address_v.hpp"
+
+#include "ip_address.hpp"
+#include "mac_address.hpp"
+#include "port_address.hpp"
+#include "tcpip_endpoint.hpp"
+#include "rfcomm_endpoint.hpp"
+#include "endpoint_set.hpp"
+
+#endif /* ADDRESSING_HPP_ */
Index: /source/ariba/utility/addressing/detail/address_convenience.hpp
===================================================================
--- /source/ariba/utility/addressing/detail/address_convenience.hpp	(revision 5284)
+++ /source/ariba/utility/addressing/detail/address_convenience.hpp	(revision 5284)
@@ -0,0 +1,46 @@
+#ifndef ADDRESS_CONVENIENCE_HPP_
+#define ADDRESS_CONVENIENCE_HPP_
+
+#include <string>
+#include "compare_to_operators.hpp"
+
+namespace ariba {
+namespace addressing {
+namespace detail {
+
+/**
+ * TODO: Doc
+ *
+ * @author Sebastian Mies <mies@tm.uka.de>
+ */
+template<class T>
+class address_convenience : public compare_to_operators<T> {
+public:
+	/// convenience method for assignment of addresses
+	inline T& operator=( const T& rhs ) {
+		static_cast<T*>(this)->assign(rhs);
+		return *this;
+	}
+
+	/// convenience method for assignment of addresses
+	inline T& operator=( const char* text ) {
+		static_cast<T*>(this)->assign(text);
+		return *this;
+	}
+
+	/// convenience method for assignment of addresses
+	inline T& operator=( const std::string& text ) {
+		static_cast<T*>(this)->assign(text);
+		return *this;
+	}
+
+	/// convenience method for assignment of a c-string address
+	inline T& assign( const char* text ) {
+		static_cast<T*>(this)->assign( std::string(text) );
+		return *this;
+	}
+};
+
+}}} // namespace ariba::addressing::detail
+
+#endif /* ADDRESS_CONVENIENCE_HPP_ */
Index: /source/ariba/utility/addressing/detail/compare_to_operators.hpp
===================================================================
--- /source/ariba/utility/addressing/detail/compare_to_operators.hpp	(revision 5284)
+++ /source/ariba/utility/addressing/detail/compare_to_operators.hpp	(revision 5284)
@@ -0,0 +1,50 @@
+#ifndef COMPARE_TO_OPERATORS_HPP_
+#define COMPARE_TO_OPERATORS_HPP_
+
+namespace ariba {
+namespace addressing {
+namespace detail {
+
+
+/**
+ * This class implements some convenient operators for the compare_to method.
+ *
+ * @author Sebastian Mies <mies@tm.uka.de>
+ */
+template<class T>
+class compare_to_operators {
+public:
+	/// convenience method for comparison of addresses
+	inline bool operator==( const T& rhs ) const {
+		return static_cast<const T*>(this)->compare_to(rhs) == 0;
+	}
+
+	/// convenience method for comparison of addresses
+	inline bool operator!=( const T& rhs ) const {
+		return static_cast<const T*>(this)->compare_to(rhs) != 0;
+	}
+
+	/// convenience method for comparison of addresses
+	inline bool operator<( const T& rhs ) const {
+		return static_cast<const T*>(this)->compare_to(rhs) < 0;
+	}
+
+	/// convenience method for comparison of addresses
+	inline bool operator<=( const T& rhs ) const {
+		return static_cast<const T*>(this)->compare_to(rhs) <= 0;
+	}
+
+	/// convenience method for comparison of addresses
+	inline bool operator>( const T& rhs ) const {
+		return static_cast<const T*>(this)->compare_to(rhs) > 0;
+	}
+
+	/// convenience method for comparison of addresses
+	inline bool operator>=( const T& rhs ) const {
+		return static_cast<const T*>(this)->compare_to(rhs) >= 0;
+	}
+};
+
+}}} // namespace ariba::addressing::detail
+
+#endif /* COMPARE_TO_OPERATORS_HPP_ */
Index: /source/ariba/utility/addressing/endpoint_set.hpp
===================================================================
--- /source/ariba/utility/addressing/endpoint_set.hpp	(revision 5284)
+++ /source/ariba/utility/addressing/endpoint_set.hpp	(revision 5284)
@@ -0,0 +1,393 @@
+#ifndef ENDPOINT_SET_HPP_
+#define ENDPOINT_SET_HPP_
+
+#include "addressing.hpp"
+#include "tcpip_endpoint.hpp"
+
+#include <sstream>
+#include <boost/unordered_set.hpp>
+#include <boost/foreach.hpp>
+#include <boost/thread.hpp>
+
+namespace ariba {
+namespace addressing {
+
+using boost::unordered_set;
+
+/**
+ * This end-point set shelters known addresses of a device.
+ * Transport protocols use this class to address devices.
+ *
+ * Example of a string representation:
+ * "tcp{500|501};ip{10.11.12.13};bluetooth{01:02:03:04:05:06};rfcomm{1234}"
+ * Inside a address type specification, addresses are separated by a bar (|).
+ *
+ * @author Sebastian Mies <mies@tm.uka.de>
+ */
+class endpoint_set {
+public:
+	// layer 2
+	unordered_set<mac_address> bluetooth;
+
+	// layer 3
+	unordered_set<ip_address> ip;
+
+	// layer 4
+	unordered_set<tcp_port_address> tcp;
+	unordered_set<rfcomm_channel_address> rfcomm;
+
+	// mutex
+	boost::mutex io_mutex;
+	typedef boost::mutex::scoped_lock scoped_lock;
+
+private:
+	template<uint8_t type, class V>
+	size_t to_bytes_dynamic( const unordered_set<V>& set, uint8_t* bytes ) const {
+		size_t size = 0;
+		bytes[0] = type;
+		uint8_t* size_ptr = bytes+1;
+		bytes +=2;
+		size += 2;
+		BOOST_FOREACH( const V& value, set ) {
+			bytes[0] = (uint8_t)value.to_bytes_size();
+			bytes++;
+			size++;
+			value.to_bytes(bytes);
+			bytes += value.to_bytes_size();
+			size += value.to_bytes_size();
+		}
+		*size_ptr = size-2;
+		return size;
+	}
+
+	template<class V>
+	void from_bytes_dynamic( unordered_set<V>& set, const uint8_t* bytes, uint8_t size ) {
+		size_t pos = 0;
+		while (pos < size) {
+			uint8_t length = bytes[0];
+			bytes++; pos++;
+			V obj(bytes,length);
+			set.insert(obj);
+			bytes+=length; pos+=length;
+		}
+	}
+
+	template<uint8_t type, class V>
+	size_t to_bytes_fixed( const unordered_set<V>& set, uint8_t* bytes ) const {
+		size_t fixed_size = V().to_bytes_size();
+		bytes[0] = type;
+		bytes[1] = (uint8_t)(set.size()* fixed_size);
+		bytes+=2;
+		BOOST_FOREACH( const V& value, set ) {
+			value.to_bytes(bytes);
+			bytes += value.to_bytes_size();
+		}
+		return 2 + set.size() * fixed_size;
+	}
+
+	template<class V>
+	void from_bytes_fixed( unordered_set<V>& set, const uint8_t* bytes, uint8_t size ) {
+		size_t fixed_size = V().to_bytes_size();
+		uint8_t num = size/fixed_size;
+		for (uint8_t i=0; i<num; i++) {
+			V obj(bytes, fixed_size);
+			set.insert(obj);
+			bytes += fixed_size;
+		}
+	}
+
+	template<class V>
+	std::string to_string_set( const unordered_set<V>& set, const std::string& type ) const {
+		if (set.size()==0) return std::string("");
+		std::ostringstream buf;
+		buf << type << "{";
+		bool first = true;
+		BOOST_FOREACH( const V& value, set ) {
+			if (!first) {
+				buf << " | ";
+			} else
+				first = false;
+			buf << value.to_string();
+		}
+		buf << "};";
+		return buf.str();
+	}
+
+	static void trim(string& str) {
+		string::size_type pos = str.find_last_not_of(' ');
+		if(pos != string::npos) {
+			str.erase(pos + 1);
+			pos = str.find_first_not_of(' ');
+			if(pos != string::npos) str.erase(0, pos);
+		}
+		else str.erase(str.begin(), str.end());
+	}
+
+	static string::size_type skip( const char* chars, string::size_type pos, const std::string& str ) {
+		bool found = true;
+		while (pos<str.size() && found) {
+			found = false;
+			for (size_t i=0; chars[i]!=0 && !found; i++)
+				if (str.at(pos)==chars[i]) {
+					pos++;
+					found = true;
+				}
+		}
+		return pos;
+	}
+
+	template<class V>
+	size_t from_string_set( unordered_set<V>& set, string::size_type pos, const std::string& str ) {
+		while (pos < str.size() && pos != string::npos) {
+			pos = skip("} |\n\r", pos, str);
+			string::size_type nend1 = str.find('}',pos);
+			string::size_type nend2 = str.find('|',pos);
+			if (nend1==string::npos && nend2==string::npos) break;
+			if (nend1==string::npos) nend1=str.size();
+			if (nend2==string::npos) nend2=str.size();
+			string::size_type nend = nend2 < nend1 ? nend2:nend1;
+			std::string sub = str.substr(pos, min(nend2,nend1)-pos);
+			trim(sub);
+//			cout << sub << endl;
+			V obj( sub );
+			set.insert(obj);
+			pos = nend+1;
+			if (nend1<nend2) break;
+		}
+		return pos-1;
+	}
+
+public:
+	enum layers {
+		Layer1 = 1, Layer2 = 2,	Layer3 = 4, Layer4 = 8, Layer5 = 16,
+		Layer6 = 32, Layer7 = 64, Layer8 = 128, AllLayers = ~0,
+		Layer1_3 = Layer1|Layer2|Layer3,
+		Layer1_4 = Layer1|Layer2|Layer3|Layer4,
+	};
+
+	endpoint_set() {
+
+	}
+
+	endpoint_set( const endpoint_set& copy ) :
+		bluetooth(copy.bluetooth), ip(copy.ip), tcp(copy.tcp), rfcomm(copy.rfcomm) {
+	}
+
+	endpoint_set( const std::string& str ) {
+		assign(str);
+	}
+
+	endpoint_set( const uint8_t* bytes, size_t size ) {
+		assign(bytes, size);
+	}
+
+	/// adds an address or endpoint to this set
+	void add( const address_v* address, int layers = AllLayers ) {
+		scoped_lock lock(io_mutex);
+		if ( address->instanceof<tcpip_endpoint> () ) {
+			const tcpip_endpoint& addr = *address;
+			if (layers & Layer3) ip.insert( addr.address() );
+			if (layers & Layer4) tcp.insert( addr.port() );
+		} else
+		if ( address->instanceof<ip_address>() ) {
+			const ip_address& addr = *address;
+			if (layers & Layer3) ip.insert( addr );
+		} else
+		if (address->instanceof<rfcomm_endpoint>() ) {
+			const rfcomm_endpoint& endp = *address;
+			if (layers & Layer2) bluetooth.insert( endp.mac() );
+			if (layers & Layer4) rfcomm.insert( endp.channel() );
+		} else
+		if (address->instanceof<mac_address>() ) {
+			const mac_address& endp = *address;
+			if (layers & Layer2) bluetooth.insert( endp );
+		}
+	}
+
+	/// adds addresses from another endpoint set
+	void add( const endpoint_set& eps, int layers = AllLayers ) {
+		scoped_lock lock(io_mutex);
+
+		// merge layer 2 addresses
+		if (layers & Layer2) {
+			bluetooth.insert(eps.bluetooth.begin(), eps.bluetooth.end() );
+		}
+
+		// merge layer 3 addresses
+		if (layers & Layer3) {
+			ip.insert(eps.ip.begin(), eps.ip.end() );
+		}
+
+		// merge layer 4 addresses
+		if (layers & Layer4) {
+			tcp.insert(eps.tcp.begin(), eps.tcp.end() );
+			rfcomm.insert(eps.rfcomm.begin(), eps.rfcomm.end() );
+		}
+	}
+
+	/// removes an address or endpoint from this set
+	void remove( const address_vf address ) {
+		scoped_lock lock(io_mutex);
+		if ( address->instanceof<tcpip_endpoint> () ) {
+			const tcpip_endpoint& addr = *address;
+			ip.erase( addr.address() );
+			tcp.erase( addr.port() );
+		} else
+		if ( address->instanceof<ip_address>() ) {
+			const ip_address& addr = *address;
+			ip.erase( addr );
+		} else
+		if (address->instanceof<rfcomm_endpoint>() ) {
+			const rfcomm_endpoint& endp = *address;
+			bluetooth.erase( endp.mac() );
+			rfcomm.erase( endp.channel() );
+		}
+	}
+
+	/// checks whether two end-points are disjoint
+	/// (only check lower level addresses)
+	bool is_disjoint_to( const endpoint_set& set ) const {
+		scoped_lock lock(const_cast<boost::mutex&>(io_mutex));
+		BOOST_FOREACH( const mac_address& mac, bluetooth )
+			if (set.bluetooth.count(mac) !=0 ) return false;
+		BOOST_FOREACH( const ip_address& ip_, ip )
+			if (set.ip.count(ip_) !=0 ) return false;
+		return true;
+	}
+
+	/// returns true, if this address has a fixed size in bytes
+	bool is_bytes_size_static() const {
+		return false;
+	}
+
+	/// returns the number of bytes used for serialization of this address
+	size_t to_bytes_size() const {
+		scoped_lock lock(const_cast<boost::mutex&>(io_mutex));
+		size_t size = 0;
+
+		// bluetooth mac list (layer 2)
+		size += bluetooth.size() * mac_address().to_bytes_size();
+
+		// ip list (layer 3)
+		BOOST_FOREACH( const ip_address& ip_, ip )
+			size += (ip_.to_bytes_size() + 1 /* =length */);
+
+		// tcp ports (layer 4)
+		size += tcp.size() * tcp_port_address().to_bytes_size();
+
+		// bluetooth rfcomm channels (layer 4)
+		size += rfcomm.size() * rfcomm_channel_address().to_bytes_size();
+
+		// length/type encoding
+		size += 4 /* number of items*/ * 2 /* length of type and length */;
+
+		return size;
+	}
+
+	/// converts this address to a binary representation
+	void to_bytes(uint8_t* bytes) const {
+		scoped_lock lock(const_cast<boost::mutex&>(io_mutex));
+
+		/// bluetooth mac list (layer 2)
+		bytes += to_bytes_fixed<0x21, mac_address>( bluetooth, bytes );
+
+		// ip list (layer 3)
+		bytes += to_bytes_dynamic<0x31, ip_address>(ip, bytes);
+
+		// tcp ports (layer 4)
+		bytes += to_bytes_fixed<0x41, tcp_port_address>( tcp, bytes );
+
+		// rfcomm channels (layer 4)
+		bytes += to_bytes_fixed<0x42, rfcomm_channel_address>( rfcomm, bytes );
+	}
+
+	/// Assigns an address using a bunch of bytes
+	bool assign(const uint8_t* bytes, size_t size) {
+		scoped_lock lock(io_mutex);
+
+		size_t pos = 0;
+		while (pos < size) {
+			uint8_t type = bytes[0];
+			uint8_t length = bytes[1];
+			bytes+=2; pos+=2;
+
+			switch (type) {
+
+			// bluetooth mac
+			case 0x21: {
+				from_bytes_fixed<mac_address>( bluetooth, bytes, length );
+				break;
+			}
+
+			// ip
+			case 0x31: {
+				from_bytes_dynamic<ip_address>( ip, bytes, length );
+				break;
+			}
+			// tcp
+			case 0x41: {
+				from_bytes_fixed<tcp_port_address>( tcp, bytes, length );
+				break;
+			}
+			// rfcomm
+			case 0x42: {
+				from_bytes_fixed<rfcomm_channel_address>( rfcomm, bytes, length );
+				break;
+			}
+
+			default: {
+				pos = size;
+				break;
+			}
+			}
+			bytes += length; pos+=length;
+		}
+		return false;
+	}
+
+	/// generates a string out of this endpoint-set
+	std::string to_string() const {
+		scoped_lock lock(const_cast<boost::mutex&>(io_mutex));
+		std::string smac = to_string_set<mac_address>(bluetooth, "bluetooth");
+		std::string sip  = to_string_set<ip_address>(ip, "ip");
+		std::string stcp = to_string_set<tcp_port_address>(tcp, "tcp");
+		std::string srfcomm = to_string_set<rfcomm_channel_address>(rfcomm, "rfcomm");
+		return smac+sip+stcp+srfcomm;
+	}
+
+	/// assigns an endpoint-set out of a string
+	void assign( const std::string& str ) {
+		scoped_lock lock(io_mutex);
+		string::size_type pos = 0;
+		while (pos < str.size() && pos!=string::npos) {
+			pos = skip("}; \n\r", pos, str );
+			string::size_type nend = str.find('{',pos);
+			if (nend == string::npos) break;
+			std::string type = str.substr(pos,nend-pos);
+			pos = nend+1;
+			trim(type);
+			if (type=="bluetooth")
+				pos = from_string_set<mac_address>(bluetooth, pos, str );
+			else if (type=="ip")
+				pos = from_string_set<ip_address>(ip, pos, str );
+			else if (type=="tcp")
+				pos = from_string_set<tcp_port_address>(tcp, pos, str );
+			else if (type=="rfcomm")
+				pos = from_string_set<rfcomm_channel_address>(rfcomm, pos, str );
+			else
+				pos = str.find('}',pos);
+		}
+	}
+
+	endpoint_set& operator=( const endpoint_set& rhs ) {
+		scoped_lock lock(io_mutex);
+		this->bluetooth = rhs.bluetooth;
+		this->ip = rhs.ip;
+		this->rfcomm = rhs.rfcomm;
+		this->tcp = rhs.tcp;
+	}
+};
+
+}} // namespace ariba::addressing
+
+#endif /* ENDPOINT_SET_HPP_ */
Index: /source/ariba/utility/addressing/facades/address_v.hpp
===================================================================
--- /source/ariba/utility/addressing/facades/address_v.hpp	(revision 5284)
+++ /source/ariba/utility/addressing/facades/address_v.hpp	(revision 5284)
@@ -0,0 +1,217 @@
+#ifndef ADDRESS_V_H_
+#define ADDRESS_V_H_
+
+#include <string>
+#include <iostream>
+
+#include "vfacade.hpp"
+
+#include "to_bytes_v.hpp"
+#include "to_string_v.hpp"
+#include "comparable_v.hpp"
+
+#include "../detail/address_convenience.hpp"
+
+namespace ariba {
+namespace addressing {
+
+using std::string;
+
+/**
+ * A virtual interface to a protocol address.
+ *
+ * @author Sebastian Mies <mies@tm.uka.de>
+ */
+class address_v: public detail::address_convenience<address_v> {
+public:
+	//--- to_string_v ---------------------------------------------------------
+
+	/// convert address to a string that can be used to reconstruct the address
+	virtual string to_string() const = 0;
+
+	/// Assigns an address using a human-readable
+	virtual bool assign(const std::string& text) = 0;
+
+	//--- to_bytes_v ----------------------------------------------------------
+
+	/// returns true, if this address has a fixed size in bytes
+	virtual bool is_bytes_size_static() const = 0;
+
+	/// returns the number of bytes used for serialization of this address
+	virtual size_t to_bytes_size() const = 0;
+
+	/// converts this address to a binary representation
+	virtual void to_bytes(uint8_t* bytes) const = 0;
+
+	/// Assigns an address using a bunch of bytes
+	virtual bool assign(const uint8_t* bytes, size_t size) = 0;
+
+	//--- comparable_v --------------------------------------------------------
+
+	/// implements comparison operators
+	virtual int compare_to(const address_v& rhs) const = 0;
+
+	//--- assignment ----------------------------------------------------------
+
+	/// Assigns an address
+	virtual bool assign(const address_v& rhs) = 0;
+
+	//--- address info --------------------------------------------------------
+
+	/// returns the name of the address
+	virtual const string& type_name() const = 0;
+
+	/// sets the type id, if possible
+	virtual uint16_t type_id() const = 0;
+
+	//--- cloneing and conversion ---------------------------------------------
+
+	/// Obtain the underlaying data type or null if it does not match the type
+	virtual void* data(const std::type_info& type) = 0;
+
+	/// Clones this address
+	virtual address_v* clone() const = 0;
+
+	//--- convenience ---------------------------------------------------------
+
+	template<class T>
+	bool instanceof() const {
+		void* value = const_cast<address_v*>(this)->data(typeid(T));
+		return value!=NULL;
+	}
+
+	/// cast operator to detailed type
+	template<class T>
+	inline operator T&() {
+		void* value = data(typeid(T));
+		assert (value!=NULL);
+		return *((T*) value);
+	}
+
+	/// cast operator to detailed type
+	template<class T>
+	inline operator T () const {
+		return T( (const T&)*this );
+	}
+
+	/// cast operator to detailed type
+	template<class T>
+	inline operator const T& () const {
+		void* value = const_cast<address_v*>(this)->data(typeid(T));
+		assert (value!=NULL);
+		return *((const T*) value);
+	}
+};
+
+/// stream operator
+std::ostream& operator<<(std::ostream& s, const address_v* addr);
+
+/// define the virtual facade for the address
+typedef vfacade<address_v> address_vf;
+
+}} // namespace ariba::addressing
+
+/// the virtual adaptor to certain class of objects
+template<class NonVirtual, class AdaptorType>
+class vobject_hull<NonVirtual, ariba::addressing::address_v, AdaptorType> : public ariba::addressing::address_v {
+
+private:
+	typedef ariba::addressing::address_v self;
+	typename AdaptorType::template adaptor_type<NonVirtual> obj;
+
+	static inline NonVirtual& conv(ariba::addressing::address_v* obj) {
+		return *((NonVirtual*) obj->data(typeid(NonVirtual)));
+	}
+
+	static inline const NonVirtual& conv(const ariba::addressing::address_v* obj) {
+		const NonVirtual* v =
+				(const NonVirtual*) const_cast<ariba::addressing::address_v*> (obj)->data(
+						typeid(NonVirtual));
+		return *v;
+	}
+
+public:
+	template<typename T>
+	explicit vobject_hull(T& obj) :
+		obj(obj) {
+	}
+	explicit vobject_hull() :
+		obj() {
+	}
+
+	//--- assignment ----------------------------------------------------------
+
+	/// Assigns an address
+	virtual bool assign(const self& rhs) {
+		return obj->assign(conv(&rhs));
+	}
+
+	//--- address info --------------------------------------------------------
+
+	/// returns the name of the address
+	virtual const string& type_name() const {
+		return obj->type_name();
+	}
+
+	/// returns the id of the address
+	virtual uint16_t type_id() const {
+		return obj->type_id();
+	}
+
+	/// returns a capsule of the object
+	virtual address_v* clone() const {
+		return vcapsule<address_v> (*obj);
+	}
+
+	/// Obtain the underlaying data type or null if it does not match the type
+	virtual void* data(const std::type_info& type) {
+		if (typeid(NonVirtual)!=type) return NULL;
+		return &(*obj);
+	}
+
+	// to_string_v
+
+	/// convert address to a string that can be used to reconstruct the address
+	virtual string to_string() const {
+		return obj->to_string();
+	}
+
+	/// Assigns an address using a human-readable
+	virtual bool assign(const std::string& text) {
+		return obj->assign(text);
+	}
+
+	// comparable_v
+
+	/// implements comparison operators
+	virtual int compare_to(const self& rhs) const {
+		const address_v* compare = dynamic_cast<const address_v*> (&rhs);
+		return obj->compare_to(conv(compare));
+	}
+
+	// to_bytes_v
+
+	/// returns true, if this address has a fixed size in bytes
+	virtual bool is_bytes_size_static() const {
+		return obj->is_bytes_size_static();
+	}
+
+	/// returns the number of bytes used for serialization of this address
+	virtual size_t to_bytes_size() const {
+		return obj->to_bytes_size();
+	}
+
+	/// converts this address to a binary representation
+	virtual void to_bytes(uint8_t* bytes) const {
+		obj->to_bytes(bytes);
+	}
+
+	/// Assigns an address using a bunch of bytes
+	virtual bool assign(const uint8_t* bytes, size_t size) {
+		return obj->assign(bytes, size);
+	}
+
+};
+
+
+#endif /* ADDRESS_V_H_ */
Index: /source/ariba/utility/addressing/facades/comparable_v.hpp
===================================================================
--- /source/ariba/utility/addressing/facades/comparable_v.hpp	(revision 5284)
+++ /source/ariba/utility/addressing/facades/comparable_v.hpp	(revision 5284)
@@ -0,0 +1,83 @@
+// comparable_v.hpp, created on 30.06.2009 by Sebastian Mies
+
+#ifndef COMPARABLE_V_HPP_
+#define COMPARABLE_V_HPP_
+
+#include "vfacade.hpp"
+
+/**
+ * TODO: Doc
+ *
+ * @author Sebastian Mies <mies@tm.uka.de>
+ */
+class comparable_v {
+public:
+	//--- comparable_v --------------------------------------------------------
+
+	/// implements comparison operators
+	virtual int compare_to(const comparable_v& rhs) const = 0;
+
+	/// convenience method for comparison
+	inline int compare_to(const comparable_v* rhs) const {
+		return compare_to(*rhs);
+	}
+
+	/// convenience method for comparison
+	inline bool operator==(const comparable_v& rhs) const {
+		return compare_to(rhs) == 0;
+	}
+
+	/// convenience method for comparison
+	inline bool operator!=(const comparable_v& rhs) const {
+		return compare_to(rhs) != 0;
+	}
+
+	/// convenience method for comparison
+	inline bool operator<(const comparable_v& rhs) const {
+		return compare_to(rhs) < 0;
+	}
+
+	/// convenience method for comparison
+	inline bool operator<=(const comparable_v& rhs) const {
+		return compare_to(rhs) <= 0;
+	}
+
+	/// convenience method for comparison
+	inline bool operator>(const comparable_v& rhs) const {
+		return compare_to(rhs) > 0;
+	}
+
+	/// convenience method for comparison
+	inline bool operator>=(const comparable_v& rhs) const {
+		return compare_to(rhs) >= 0;
+	}
+};
+
+typedef vfacade<comparable_v> comparable_vf;
+
+template<class NonVirtual, class AdaptorType>
+class vobject_hull<NonVirtual, comparable_v, AdaptorType> : public comparable_v {
+private:
+	typename AdaptorType::template adaptor_type<NonVirtual> obj;
+
+public:
+	template<typename T>
+	explicit vobject_hull(T& obj) :
+		obj(obj) {
+	}
+
+	explicit vobject_hull() :
+		obj() {
+	}
+
+	//--- comparable_v --------------------------------------------------------
+
+	/// implements comparison operators
+	virtual int compare_to(const comparable_v& rhs) const {
+		return obj->compare_to(rhs);
+	}
+};
+
+
+
+#endif /* COMPARABLE_V_HPP_ */
Index: /source/ariba/utility/addressing/facades/to_bytes_v.hpp
===================================================================
--- /source/ariba/utility/addressing/facades/to_bytes_v.hpp	(revision 5284)
+++ /source/ariba/utility/addressing/facades/to_bytes_v.hpp	(revision 5284)
@@ -0,0 +1,72 @@
+// to_bytes_v.hpp, created on 30.06.2009 by Sebastian Mies
+
+#ifndef TO_BYTES_V_HPP_
+#define TO_BYTES_V_HPP_
+
+#include <memory>
+#include "vfacade.hpp"
+
+/**
+ * TODO: Doc
+ *
+ * @author Sebastian Mies <mies@tm.uka.de>
+ */
+class to_bytes_v {
+public:
+	//--- to_bytes_v ----------------------------------------------------------
+
+	/// returns true, if this address has a fixed size in bytes
+	virtual bool is_bytes_size_static() const = 0;
+
+	/// returns the number of bytes used for serialization of this address
+	virtual size_t to_bytes_size() const = 0;
+
+	/// converts this address to a binary representation
+	virtual void to_bytes(uint8_t* bytes) const = 0;
+
+	/// Assigns an address using a bunch of bytes
+	virtual bool assign(const uint8_t* bytes, size_t size) = 0;
+};
+
+typedef vfacade<to_bytes_v> to_bytes_vf;
+
+template<class NonVirtual, class AdaptorType>
+class vobject_hull<NonVirtual, to_bytes_v, AdaptorType> : public to_bytes_v {
+private:
+	typename AdaptorType::template adaptor_type<NonVirtual> obj;
+
+public:
+	template<typename T>
+	explicit vobject_hull(T& obj) :
+		obj(obj) {
+	}
+
+	explicit vobject_hull() :
+		obj() {
+	}
+
+	//--- to_bytes_v ----------------------------------------------------------
+
+	/// returns true, if this address has a fixed size in bytes
+	virtual bool is_bytes_size_static() const {
+		return obj->is_bytes_size_static();
+	}
+
+	/// returns the number of bytes used for serialization of this address
+	virtual size_t to_bytes_size() const {
+		return obj->to_bytes_size();
+	}
+
+	/// converts this address to a binary representation
+	virtual void to_bytes(uint8_t* bytes) const {
+		obj->to_bytes(bytes);
+	}
+
+	/// Assigns an address using a bunch of bytes
+	virtual bool assign(const uint8_t* bytes, size_t size) {
+		return obj->assign(bytes,size);
+	}
+};
+
+
+#endif /* TO_BYTES_V_HPP_ */
Index: /source/ariba/utility/addressing/facades/to_string_v.hpp
===================================================================
--- /source/ariba/utility/addressing/facades/to_string_v.hpp	(revision 5284)
+++ /source/ariba/utility/addressing/facades/to_string_v.hpp	(revision 5284)
@@ -0,0 +1,77 @@
+// to_string_v.hpp, created on 30.06.2009 by Sebastian Mies
+
+#ifndef TO_STRING_V_HPP_
+#define TO_STRING_V_HPP_
+
+#include <string>
+#include "vfacade.hpp"
+
+using namespace std;
+
+/**
+ * TODO: Doc
+ *
+ * @author Sebastian Mies <mies@tm.uka.de>
+ */
+/// a to to string interface
+class to_string_v {
+public:
+	//--- to_string_v ---------------------------------------------------------
+
+	/// convert address to a string that can be used to reconstruct the address
+	virtual string to_string() const = 0;
+
+	/// Assigns an address using a human-readable
+	virtual bool assign(const std::string& text) = 0;
+
+	/// convenience method for assignment of a c-strings
+	inline to_string_v& assign(const char* text) {
+		to_string_v::assign(std::string(text));
+		return *this;
+	}
+
+	/// convenience method for assignment of strings
+	inline to_string_v& operator=(const std::string& text) {
+		assign(text);
+		return *this;
+	}
+
+	/// convenience method for assignment of strings
+	inline to_string_v& operator=(const char* text) {
+		assign(text);
+		return *this;
+	}
+};
+
+typedef vfacade<to_string_v> to_string_vf;
+
+/// the object hull for to_string interfaces
+template<class NonVirtual, class AdaptorType>
+class vobject_hull<NonVirtual, to_string_v, AdaptorType> : public to_string_v {
+private:
+	typename AdaptorType::template adaptor_type<NonVirtual> obj;
+
+public:
+	template<typename T>
+	explicit vobject_hull(T& obj) :
+		obj(obj) {
+	}
+
+	explicit vobject_hull() :
+		obj() {
+	}
+
+	//--- to_string_v ---------------------------------------------------------
+
+	/// convert address to a string that can be used to reconstruct the address
+	virtual string to_string() const {
+		return obj->to_string();
+	}
+
+	/// Assigns an address using a human-readable
+	virtual bool assign(const std::string& text) {
+		return obj->assign(text);
+	}
+};
+
+#endif /* TO_STRING_V_HPP_ */
Index: /source/ariba/utility/addressing/facades/vfacade.hpp
===================================================================
--- /source/ariba/utility/addressing/facades/vfacade.hpp	(revision 5284)
+++ /source/ariba/utility/addressing/facades/vfacade.hpp	(revision 5284)
@@ -0,0 +1,237 @@
+#ifndef VFACADE_HPP_
+#define VFACADE_HPP_
+
+#include <iostream>
+#include <typeinfo>
+
+#include <assert.h>
+#include <memory.h>
+
+/**
+ * TODO: Doc
+ *
+ * @author Sebastian Mies <mies@tm.uka.de>
+ */
+/// the virtual object adaptor class
+template<class NonVirtual, class Virtual, class Adaptor>
+class vobject_hull : public Virtual {
+};
+
+/**
+ * TODO: Doc
+ *
+ * @author Sebastian Mies <mies@tm.uka.de>
+ */
+/// the vfacade adaptor type
+struct vfacade_adaptor_type {
+	template<class NonVirtual>
+	class adaptor_type {
+	private:
+		NonVirtual* obj_;
+	public:
+		explicit inline adaptor_type() :
+			obj_() {
+		}
+		explicit inline adaptor_type(NonVirtual& obj) :
+			obj_(&obj) {
+		}
+		explicit inline adaptor_type(const NonVirtual& obj) :
+			obj_(&obj) {
+		}
+		inline void set(NonVirtual& obj) {
+			obj_ = &obj;
+		}
+		inline NonVirtual* operator->() {
+			return obj_;
+		}
+		inline const NonVirtual* operator->() const {
+			return obj_;
+		}
+		inline const NonVirtual& operator*() const {
+			return *obj_;
+		}
+		inline NonVirtual& operator*() {
+			return *obj_;
+		}
+	};
+};
+
+/**
+ * TODO: Doc
+ *
+ * @author Sebastian Mies <mies@tm.uka.de>
+ */
+/// the virtual capsule adaptor type
+struct vcapsule_adaptor_type {
+	template<class NonVirtual>
+	class adaptor_type {
+	private:
+		NonVirtual obj_;
+	public:
+		inline adaptor_type() :
+			obj_() {
+		}
+		inline adaptor_type(const NonVirtual& obj) :
+			obj_(obj) {
+		}
+		inline void assign(const NonVirtual& obj) {
+			obj_ = obj;
+		}
+		inline NonVirtual* operator->() {
+			return &obj_;
+		}
+		inline const NonVirtual* operator->() const {
+			return &obj_;
+		}
+		inline const NonVirtual& operator*() const {
+			return obj_;
+		}
+		inline NonVirtual& operator*() {
+			return obj_;
+		}
+	};
+};
+
+/**
+ * TODO: Doc
+ *
+ * @author Sebastian Mies <mies@tm.uka.de>
+ */
+/// placeholder
+class vfacade_no_class {};
+
+/**
+ * TODO: Doc
+ *
+ * @author Sebastian Mies <mies@tm.uka.de>
+ */
+/// a virtual fascade implementation
+template<class Virtual, class Extension = vfacade_no_class>
+class vfacade : public Extension {
+public:
+	typedef vfacade<Virtual> self;
+
+private:
+	void* vtable;
+	void* vadaptor;
+
+	template<class T>
+	void assign(T& obj) {
+		typedef vobject_hull<T, Virtual, vfacade_adaptor_type> adaptor_type;
+		adaptor_type adaptor(obj);
+		assert( sizeof(adaptor_type) == sizeof(vfacade) );
+		memcpy((void*) this, (void*) &adaptor, sizeof(vfacade));
+	}
+
+	template<class T>
+	void assign(const T& obj) {
+		T& obj_ = *const_cast<T*>(&obj);
+		typedef vobject_hull<T, Virtual, vfacade_adaptor_type> adaptor_type;
+		adaptor_type adaptor(obj_);
+		assert( sizeof(adaptor_type) == sizeof(vfacade) );
+		memcpy((void*) this, (void*) &adaptor, sizeof(vfacade));
+	}
+
+	void assign(self& copy) {
+		this->vtable = copy.vtable;
+		this->vadaptor = copy.vadaptor;
+	}
+
+	void assign(const self& copy) {
+		this->vtable = copy.vtable;
+		this->vadaptor = copy.vadaptor;
+	}
+
+public:
+	/// constructs an undefined virtual facade
+	inline vfacade() {
+		this->vtable = NULL;
+		this->vadaptor = NULL;
+	}
+
+	/// constructs an initialized virtual facade
+	template<class T>
+	inline vfacade(T& obj) {
+		assign(*const_cast<T*>(&obj));
+	}
+
+	/// assigns a new object to this facade
+	template<class T>
+	inline self& operator=(T& obj) {
+		assign(obj);
+		return *this;
+	}
+
+	/// returns true, if the facade is unassigned
+	inline bool is_null() const {
+		return this->vtable == NULL;
+	}
+
+	inline operator Virtual* () {
+		assert(vtable!=NULL);
+		return (Virtual*) this;
+	}
+
+	inline operator const Virtual* () const {
+		assert(vtable!=NULL);
+		return (const Virtual*) this;
+	}
+
+	inline operator Virtual& () {
+		assert(vtable!=NULL);
+		return *(Virtual*) this;
+	}
+
+	inline operator const Virtual& () const {
+		assert(vtable!=NULL);
+		return *(const Virtual*) this;
+	}
+
+	/// returns the virtual object of the facade
+	inline Virtual* operator->() {
+		assert(vtable!=NULL);
+		return (Virtual*) this;
+	}
+
+	/// returns a virtual object reference
+	inline Virtual& operator*() {
+		assert(vtable!=NULL);
+		return *((Virtual*) this);
+	}
+
+	/// returns a virtual object reference
+	inline const Virtual& operator*() const {
+		assert(vtable!=NULL);
+		return *((const Virtual*) this);
+	}
+
+	/// returns a constant virtual object of the facade
+	inline const Virtual* operator->() const {
+		assert(vtable!=NULL);
+		return (const Virtual*) this;
+	}
+};
+
+/**
+ * TODO: Doc
+ *
+ * @author Sebastian Mies <mies@tm.uka.de>
+ */
+/// creates a virtual capsule for an object
+template<class Virtual, class NonVirtual>
+Virtual* vcapsule(const NonVirtual& obj) {
+	return new vobject_hull<NonVirtual, Virtual, vcapsule_adaptor_type> (obj);
+}
+
+/**
+ * TODO: Doc
+ *
+ * @author Sebastian Mies <mies@tm.uka.de>
+ */
+/// returns the size in bytes of a virtual capsule
+template<class Virtual, class NonVirtual>
+size_t vcapsule_size(const NonVirtual& obj) {
+	return sizeof(vobject_hull<NonVirtual, Virtual, vcapsule_adaptor_type> (obj));
+}
+
+#endif /* VFACADE_HPP_ */
Index: /source/ariba/utility/addressing/ip_address.cpp
===================================================================
--- /source/ariba/utility/addressing/ip_address.cpp	(revision 5284)
+++ /source/ariba/utility/addressing/ip_address.cpp	(revision 5284)
@@ -0,0 +1,9 @@
+#include "ip_address.hpp"
+
+namespace ariba {
+namespace addressing {
+
+const std::string ip_address::type_name_ip = "ip";
+
+}} // namespace ariba::addressing
+
Index: /source/ariba/utility/addressing/ip_address.hpp
===================================================================
--- /source/ariba/utility/addressing/ip_address.hpp	(revision 5284)
+++ /source/ariba/utility/addressing/ip_address.hpp	(revision 5284)
@@ -0,0 +1,188 @@
+#ifndef IP_ADDRESS_HPP_
+#define IP_ADDRESS_HPP_
+
+#include <string>
+#include <boost/tr1/functional.hpp>
+#include <boost/asio/ip/address.hpp>
+
+#include "detail/address_convenience.hpp"
+
+namespace ariba {
+namespace addressing {
+
+using boost::asio::ip::address;
+using boost::asio::ip::address_v4;
+using boost::asio::ip::address_v6;
+
+/**
+ * TODO: Doc
+ *
+ * @author Sebastian Mies <mies@tm.uka.de>
+ */
+class ip_address: public detail::address_convenience<ip_address> {
+private:
+	address addr;
+	static const std::string type_name_ip;
+
+public:
+	ip_address() : addr() {
+	}
+
+	ip_address(const ip_address& copy) : addr(copy.addr) {
+
+	}
+
+	ip_address(const address& addr) : addr(addr) {
+
+	}
+
+	ip_address(const address_v4& addr) : addr(addr) {
+
+	}
+
+	ip_address(const address_v6& addr) : addr(addr) {
+
+	}
+
+	ip_address(const std::string& text) {
+		assign(text);
+	}
+
+	ip_address(const char* text) {
+		assign(std::string(text));
+	}
+
+	ip_address(const uint8_t* bytes, size_t size) {
+		assign(bytes, size);
+	}
+
+	//--- compare operations --------------------------------------------------
+
+	/// implements comparison operators
+	int compare_to(const ip_address& rhs) const {
+		if (addr == rhs.addr) return 0;
+		if (addr < rhs.addr) return -1; else return 1;
+	}
+
+	//--- byte representation -------------------------------------------------
+
+	/// returns true, if this address has a fixed size in bytes
+	bool is_bytes_size_static() const {
+		return false;
+	}
+
+	/// returns the number of bytes used for serialization of this address
+	size_t to_bytes_size() const {
+		return addr.is_v4() ? 4 : 16;
+	}
+
+	/// converts this address to a binary representation
+	void to_bytes(uint8_t* bytes) const {
+		if (addr.is_v4()) {
+			address_v4::bytes_type bytes_ = addr.to_v4().to_bytes();
+			for (size_t i=0; i<bytes_.size(); i++) bytes[i] = bytes_[i];
+		} else {
+			address_v6::bytes_type bytes_ = addr.to_v6().to_bytes();
+			for (size_t i=0; i<bytes_.size(); i++) bytes[i] = bytes_[i];
+		}
+	}
+
+	/// Assigns an address using a bunch of bytes
+	bool assign(const uint8_t* bytes, size_t size) {
+		if (size == 4) {
+			address_v4::bytes_type bytes_;
+			for (size_t i=0; i<bytes_.size(); i++) bytes_[i] = bytes[i];
+			addr = address_v4(bytes_);
+			return false;
+		} else
+		if (size == 16) {
+			address_v6::bytes_type bytes_;
+			for (size_t i=0; i<bytes_.size(); i++) bytes_[i] = bytes[i];
+			addr = address_v6(bytes_);
+			return false;
+		}
+		return true;
+	}
+
+	//--- string representation -----------------------------------------------
+
+	/// convert address to a string that can be used to reconstruct the address
+	std::string to_string() const {
+		return addr.to_string();
+	}
+
+	/// Assigns an address using a human-readable
+	bool assign(const std::string& text) {
+		addr = address::from_string(text);
+		return false;
+	}
+
+	//--- assignment ----------------------------------------------------------
+
+	/// Assigns an address
+	bool assign(const ip_address& rhs) {
+		addr = rhs.addr;
+		return false;
+	}
+
+	//--- address info --------------------------------------------------------
+
+	const std::string& type_name() const {
+		return type_name_ip;
+	}
+
+	const uint16_t type_id() const {
+		return 0x81DD;
+	}
+
+	//--- address delegates ---------------------------------------------------
+
+	bool is_multicast() const {
+		if (addr.is_v4()) return addr.to_v4().is_multicast();
+		return addr.to_v6().is_multicast();
+	}
+
+	bool is_loopback() const {
+		if (addr.is_v4()) return addr.to_v4() == address_v4::loopback();
+		return addr.to_v6().is_loopback();
+	}
+
+	bool is_any() const {
+		if (addr.is_v4()) return addr.to_v4() == address_v4::any();
+		return addr.to_v6() == address_v6::any();
+	}
+
+	bool is_v4() const {
+		return addr.is_v4();
+	}
+
+	bool is_v6() const {
+		return addr.is_v6();
+	}
+
+	//--- address conversions -------------------------------------------------
+
+	const address& asio() const {
+		return addr;
+	}
+
+	void asio( const address& addr ) {
+		this->addr = addr;
+	}
+};
+
+}} // namespace ariba::addressing
+
+namespace boost {
+
+template<>
+struct hash<ariba::addressing::ip_address>: public std::unary_function<ariba::addressing::ip_address, std::size_t> {
+	std::size_t operator()(const ariba::addressing::ip_address& ep) const {
+		return hash_value(ep.to_string());
+	}
+};
+
+}
+
+
+#endif /* IP_ADDRESS_HPP_ */
Index: /source/ariba/utility/addressing/mac_address.cpp
===================================================================
--- /source/ariba/utility/addressing/mac_address.cpp	(revision 5284)
+++ /source/ariba/utility/addressing/mac_address.cpp	(revision 5284)
@@ -0,0 +1,10 @@
+#include "mac_address.hpp"
+
+namespace ariba {
+namespace addressing {
+
+const uint16_t mac_address_info::type_id = 0xFF28;
+const std::string mac_address_info::type_name = "mac";
+
+}} // namespace ariba::addressing
+
Index: /source/ariba/utility/addressing/mac_address.hpp
===================================================================
--- /source/ariba/utility/addressing/mac_address.hpp	(revision 5284)
+++ /source/ariba/utility/addressing/mac_address.hpp	(revision 5284)
@@ -0,0 +1,155 @@
+#ifndef MAC_ADDRESS_HPP_
+#define MAC_ADDRESS_HPP_
+
+#include "detail/address_convenience.hpp"
+
+#include<string>
+#include<cassert>
+#include<boost/tr1/functional.hpp>
+#include<bluetooth/bluetooth.h>
+
+namespace ariba {
+namespace addressing {
+
+struct mac_address_info {
+	static const uint16_t type_id;
+	static const std::string type_name;
+};
+
+/**
+ * TODO: Doc
+ *
+ * @author Sebastian Mies <mies@tm.uka.de>
+ */
+template<class AddressInfo = mac_address_info>
+class mac_address_tpl: public detail::address_convenience<mac_address_tpl<AddressInfo> > {
+private:
+	uint8_t mac[6];
+
+public:
+	mac_address_tpl() {
+		for (int i = 0; i < 6; i++)
+			mac[i] = 0;
+	}
+
+	mac_address_tpl( const mac_address_tpl& copy ) {
+		assign(copy);
+	}
+
+	mac_address_tpl(const std::string& text) {
+		assign(text);
+	}
+
+	mac_address_tpl(const char* text) {
+		assign(std::string(text));
+	}
+
+	mac_address_tpl(const uint8_t* bytes, size_t size) {
+		assign(bytes, size);
+	}
+
+	//--- compare operations --------------------------------------------------
+
+	/// implements comparison operators
+	int compare_to(const mac_address_tpl& rhs) const {
+		size_t i = 0;
+		while (rhs.mac[i] == mac[i] && i < 6)
+			i++;
+		return (6 - i);
+	}
+
+	//--- bytes representation ------------------------------------------------
+
+	/// returns true, if this address has a fixed size in bytes
+	bool is_bytes_size_static() const {
+		return true;
+	}
+
+	/// returns the number of bytes used for serialization of this address
+	size_t to_bytes_size() const {
+		return 6;
+	}
+
+	/// converts this address to a binary representation
+	void to_bytes(uint8_t* bytes) const {
+		for (size_t i = 0; i < 6; i++)
+			bytes[i] = mac[i];
+	}
+
+	/// Assigns an address using a bunch of bytes
+	bool assign(const uint8_t* bytes, size_t size) {
+		assert(size==6);
+		for (size_t i = 0; i < 6; i++)
+			mac[i] = bytes[i];
+		return false;
+	}
+
+	//--- string representation -----------------------------------------------
+
+	/// convert address to a string that can be used to reconstruct the address
+	std::string to_string() const {
+		char str[80];
+		sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
+				mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+		return std::string(str);
+	}
+
+	/// Assigns an address using a human-readable
+	bool assign(const std::string& text) {
+		unsigned int mac_[6];
+		sscanf(text.c_str(), "%x:%x:%x:%x:%x:%x", &mac_[0], &mac_[1], &mac_[2],
+				&mac_[3], &mac_[4], &mac_[5]);
+		for (size_t i = 0; i < 6; i++)
+			mac[i] = (uint8_t) mac_[i];
+		return false;
+	}
+
+	//--- assignment ----------------------------------------------------------
+
+	/// Assigns an address
+	bool assign(const mac_address_tpl& rhs) {
+		for (size_t i = 0; i < 6; i++)
+			mac[i] = rhs.mac[i];
+		return false;
+	}
+
+	//--- address info --------------------------------------------------------
+
+	const std::string& type_name() const {
+		return AddressInfo::type_name;
+	}
+
+	const uint16_t type_id() const {
+		return AddressInfo::type_id;
+	}
+
+	//--- conversion ----------------------------------------------------------
+
+	bdaddr_t bluetooth() const {
+		bdaddr_t addr;
+		for (size_t i=0; i<6; i++) addr.b[i] = mac[5-i];
+		return addr;
+	}
+
+	void bluetooth( bdaddr_t addr ) {
+		for (size_t i=0; i<6; i++) mac[i] = addr.b[5-i];
+	}
+};
+
+typedef mac_address_tpl<> mac_address;
+
+}} // namespace ariba::addressing
+
+namespace boost {
+
+template<class T>
+struct hash<ariba::addressing::mac_address_tpl<T> >: public std::unary_function<ariba::addressing::mac_address_tpl<T>, std::size_t> {
+	std::size_t operator()(const ariba::addressing::mac_address_tpl<T>& ep) const {
+		return hash_value(ep.to_string());
+	}
+};
+
+}
+
+
+#endif /* MAC_ADDRESS_HPP_ */
Index: /source/ariba/utility/addressing/port_address.cpp
===================================================================
--- /source/ariba/utility/addressing/port_address.cpp	(revision 5284)
+++ /source/ariba/utility/addressing/port_address.cpp	(revision 5284)
@@ -0,0 +1,10 @@
+#include "port_address.hpp"
+
+namespace ariba {
+namespace addressing {
+
+const uint16_t port_address_info::type_id = 0xFF01;
+const std::string port_address_info::type_name = "generic-port";
+
+}} // namespace ariba::addressing
+
Index: /source/ariba/utility/addressing/port_address.hpp
===================================================================
--- /source/ariba/utility/addressing/port_address.hpp	(revision 5284)
+++ /source/ariba/utility/addressing/port_address.hpp	(revision 5284)
@@ -0,0 +1,162 @@
+// port_address.hpp, created on 24.06.2009 by Sebastian Mies
+
+#ifndef PORT_ADDRESS_HPP_
+#define PORT_ADDRESS_HPP_
+
+#include<string>
+#include<boost/tr1/functional.hpp>
+
+#include "detail/address_convenience.hpp"
+
+namespace ariba {
+namespace addressing {
+
+struct port_address_info {
+	static const uint16_t type_id;
+	static const std::string type_name;
+};
+
+/**
+ * TODO: Doc
+ *
+ * @author Sebastian Mies <mies@tm.uka.de>
+ */
+template<class AddressInfo = port_address_info>
+class port_address_tpl: public detail::address_convenience<
+		port_address_tpl<AddressInfo> > {
+private:
+	uint16_t port;
+
+public:
+	typedef port_address_tpl<AddressInfo> self;
+
+	port_address_tpl() {
+		port = 0;
+	}
+
+	port_address_tpl( const port_address_tpl& copy ) : port(copy.port) {
+
+	}
+
+	port_address_tpl(const std::string& text) {
+		assign( text );
+	}
+
+	port_address_tpl(const char* text) {
+		assign( std::string(text) );
+	}
+
+	port_address_tpl(uint16_t port) : port(port) {
+
+	}
+
+	port_address_tpl(const uint8_t* bytes, size_t size) {
+		assign( bytes, size );
+	}
+
+	//--- compare operations --------------------------------------------------
+
+	/// implements comparison operators
+	int compare_to(const self& rhs) const {
+		return port - rhs.port;
+	}
+
+	//--- bytes representation ------------------------------------------------
+
+	/// returns true, if this address has a fixed size in bytes
+	bool is_bytes_size_static() const {
+		return true;
+	}
+
+	/// returns the number of bytes used for serialization of this address
+	size_t to_bytes_size() const {
+		return 2;
+	}
+
+	/// converts this address to a binary representation
+	void to_bytes(uint8_t* bytes) const {
+		bytes[0] = port >> 8;
+		bytes[1] = port & 0xFF;
+	}
+
+	/// Assigns an address using a bunch of bytes
+	bool assign(const uint8_t* bytes, size_t size) {
+		port = ((bytes[0] << 8) + bytes[1]);
+		return false;
+	}
+
+	//--- text representation -------------------------------------------------
+
+	/// convert address to a string that can be used to reconstruct the address
+	std::string to_string() const {
+		char str[8];
+		sprintf(str, "%d", port);
+		return std::string(str);
+	}
+
+	/// Assigns an address using a human-readable
+	bool assign(const std::string& text) {
+		unsigned int port_;
+		sscanf(text.c_str(), "%d", &port_);
+		if (port_ >= 0 && port_ <= 65535) {
+			port = (uint16_t) port_;
+			return false;
+		}
+		return true;
+	}
+
+	//--- assignment ----------------------------------------------------------
+
+	/// Assigns an address
+	bool assign(const self& rhs) {
+		port = rhs.port;
+		return false;
+	}
+
+	//--- address info --------------------------------------------------------
+
+	/// returns the type name
+	const std::string& type_name() const {
+		return AddressInfo::type_name;
+	}
+
+	/// returns the type identifier
+	const uint16_t type_id() const {
+		return AddressInfo::type_id;
+	}
+
+	//--- conversions ---------------------------------------------------------
+
+	uint16_t asio() const {
+		return port;
+	}
+
+	void asio( uint16_t port ) {
+		this->port = port;
+	}
+
+	uint16_t value() const {
+		return port;
+	}
+
+	void value( uint16_t v ) {
+		port  = v;
+	}
+};
+
+typedef port_address_tpl<> port_address;
+
+}} // namespace ariba::addressing
+
+namespace boost {
+
+template<class T>
+struct hash<ariba::addressing::port_address_tpl<T> >: public std::unary_function<ariba::addressing::port_address_tpl<T>, std::size_t> {
+	std::size_t operator()(const ariba::addressing::port_address_tpl<T>& ep) const {
+		return hash_value(ep.value());
+	}
+};
+
+}
+
+#endif /* PORT_ADDRESS_HPP_ */
Index: /source/ariba/utility/addressing/rfcomm_endpoint.cpp
===================================================================
--- /source/ariba/utility/addressing/rfcomm_endpoint.cpp	(revision 5284)
+++ /source/ariba/utility/addressing/rfcomm_endpoint.cpp	(revision 5284)
@@ -0,0 +1,11 @@
+
+#include "rfcomm_endpoint.hpp"
+
+namespace ariba {
+namespace addressing {
+
+const uint16_t rfcomm_channel_address_info::type_id = 0xFE02;
+const std::string rfcomm_channel_address_info::type_name = "rfcomm-channel";
+const std::string rfcomm_endpoint::protocol_name = "rfcomm";
+
+}} // namespace ariba::addressing
Index: /source/ariba/utility/addressing/rfcomm_endpoint.hpp
===================================================================
--- /source/ariba/utility/addressing/rfcomm_endpoint.hpp	(revision 5284)
+++ /source/ariba/utility/addressing/rfcomm_endpoint.hpp	(revision 5284)
@@ -0,0 +1,175 @@
+#ifndef RFCOMM_ENDPOINT_HPP_
+#define RFCOMM_ENDPOINT_HPP_
+
+#include<string>
+
+#include<boost/tr1/functional.hpp>
+#include<boost/asio.hpp>
+
+#include "detail/address_convenience.hpp"
+
+#include "port_address.hpp"
+#include "mac_address.hpp"
+
+namespace ariba {
+namespace addressing {
+
+using namespace std;
+
+struct rfcomm_channel_address_info {
+	static const uint16_t type_id;
+	static const std::string type_name;
+};
+typedef port_address_tpl<rfcomm_channel_address_info> rfcomm_channel_address;
+
+/**
+ * TODO: Doc
+ *
+ * @author Sebastian Mies <mies@tm.uka.de>
+ */
+class rfcomm_endpoint : public detail::address_convenience<rfcomm_endpoint> {
+private:
+	mac_address mac_;
+	rfcomm_channel_address channel_;
+	static const std::string protocol_name;
+
+public:
+	typedef rfcomm_endpoint self;
+
+public:
+	rfcomm_endpoint() :
+		mac_(), channel_() {
+	}
+
+	rfcomm_endpoint( const rfcomm_endpoint& copy ) {
+		assign(copy);
+	}
+
+	rfcomm_endpoint( const mac_address& mac, const rfcomm_channel_address& channel) :
+		mac_(mac), channel_(channel) {
+	}
+
+	rfcomm_endpoint(const  std::string& mac, const std::string& channel) :
+		mac_(mac), channel_(channel) {
+	}
+
+	rfcomm_endpoint(const std::string& mac, uint16_t channel) :
+		mac_(mac), channel_(channel) {
+	}
+
+	rfcomm_endpoint(const std::string& text) {
+		assign( text );
+	}
+
+	rfcomm_endpoint(const char* text) {
+		assign( std::string(text) );
+	}
+
+	rfcomm_endpoint(const uint8_t* bytes, size_t size) {
+		assign( bytes, size );
+	}
+
+	bool assign( const self& copy ) {
+		this->mac_ = copy.mac_;
+		this->channel_ = copy.channel_;
+		return false;
+	}
+
+	//--- compare operations --------------------------------------------------
+
+	/// implements comparison operators
+	int compare_to(const self& rhs) const {
+		if (mac_.compare_to(rhs.mac_)==0 && channel_.compare_to(rhs.channel_)==0) return 0;
+		return 1;
+	}
+
+	//--- bytes representation ------------------------------------------------
+
+	/// returns true, if this address has a fixed size in bytes
+	bool is_bytes_size_static() const {
+		return true;
+	}
+
+	/// returns the number of bytes used for serialization of this address
+	size_t to_bytes_size() const {
+		return mac_.to_bytes_size() + channel_.to_bytes_size();
+	}
+
+	/// converts this address to a binary representation
+	void to_bytes(uint8_t* bytes) const {
+		mac_.to_bytes(bytes);
+		channel_.to_bytes(bytes+mac_.to_bytes_size());
+	}
+
+	/// Assigns an address using a bunch of bytes
+	bool assign(const uint8_t* bytes, size_t size) {
+		assert(size==8);
+		return false;
+	}
+
+	//--- text representation -------------------------------------------------
+
+	/// convert address to a string that can be used to reconstruct the address
+	std::string to_string() const {
+		return std::string("[")+mac_.to_string()+std::string("]:")+channel_.to_string();
+	}
+
+	/// Assigns an address using a human-readable
+	bool assign(const std::string& text) {
+		std::string mac_str;
+		std::string channel_str;
+		if (text.at(0)=='[') {
+			int i = text.find(']',1);
+			mac_str = text.substr(1,i-1);
+			channel_str = text.substr(i+2, text.size()-i-1);
+			return mac_.assign(mac_str) || channel_.assign(channel_str);
+		}
+		return true;
+	}
+
+	//--- address info --------------------------------------------------------
+
+	/// returns the name of the address
+	const string& type_name() const {
+		return protocol_name;
+	}
+
+	/// returns the id of the address
+	uint16_t type_id() const {
+		return 0xFE05;
+	}
+
+	//--- endpoint elements ---------------------------------------------------
+
+	mac_address& mac() {
+		return mac_;
+	}
+
+	const mac_address& mac() const {
+		return mac_;
+	}
+
+	rfcomm_channel_address& channel() {
+		return channel_;
+	}
+
+	const rfcomm_channel_address& channel() const {
+		return channel_;
+	}
+};
+
+}} // namespace ariba::addressing
+
+namespace boost {
+
+template<>
+struct hash<ariba::addressing::rfcomm_endpoint>: public std::unary_function<ariba::addressing::rfcomm_endpoint, std::size_t> {
+	std::size_t operator()(const ariba::addressing::rfcomm_endpoint& ep) const {
+		return hash_value(ep.to_string());
+	}
+};
+
+}
+
+
+#endif /* RFCOMM_ENDPOINT_HPP_ */
Index: /source/ariba/utility/addressing/tcpip_endpoint.cpp
===================================================================
--- /source/ariba/utility/addressing/tcpip_endpoint.cpp	(revision 5284)
+++ /source/ariba/utility/addressing/tcpip_endpoint.cpp	(revision 5284)
@@ -0,0 +1,10 @@
+#include "tcpip_endpoint.hpp"
+
+namespace ariba {
+namespace addressing {
+
+const uint16_t tcp_address_info::type_id = 6;
+const std::string tcp_address_info::type_name = "tcp-port";
+const std::string tcpip_endpoint::protocol_name = "tcp-ip";
+
+}} // namespace ariba::addressing
Index: /source/ariba/utility/addressing/tcpip_endpoint.hpp
===================================================================
--- /source/ariba/utility/addressing/tcpip_endpoint.hpp	(revision 5284)
+++ /source/ariba/utility/addressing/tcpip_endpoint.hpp	(revision 5284)
@@ -0,0 +1,206 @@
+#ifndef TCPIP_ENDPOINT_HPP_
+#define TCPIP_ENDPOINT_HPP_
+
+#include<string>
+
+#include<boost/tr1/functional.hpp>
+#include<boost/asio.hpp>
+
+#include "detail/address_convenience.hpp"
+#include "port_address.hpp"
+#include "ip_address.hpp"
+
+namespace ariba {
+namespace addressing {
+
+using boost::asio::ip::tcp;
+using namespace std;
+
+struct tcp_address_info {
+	static const uint16_t type_id;
+	static const std::string type_name;
+};
+
+typedef port_address_tpl<tcp_address_info> tcp_port_address;
+
+/**
+ * TODO: Doc
+ *
+ * @author Sebastian Mies <mies@tm.uka.de>
+ */
+class tcpip_endpoint : public detail::address_convenience<tcpip_endpoint> {
+private:
+	ip_address ip;
+	tcp_port_address port_;
+	static const std::string protocol_name;
+
+public:
+	typedef tcpip_endpoint self;
+
+public:
+	tcpip_endpoint() :
+		ip(), port_() {
+	}
+
+	tcpip_endpoint( const tcpip_endpoint& copy ) {
+		assign(copy);
+	}
+
+	tcpip_endpoint( uint16_t port ) : ip(address_v6::any()), port_(port) {
+	}
+
+	tcpip_endpoint( const ip_address& ip, const tcp_port_address& port) :
+		ip(ip), port_(port) {
+	}
+
+	tcpip_endpoint(const  std::string& ip, const std::string& port) :
+		ip(ip), port_(port) {
+	}
+
+	tcpip_endpoint(const std::string& ip, uint16_t port) :
+		ip(ip), port_(port) {
+	}
+
+	tcpip_endpoint(const std::string& text) {
+		assign( text );
+	}
+
+	tcpip_endpoint(const char* text) {
+		assign( std::string(text) );
+	}
+
+	tcpip_endpoint(const uint8_t* bytes, size_t size) {
+		assign( bytes, size );
+	}
+
+	bool assign( const self& copy ) {
+		this->ip = copy.ip;
+		this->port_ = copy.port_;
+		return false;
+	}
+
+	//--- compare operations --------------------------------------------------
+
+	/// implements comparison operators
+	int compare_to(const self& rhs) const {
+		if (ip.compare_to(rhs.ip)==0 && port_.compare_to(rhs.port_)==0) return 0;
+		return 1;
+	}
+
+	//--- bytes representation ------------------------------------------------
+
+	/// returns true, if this address has a fixed size in bytes
+	bool is_bytes_size_static() const {
+		return false;
+	}
+
+	/// returns the number of bytes used for serialization of this address
+	size_t to_bytes_size() const {
+		return ip.to_bytes_size() + port_.to_bytes_size();
+	}
+
+	/// converts this address to a binary representation
+	void to_bytes(uint8_t* bytes) const {
+		ip.to_bytes(bytes);
+		port_.to_bytes(bytes+ip.to_bytes_size());
+	}
+
+	/// Assigns an address using a bunch of bytes
+	bool assign(const uint8_t* bytes, size_t size) {
+		assert(size==6 || size==18);
+		if (size==6) {
+			ip.assign(bytes,4);
+			port_.assign(bytes+4,2);
+		} else {
+			ip.assign(bytes,16);
+			port_.assign(bytes+16,2);
+		}
+		return false;
+	}
+
+	//--- text representation -------------------------------------------------
+
+	/// convert address to a string that can be used to reconstruct the address
+	std::string to_string() const {
+		if (ip.asio().is_v4())
+			return ip.to_string()+std::string(":")+port_.to_string();
+		else
+			return std::string("[")+ip.to_string()+std::string("]:")+port_.to_string();
+	}
+
+	/// Assigns an address using a human-readable
+	bool assign(const std::string& text) {
+		std::string ip_str;
+		std::string port_str;
+		if (text.at(0)=='[') {
+			int i = text.find(']',1);
+			ip_str = text.substr(1,i-1);
+			port_str = text.substr(i+2, text.size()-i-1);
+		} else {
+			int i = text.find(':',1);
+			ip_str = text.substr(0,i);
+			port_str = text.substr(i+1, text.size()-i-1);
+		}
+		return ip.assign(ip_str) || port_.assign(port_str);
+	}
+
+	//--- address info --------------------------------------------------------
+
+	/// returns the name of the address
+	const string& type_name() const {
+		return protocol_name;
+	}
+
+	/// returns the id of the address
+	uint16_t type_id() const {
+		return 6;
+	}
+
+	//--- endpoint elements ---------------------------------------------------
+
+	ip_address& address() {
+		return ip;
+	}
+
+	const ip_address& address() const {
+		return ip;
+	}
+
+	tcp_port_address& port() {
+		return port_;
+	}
+
+	const tcp_port_address& port() const {
+		return port_;
+	}
+
+	//--- conversions ---------------------------------------------------------
+
+	/// returns the asio endpoint
+	tcp::endpoint asio() const {
+		return tcp::endpoint(ip.asio(), port_.asio());
+	}
+
+	/// sets the asio endpoint
+	void asio( tcp::endpoint& endp ) {
+		ip.asio(endp.address());
+		port_.asio(endp.port());
+	}
+};
+
+}} // namespace ariba::addressing
+
+namespace boost {
+
+template<>
+struct hash<ariba::addressing::tcpip_endpoint>:
+	public std::unary_function<ariba::addressing::tcpip_endpoint, std::size_t> {
+	std::size_t operator()(const ariba::addressing::tcpip_endpoint& ep) const {
+		return hash_value(ep.to_string());
+	}
+};
+
+}
+
+
+#endif /* TCPIP_ENDPOINT_HPP_ */
Index: /source/ariba/utility/addressing/test_addressing.hpp
===================================================================
--- /source/ariba/utility/addressing/test_addressing.hpp	(revision 5284)
+++ /source/ariba/utility/addressing/test_addressing.hpp	(revision 5284)
@@ -0,0 +1,81 @@
+#ifndef TEST_ADDRESSING_HPP_
+#define TEST_ADDRESSING_HPP_
+
+#include "addressing.hpp"
+
+namespace ariba {
+namespace addressing {
+namespace detail {
+
+using namespace ariba::addressing;
+
+void test() {
+
+	mac_address mac("01:02:03:04:05:06");
+	port_address port("12345");
+	ip_address ipv4("127.0.0.1");
+	ip_address ipv6("::127.0.0.1");
+
+	tcpip_endpoint tcpip;
+	tcpip = "10.11.12.13:5001";
+	cout << tcpip.to_string() << endl;
+	tcpip = "[::10.11.12.13]:5001";
+	cout << tcpip.to_string() << endl;
+
+	address_vf addr_mac  = mac;
+	address_vf addr_port = port;
+	to_string_vf addr_to_string = ipv4;
+
+	cout << addr_to_string->to_string() << endl;
+	cout << addr_mac->clone()->to_string() << endl;
+	cout << (*addr_mac == *addr_mac) << endl;
+
+	uint8_t bytes[80];
+
+	tcpip.to_bytes(bytes);
+	for (size_t i=0; i<tcpip.to_bytes_size(); i++) printf("%02X",bytes[i]);
+	printf("\n");
+	tcpip = "10.11.12.13:5001";
+	tcpip.assign( bytes, 18 );
+	cout << tcpip.to_string() << endl;
+
+	cout << "Testing endpoint_set: " << endl;
+	cout << "-> to_string methods:" << endl;
+	string set_test = "tcp{5001 | 5002};ip{::10.11.12.13 | 127.0.0.1};bluetooth{01:02:03:04:05:06};rfcomm{10 | 11 | 12 | 13};";
+	endpoint_set set = set_test;
+	cout << "   * This = " << set.to_string() << endl;
+	cout << "   * That = " << set_test << endl;
+	cout << "   * Ok = " << (set.to_string().size() == set_test.size()) << endl;
+	cout << "-> to_bytes methods:" << endl;
+	uint8_t* set_bytes = new uint8_t[set.to_bytes_size()];
+	set.to_bytes(set_bytes);
+	endpoint_set new_set(set_bytes, set.to_bytes_size());
+	cout << "   * Bin  = ";
+	for (size_t i=0; i<set.to_bytes_size(); i++) printf("%02X",set_bytes[i]);
+	cout << endl;
+	cout << "   * This = " << set.to_string() << endl;
+	cout << "   * That = " << new_set.to_string() << endl;
+	cout << "   * Ok = " << (set.to_string().size() == new_set.to_string().size()) << endl;
+
+/*
+	tcpip_endpoint tcp("10.11.12.13", "1234");
+	endpoint_vf endp_tcp = tcp;
+	*endp_tcp->get(0) = "::12.13.14.15";
+
+	cout << endp_tcp->get(0)->to_string() << endl;
+	cout << tcp.address().to_string() << endl;
+
+	cout << endp_tcp->to_string() << endl;
+
+//	*addr_mac = "0a:0b:0c:0d:0e:0f";
+
+	cout << mac.to_string() << endl;
+	cout << addr_mac->clone() << endl;
+	cout << addr_port->clone() << endl;
+	cout << (*addr_mac == *addr_mac) << endl;
+*/
+}
+
+}}} // namespace ariba::addressing::detail
+
+#endif /* TEST_ADDRESSING_HPP_ */
Index: /source/ariba/utility/bootstrap/modules/multicastdns/MulticastDns.cpp
===================================================================
--- /source/ariba/utility/bootstrap/modules/multicastdns/MulticastDns.cpp	(revision 5274)
+++ /source/ariba/utility/bootstrap/modules/multicastdns/MulticastDns.cpp	(revision 5284)
@@ -1,2 +1,3 @@
+
 // [License]
 // The Ariba-Underlay Copyright
Index: /source/ariba/utility/serialization/DataStream.hpp
===================================================================
--- /source/ariba/utility/serialization/DataStream.hpp	(revision 5274)
+++ /source/ariba/utility/serialization/DataStream.hpp	(revision 5284)
@@ -44,4 +44,5 @@
 #include <boost/type_traits/make_unsigned.hpp>
 
+#include <cassert>
 #include <iostream>
 #include <vector>
@@ -331,4 +332,17 @@
 		bits.setLength(index);
 		return bits;
+	}
+
+	finline uint8_t* bytes( size_t length ) {
+		assert((index%bits.word_width)==0);
+		if (!isMeasure()) {
+			bits.ensureLength( index + length * 8);
+			uint8_t* buffer = (uint8_t*)bits.getBuffer()+(index/bits.word_width);
+			index += length*8;
+			return buffer;
+		} else {
+			index += length*8;
+			return NULL;
+		}
 	}
 
Index: /source/ariba/utility/system/StartupWrapper.cpp
===================================================================
--- /source/ariba/utility/system/StartupWrapper.cpp	(revision 5274)
+++ /source/ariba/utility/system/StartupWrapper.cpp	(revision 5284)
@@ -98,15 +98,15 @@
 	{
 		log4cxx::LoggerPtr logger(log4cxx::Logger::getRootLogger());
-		logger->setLevel(log4cxx::Level::getDebug());
+		logger->setLevel(log4cxx::Level::getError());
 	}
 
 	// set up again an individual level if you like
 	{
-//		log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger("PingPong"));
-//		logger->setLevel(log4cxx::Level::getDebug());
+		log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger("PingPong"));
+		logger->setLevel(log4cxx::Level::getDebug());
 	}
 	{
-//		log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger("BaseCommunication"));
-//		logger->setLevel(log4cxx::Level::getDebug());
+		log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger("BaseCommunication"));
+		logger->setLevel(log4cxx::Level::getInfo());
 	}
 
Index: /source/ariba/utility/transport/asio/asio_io_service.cpp
===================================================================
--- /source/ariba/utility/transport/asio/asio_io_service.cpp	(revision 5284)
+++ /source/ariba/utility/transport/asio/asio_io_service.cpp	(revision 5284)
@@ -0,0 +1,99 @@
+// Internal version: Please do not publish!
+// (... until released under FreeBSD-like license *g*)
+// Code: Sebastian Mies <mies@tm.uka.de>
+
+#include "asio_io_service.h"
+
+#include <boost/asio.hpp>
+#include <boost/thread.hpp>
+
+namespace ariba {
+namespace transport {
+namespace detail {
+
+using namespace boost::asio;
+using namespace std;
+
+asio_io_service* asio_io_service::singleton = NULL;
+
+//#define DBG(x) cout << x << endl;
+#define DBG(x)
+
+void asio_io_service::operator ()() {
+	running = true;
+	DBG("io_service started");
+	boost::asio::io_service::work work(*service);
+	service->run();
+	DBG("io_service stopped");
+	if (destroy) {
+		delete singleton;
+		singleton = NULL;
+		DBG(cout << "asio io_service singleton destroyed" << endl);
+	}
+	running = false;
+}
+
+asio_io_service::asio_io_service() :
+	references(1), running(false), destroy(false), thread(NULL), service(NULL) {
+	service = new io_service();
+}
+
+asio_io_service::~asio_io_service() {
+	if (thread != NULL) delete thread;
+	if (service != NULL) delete service;
+	thread = NULL;
+	service = NULL;
+}
+
+void asio_io_service::internal_start() {
+	if (!running) {
+		if (thread != NULL) delete thread;
+		thread = new boost::thread(boost::ref(*this));
+	}
+}
+
+void asio_io_service::internal_stop() {
+	service->stop();
+	singleton->running = false;
+}
+
+io_service& asio_io_service::alloc() {
+	if (singleton != NULL) {
+		DBG("new asio io_service reference");
+		singleton->references++;
+		return *singleton->service;
+	} else {
+		DBG("creating new asio io_service singleton");
+		singleton = new asio_io_service();
+		return *singleton->service;
+	}
+}
+
+void asio_io_service::free() {
+	if (singleton != NULL) {
+		DBG("decreasing asio io_service reference");
+		singleton->references--;
+		if (singleton->references == 0) {
+			DBG("request asio io_service destruction");
+			if (singleton->running == false) {
+				delete singleton;
+				singleton = NULL;
+				DBG("asio io_service singleton destroyed");
+			} else {
+				singleton->destroy = true;
+				singleton->service->stop();
+			}
+		}
+	}
+}
+
+void asio_io_service::start() {
+	singleton->internal_start();
+}
+
+void asio_io_service::stop() {
+	singleton->internal_stop();
+}
+
+
+}}} // namespace ariba::transport::detail
Index: /source/ariba/utility/transport/asio/asio_io_service.h
===================================================================
--- /source/ariba/utility/transport/asio/asio_io_service.h	(revision 5284)
+++ /source/ariba/utility/transport/asio/asio_io_service.h	(revision 5284)
@@ -0,0 +1,48 @@
+// Internal version: Please do not publish!
+// (... until released under FreeBSD-like license *g*)
+// Code: Sebastian Mies <mies@tm.uka.de>
+
+#ifndef ASIO_IO_SERVICE_H_
+#define ASIO_IO_SERVICE_H_
+
+#include<boost/thread.hpp>
+#include<boost/asio.hpp>
+
+namespace ariba {
+namespace transport {
+namespace detail {
+
+/**
+ * TODO: Doc
+ *
+ * @author Sebastian Mies <mies@tm.uka.de>
+ */
+class asio_io_service {
+private:
+	int references;
+	volatile bool running;
+	volatile bool destroy;
+	boost::thread* thread;
+	boost::asio::io_service* service;
+
+	static asio_io_service* singleton;
+
+	friend class boost::thread;
+	friend class boost::detail::thread_data<boost::reference_wrapper<asio_io_service> >;
+
+protected:
+	void operator ()();
+	asio_io_service();
+	~asio_io_service();
+	void internal_start();
+	void internal_stop();
+public:
+	static boost::asio::io_service& alloc();
+	static void free();
+	static void start();
+	static void stop();
+};
+
+}}} // namespace ariba::transport::detail
+
+#endif /* ASIO_IO_SERVICE_H_ */
Index: /source/ariba/utility/transport/asio/bluetooth_endpoint.hpp
===================================================================
--- /source/ariba/utility/transport/asio/bluetooth_endpoint.hpp	(revision 5284)
+++ /source/ariba/utility/transport/asio/bluetooth_endpoint.hpp	(revision 5284)
@@ -0,0 +1,181 @@
+#ifndef BOOST_ASIO_BLUETOOTH_BLUETOOTH_ENDPOINT_HPP__
+#define BOOST_ASIO_BLUETOOTH_BLUETOOTH_ENDPOINT_HPP__
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/rfcomm.h>
+
+#include <boost/asio/basic_stream_socket.hpp>
+
+namespace boost {
+namespace asio {
+namespace bluetooth {
+
+/**
+ * Describes an endpoint for a RFCOMM Bluetooth socket.
+ *
+ * @author Martin Florian <mflorian@lafka.net>
+ */
+template<typename BluetoothProtocol>
+class bluetooth_endpoint {
+private:
+	static bdaddr_t addr_any;
+
+public:
+	/// The protocol type associated with the endpoint.
+	typedef BluetoothProtocol protocol_type;
+
+	/// The type of the endpoint structure. This type is dependent on the
+	/// underlying implementation of the socket layer.
+	typedef boost::asio::detail::socket_addr_type data_type; // <-- Do I need this?
+	//typedef sockaddr_rc data_type;
+
+	/// Default constructor.
+	bluetooth_endpoint() :
+		data_() {
+		data_.rc_family = AF_BLUETOOTH;
+		data_.rc_bdaddr = addr_any;
+		data_.rc_channel = (uint8_t) 0;
+	}
+
+	bluetooth_endpoint(const BluetoothProtocol& protocol,
+			unsigned short channel) :
+		data_() {
+		data_.rc_family = AF_BLUETOOTH;
+		data_.rc_bdaddr = addr_any;
+		data_.rc_channel = channel;
+	}
+
+	/// Construct an endpoint using a port number, specified in the host's byte
+	/// order. The IP address will be the any address (i.e. INADDR_ANY or
+	/// in6addr_any). This constructor would typically be used for accepting new
+	/// connections.
+	bluetooth_endpoint(unsigned short channel) :
+		data_() {
+		data_.rc_family = AF_BLUETOOTH;
+		data_.rc_bdaddr = *BDADDR_ANY;
+		data_.rc_channel = channel;
+	}
+
+	/// Construct an endpoint using a port number and an BT address.
+	/// The address is in human readable form as a string.
+	bluetooth_endpoint(const char *addr, unsigned short channel) :
+		data_() {
+		data_.rc_family = AF_BLUETOOTH;
+		data_.rc_channel = channel;
+		str2ba(addr, &data_.rc_bdaddr);
+	}
+
+	/// Construct an endpoint using a port number and an BT address.
+	/// The address is given in the bluetooth-internal format.
+	bluetooth_endpoint(bdaddr_t addr, unsigned short channel) :
+		data_() {
+		data_.rc_family = AF_BLUETOOTH;
+		data_.rc_channel = channel;
+		data_.rc_bdaddr = addr;
+	}
+
+	/// Copy constructor.
+	bluetooth_endpoint(const bluetooth_endpoint& other) :
+		data_(other.data_) {
+	}
+
+	/// Assign from another endpoint.
+	bluetooth_endpoint& operator=(const bluetooth_endpoint& other) {
+		data_ = other.data_;
+		return *this;
+	}
+
+	/// The protocol associated with the endpoint.
+	protocol_type protocol() const {
+		return protocol_type::get();
+	}
+
+	/// Get the underlying endpoint in the native type.
+	/// TODO: make this nice and generic -> union like in tcp
+	data_type* data() {
+		return (boost::asio::detail::socket_addr_type*) &data_;
+	}
+
+	/// Get the underlying endpoint in the native type.
+	const data_type* data() const {
+		return (boost::asio::detail::socket_addr_type*) &data_;
+	}
+
+	/// Get the underlying size of the endpoint in the native type.
+	std::size_t size() const {
+		return sizeof(data_type);
+	}
+
+	/// Set the underlying size of the endpoint in the native type.
+	void resize(std::size_t size) {
+		if (size > sizeof(data_type)) {
+			boost::system::system_error e(boost::asio::error::invalid_argument);
+			boost::throw_exception(e);
+		}
+	}
+
+	/// Get the capacity of the endpoint in the native type.
+	std::size_t capacity() const {
+		return sizeof(data_type);
+	}
+
+	/// Get the channel associated with the endpoint. The port number is always in
+	/// the host's byte order.
+	unsigned short channel() const {
+		return data_.rc_channel;
+	}
+
+	/// Set the channel associated with the endpoint. The port number is always in
+	/// the host's byte order.
+	void channel(unsigned short channel_num) {
+		data_.rc_channel = channel_num;
+	}
+
+	/// Get the Bluetooth address associated with the endpoint.
+	bdaddr_t address() const {
+		return data_.rc_bdaddr;
+	}
+
+	/// Set the Bluetooth address associated with the endpoint.
+	void address(const boost::asio::ip::address& addr) {
+		bluetooth_endpoint<BluetoothProtocol> tmp_endpoint(addr, channel());
+		data_ = tmp_endpoint.data_;
+	}
+
+	/// Get the Bluetooth address in human readable form and write it to buf.
+	void address_hr(char &buf) {
+		ba2str(&data_.rc_bdaddr, buf);
+	}
+
+	/// Compare two endpoints for equality.
+	friend bool operator==(const bluetooth_endpoint& e1,
+			const bluetooth_endpoint& e2) {
+		return e1.address() == e2.address() && e1.channel() == e2.channel();
+	}
+
+	/// Compare two endpoints for inequality.
+	friend bool operator!=(const bluetooth_endpoint& e1,
+			const bluetooth_endpoint& e2) {
+		return e1.address() != e2.address() || e1.channel() != e2.channel();
+	}
+
+	/// Compare endpoints for ordering.
+	friend bool operator<(const bluetooth_endpoint<BluetoothProtocol>& e1,
+			const bluetooth_endpoint<BluetoothProtocol>& e2) {
+		if (e1.address() < e2.address()) return true;
+		if (e1.address() != e2.address()) return false;
+		return e1.channel() < e2.channel();
+	}
+
+private:
+	// The underlying rfcomm socket address structure thingy.
+	//struct data_type data_;
+	struct sockaddr_rc data_;
+};
+
+template<typename X>
+bdaddr_t bluetooth_endpoint<X>::addr_any = (bdaddr_t) { {0, 0, 0, 0, 0, 0}};
+
+}}} // namespace boost::asio::bluetooth
+
+#endif
Index: /source/ariba/utility/transport/asio/rfcomm.hpp
===================================================================
--- /source/ariba/utility/transport/asio/rfcomm.hpp	(revision 5284)
+++ /source/ariba/utility/transport/asio/rfcomm.hpp	(revision 5284)
@@ -0,0 +1,54 @@
+#ifndef BOOST_ASIO_BLUETOOTH_RFCOMM_HPP__
+#define BOOST_ASIO_BLUETOOTH_RFCOMM_HPP__
+
+#include "bluetooth_endpoint.hpp"
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/rfcomm.h>
+
+namespace boost {
+namespace asio {
+namespace bluetooth {
+
+/**
+ * The rfcomm class contains flags necessary for RFCOMM sockets.
+ *
+ * @author Martin Florian <mflorian@lafka.net>
+ */
+class rfcomm {
+public:
+	/// The type of endpoint.
+	typedef bluetooth_endpoint<rfcomm> endpoint;
+
+	/// Get an Instance.
+	/// We need this to fulfill the asio Endpoint requirements, I think.
+	static rfcomm get() {
+		return rfcomm();
+	}
+
+	/// Obtain an identifier for the type of the protocol.
+	int type() const {
+		return SOCK_STREAM;
+	}
+
+	/// Obtain an identifier for the protocol.
+	int protocol() const {
+		return BTPROTO_RFCOMM;
+	}
+
+	/// Obtain an identifier for the protocol family.
+	int family() const {
+		return AF_BLUETOOTH;
+	}
+
+	/// The RFCOMM socket type, lets pray that this will work.
+	typedef basic_stream_socket<rfcomm> socket;
+
+	/// The RFCOMM acceptor type.
+	typedef basic_socket_acceptor<rfcomm> acceptor;
+
+};
+
+}}} // namespace boost::asio::bluetooth
+
+#endif /* BOOST_ASIO_BLUETOOTH_RFCOMM_HPP__ */
Index: /source/ariba/utility/transport/rfcomm/rfcomm.cpp
===================================================================
--- /source/ariba/utility/transport/rfcomm/rfcomm.cpp	(revision 5284)
+++ /source/ariba/utility/transport/rfcomm/rfcomm.cpp	(revision 5284)
@@ -0,0 +1,334 @@
+#include "rfcomm.hpp"
+
+#include "../asio/asio_io_service.h"
+#include "../asio/rfcomm.hpp"
+#include "../asio/bluetooth_endpoint.hpp"
+
+#include <boost/asio.hpp>
+#include <boost/thread.hpp>
+#include <boost/array.hpp>
+#include <memory.h>
+#include <deque>
+
+
+namespace ariba {
+namespace transport {
+
+using namespace boost::asio;
+using namespace detail;
+using namespace std;
+
+using boost::system::error_code;
+
+class link_data {
+public:
+	uint8_t size_[4];
+	size_t size;
+	uint8_t* buffer;
+};
+
+class link_info {
+public:
+	link_info(io_service& io ) :
+		up(false), local(), remote(), socket(io), size(0), buffer(NULL), sending(false) {
+	}
+
+	// state
+	bool up;
+	rfcomm_endpoint local, remote;
+	bluetooth::rfcomm::socket socket;
+
+	// read buffer
+	uint8_t size_[4];
+	size_t size;
+	uint8_t* buffer;
+
+	// send buffer
+	bool sending;
+	boost::mutex mutex;
+	std::deque<link_data> send_buffer;
+};
+
+inline bluetooth::rfcomm::endpoint convert( const rfcomm_endpoint& endpoint ) {
+	return bluetooth::rfcomm::endpoint(
+		endpoint.mac().bluetooth(), endpoint.channel().value()
+	);
+}
+
+inline rfcomm_endpoint convert( const bluetooth::rfcomm::endpoint& endpoint ) {
+	mac_address mac;
+	mac.bluetooth( endpoint.address() );
+	rfcomm_channel_address channel;
+	channel.value( endpoint.channel() );
+	return rfcomm_endpoint( mac, channel );
+}
+
+
+rfcomm::rfcomm(uint16_t channel) :
+	channel(channel), io(asio_io_service::alloc()) {
+}
+
+rfcomm::~rfcomm() {
+	asio_io_service::free();
+}
+
+void rfcomm::start() {
+
+	// start io service
+	asio_io_service::start();
+
+	// create acceptor
+	cout << "Binding to channel " << channel << endl;
+	acceptor = new bluetooth::rfcomm::acceptor(io,
+		bluetooth::rfcomm::endpoint(bluetooth::rfcomm::get(), channel )
+	);
+
+	// start accepting
+	start_accept();
+}
+
+void rfcomm::stop() {
+
+}
+
+void rfcomm::send(const address_v* remote, const uint8_t* data, size_t size) {
+	// get end-point
+	rfcomm_endpoint endpoint = *remote;
+	endpoint = convert(convert(endpoint));
+
+	// try to find established connector
+	link_info* info = NULL;
+	for (size_t i = 0; i < links.size(); i++)
+		if (links[i]->remote.mac() == endpoint.mac()) {
+			info = links[i];
+			break;
+		}
+
+	// not found? ->try to connect
+	if (info==NULL) {
+		cout << "Connecting to " << endpoint.to_string() << endl;
+		info = new link_info(io);
+		info->socket.async_connect( convert(endpoint), boost::bind(
+			&rfcomm::handle_connect, this,
+			boost::asio::placeholders::error, info
+		));
+		asio_io_service::start();
+	}
+
+	// copy message
+	link_data ldata;
+	ldata.size = size;
+	ldata.size_[0] = (size >> 24) & 0xFF;
+	ldata.size_[1] = (size >> 16) & 0xFF;
+	ldata.size_[2] = (size >> 8) & 0xFF;
+	ldata.size_[3] = (size >> 0) & 0xFF;
+	ldata.buffer = new uint8_t[size];
+	memcpy(ldata.buffer, data, size);
+
+	// enqueue message
+	info->mutex.lock();
+	info->send_buffer.push_back(ldata);
+	info->mutex.unlock();
+
+	// start writing
+	start_write(info);
+}
+
+void rfcomm::send(const endpoint_set& endpoints, const uint8_t* data, size_t size) {
+	// send a message to each combination of mac-address and channel
+	BOOST_FOREACH( const mac_address mac, endpoints.bluetooth ) {
+		BOOST_FOREACH( const rfcomm_channel_address channel, endpoints.rfcomm ) {
+			rfcomm_endpoint endpoint(mac, channel);
+			address_vf vf = endpoint;
+			send(vf,data,size);
+		}
+	}
+}
+
+void rfcomm::terminate(const address_v* local, const address_v* remote) {
+	// not supported right now!
+}
+
+void rfcomm::register_listener(transport_listener* listener) {
+	this->listener = listener;
+}
+
+void rfcomm::start_accept() {
+
+	cout << "Waiting for connections ..." << endl;
+
+	// start accepting a connection
+	link_info* info = new link_info(io);
+	acceptor->async_accept(info->socket, boost::bind(
+		// bind parameters
+		&rfcomm::handle_accept, this,
+
+		// handler parameters
+		boost::asio::placeholders::error, info
+	));
+	asio_io_service::start();
+}
+
+void rfcomm::handle_accept(const error_code& error, link_info* info) {
+	if (error) {
+		cout << "Error accepting" << endl;
+		delete info;
+		return;
+	}
+
+	// convert endpoints
+	info->up = true;
+	info->local  = convert( info->socket.local_endpoint()  );
+	info->remote = convert( info->socket.remote_endpoint() );
+
+	cout << "Accepting incoming connection from " << info->remote.to_string() << endl;
+
+	// add to list
+	links_mutex.lock();
+	links.push_back(info);
+	links_mutex.unlock();
+
+	// start i/o
+	start_read(info);
+	start_write(info);
+
+	// restart accept
+	start_accept();
+}
+
+void rfcomm::handle_connect( const error_code& error, link_info* info ) {
+	if (error) {
+		cout << "Error connecting ..." << endl;
+		delete info;
+		return;
+	}
+
+	// convert endpoints
+	info->up = true;
+	info->local  = convert( info->socket.local_endpoint()  );
+	info->remote = convert( info->socket.remote_endpoint() );
+
+	cout << "Connected to " << info->remote.to_string() << endl;
+
+	// add to list
+	links_mutex.lock();
+	links.push_back(info);
+	links_mutex.unlock();
+
+	// start i/o
+	start_read(info);
+	start_write(info);
+}
+
+void rfcomm::start_read(link_info* info) {
+	cout << "Waiting for messages..." << endl;
+
+	// start read
+	boost::asio::async_read(info->socket,
+		// read size of packet
+		boost::asio::buffer(info->size_, 4),
+		// bind handler
+		boost::bind(
+			// bind parameters
+			&rfcomm::handle_read_header, this,
+			// handler parameters
+			placeholders::error, placeholders::bytes_transferred, info
+		)
+	);
+}
+
+void rfcomm::handle_read_header(const error_code& error, size_t bytes,
+	link_info* info) {
+
+	// ignore errors and wait for all data to be received
+	if (error || bytes != 4) return;
+
+	// get size
+	info->size = (info->size_[0]<<24) + (info->size_[1] << 16) +
+			(info->size_[2]<< 8) + (info->size_[3] << 0);
+
+	cout << "receive message of size " << info->size << endl;
+
+	// allocate buffer
+	info->buffer = new uint8_t[info->size];
+
+	// start read
+	boost::asio::async_read(info->socket,
+		// read size of packet
+		boost::asio::buffer(info->buffer, info->size),
+		// bind handler
+		boost::bind(
+			// bind parameters
+			&rfcomm::handle_read_data, this,
+			// handler parameters
+			placeholders::error, placeholders::bytes_transferred, info
+		)
+	);
+}
+
+void rfcomm::handle_read_data(const error_code& error, size_t bytes,
+	link_info* info) {
+
+	// ignore errors and wait for all data to be received
+	if (error || bytes != info->size) return;
+
+	cout << "received message of size " << info->size << endl;
+
+	// deliver data
+	listener->receive_message(this, info->local, info->remote, info->buffer, info->size );
+
+	// free buffers and reset size buffer
+	delete [] info->buffer;
+	for (size_t i=0; i<4; i++) info->size_[i] = 0;
+}
+
+void rfcomm::start_write( link_info* info ) {
+	// do not start writing if sending is in progress
+	if (info->sending || !info->up || info->send_buffer.size()==0) return;
+
+	cout << "Sending messages..." << endl;
+
+	// safely remove data from deque
+	info->mutex.lock();
+	link_data data = info->send_buffer.front();
+	info->send_buffer.pop_front();
+	info->mutex.unlock();
+
+	boost::array<boost::asio::mutable_buffer, 2> buffer;
+	buffer[0] = boost::asio::buffer(data.size_,4);
+	buffer[1] = boost::asio::buffer(data.buffer,data.size);
+
+	// start writing
+	boost::asio::async_write(info->socket,
+		// read size of packet
+		buffer,
+		// bind handler
+		boost::bind(
+			// bind parameters
+			&rfcomm::handle_write_data, this,
+			// handler parameters
+			placeholders::error, placeholders::bytes_transferred,
+			info, data.size, data.buffer
+		)
+	);
+}
+
+void rfcomm::handle_write_data(const error_code& error, size_t bytes,
+	link_info* info, size_t size, uint8_t* buffer ) {
+
+	// ignore errors and wait for all data to be sent
+	if (error || bytes != (size+4) ) {
+		if (error) cout << "Message sent error" << endl;
+		return;
+	}
+
+	cout << "Message sent" << endl;
+
+	// free buffer
+	delete [] buffer;
+
+	// restart-write
+	start_write(info);
+}
+
+}} // namespace ariba::transport
Index: /source/ariba/utility/transport/rfcomm/rfcomm.hpp
===================================================================
--- /source/ariba/utility/transport/rfcomm/rfcomm.hpp	(revision 5284)
+++ /source/ariba/utility/transport/rfcomm/rfcomm.hpp	(revision 5284)
@@ -0,0 +1,65 @@
+#ifndef RFCOMM_HPP_
+#define RFCOMM_HPP_
+
+#include "../transport.hpp"
+#include "../asio/asio_io_service.h"
+#include "../asio/bluetooth_endpoint.hpp"
+#include "../asio/rfcomm.hpp"
+
+#include <boost/thread.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/asio/io_service.hpp>
+
+namespace ariba {
+namespace transport {
+
+using boost::system::error_code;
+using namespace boost::asio;
+
+class link_info;
+
+/**
+ * TODO: Doc
+ *
+ * @author Sebastian Mies <mies@tm.uka.de>
+ */
+class rfcomm : public transport_protocol {
+public:
+	rfcomm( uint16_t channel );
+	virtual ~rfcomm();
+	virtual void start();
+	virtual void stop();
+	virtual void send( const address_v* remote, const uint8_t* data, size_t size );
+	virtual void send( const endpoint_set& endpoints, const uint8_t* data, size_t size );
+	virtual void terminate( const address_v* local, const address_v* remote );
+	virtual void register_listener( transport_listener* listener );
+
+private:
+	uint16_t channel;
+	boost::mutex links_mutex;
+	vector<link_info*> links;
+	io_service& io;
+	transport_listener* listener;
+	bluetooth::rfcomm::acceptor* acceptor;
+
+	void start_accept();
+
+	void handle_accept(  const error_code& error, link_info* info );
+
+	void start_read( link_info* info );
+
+	void handle_read_header( const error_code& error, size_t bytes, link_info* info );
+
+	void handle_read_data(  const error_code& error, size_t bytes, link_info* info );
+
+	void handle_connect( const error_code& error, link_info* info );
+
+	void start_write( link_info* info );
+
+	void handle_write_data(const error_code& error, size_t bytes,
+		link_info* info, size_t size, uint8_t* buffer );
+};
+
+}} // namespace ariba::transport
+
+#endif /* RFCOMM_HPP_ */
Index: /source/ariba/utility/transport/tcpip/protlib/address.cpp
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/address.cpp	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/address.cpp	(revision 5284)
@@ -0,0 +1,1564 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file address.cpp
+/// GIST address objects
+/// ----------------------------------------------------------
+/// $Id: address.cpp 3046 2008-06-18 14:40:43Z hiwi-laier $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/src/address.cpp $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+/** @ingroup ieaddress
+ * GIST address objects
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "address.h"
+#include "threadsafe_db.h"
+#include "logfile.h"
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <ifaddrs.h>
+#include <iomanip>
+#include <netdb.h>
+
+namespace protlib {
+
+/** @addtogroup ieaddress Address Objects
+ * @{
+ */
+  using namespace log;
+/***** class address *****/
+
+/** Set subtype. */
+address::address(subtype_t st) 
+	: subtype(st) 
+{ 
+  //Log(DEBUG_LOG,LOG_NORMAL,"address","address constructor called for " << (void *) this); 
+}
+
+/** Log and throw a nomem_error */
+void address::throw_nomem_error() const {
+	try {
+	  ERRCLog("address", "Not enough memory for address");
+	} catch(...) {}
+	throw IEError(IEError::ERROR_NO_MEM);
+} // end throw_nomem_error
+
+
+/***** class hostaddress *****/
+
+/***** inherited from IE *****/
+
+hostaddress* hostaddress::new_instance() const {
+	hostaddress* ha = NULL;
+	catch_bad_alloc(ha = new hostaddress());
+	return ha;
+} // end new_instance
+
+hostaddress* hostaddress::copy() const {
+	hostaddress* ha = NULL;
+	catch_bad_alloc(ha =  new hostaddress(*this));
+	return ha;
+} // end copy 
+
+bool hostaddress::operator==(const address& ie) const {
+	const hostaddress* haddr = dynamic_cast<const hostaddress*>(&ie);
+	if (haddr) {
+#ifdef DEBUG_HARD
+	  Log(DEBUG_LOG,LOG_NORMAL,"hostaddress","::operator==()" << haddr->get_ip_str()<<"=="<<this->get_ip_str());
+	  if (!ipv4flag)
+	    Log(DEBUG_LOG,LOG_NORMAL,"hostaddress","::operator==(), v6=" << IN6_ARE_ADDR_EQUAL(ipv6addr.s6_addr, haddr->ipv6addr.s6_addr));
+#endif
+	  return ipv4flag ? (ipv4addr.s_addr==haddr->ipv4addr.s_addr) :
+	                    IN6_ARE_ADDR_EQUAL(ipv6addr.s6_addr, haddr->ipv6addr.s6_addr);
+	} else return false;
+} // end operator==
+
+/***** new in hostaddress *****/
+
+
+/** Initialize hostaddress from string if possible. */
+hostaddress::hostaddress(const char *str, bool *res) 
+	: address(IPv6HostAddress),
+	  ipv4flag(false), 
+	  outstring(NULL)
+{
+	register bool tmpres = false;
+	clear_ip();
+	tmpres = set_ip(str);
+	if (res) *res = tmpres;
+} // end string constructor hostaddress
+
+
+/** Set IPv4 from string or leave object unchanged.
+ * This changes object type to IPv4.
+ * @return true on success.
+ */
+bool 
+hostaddress::set_ipv4(const char *str) {
+	struct in_addr in;
+	if (str && (inet_pton(AF_INET,str,&in)>0)) {
+		set_ip(in);
+		return true;
+	} else return false;
+} // end set_ipv4
+
+/** Set IPv4 address from struct in_addr. 
+ * This changes object type to IPv4. 
+ */
+void hostaddress::set_ip(const struct in_addr &in) {
+	clear_ip();
+	ipv4addr = in;	
+	// set subtype to IPv4
+	set_subtype(true);
+	return;
+} // end set_ip(in_addr)
+
+/** Set IPv6 from string or leave object unchanged.
+ * This changes object type to IPv6.
+ * @return true on success.
+ */
+bool hostaddress::set_ipv6(const char *str) {
+	struct in6_addr in;
+	if (str && (inet_pton(AF_INET6,str,&in)>0)) {
+		set_ip(in);
+		return true;
+	} else return false;
+} // end set_ipv6	
+
+/** Set IPv6 address from struct in6_addr. 
+ * This changes object type to IPv6. 
+ */
+void 
+hostaddress::set_ip(const struct in6_addr &in) {
+	clear_ip();
+	ipv6addr = in;	
+	// set subtype to IPv6
+	set_subtype(false);
+	return;
+} // end set_ip(in6_addr)
+
+
+
+void hostaddress::set_ip(const hostaddress& h) {
+	clear_ip();
+	if (h.ipv4flag) {
+		ipv4addr = h.ipv4addr;
+	} else {
+		ipv6addr = h.ipv6addr;
+	} // end if ipv4flag
+	set_subtype(h.ipv4flag);
+} // end set_ip(hostaddress)
+
+/** Check if IP address is unspecified (set to 0). */
+bool hostaddress::is_ip_unspec() const {
+	if (ipv4flag) return (ipv4addr.s_addr==0);
+	else return IN6_IS_ADDR_UNSPECIFIED(ipv6addr.s6_addr);
+	// never reached
+	return true;
+} // end is_unspec
+
+/** Get IP address as a string. The output string is kept inside the
+ * hostaddress object and should be copied if used for a longer time.
+ */
+const char* hostaddress::get_ip_str() const 
+{
+  // If outstring exists then it is valid.
+  if (outstring) 
+    return outstring;
+  else
+    outstring= (ipv4flag ? new(nothrow) char[INET_ADDRSTRLEN] : 
+		           new(nothrow) char[INET6_ADDRSTRLEN]);
+
+  if (hostaddress::get_ip_str(outstring)) 
+    return outstring;
+  else 
+  {
+    // error
+    if (outstring) 
+      delete[] outstring;
+
+    return (outstring = NULL);
+  } // end if get_ip_str()
+} // end get_ip_str
+
+/** Get IP address as a string.
+ * @param str string buffer
+ */
+const char* hostaddress::get_ip_str(char *str) const 
+{
+  if (!str) return NULL;
+  memset(str,0, ipv4flag ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN);
+  return ipv4flag ? inet_ntop(AF_INET,(void*)&ipv4addr,str,INET_ADDRSTRLEN) 
+                  : inet_ntop(AF_INET6,(void*)&ipv6addr,str,INET6_ADDRSTRLEN);
+} // end get_ip_str(char*)
+
+
+/** Get IP address as an in_addr if possible.
+ * @return true on success.
+ */
+bool hostaddress::get_ip(struct in_addr& in) const {
+	if (ipv4flag) {
+		in = ipv4addr;
+		return true;
+	} else if (IN6_IS_ADDR_V4MAPPED(ipv6addr.s6_addr)) {
+		memcpy(&(in.s_addr),ipv6addr.s6_addr+12,4);
+		return true;
+	} else return false;
+} // get_ip
+
+/** Get IP address as an in6_addr.
+ * If this is an IPv4 address, it is mapped to IPv6.
+ * @return true since this is always possible.
+ */
+bool hostaddress::get_ip(struct in6_addr& in) const {
+	if (ipv4flag) {
+		// map to IPv6
+		memset(in.s6_addr,0,10);
+		memset(in.s6_addr+10,255,2);
+		memcpy(in.s6_addr+12,&(ipv4addr.s_addr),4);
+	} else in = ipv6addr;
+	return true;
+} // get_ip
+
+/// returns false if address is not allowed to be used
+/// as source address: loopback, multicast, broadcast, unspecified
+bool 
+hostaddress::is_bogus_source() const
+{
+  if (ipv4flag)
+  { // IPv4
+    if ( IN_MULTICAST(ipv4addr.s_addr) || 
+	 ipv4addr.s_addr == INADDR_LOOPBACK  ||
+         ipv4addr.s_addr == INADDR_ANY ||
+         ipv4addr.s_addr == INADDR_BROADCAST
+       )
+    {
+      return true;
+    }
+  }
+  else
+  { // IPv6
+    if ( ipv6addr.s6_addr == in6addr_any.s6_addr ||
+	 ipv6addr.s6_addr == in6addr_loopback.s6_addr )
+      return true;
+  }
+
+  return false;
+}
+
+
+/** Convert the IP address to IPv6 by mapping it from IPv4 to IPv6 if
+ * necessary
+ */
+void hostaddress::convert_to_ipv6() {
+	if (ipv4flag) {
+		if (is_ip_unspec()) {
+			// clear IP and set to IPv6
+			clear_ip();
+			set_subtype(false);
+		} else {
+			// map to IPv6
+			struct in6_addr in;
+			get_ip(in);
+			// set IP
+			set_ip(in);
+		} // end if is_ip_unspec()
+	} // end if ipv4flag
+} // end convert_to_ipv6
+
+/** Two addresses are equivalent if they are equal after converting both to
+ * IPv6.
+ */
+bool hostaddress::equiv(const hostaddress& h) const {
+	bool thisipv4 = is_ipv4();
+	bool result = false;
+	hostaddress* ipv4haddr = NULL;
+	const hostaddress* ipv6haddr = NULL;
+	// if both IPv4 or both IPv6 then just test for equality
+	if (thisipv4==h.is_ipv4()) return operator==(h);
+	// OK, one is IPv6 and the other is IPv4 (to be converted!).
+	// Allocating memory dynamically because I do not know the concrete
+	// type of *this or h.
+	try {
+		if (thisipv4) {
+			ipv6haddr = &h;
+			if (h.is_mapped_ip()) ipv4haddr = this->copy();
+		} else {
+			ipv6haddr = this;
+			if (is_mapped_ip()) ipv4haddr = h.copy();
+		} // end if thisipv4
+	} catch(IEError&) { ipv4haddr = NULL; }
+	if (ipv4haddr) {
+		ipv4haddr->convert_to_ipv6();
+		result = ((*ipv4haddr)==(*ipv6haddr));
+		delete ipv4haddr;
+		return result;
+	} else return false;
+} // end equiv
+
+
+/** Set subtype and IPv4 flag. This does NOT clear the outstring buffer.
+ * Use clear_ip(). 
+ */
+void hostaddress::set_subtype(bool ipv4) {
+	ipv4flag = ipv4; 
+	subtype = ipv4flag ? IPv4HostAddress : IPv6HostAddress;
+} // end set_subtype
+
+/** Clear the IP address buffer and the outstring if it exists. */
+void hostaddress::clear_ip() {
+	// only need to clear ipv6 because of union
+	ipv6addr = in6addr_any;
+	if (outstring) {
+		delete[] outstring;
+		outstring = NULL;
+	} // end if outstring
+} // end clear_ip
+
+
+/** Match this IP address against another IP address.
+ * Two IP addresses match if they are equal.
+ * @return -1 on no match or error, e.g. when IPv4 and IPv6 are matched
+ * @return the length of the matched prefix.
+ */
+int hostaddress::match_against(const hostaddress& ha) const {
+	if (ipv4flag==ha.ipv4flag) {
+		if (operator==(ha)) {
+			if (ipv4flag) return 32;
+			else return 128;
+		} else return -1;
+	} else return -1;
+} // end match_against(
+
+/** Match this IP address against the given network prefix.
+ * @return -1 on no match or error, e.g. when IPv4 and IPv6 are matched
+ * @return the length of the matched prefix.
+ */
+int hostaddress::match_against(const netaddress& na) const {
+	uint32 word1 = 0;
+	uint32 word2 = 0;
+	const prefix_length_t preflen = na.get_pref_len();
+	prefix_length_t lenwords = preflen/32;
+	prefix_length_t lenbits = preflen%32;
+	// now 0<=lenwords<=4, 0<=lenbits<=31
+	prefix_length_t i;
+	const hostaddress& ha = dynamic_cast<const hostaddress&>(na);
+	if (ipv4flag==na.ipv4flag) {
+		if (ipv4flag) {
+			if (preflen >= 32)
+				lenbits = 32;
+			// match IPv4
+			word1 = ntohl(ipv4addr.s_addr);
+			word2 = ntohl(ha.ipv4addr.s_addr);
+			// shift right
+			word1 >>= (32-lenbits);
+			word2 >>= (32-lenbits);
+			if (word1==word2) return preflen;
+			else return -1;
+		} else {
+			if (preflen > 128)
+				return -1;
+			// match IPv6
+			// match words
+			for (i=0;i<lenwords;i++) {
+			  word1 = ntohl(ipv6addr.s6_addr32[i]);    // RB: as long as both words are in same order we dont need ntohl?!
+			  word2 = ntohl(ha.ipv6addr.s6_addr32[i]);
+				if (word1!=word2) return -1;
+			} // end for i
+			// now i points to the next word to be matched
+			// match bits
+			if (lenbits) {
+				word1 = ntohl(ipv6addr.s6_addr32[i]);
+				word2 = ntohl(ha.ipv6addr.s6_addr32[i]);
+				// shift right
+				word1 >>= (32-lenbits);
+				word2 >>= (32-lenbits);
+				if (word1==word2) return preflen;
+				else return -1;
+			} else {
+				// no extra bits to match and everything OK
+				return preflen;
+			} // end if lenbits
+		} // end if ipv4flag
+	} else return -1;
+} // end match_against
+
+/***** class appladdress *****/
+
+/***** inherited from IE *****/
+
+appladdress* appladdress::new_instance() const {
+	appladdress* aa = NULL;
+	catch_bad_alloc(aa = new appladdress());
+	return aa;
+} // end new_instance
+
+appladdress* appladdress::copy() const {
+	appladdress* aa = NULL;
+	catch_bad_alloc(aa = new appladdress(*this));
+	return aa;
+} // end copy 
+
+bool appladdress::operator==(const address& ie) const {
+	const appladdress* app = dynamic_cast<const appladdress*>(&ie);
+	if (app) {
+		// if the IEs are equal when casted to type hostaddress, then
+		// only protocols and ports have to be checked.
+		// Otherwise they are not equal.
+		if (hostaddress::operator==(ie)) {
+		    if (proto!=app->proto) cout << "protocols not matching" << endl;
+		    if (port !=app->port) cout << "ports not matching" << endl;
+
+		    return ((proto==app->proto) && (port==app->port));
+		} else return false;
+	} else return false;
+} // end operator==
+
+
+/***** class netaddress *****/
+
+/***** inherited from IE *****/
+
+netaddress* netaddress::new_instance() const {
+	netaddress* na = NULL;
+	catch_bad_alloc(na = new netaddress());
+	return na;
+} // end new_instance
+
+netaddress* netaddress::copy() const {
+	netaddress* na = NULL;
+	catch_bad_alloc(na = new netaddress(*this));
+	return na;
+} // end copy 
+
+bool netaddress::operator==(const address& ie) const {
+	const netaddress* na = dynamic_cast<const netaddress*>(&ie);
+	if (na) {
+		// if the IEs are equal when casted to type hostaddress, then
+		// only prefix lengths have to be checked.
+		// Otherwise they are not equal.
+		if (hostaddress::operator==(ie)) {
+		    if (prefix_length!=na->prefix_length) cout << "Prefix length not matching" << endl;
+		    return (prefix_length==na->prefix_length);
+		} else return false;
+	} else return false;
+} // end operator==
+
+
+/***** inherited from hostaddress *****/
+
+/** Convert the IP address to IPv6 by mapping it from IPv4 to IPv6 if
+ * necessary. The prefix length is converted, too.
+ */
+void netaddress::convert_to_ipv6() {
+	if (ipv4flag) {
+		// map IP
+		hostaddress::convert_to_ipv6();
+		// adjust prefix length
+		set_pref_len(prefix_length+96);
+	} // end if ipv4flag
+} // end convert_to_ipv6
+
+/** Set subtype and IPv4 flag. This does NOT clear the outstring buffer.
+ * Use clear_ip(). 
+ * In addition the prefix length is checked and set to reasonable values.
+ */
+void netaddress::set_subtype(bool ipv4) {
+	ipv4flag = ipv4; 
+	if (ipv4) {
+		subtype = IPv4NetAddress; 
+		if (prefix_length>32) prefix_length = 32;
+	} else {
+		subtype = IPv6NetAddress;
+		if (prefix_length>128) prefix_length = 128;
+	} // end if ipv4flag
+} // end set_subtype
+
+/***** new members in netaddress *****/
+
+/** Constructor sets address type and clears prefix length. */
+netaddress::netaddress() : 
+  hostaddress(),
+  prefix_length(0)
+ {
+	set_subtype(ipv4flag);
+} // end constructor
+
+netaddress::netaddress(const netaddress& na) : hostaddress(na) {
+	prefix_length = na.prefix_length;
+	set_subtype(ipv4flag);
+} // end copy constructor
+
+/** Initialize with the given host address and prefix length. 
+ * Prefix length is optional and set to 0 if missing.
+ */
+netaddress::netaddress(const hostaddress& h, prefix_length_t len) : hostaddress(h) {
+  set_subtype(ipv4flag);
+  set_pref_len(len); // this will cut the prefix value accordingly
+} // end constructor(hostaddress,len)
+
+/** Initialize from string which contains IP and prefix length separated by
+ * '/'.
+ */
+netaddress::netaddress(const char* str, bool *res) : hostaddress() {
+	bool tmpres = true; // MUST BE true
+	bool tmpres2 = false;
+	long int len = 0;
+	uint32 iplen;
+	char* i = NULL;
+	char* errptr = NULL;
+	char ipstr[INET6_ADDRSTRLEN] = {0};
+	// look for /
+	i = strchr(str,'/');
+	if (i) {
+		iplen = i-str;
+		i++;
+		// decode prefix length
+		len = strtol(i,&errptr,10);
+		if ((*i) && errptr && ((*errptr)==0)) {
+			// prefix OK
+			prefix_length = len;
+		} else {
+			prefix_length = 0;
+			tmpres = false;
+		} // end if prefix OK
+		if (iplen<=INET6_ADDRSTRLEN) {
+			// copy IP string
+			strncpy(ipstr,str,iplen);
+			ipstr[INET6_ADDRSTRLEN-1] = 0;
+			// set str to ipstr
+			str = ipstr;
+		} // end if iplen valid
+	} else {
+		// no prefix found, OK
+		prefix_length = 0;
+	} // end if i
+	// set IP, this also sets ipvflag.
+	tmpres2 = set_ip(str);
+	if (res) *res = (tmpres && tmpres2);
+	set_subtype(ipv4flag);
+} // end constructor(string)
+
+/** Initialize from string and prefix length.
+ * If the string does not contain a valid IP address, it is set to all 0 by
+ * the hostaddress constructor.
+ */
+netaddress::netaddress(const char* str, prefix_length_t len, bool *res) : hostaddress(str,res) {
+  set_subtype(ipv4flag);
+  set_pref_len(len); // this will cut the prefix value accordingly
+} // end constructor(string,port)
+
+/** Assigns the given netaddress address by using hostaddress::operator=(). */
+netaddress& netaddress::operator=(const netaddress& na) {
+  prefix_length = na.prefix_length;
+  hostaddress::operator=(na);
+  return *this;
+} // end operator=
+
+
+/** Assigns the given netaddress address by using hostaddress::operator=(). */
+netaddress& netaddress::operator=(const hostaddress& na) {
+	hostaddress::operator=(na);
+	set_pref_len(128);
+	return *this;
+} // end operator=
+
+
+/** Set prefix length and return old value.
+ * will also cut prefix_length if needed (i.e., if len too large for addr type)
+ */
+prefix_length_t netaddress::set_pref_len(prefix_length_t len) {
+	register prefix_length_t olen = prefix_length;
+	prefix_length = ipv4flag ? ( (len>32) ? 32 : len ) :
+	                           ( (len>128) ? 128 : len );
+	return olen;
+} // end set_port
+
+
+
+/** Compare two netaddress objects. If neither a<b and b<a then a and b are
+ * considered equal.
+ */
+bool netaddress::operator<(const netaddress& na) const {
+	uint32 word1 = 0;
+	uint32 word2 = 0;
+	prefix_length_t lenwords = prefix_length/32;
+	prefix_length_t lenbits = prefix_length%32;
+	// now 0<=lenwords<=4, 0<=lenbits<=31
+	prefix_length_t i;
+	// IPv4 is always < IPv6
+	if ((!ipv4flag) && na.ipv4flag) return false;
+	else if (ipv4flag && (!na.ipv4flag)) return true;
+	// now ipv4flag == na.ipv4flag
+	else if (prefix_length<na.prefix_length) return true;
+	else if (prefix_length>na.prefix_length) return false;
+	// now prefix_length == na.prefix_length
+	else if (ipv4flag) {
+		// compare IPv4 with same prefix length
+		word1 = ntohl(ipv4addr.s_addr);
+		word2 = ntohl(na.ipv4addr.s_addr);
+		// shift right
+		word1 >>= (32-lenbits);
+		word2 >>= (32-lenbits);
+		if (word1<word2) return true;
+		else return false;
+	} else {
+		// compare IPv6 with same prefix length
+		// compare words
+		for (i=0;i<lenwords;i++) {
+			word1 = ntohl(ipv6addr.s6_addr32[i]);
+			word2 = ntohl(na.ipv6addr.s6_addr32[i]);
+			if (word1<word2) return true;
+			if (word1>word2) return false;
+		} // end for i
+		// now i points to the next word to be compared and previous words are equal
+		// compare bits
+		if (lenbits) {
+			word1 = ntohl(ipv6addr.s6_addr32[i]);
+			word2 = ntohl(na.ipv6addr.s6_addr32[i]);
+			// shift right
+			word1 >>= (32-lenbits);
+			word2 >>= (32-lenbits);
+			if (word1<word2) return true;
+			else return false;
+		} else {
+			// no extra bist to compare and everything equal
+			return false;
+		} // end if lenbits
+	} // end if ipv4flag, prefox
+} // end match_against
+
+/**
+ * Compare function for the radix trie:
+ *
+ * Compare this and na from *pos up to max(this->prefix, na->prefix)
+ *
+ * In pos return the position where the compare ended.
+ *
+ * The return value is 0 if the strings are equal and all of this' string
+ * was consumed, otherwise the sign will indicate the bit in this' string
+ * at pos (i.e. if the search should continue left or right of na).
+ *
+ * pos < 0 indicates error
+ */
+int
+netaddress::rdx_cmp(const netaddress *na, int *pos) const
+{
+	if (na == NULL) {
+		*pos = -1;
+		return 0;
+	}
+
+	if (na->ipv4flag != ipv4flag ||
+	    *pos > na->prefix_length ||
+	    *pos > prefix_length) {
+		*pos = -1;
+		return 0;
+	}
+
+	if (na->prefix_length == 0) {
+		*pos = 1;
+		if (ipv4flag)
+			return ((ntohl(ipv4addr.s_addr) & 0x80000000) == 0 ?
+			    -1 : 1);
+		else
+			return ((htonl(ipv6addr.s6_addr32[0]) & 0x80000000) == 0 ?
+			    -1 : 1);
+	}
+
+	if (*pos < 0)
+		*pos = 0;
+
+	uint32_t w1, w2, w3;
+	int diff, i, p1, p2;
+
+	if (ipv4flag) {
+		diff = *pos;
+		w1 = ntohl(ipv4addr.s_addr);
+		w2 = ntohl(na->ipv4addr.s_addr);
+		// in w3 store the difference
+		w3 = w1 ^ w2;
+		// mask out anything after prefix_length and before *pos
+		w3 = (w3 >> (32 - prefix_length)) << (32 - prefix_length + diff);
+		if (w3 == 0 && prefix_length <= na->prefix_length) {
+			*pos = min(prefix_length, na->prefix_length);
+			return 0;
+		}
+		// pos = 0 means start up front, so we need to fix up to that
+		diff++;
+		while (diff <= prefix_length && diff <= na->prefix_length) {
+			if ((w3 & 0x80000000) != 0) {
+				*pos = diff;
+				return (((w1 & (1 << (32 - diff))) >>
+				    (32 - diff)) == 0 ? -1 : 1);
+			}
+			w3 = w3 << 1;
+			diff++;
+		}
+		// difference past na->prefix_length
+		*pos = diff;
+		return (((w1 & (1 << (32 - diff))) >>
+		    (32 - diff)) == 0 ? -1 : 1);
+	}
+
+	diff = *pos;
+	for (i = diff / 32; i < 4; i++) {
+		diff = diff % 32;
+		w1 = ntohl(ipv6addr.s6_addr32[i]);
+		w2 = ntohl(na->ipv6addr.s6_addr32[i]);
+		w3 = w1 ^ w2;
+		p1 = (prefix_length - (i * 32));
+		p1 = p1 > 32 ? 32 : p1;
+		p2 = (na->prefix_length - (i * 32));
+		p1 = p2 > 32 ? 32 : p2;
+
+		w3 = (w3 >> (32 - p1)) << (32 - p1 + diff);
+		if (w3 == 0 && prefix_length <= na->prefix_length) {
+			*pos = min(prefix_length, na->prefix_length);
+			if (prefix_length <= ((i + 1) * 32))
+				return 0;
+		}
+		// pos = 0 means start up front, so we need to fix up to that
+		diff++;
+		while (diff <= p1 && diff <= p2) {
+			if ((w3 & 0x80000000) != 0) {
+				*pos = diff + (i * 32);
+				return (((w1 & (1 << (32 - diff))) >>
+				    (32 - diff)) == 0 ? -1 : 1);
+			}
+			w3 = w3 << 1;
+			diff++;
+		}
+		if (diff + (32 * i) <= prefix_length &&
+		    diff + (32 * i) <= na->prefix_length) {
+			diff--;
+			continue;
+		}
+		// difference past na->prefix_length
+		*pos = diff + (i * 32);
+		if (diff == 33) {
+			diff = 1;
+			if (i == 3)
+				abort();
+			w1 = ntohl(ipv6addr.s6_addr32[i+1]);
+		}
+		return (((w1 & (1 << (32 - diff))) >>
+		    (32 - diff)) == 0 ? -1 : 1);
+	}
+
+	// Not reachable, but gcc complains
+	return 0;
+}
+
+udsaddress* udsaddress::new_instance() const {
+	udsaddress* ha = NULL;
+	catch_bad_alloc(ha = new udsaddress());
+	return ha;
+} // end new_instance
+
+udsaddress* udsaddress::copy() const {
+        udsaddress* ha = NULL;
+	catch_bad_alloc(ha =  new udsaddress(*this));
+	return ha;
+} // end copy 
+
+bool udsaddress::operator==(const address& ie) const {
+	const udsaddress* app = dynamic_cast<const udsaddress*>(&ie);
+	if (app) {
+	    return (app->socknum == socknum) && (app->uds_socket == uds_socket);
+	} else return false;
+} // end operator==
+
+AddressList::AddrProperty *AddressList::LocalAddr_P;
+AddressList::AddrProperty *AddressList::ConfiguredAddr_P;
+AddressList::AddrProperty *AddressList::IgnoreAddr_P;
+AddressList::AddrProperty *AddressList::AnyAddr_P;
+
+AddressList::AddressList()
+{
+	if (LocalAddr_P == 0) {
+		LocalAddr_P = new AddrProperty("local");
+		ConfiguredAddr_P = new AddrProperty("configured");
+		IgnoreAddr_P = new AddrProperty("ignore");
+		AnyAddr_P = new AddrProperty("wildcard");
+	}
+	interfaces = 0;
+}
+
+AddressList::~AddressList()
+{
+	// Refcount AddressLists in order to GC properties?
+}
+
+AddressList::iflist_t *
+AddressList::get_interfaces()
+{
+	iflist_t *iflist;
+
+	if (interfaces != 0)
+		iflist = new iflist_t(*interfaces);
+	else {
+		iflist = new iflist_t();
+		getifaddrs_iflist(*iflist);
+	}
+
+	return iflist;
+}
+
+bool
+AddressList::by_interface(bool start_empty)
+{
+	if (interfaces != 0)
+		return false;
+
+	interfaces = new iflist_t();
+	if (!start_empty)
+		getifaddrs_iflist(*interfaces);
+
+	return true;
+}
+
+bool
+AddressList::add_interface(char *name)
+{
+	if (interfaces == 0)
+		return false;
+
+	return (interfaces->insert(name)).second;
+}
+
+bool
+AddressList::del_interface(char *name)
+{
+	if (interfaces == 0)
+		return false;
+
+	return (interfaces->erase(name) > 0);
+}
+
+bool
+AddressList::add_property(netaddress &na, AddrProperty *p, bool propagate)
+{
+	propmap_t *props, *lpfm_props;
+	propmap_t::iterator it;
+	addr2prop_t::node *node;
+
+	node = prop_trie.lookup_node(na, false, false);
+	if (node != NULL) {
+		props = node->data;
+		if (props == NULL) {
+			props = new propmap_t();
+			node->data = props;
+		}
+		props->insert(pair<AddrProperty *, bool>(p, propagate));
+		
+	} else {
+		props = new propmap_t();
+		props->insert(pair<AddrProperty *, bool>(p, propagate));
+		node = prop_trie.insert(na, *props);
+	}
+
+	if (propagate)
+		bequeath(node, p, true);
+
+	// copy lpfm properties
+	lpfm_props = prop_trie.lookup(na, true);
+	if (lpfm_props == NULL)
+		return true;
+
+	for (it = lpfm_props->begin(); it != lpfm_props->end(); it++) {
+		if ((*it).second)
+			props->insert((*it));
+	}
+
+	return true;
+}
+
+bool
+AddressList::del_property(netaddress &na, AddrProperty *p, bool propagate)
+{
+	propmap_t *props, *lpfm_props;
+	propmap_t::iterator it;
+	addr2prop_t::node *node;
+
+	node = prop_trie.lookup_node(na, false, true);
+	if (node == NULL) {
+		// no exact match
+		if (!propagate) {
+			node = prop_trie.lookup_node(na, true, true);
+			if (node == NULL) {
+				// no lpfm either, we're done
+				return false;
+			}
+
+			props = node->data;
+			it = props->find(p);
+			if (it == props->end()) {
+				// lpfm doesn't have p set -> done
+				return false;
+			}
+		}
+		// insert an empty propmap
+		props = new propmap_t();
+		node = prop_trie.insert(na, *props);
+
+		// copy other lpfm properties
+		lpfm_props = prop_trie.lookup(na, true);
+		if (p != AnyAddr_P && lpfm_props != NULL) {
+			for (it = lpfm_props->begin(); it != lpfm_props->end();
+			    it++) {
+				if ((*it).first != p && (*it).second)
+					props->insert((*it));
+			}
+		}
+	} else {
+		props = node->data;
+		if (p == AnyAddr_P) {
+			props->clear();
+		} else {
+			it = props->find(p);
+			if (it == props->end() && !propagate)
+				return false;
+
+			props->erase(it);
+		}
+	}
+
+	if (propagate)
+		bequeath(node, p, false);
+
+	return true;
+}
+
+bool
+AddressList::add_host_prop(const char *name, AddrProperty *p)
+{
+	netaddress na;
+	sockaddr_in *sin;
+	sockaddr_in6 *sin6;
+	struct addrinfo hints = {0}, *res, *cur;
+	int error;
+	char buf[1024];
+
+	if (name == NULL) {
+		name = buf;
+		if (gethostname(buf, sizeof(buf)) != 0)
+			return false;
+		buf[sizeof(buf) - 1] = '\0';
+	}
+	hints.ai_flags = AI_ADDRCONFIG | AI_CANONNAME;
+	hints.ai_family = AF_UNSPEC;
+	error = getaddrinfo(name, NULL, &hints, &res);
+	if (error != 0)
+		return false;
+
+	for(cur = res; cur != NULL && error == 0; cur = cur->ai_next) {
+		if (cur->ai_family == AF_INET) {
+			sin = (struct sockaddr_in *)cur->ai_addr;
+			na.set_ip(sin->sin_addr);
+			na.set_pref_len(32);
+		} else if (cur->ai_family == AF_INET6) {
+			sin6 = (struct sockaddr_in6 *)cur->ai_addr;
+			na.set_ip(sin6->sin6_addr);
+			na.set_pref_len(128);
+		} else
+			continue;
+
+		// cout << ++i << "XXMOB: " << na << endl;
+
+		error += add_property(na, p) ? 0 : 1;
+		// XXXMOB: for some reason we need a 'reset' here
+		//         if we want to use /etc/hosts
+		na.set_ip("127.0.0.1");
+	}
+	freeaddrinfo(res);
+
+	return (error == 0);
+}
+
+bool
+AddressList::del_host_prop(const char *name, AddrProperty *p)
+{
+	netaddress na;
+	sockaddr_in *sin;
+	sockaddr_in6 *sin6;
+	struct addrinfo hints = {0}, *res, *cur;
+	int error;
+	char buf[1024];
+
+	if (name == NULL) {
+		name = buf;
+		if (gethostname(buf, sizeof(buf)) != 0)
+			return false;
+		buf[sizeof(buf) - 1] = '\0';
+	}
+	hints.ai_flags = AI_ADDRCONFIG;
+	hints.ai_family = AF_UNSPEC;
+	error = getaddrinfo(name, NULL, &hints, &res);
+	if (error != 0)
+		return false;
+
+	for(cur = res; cur != NULL && error == 0; cur = cur->ai_next) {
+		if (cur->ai_family == AF_INET) {
+			sin = (struct sockaddr_in *)cur->ai_addr;
+			na.set_ip(sin->sin_addr);
+			na.set_pref_len(32);
+		} else if (cur->ai_family == AF_INET6) {
+			sin6 = (struct sockaddr_in6 *)cur->ai_addr;
+			na.set_ip(sin6->sin6_addr);
+			na.set_pref_len(128);
+		} else
+			continue;
+
+		error += del_property(na, p) ? 0 : 1;
+	}
+	freeaddrinfo(res);
+
+	return (error == 0);
+}
+
+bool
+AddressList::ignore(netaddress &na, bool propagate)
+{
+	del_property(na, AnyAddr_P, propagate);
+	return add_property(na, IgnoreAddr_P);
+}
+
+bool
+AddressList::unignore(netaddress &na, bool propagate)
+{
+	return del_property(na, IgnoreAddr_P, propagate);
+}
+
+bool
+AddressList::ignore_bogons(void)
+{
+	netaddress na;
+
+	// according to IANA Tue Apr 17 09:14:31 PDT 2007
+	na.set_ip("0.0.0.0");na.set_pref_len(7);
+	ignore(na);
+	na.set_ip("2.0.0.0");na.set_pref_len(8);
+	ignore(na);
+	na.set_ip("5.0.0.0");na.set_pref_len(8);
+	ignore(na);
+	na.set_ip("7.0.0.0");na.set_pref_len(8);
+	ignore(na);
+	na.set_ip("23.0.0.0");na.set_pref_len(8);
+	ignore(na);
+	na.set_ip("27.0.0.0");na.set_pref_len(8);
+	ignore(na);
+	na.set_ip("31.0.0.0");na.set_pref_len(8);
+	ignore(na);
+	na.set_ip("36.0.0.0");na.set_pref_len(7);
+	ignore(na);
+	na.set_ip("39.0.0.0");na.set_pref_len(8);
+	ignore(na);
+	na.set_ip("42.0.0.0");na.set_pref_len(8);
+	ignore(na);
+	na.set_ip("49.0.0.0");na.set_pref_len(8);
+	ignore(na);
+	na.set_ip("50.0.0.0");na.set_pref_len(8);
+	ignore(na);
+	na.set_ip("94.0.0.0");na.set_pref_len(7);
+	ignore(na);
+	na.set_ip("100.0.0.0");na.set_pref_len(6);
+	ignore(na);
+	na.set_ip("104.0.0.0");na.set_pref_len(5);
+	ignore(na);
+	na.set_ip("112.0.0.0");na.set_pref_len(6);
+	ignore(na);
+	na.set_ip("169.254.0.0");na.set_pref_len(16);
+	ignore(na);
+	na.set_ip("173.0.0.0");na.set_pref_len(8);
+	ignore(na);
+	na.set_ip("174.0.0.0");na.set_pref_len(7);
+	ignore(na);
+	na.set_ip("176.0.0.0");na.set_pref_len(5);
+	ignore(na);
+	na.set_ip("184.0.0.0");na.set_pref_len(6);
+	ignore(na);
+	na.set_ip("191.0.0.0");na.set_pref_len(8);
+	ignore(na);
+	na.set_ip("192.0.2.0");na.set_pref_len(24);
+	ignore(na);
+	na.set_ip("197.0.0.0");na.set_pref_len(8);
+	ignore(na);
+	na.set_ip("198.18.0.0");na.set_pref_len(15);
+	ignore(na);
+	na.set_ip("223.0.0.0");na.set_pref_len(8);
+	ignore(na);
+	na.set_ip("240.0.0.0");na.set_pref_len(4);
+	ignore(na);
+	// according to http://www.cymru.com/Documents/bogonv6-list.html#agg
+	na.set_ip("0000::");na.set_pref_len(8);
+	ignore(na);
+	na.set_ip("0100::");na.set_pref_len(8);
+	ignore(na);
+	na.set_ip("0200::");na.set_pref_len(7);
+	ignore(na);
+	na.set_ip("0400::");na.set_pref_len(7);
+	ignore(na);
+	na.set_ip("0600::");na.set_pref_len(7);
+	ignore(na);
+	na.set_ip("0800::");na.set_pref_len(5);
+	ignore(na);
+	na.set_ip("1000::");na.set_pref_len(4);
+	ignore(na);
+	na.set_ip("2000::");na.set_pref_len(16);
+	ignore(na);
+	na.set_ip("2001:1000::");na.set_pref_len(23);
+	ignore(na);
+	na.set_ip("2001:1600::");na.set_pref_len(23);
+	ignore(na);
+	na.set_ip("2001:2000::");na.set_pref_len(20);
+	ignore(na);
+	na.set_ip("2001:3000::");na.set_pref_len(20);
+	ignore(na);
+	na.set_ip("2001:4000::");na.set_pref_len(20);
+	ignore(na);
+	na.set_ip("2001:5000::");na.set_pref_len(20);
+	ignore(na);
+	na.set_ip("2001:6000::");na.set_pref_len(20);
+	ignore(na);
+	na.set_ip("2001:7000::");na.set_pref_len(20);
+	ignore(na);
+	na.set_ip("2001:8000::");na.set_pref_len(20);
+	ignore(na);
+	na.set_ip("2001:9000::");na.set_pref_len(20);
+	ignore(na);
+	na.set_ip("2001:A000::");na.set_pref_len(20);
+	ignore(na);
+	na.set_ip("2001:B000::");na.set_pref_len(20);
+	ignore(na);
+	na.set_ip("2001:C000::");na.set_pref_len(20);
+	ignore(na);
+	na.set_ip("2001:D000::");na.set_pref_len(20);
+	ignore(na);
+	na.set_ip("2001:E000::");na.set_pref_len(20);
+	ignore(na);
+	na.set_ip("2001:F000::");na.set_pref_len(20);
+	ignore(na);
+	na.set_ip("3FFF::");na.set_pref_len(16);
+	ignore(na);
+	na.set_ip("4000::");na.set_pref_len(3);
+	ignore(na);
+	na.set_ip("6000::");na.set_pref_len(3);
+	ignore(na);
+	na.set_ip("8000::");na.set_pref_len(3);
+	ignore(na);
+	na.set_ip("A000::");na.set_pref_len(3);
+	ignore(na);
+	na.set_ip("C000::");na.set_pref_len(3);
+	ignore(na);
+	na.set_ip("E000::");na.set_pref_len(4);
+	ignore(na);
+	na.set_ip("F000::");na.set_pref_len(5);
+	ignore(na);
+	na.set_ip("F800::");na.set_pref_len(6);
+	ignore(na);
+	na.set_ip("FC00::");na.set_pref_len(7);
+	ignore(na);
+	na.set_ip("FE00::");na.set_pref_len(9);
+	ignore(na);
+
+	return true;
+}
+
+bool
+AddressList::ignore_locals(void)
+{
+	netaddress na;
+
+	na.set_ip("10.0.0.0");na.set_pref_len(8);
+	ignore(na);
+	na.set_ip("172.16.0.0");na.set_pref_len(12);
+	ignore(na);
+	na.set_ip("192.168.0.0");na.set_pref_len(16);
+	ignore(na);
+	na.set_ip("FE80::");na.set_pref_len(10);
+	ignore(na);
+	na.set_ip("FEC0::");na.set_pref_len(10);
+	ignore(na);
+
+	return true;
+}
+
+bool
+AddressList::ignore_loopback(void)
+{
+	netaddress na;
+
+	na.set_ip("127.0.0.0");na.set_pref_len(8);
+	ignore(na);
+	na.set_ip("::1");na.set_pref_len(128);
+	ignore(na);
+
+	return true;
+}
+
+bool
+AddressList::addr_is(netaddress &na, AddrProperty *prop)
+{
+	propmap_t *props;
+	propmap_t::iterator it;
+
+	if (addr_is_in(na, IgnoreAddr_P))
+		return false;
+
+	props = prop_trie.lookup(na, false);
+	if (props != NULL) {
+		it = props->find(prop);
+		if (it != props->end()) {
+			return true;
+		}
+	}
+
+	if (prop != LocalAddr_P)
+		return false;
+
+	return getifaddrs_is_local(na);
+}
+
+bool
+AddressList::addr_is_in(netaddress &na, AddrProperty *prop)
+{
+	addr2prop_t::node *node;
+	propmap_t *props;
+	propmap_t::iterator it;
+
+	node = prop_trie.lookup_node(na, true, true);
+	if (node == NULL)
+		return false;
+
+	props = node->data;
+	it = props->find(prop);
+	if (it == props->end())
+		return false;
+
+	if (!(*it).second && props != prop_trie.lookup(na, false))
+			return false;
+
+	return true;
+}
+
+AddressList::addrlist_t *
+AddressList::get_addrs(AddrProperty *prop)
+{
+	addr2prop_t::node *node;
+	netaddress na;
+	addrlist_t *res = new addrlist_t();
+
+	if (res == 0)
+		return res;
+
+	if (prop == LocalAddr_P || prop == AnyAddr_P)
+		getifaddrs_get_addrs(*res);
+
+	na.set_ip("0.0.0.0");
+	na.set_pref_len(0);
+	node = prop_trie.lookup_node(na, true, false);
+	collect(node, prop, *res);
+
+	na.set_ip("::");
+	node = prop_trie.lookup_node(na, true, false);
+	collect(node, prop, *res);
+
+	return res;
+}
+
+netaddress *
+AddressList::get_first(AddrProperty *p, bool IPv4)
+{
+	addr2prop_t::node *node;
+	netaddress na;
+	addrlist_t list;
+	addrlist_t::iterator it;
+
+	if (IPv4) {
+		na.set_ip("0.0.0.0");
+		na.set_pref_len(0);
+	} else {
+		na.set_ip("::");
+		na.set_pref_len(0);
+	}
+
+	node = prop_trie.lookup_node(na, true, false);
+	node = collect_first(node, p);
+	if (node != NULL)
+		return new netaddress(*node->key);
+
+	if (p == LocalAddr_P) {
+		getifaddrs_get_addrs(list);
+		for (it = list.begin(); it != list.end(); it++)
+			if ((*it).is_ipv4() == IPv4)
+				return new netaddress(*it);
+	}
+
+	return NULL;
+}
+
+netaddress *
+AddressList::get_src_addr(const netaddress &dest, uint32_t *prefs)
+{
+	netaddress *res;
+	int sfd;
+
+	sfd = socket(dest.is_ipv4()?AF_INET:AF_INET6, SOCK_DGRAM, 0);
+	if (sfd == -1)
+		return NULL;
+
+#ifdef IPV6_ADDR_PREFERENCES
+	if (prefs != NULL && setsockopt(s, IPV6_ADDR_PREFERENCES,
+	    (void *)prefs, sizeof (*prefs)) == -1) {
+		close(sfd);
+		return NULL;
+	}
+#endif
+	if (dest.is_ipv4()) {
+		struct sockaddr_in sin = {0};
+		socklen_t slen = sizeof(sin);
+		sin.sin_family = AF_INET;
+		sin.sin_port = htons(4);
+		dest.get_ip(sin.sin_addr);
+		if (connect(sfd, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
+			close(sfd);
+			return NULL;
+		}
+		if (getsockname(sfd, (struct sockaddr *)&sin, &slen) == -1) {
+			close(sfd);
+			return NULL;
+		}
+		close(sfd);
+		res = new netaddress();
+		res->set_ip(sin.sin_addr);
+		res->set_pref_len(32);
+		return (res);
+	} else {
+		struct sockaddr_in6 sin6 = {0};
+		socklen_t slen = sizeof(sin6);
+		sin6.sin6_family = AF_INET6;
+		sin6.sin6_port = htons(4);
+		dest.get_ip(sin6.sin6_addr);
+		if (connect(sfd, (struct sockaddr *)&sin6,
+		    sizeof(sin6)) == -1) {
+			close(sfd);
+			return NULL;
+		}
+		if (getsockname(sfd, (struct sockaddr *)&sin6, &slen) == -1) {
+			close(sfd);
+			return NULL;
+		}
+		close(sfd);
+		res = new netaddress();
+		res->set_ip(sin6.sin6_addr);
+		res->set_pref_len(128);
+		return (res);
+	}
+}
+
+void
+AddressList::getifaddrs_iflist(iflist_t &list)
+{
+	struct ifaddrs *ifap, *cifa;
+
+	if (::getifaddrs(&ifap) != 0)
+		return;
+
+	for (cifa = ifap; cifa != NULL; cifa = cifa->ifa_next) {
+		list.insert(cifa->ifa_name);
+	}
+
+	freeifaddrs(ifap);
+}
+
+bool
+AddressList::getifaddrs_is_local(netaddress &na)
+{
+	struct ifaddrs *ifap, *cifa;
+
+	if (::getifaddrs(&ifap) != 0)
+		return false;
+
+	for (cifa = ifap; cifa != NULL; cifa = cifa->ifa_next) {
+		hostaddress ha;
+
+		if (cifa->ifa_addr->sa_family == AF_INET) {
+			ha.set_ip(
+			    ((struct sockaddr_in *)cifa->ifa_addr)->sin_addr);
+		} else if (cifa->ifa_addr->sa_family == AF_INET6) {
+			ha.set_ip(
+			    ((struct sockaddr_in6 *)cifa->ifa_addr)->sin6_addr);
+		} else {
+			continue;
+		}
+
+		if (interfaces &&
+		    interfaces->find(cifa->ifa_name) == interfaces->end())
+			continue;
+
+		if (ha.match_against(na) >= na.get_pref_len()) {
+			freeifaddrs(ifap);
+			return true;
+		}
+	}
+
+	freeifaddrs(ifap);
+
+	return false;
+}
+
+void
+AddressList::getifaddrs_get_addrs(addrlist_t &list)
+{
+	struct ifaddrs *ifap, *cifa;
+
+	if (::getifaddrs(&ifap) != 0)
+		return;
+
+	for (cifa = ifap; cifa != NULL; cifa = cifa->ifa_next) {
+		hostaddress *ha;
+		netaddress na;
+
+		if (interfaces &&
+		    interfaces->find(cifa->ifa_name) == interfaces->end())
+			continue;
+
+		if (cifa->ifa_addr->sa_family == AF_INET) {
+			ha = new hostaddress;
+			ha->set_ip(
+			    ((struct sockaddr_in *)cifa->ifa_addr)->sin_addr);
+			na.set_pref_len(32);
+		} else if (cifa->ifa_addr->sa_family == AF_INET6) {
+			ha = new hostaddress;
+			ha->set_ip(
+			    ((struct sockaddr_in6 *)cifa->ifa_addr)->sin6_addr);
+			na.set_pref_len(128);
+		} else {
+			continue;
+		}
+
+		na.set_ip(*ha);
+		if (!addr_is_in(na, IgnoreAddr_P))
+			list.insert(*ha);
+	}
+
+	freeifaddrs(ifap);
+}
+
+void
+AddressList::bequeath(addr2prop_t::node *head, AddrProperty *p, bool add)
+{
+	propmap_t *props;
+	propmap_t::iterator it;
+
+	if (p == AnyAddr_P && add)
+		return;
+
+	props = head->data;
+	if (props != NULL) {
+		if (p == AnyAddr_P) {
+			props->clear();
+		} else {
+			if (add) {
+				props->insert(pair<AddrProperty *, bool>
+				    (p, true));
+			} else {
+				it = props->find(p);
+				if (it != props->end())
+					props->erase(it);
+			}
+		}
+	}
+
+	if (head->left->index > head->index)
+		bequeath(head->left, p, add);
+	if (head->right->index > head->index)
+		bequeath(head->right, p, add);
+}
+
+void
+AddressList::collect(addr2prop_t::node *head, AddrProperty *p,
+    addrlist_t &list)
+{
+	propmap_t *props;
+	propmap_t::iterator it;
+
+	props = head->data;
+	if (props != NULL) {
+		if (p == AnyAddr_P) {
+			it = props->begin();
+		} else {
+			it = props->find(p);
+		}
+		if (it != props->end()) {
+			list.insert(*(new netaddress(*head->key)));
+		}
+	}
+
+	if (head->left->index > head->index)
+		collect(head->left, p, list);
+	if (head->right->index > head->index)
+		collect(head->right, p, list);
+	
+}
+
+AddressList::addr2prop_t::node *
+AddressList::collect_first(addr2prop_t::node *head, AddrProperty *p)
+{
+	addr2prop_t::node *res = NULL;
+	propmap_t *props;
+	propmap_t::iterator it;
+
+	props = head->data;
+	if (props != NULL) {
+		if (p == AnyAddr_P) {
+			it = props->begin();
+		} else {
+			it = props->find(p);
+		}
+		if (it != props->end()) {
+			return head;
+		}
+	}
+
+	if (head->left->index > head->index) {
+		res = collect_first(head->left, p);
+		if (res != NULL)
+			return res;
+	}
+	if (head->right->index > head->index) {
+		res = collect_first(head->right, p);
+		if (res != NULL)
+			return res;
+	}
+
+	return NULL;
+}
+
+
+} // end namespace protlib
Index: /source/ariba/utility/transport/tcpip/protlib/address.h
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/address.h	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/address.h	(revision 5284)
@@ -0,0 +1,1452 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file address.h
+/// GIST address objects
+/// ----------------------------------------------------------
+/// $Id: address.h 3063 2008-07-02 08:02:45Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/address.h $
+// ===========================================================
+//
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+/** @ingroup ieaddress
+ *
+ * GIST address objects
+ */
+
+#ifndef PROTLIB__ADDRESS_H
+#define PROTLIB__ADDRESS_H
+
+#include "protlib_types.h"
+#include "ie.h"
+
+#include <ext/hash_map>
+#include <netinet/in.h>
+#include <set>
+
+#include "logfile.h"
+#include "threadsafe_db.h"
+
+namespace protlib {
+  using namespace log;
+
+/// Address base class
+/** This is the base class for IP host and application addresses, router,
+ * interface and user identification and AS numbers.
+ */
+class address {
+  public:
+	virtual address* new_instance() const = 0;
+	virtual address* copy() const = 0;
+	virtual bool operator==(const address& address) const = 0;
+
+	inline bool operator!=(const address& address) const {
+		return (!(*this==address));
+	}
+
+
+	enum subtype_t {
+		/** 255 is not a valid subtype and is used to register for all
+		 * subtypes.
+		 * @note This is no valid subtype because it is not in 0..64.
+		 */
+		all_subtypes          = 255,
+		// @{
+		/// address subtypes
+		/** These are the address-specific subtypes. */
+		IPv4HostAddress       =   1,
+		IPv6HostAddress       =   2,
+		IPv4NetAddress        =   3,
+		IPv6NetAddress        =   4,
+		IPv4ApplAddress       =   5,
+		IPv6ApplAddress       =   6,
+		IPv6Unspecified	      =   7,
+		UDSAddress            =   8,
+		FlowAddressSpec       =  12,
+		AS16                  =  14,
+		AS32                  =  15,
+		IEEE48                =  16,
+		EUI48                 =  17,
+		EUI64                 =  18,
+		NAI                   =  32,
+		X509                  =  33
+		// @}
+	}; // end subtype_t
+
+	virtual ~address() {};
+
+  subtype_t get_type() const { return subtype; };
+
+  protected:
+	/// constructor with subtype
+	address(subtype_t st);
+        /// virtual destructor
+
+	void throw_nomem_error() const;
+
+	subtype_t subtype;
+};
+
+// forward declaration
+class netaddress;
+
+/// IP Host Address
+/** This class can hold IPv4 and IPv6 Host Addresses. */
+class hostaddress : public address {
+
+  public:
+	virtual hostaddress* new_instance() const;
+	virtual hostaddress* copy() const;
+	virtual bool operator==(const address& ie) const;
+
+	/// constructor
+	hostaddress();
+	/// copy constructor
+	hostaddress(const hostaddress& h);
+	/// assignment
+	hostaddress& operator=(const hostaddress& h);
+	/// constructor from string
+	hostaddress(const char *str, bool *res = NULL);
+	/// constructor from in6_addr
+	hostaddress(const struct in6_addr& ipv6addr);
+	/// destructor
+	virtual ~hostaddress();
+	/// set IPv4 from string
+	bool set_ipv4(const char *str);
+	/// set IPv4 from in_addr
+	void set_ip(const struct in_addr &in);
+	/// set IPv6 from string
+	bool set_ipv6(const char *str);
+	/// set IPv6 from in6_addr
+	void set_ip(const struct in6_addr &in);
+	/// set IPv4 or IPv6 from string
+	bool set_ip(const char *str);
+	bool set_ip(const string& str);
+	/// set IP from hostaddress
+	void set_ip(const hostaddress& h);
+	/// is IP unspecified
+	bool is_ip_unspec() const;
+	/// get ip address as string
+	const char *get_ip_str() const;
+	/// get ip address as string
+	const char *get_ip_str(char *str) const;
+	/// is it IPv4
+	bool is_ipv4() const;
+	/// is it IPv6
+	bool is_ipv6() const;
+	/// is bogus source (e.g. localhost, multicast)
+	bool is_bogus_source() const;
+	/// is it a 4to6-mapped address?
+	bool is_mapped_ip() const;
+	/// get as in_addr?
+	bool get_ip(struct in_addr& in) const;
+	/// get as in6_addr?
+	bool get_ip(struct in6_addr& in) const;
+	/// get as in6_addr?
+	const struct in6_addr *get_ip() const { return ipv4flag ? 0 : &ipv6addr; };
+	/// convert to iPv6
+	virtual void convert_to_ipv6();
+	/// are they equivalent
+	virtual bool equiv(const hostaddress& h) const;
+	/// lookup host name
+	string get_host_name(bool *res = NULL) const;
+	/// hash function
+	virtual size_t get_hash() const;
+	/// match against IP address
+	virtual int match_against(const hostaddress& ha) const;
+        /// match against network prefix
+	virtual int match_against(const netaddress& na) const;
+protected:
+	/// IPv4 flag
+	bool ipv4flag;
+	/// set subtype and IPv4 flag
+	virtual void set_subtype(bool ipv4);
+	/// IP buffer
+	/** I in protected and NOT private scope because subclasses have to
+	 * (de)serialize it.
+	 */
+	union {
+		/// IPv4 address
+		struct in_addr ipv4addr;
+		/// IPv6 address
+		struct in6_addr ipv6addr;
+	}; // end union
+public:
+	/// clear IP buffer (sets IP address to undefined/any and deletes any outstring)
+	void clear_ip();
+private:
+	/// pointer to IP string representation
+	mutable char *outstring;
+}; // end hostaddress
+
+inline ostream &operator<<(ostream &out, const hostaddress &addr) {
+     return out << addr.get_ip_str();
+}
+
+inline
+hostaddress::hostaddress(const struct in6_addr& ipv6addr)
+  : address(IPv6HostAddress),
+    ipv4flag(false),
+    ipv6addr(ipv6addr),
+    outstring(NULL)
+{ set_subtype(false); }
+
+
+/// ========================================================
+/// IP Application Address
+/// ========================================================
+/** Consists of a IP Host Address and a port number. */
+class appladdress : public hostaddress {
+    public:
+	virtual appladdress* new_instance() const;
+	virtual appladdress* copy() const;
+	virtual bool operator==(const address& ie) const;
+
+	/// hash function
+	virtual size_t get_hash() const;
+
+    protected:
+	/// set subtype and IPv4 flag
+	virtual void set_subtype(bool ipv4);
+
+    public:
+	/// constructor
+	appladdress();
+	/// copy constructor
+	appladdress(const appladdress& app);
+	///constructor for use as Unix Domain Address
+	appladdress(string socket);
+	///constructor for use to specify a explicit socket number (used when no addressing for peer can be derived)
+	appladdress(int socket);
+        /// constructor from hostaddress, protocol ID and port
+	appladdress(const hostaddress& h, protocol_t prot, port_t p);
+	/// constructor from sockaddr_in6 sockaddr
+	appladdress(const sockaddr_in6& sockaddr,  protocol_t prot);
+	/// constructor from hostaddress, protocol name and port
+	appladdress(const hostaddress& h, const char* pname, port_t p, bool *res = NULL);
+	/// constructor from string, protocol ID and port
+	appladdress(const char* str, protocol_t prot, port_t p, bool *res = NULL);
+	/// constructor from string, protocol name and port
+	appladdress(const char* str, const char* pname, port_t p, bool *res = NULL);
+	/// constructor from string, protocol name and port name
+	appladdress(const char* str, const char* pname, const char* portname, bool *res = NULL);
+	/// assignment
+	appladdress& operator=(const appladdress& app);
+        /// virtual destructor
+        virtual ~appladdress() {};
+
+
+	/// are they equivalent
+        ///virtual bool equiv(const appladdress& h) const { return hostaddress::equiv(h); }
+
+	/// set port
+	port_t set_port(port_t p);
+	/// set port
+	port_t set_port(const char* pname, bool *res = NULL);
+	/// set port
+	port_t set_port(const string& pname, bool *res = NULL);
+	/// get port
+	port_t get_port() const;
+
+	/// get sockaddr_in6
+	void get_sockaddr(struct sockaddr_in6& sockaddr) const;
+	/// get port name
+	string get_port_name(bool *res = NULL) const;
+	/// set protocol by ID
+	protocol_t set_protocol(protocol_t p);
+	/// set protocol by name
+	protocol_t set_protocol(const char* pname, bool *res = NULL);
+	/// set protocol by name
+	protocol_t set_protocol(const string& pname, bool *res = NULL);
+	/// get protocol ID
+	protocol_t get_protocol() const;
+	/// get protocol name
+	string get_protocol_name(bool *res = NULL) const;
+	/// get prefix
+	inline
+	uint8 get_prefix() const {
+	    return prefix;
+	}
+
+	/// set prefix
+	inline
+	void set_prefix(uint8 prfx) {
+	    prefix=prfx;
+	}
+
+	/// set IP TTL
+	inline
+	void set_ip_ttl(uint16 ttl) {
+	    ip_ttl = ttl;
+	}
+
+
+	/// unset IP TTL
+	inline
+	void unset_ip_ttl() {
+	    ip_ttl = 0;
+	}
+
+
+	/// get IP TTL, if == 0, no IP TTL should be set
+	inline
+	uint16 get_ip_ttl() const {
+	return ip_ttl;
+	}
+
+
+	/// set RAO value
+	inline
+	void set_rao(uint16 value) {
+	    rao_presence = true;
+	    rao = value;
+	}
+
+	/// unset RAO value
+	inline
+	void unset_rao() {
+	    rao_presence = false;
+	    rao = 0;
+	}
+
+	/// get RAO value
+	inline
+	uint16 get_rao() const {
+	    return rao;
+	}
+
+
+	/// test if RAO present
+	inline
+	bool rao_present() const {
+	return rao_presence;
+	}
+
+	/// set outgoing Interface index
+	inline
+	void set_if_index(uint16 value) {
+	if_index = value;
+	}
+
+	/// get outgoing Interface index
+	inline
+	uint16 get_if_index() const {
+	    return if_index;
+	}
+
+	/// unset outgoing Interface index
+	inline
+	void unset_if_index() {
+	    if_index = 0;
+	}
+
+
+
+
+
+    private:
+	protocol_t proto;
+	port_t port;
+	uint8 prefix;
+
+	uint16 rao;
+	uint16 ip_ttl;
+	bool rao_presence;
+	uint16 if_index;
+
+    }; // end appladdress
+
+
+inline
+appladdress::appladdress(const sockaddr_in6& sockaddr, protocol_t prot)
+    : hostaddress(sockaddr.sin6_addr), proto(prot), port(ntohs(sockaddr.sin6_port)), rao(0), ip_ttl(0), rao_presence(false), if_index(0)
+{
+  //Log(DEBUG_LOG,LOG_NORMAL,"address","address constructor called for sockaddr_in6");
+}
+
+/** Constructor sets address type and clears port sets prefix to 32 (ipv4). */
+inline
+appladdress::appladdress() : hostaddress(),
+			     proto(0),
+			     port(0),
+			     prefix(32),
+     			     rao(0),
+			     ip_ttl(0),
+			     rao_presence(false),
+			     if_index(0)
+
+{
+  //Log(DEBUG_LOG,LOG_NORMAL,"address","address constructor called for bool ipv4=" << ipv4);
+  set_subtype(ipv4flag);
+} // end constructor
+
+inline
+appladdress::appladdress(const appladdress& app) : hostaddress(app),
+						   proto(app.proto),
+						   port(app.port),
+						   prefix(app.prefix),
+						   rao(app.rao),
+						   ip_ttl(app.ip_ttl),
+						   rao_presence(app.rao_presence),
+						   if_index(app.if_index)
+
+{
+    //Log(DEBUG_LOG,LOG_NORMAL,"appladdress", "Copy address constructor called for appladdress& app:" << app);
+    //DLog("appladdress", "UDSsocket copied: " << uds_socket);
+  //DLog("appladdress", "ip_ttl: " << ip_ttl << " if_index: " << if_index);
+
+
+    set_subtype(ipv4flag);
+} // end copy constructor
+
+/** Initialize with the given host address, protocol ID and port number. */
+inline
+appladdress::appladdress(const hostaddress& h, protocol_t prot, port_t p)
+    : hostaddress(h),
+      proto(prot),
+      port(p),
+      prefix(0),
+      rao(0),
+      ip_ttl(0),
+      rao_presence(false),
+      if_index(0)
+{
+  //Log(DEBUG_LOG,LOG_NORMAL,"address","address constructor called for (const hostaddress& h, protocol_t prot, port_t p)");
+
+  set_subtype(ipv4flag);
+} // end constructor(hostaddress,prot,port)
+
+/** Initialize with the given host address, protocol name and port number.
+ * If no protocol ID can be found in the protocol database, it is set to 0.
+ */
+inline
+appladdress::appladdress(const hostaddress& h, const char* pname, port_t p, bool *res)
+  : hostaddress(h),
+    proto(tsdb::getprotobyname(pname,res)),
+    port(p),
+    prefix(0),
+    rao(0),
+    ip_ttl(0),
+    rao_presence(false),
+    if_index(0)
+
+{
+  //Log(DEBUG_LOG,LOG_NORMAL,"address","address constructor called for (const hostaddress& h, const char* pname, port_t p, bool *res)");
+
+    set_subtype(ipv4flag);
+} // end constructor(hostaddress,pname,port)
+
+/** Initialize from string, protocol ID and port.
+ * If the string does not contain a vaild IP address, it is set to all 0 by
+ * the hostaddress constructor.
+ */
+inline
+appladdress::appladdress(const char* str, protocol_t prot, port_t p, bool *res)
+  : hostaddress(str,res),
+    proto(prot),
+    port(p),
+    prefix(0),
+    rao(0),
+    ip_ttl(0),
+    rao_presence(false),
+    if_index(0)
+{
+    set_subtype(ipv4flag);
+} // end constructor(string,prot,port)
+
+/** Initialize from string, protocol name and port.
+ * If the string does not contain a vaild IP address, it is set to all 0 by
+ * the hostaddress constructor.
+ * If no protocol ID can be found in the protocol database, it is set to 0.
+ */
+inline
+appladdress::appladdress(const char* str, const char* pname, port_t p, bool *res)
+  : hostaddress(str,res),
+    port(p),
+    prefix(0),
+    rao(0),
+    ip_ttl(0),
+    rao_presence(false),
+    if_index(0)
+{
+  //Log(DEBUG_LOG,LOG_NORMAL,"address","address constructor called for (const char* str, const char* pname, port_t p, bool *res)");
+
+    register bool tmpres = false;
+    proto = tsdb::getprotobyname(pname,&tmpres);
+    if (res) *res = ((*res) && tmpres);
+    set_subtype(ipv4flag);
+} // end constructor(string,pname,port)
+
+/** Initialize from string, protocol name and port name.
+ * If the string does not contain a vaild IP address, it is set to all 0 by
+ * the hostaddress constructor.
+ * If no protocol ID can be found in the protocol database, it is set to 0.
+ * If no port number can be found in the service database, it is set to 0.
+ */
+inline
+appladdress::appladdress(const char* str, const char* pname, const char* portname, bool *res)
+    : hostaddress(str,res),
+      prefix(0),
+      rao(0),
+      ip_ttl(0),
+      rao_presence(false),
+      if_index(0)
+{
+  //Log(DEBUG_LOG,LOG_NORMAL,"address","address constructor called for (const char* str, const char* pname, const char* portname, bool *res)");
+
+    bool res1 = false;
+    bool res2 = false;
+    proto = tsdb::getprotobyname(pname,&res1);
+    port = tsdb::get_portnumber(portname,proto,&res2);
+    if (res) *res = ((*res) && res1 && res2);
+    set_subtype(ipv4flag);
+    prefix = 0;
+} // end constructor(string,pname,portname)
+
+/** Assigns the given application address by using hostaddress::operator=(). */
+inline
+appladdress&
+appladdress::operator=(const appladdress& app)
+{
+	hostaddress::operator=(app);
+	proto = app.proto;
+	port = app.port;
+	prefix = app.prefix;
+	ip_ttl = app.ip_ttl;
+	rao_presence = app.rao_presence;
+	rao = app.rao;
+	if_index = app.if_index;
+	return *this;
+} // end operator=
+
+
+/** Set port and return old value. */
+inline
+port_t appladdress::set_port(port_t p) {
+	register port_t op = port;
+	port = p;
+	return op;
+} // end set_port
+
+
+
+/** Set port and return old value.
+ * If the port name is not found in the service database, port is set to 0.
+ */
+inline
+port_t appladdress::set_port(const char* pname, bool *res) {
+	register port_t op = port;
+	port = tsdb::get_portnumber(pname,proto,res);
+	return op;
+} // end set_port
+
+/** Set port and return old value.
+ * If the port name is not found in the service database, port is set to 0.
+ */
+inline
+port_t appladdress::set_port(const string& pname, bool *res) {
+	register port_t op = port;
+	port = tsdb::get_portnumber(pname,proto,res);
+	return op;
+} // end set_port
+
+inline
+port_t appladdress::get_port() const { return port; }
+
+inline
+string appladdress::get_port_name(bool *res) const {
+	return tsdb::get_portname(port,proto,res);
+} // end get_port_name
+
+/** Set protocol ID and return old value. */
+inline
+protocol_t appladdress::set_protocol(protocol_t p) {
+	register protocol_t o = proto;
+	proto = p;
+	return o;
+} // end set_protocol
+
+/** Set protocol ID and return old value.
+ * If no protocol ID can be found in the protocol database, it is set to 0.
+ */
+inline
+protocol_t appladdress::set_protocol(const char* pname, bool *res) {
+	register protocol_t o = proto;
+	proto = tsdb::getprotobyname(pname,res);
+	return o;
+} // end set_protocol
+
+/** Set protocol ID and return old value.
+ * If no protocol ID can be found in the protocol database, it is set to 0.
+ */
+inline
+protocol_t appladdress::set_protocol(const string& pname, bool *res) {
+	register protocol_t o = proto;
+	proto = tsdb::getprotobyname(pname,res);
+	return o;
+} // end set_protocol
+
+inline
+protocol_t appladdress::get_protocol() const { return proto; }
+
+inline
+string appladdress::get_protocol_name(bool *res) const {
+	return tsdb::getprotobynumber(proto,res);
+} // end get_protocol_name
+
+inline
+size_t appladdress::get_hash() const {
+	uint32 tmp = (proto<<16)+port;
+	return (hostaddress::get_hash() ^ tmp);
+} // end get_hash
+
+inline
+void
+appladdress::get_sockaddr(struct sockaddr_in6& sa) const
+{
+  if (!ipv4flag)
+  {
+    sa.sin6_family= PF_INET6;
+    sa.sin6_port  = htons(port);
+    sa.sin6_addr  = ipv6addr;
+  }
+}
+
+/// Network Prefix (or net address)
+/** Holds an IP address and a prefix length in bits. */
+class netaddress : public hostaddress {
+/***** inherited from IE ****/
+public:
+	virtual netaddress* new_instance() const;
+	virtual netaddress* copy() const;
+	virtual bool operator==(const address& ie) const;
+
+	/// convert to iPv6
+	virtual void convert_to_ipv6();
+	/// hash function
+	virtual size_t get_hash() const;
+	virtual int match_against(const netaddress& na) const;
+protected:
+	/// set subtype and IPv4 flag
+	virtual void set_subtype(bool ipv4);
+/***** new members *****/
+public:
+	/// constructor
+	netaddress();
+	/// copy constructor
+	netaddress(const netaddress& na);
+	/// constructor from hostaddress and prefix length
+	netaddress(const hostaddress& h, prefix_length_t len = 128);
+	/// constructor from string
+	netaddress(const char* str, bool *res = NULL);
+	/// constructor from string and prefix length
+	netaddress(const char* str, prefix_length_t len, bool *res = NULL);
+	/// assignment
+	netaddress& operator=(const netaddress& na);
+	/// assignment
+	netaddress& operator=(const hostaddress& ha);
+
+	// set prefix length
+	prefix_length_t set_pref_len(prefix_length_t len);
+	// get prefix length
+	prefix_length_t get_pref_len() const;
+	/// comparison for prefixmap
+	bool operator<(const netaddress& na) const;
+
+	int rdx_cmp(const netaddress *na, int *pos) const;
+private:
+	prefix_length_t prefix_length;
+}; // end netaddress
+
+inline ostream &operator<<(ostream &out, const netaddress &addr) {
+     return out << addr.get_ip_str() << "/" << (int)addr.get_pref_len();
+}
+
+/// Unix Domain Socket Address
+/** This class can hold a Unix Domain Socket Address OR a Socket Number. */
+class udsaddress : public address {
+
+  public:
+    virtual udsaddress* new_instance() const;
+    virtual udsaddress* copy() const;
+    virtual bool operator==(const address& ie) const;
+
+    /// constructor
+    udsaddress() : address(UDSAddress) { uds_socket = ""; socknum=0;};
+    /// copy constructor
+    udsaddress(const udsaddress& h) : address(UDSAddress) { uds_socket = string(h.uds_socket.c_str()); socknum = h.socknum; };
+    /// assignment
+    udsaddress& operator=(const udsaddress& uds) {
+	uds_socket = string(uds.uds_socket);
+	socknum = uds.socknum;
+	return *this;
+    };
+    /// constructor from string
+    udsaddress(string sockstring): address(UDSAddress) { uds_socket = string(sockstring.c_str()); socknum=0; };
+    /// constructor from int
+    udsaddress(int num): address(UDSAddress) { socknum = num; uds_socket=""; };
+    /// constructor from both
+    udsaddress(string sockstring, int num): address(UDSAddress) { socknum = num; uds_socket=string(sockstring.c_str()); };
+    /// destructor
+    virtual ~udsaddress() {};
+
+    /// hash function
+    virtual size_t get_hash() const;
+
+private:
+    /// uds socket string
+    string uds_socket;
+    /// socket number
+    int socknum;
+
+public:
+
+/** Set UDS socket path. */
+inline
+void set_udssocket(string socket) {
+    uds_socket = socket;
+} // end set_uds socket path
+
+
+/** Get UDS socket path. */
+inline
+const string get_udssocket() const {
+    return uds_socket;
+} // end get_udspath
+
+
+/** Set Socket Number */
+inline
+void set_socknum(int socket) {
+    socknum = socket;
+} // end set_socknum
+
+/** Get Socket Number */
+inline
+const int get_socknum() const {
+    return socknum;
+} // end get_socknum
+
+
+
+}; // end udsaddress
+
+template <typename _dT>
+class RadixTrie {
+public:
+	typedef _dT	data_type;
+
+	struct node {
+		node(netaddress *k, data_type *d) : key(k), data(d) {
+			left = right = this;
+			index = 0;
+		}
+		~node() {
+			if (data)
+				delete data;
+			if (key)
+				delete key;
+			if (left != 0 && left->index > index)
+				delete left;
+			if (right != 0 && right->index > index)
+				delete right;
+		}
+		node			*left;
+		node			*right;
+		netaddress		*key;
+		data_type		*data;
+		int			 index;
+	};
+
+	RadixTrie() {
+		netaddress *def;
+		def = new netaddress("0.0.0.0", (prefix_length_t)0);
+		v4head = new node(def, 0);
+		def = new netaddress("::", (prefix_length_t)0);
+		v6head = new node(def, 0);
+	}
+
+	~RadixTrie() {
+		delete v4head;
+		delete v6head;
+	}
+
+	node *insert(netaddress &key, data_type &dat) {
+		node *a, *b, *c, *n, *m;
+		int cmp, pos = 0;
+
+		c = a = key.is_ipv4() ? v4head : v6head;
+
+		// search the tree as long as there are bits left in key
+		while (key.get_pref_len() > a->index) {
+
+			// compare key to key in node a from position a->index
+			pos = a->index - 1;
+			cmp = key.rdx_cmp(a->key, &pos);
+			if (pos < 0)
+				abort();
+
+			// in case of a perfect match
+			if ((cmp == 0) &&
+			    (a->key->get_pref_len() == key.get_pref_len())) {
+			    // replace data in node
+				if (a->data)
+					delete a->data;
+				a->data = &dat;
+				return a;
+			}
+
+			if (cmp == 0)
+				break;
+
+			// select node to continue the search based on the
+			// first different bit between a and key
+			b = cmp < 0 ? a->left : a->right;
+
+			// we reached a dead end
+			if (b->index <= a->index)
+				break;
+
+			// the first difference was before a's bitmask ended
+			// we must not make any more progress
+			if (pos <= a->key->get_pref_len())
+				break;
+
+			c = a;
+			a = b;
+		}
+
+		// first check if a and key share a common prefix
+		if ((key.get_pref_len() == a->key->get_pref_len()) ||
+		   (pos > a->index && pos <= a->key->get_pref_len())) {
+		   	int opos = pos;
+
+		   	// make sure we didn't just miss the perfect match
+			pos = a->index;
+			cmp = key.rdx_cmp(a->key, &pos);
+			if (cmp == 0 &&
+			    (a->key->get_pref_len() == key.get_pref_len())) {
+			    // replace data in node
+				if (a->data)
+					delete a->data;
+				a->data = &dat;
+				return a;
+			}
+
+		   	// create a node with that prefix
+		   	pos = opos;
+			n = new node(new netaddress(key), 0);
+			n->key->set_pref_len(pos - 1);
+
+			// hook it to the previous node(c)
+			pos = c->index;
+			cmp = n->key->rdx_cmp(c->key, &pos);
+			n->index = pos;
+			if (n->index <= c->index) {
+				cout << "DEAD NODE INSERTION!!!" << endl;
+				abort();
+			}
+			if (cmp < 0) {
+				if (c->left != a) {
+					cout << "TREE CORRUPTION!!!" << endl;
+					abort();
+				}
+				c->left = n;
+			} else {
+				if (c->right != a) {
+					cout << "TREE CORRUPTION!!!" << endl;
+					abort();
+				}
+				c->right = n;
+			}
+
+			// hook the current node(a) to the common prefix
+			// node(n)
+			pos = n->index;
+			cmp = a->key->rdx_cmp(n->key, &pos);
+			a->index = pos;
+			if (a->index <= n->index) {
+				cout << "DEAD NODE INSERTION!!!" << endl;
+				abort();
+			}
+			if (cmp < 0)
+				n->left = a;
+			else
+				n->right = a;
+
+			// create a new node(m) for the insert
+			m = new node(new netaddress(key), &dat);
+			// hook node(m) to the common prefix node(n)
+			pos = n->index;
+			cmp = m->key->rdx_cmp(n->key, &pos);
+			m->index = pos;
+			if (cmp < 0) {
+				if (n->left == a) {
+					cout << "OVERWRITE!!!" << endl;
+					abort();
+				}
+				n->left = m;
+			} else {
+				if (n->right == a) {
+					cout << "OVERWRITE!!!" << endl;
+					abort();
+				}
+				n->right = m;
+			}
+
+			return m;
+		}
+
+		// c is a prefix of key, key is a prefix of a
+		if (a->index >= pos) {
+			// create a new node for the key
+			n = new node(new netaddress(key), &dat);
+			// hook it to the previous node(c)
+			n->index = pos;
+			if (n->index <= c->index) {
+				cout << "DEAD NODE INSERTION!!!" << endl;
+				abort();
+			}
+			if (cmp < 0) {
+				if (c->left != a) {
+					cout << "TREE CORRUPTION!!!" << endl;
+					abort();
+				}
+				c->left = n;
+			} else {
+				if (c->right != a) {
+					cout << "TREE CORRUPTION!!!" << endl;
+					abort();
+				}
+				c->right = n;
+			}
+
+			// hook the current node(a) to the newly created
+			// node(n)
+			pos = n->index;
+			cmp = a->key->rdx_cmp(n->key, &pos);
+			a->index = pos;
+			if (a->index <= c->index) {
+				cout << "DEAD NODE INSERTION!!!" << endl;
+				abort();
+			}
+			if (cmp < 0)
+				n->left = a;
+			else
+				n->right = a;
+
+			return n;
+		}
+
+		// reached a deadend, simply add a new node
+		n = new node(new netaddress(key), &dat);
+		n->index = pos;
+		if (n->index <= a->index) {
+			cout << "DEAD NODE INSERTION!!!" << endl;
+			abort();
+		}
+		if (b->index <= a->index) {
+			if (cmp < 0)
+				a->left = n;
+			else
+				a->right = n;
+		} else {
+			cout << "TREE CORRUPTION!!!" << endl;
+			abort();
+		}
+
+		return n;
+	}
+
+	node *lookup_node(netaddress &key, bool lpfm = true,
+	    bool with_data = true) {
+		node *a, *b, *c, *lpfn;
+		int cmp, pos = 0;
+
+		lpfn = 0;
+		c = b = a = key.is_ipv4() ? v4head : v6head;
+		if (lpfm) {
+			if (!with_data)
+				lpfn = a;
+			else if (a->data)
+				lpfn = a;
+		}
+
+		// search the tree as long as there are bits left in key
+		while (key.get_pref_len() > a->index) {
+
+			// compare key to key in node a from pos
+			pos--;
+			cmp = key.rdx_cmp(a->key, &pos);
+
+			// all of key consumed
+			if (cmp == 0) {
+				// key is less specific than a
+				if (key.get_pref_len() <
+				    a->key->get_pref_len())
+					return lpfm ? lpfn : NULL;
+
+				// key is an exact match for a
+				if (key.get_pref_len() >=
+				    a->key->get_pref_len()) {
+					if (!with_data)
+						return a;
+					if (a->data)
+						return a;
+					return lpfm ? lpfn : NULL;
+				}
+			}
+
+			// all of a consumed -> a is a prefix of key
+			if (pos > a->key->get_pref_len()) {
+				if (!with_data)
+					lpfn = a;
+				else if (a->data)
+					lpfn = a;
+			}
+
+			// select node to continue the search based on the
+			// first different bit between a and key
+			b = cmp < 0 ? a->left : a->right;
+
+			// we reached a dead end
+			if (b->index <= a->index)
+				break;
+
+			c = a;
+			a = b;
+		}
+
+		return lpfm ? lpfn : NULL;
+	}
+
+	data_type *lookup(netaddress &key, bool lpfm = true) {
+		node *n = lookup_node(key, lpfm);
+
+		return n ? n->data : NULL;
+	}
+
+	bool remove(netaddress &key) {
+		node *n = lookup_node(key);
+
+		if (n && n->data) {
+			delete n->data;
+			n->data = NULL;
+		}
+
+		return (n != 0);
+	}
+
+	bool remove_all(netaddress &key) {
+		node *n = lookup_node(key, false, false);
+
+		if (n == 0)
+			return false;
+
+		if (n->data) {
+			delete n->data;
+			n->data = NULL;
+		}
+
+		if (n->left->index > n->index) {
+			delete n->left;
+			n->left = n;
+		}
+		if (n->right->index > n->index) {
+			delete n->right;
+			n->right = n;
+		}
+
+		return true;
+	}
+
+	void print() {
+		cout << "v4_TREE: " << endl;
+		print_node(v4head);
+		cout << "v6_TREE: " << endl;
+		print_node(v6head);
+	}
+
+	void print_node(node *x, bool decent = true) {
+		if (x && x->key) {
+			cout << "node: " << x << " key: " <<  *x->key;
+			if (x->data != 0)
+				cout << " data: " << x->data;
+			else
+				cout << " data: NULL";
+			cout << " index: " << x->index << endl;
+			cout << "\tleft: " << x->left << " right: " << x->right << endl;
+			if (decent) {
+				if (x->left->index > x->index)
+					print_node(x->left);
+				if (x->right->index > x->index)
+					print_node(x->right);
+			}
+		}
+	}
+
+private:
+	struct node *v4head;
+	struct node *v6head;
+};
+
+
+/*
+ * AddressList
+ */
+
+class AddressList {
+public:
+	class AddrProperty {
+		public:
+			AddrProperty(const char *name) {
+				pname = new string(name);
+			}
+			~AddrProperty() {
+				delete pname;
+			};
+
+			string *pname;
+	};
+
+	// Default properties, N.B. Ignore will remove all other properties
+	static AddrProperty *LocalAddr_P;
+	static AddrProperty *ConfiguredAddr_P;
+
+private:
+	// This is special
+	static AddrProperty *IgnoreAddr_P;
+	static AddrProperty *AnyAddr_P;
+
+public:
+	struct ltstr {
+		bool operator()(const char* s1, const char* s2) const
+		{ return strcmp(s1, s2) < 0; }
+	};
+	struct ltna {
+		bool operator()(const netaddress &s1, const netaddress &s2)
+		    const {
+		    	if (s1.is_ipv4() != s2.is_ipv4())
+		    		return (s1.is_ipv4());
+			int cmp, pos = 0;
+			cmp = s1.rdx_cmp(&s2, &pos);
+			return (cmp < 0);
+		}
+
+	};
+	typedef set<char *, ltstr>	iflist_t;
+	typedef set<netaddress, ltna>	addrlist_t;
+
+	AddressList();
+	~AddressList();
+
+	// Configure by interfaces
+	// Return a list of all local interfaces, which are monitored
+	iflist_t *get_interfaces();
+	// Begin interface list (otherwise the following have no effect)
+	// If start_empty is true use an empty list, otherwise add all
+	// currently configured interfaces
+	bool by_interface(bool start_empty = true);
+	// Add interface to monitoring
+	bool add_interface(char *name);
+	// Remove interface from monitoring
+	bool del_interface(char *name);
+
+	// Manage properties
+	// If 'all' is true operate on all matching addresses as well
+	bool add_property(netaddress &na, AddrProperty *p = ConfiguredAddr_P,
+	    bool propagate = true);
+	bool del_property(netaddress &na, AddrProperty *p = ConfiguredAddr_P,
+	    bool propagate = true);
+	inline bool purge_properties(netaddress &na, bool prop = true) {
+		return del_property(na, AnyAddr_P, prop);
+	};
+	bool add_host_prop(const char *name, AddrProperty *p = ConfiguredAddr_P);
+	bool del_host_prop(const char *name, AddrProperty *p = ConfiguredAddr_P);
+	inline bool purge_host_prop(const char *name) {
+		return del_host_prop(name, AnyAddr_P);
+	}
+
+	// Special property
+	bool ignore(netaddress &na, bool propagate = true);
+	bool unignore(netaddress &na, bool propagate = true);
+	bool ignore_bogons(void);
+	bool ignore_locals(void);
+	bool ignore_loopback(void);
+
+	// Check if the given address has the given property
+	bool addr_is(netaddress &na, AddrProperty *prop);
+	bool addr_is(const hostaddress &ha, AddrProperty *prop) {
+		netaddress na(ha);
+		return addr_is(na, prop);
+	}
+	// Check if the given address is in a network with the given property
+	bool addr_is_in(netaddress &na, AddrProperty *prop);
+	bool addr_is_in(const hostaddress &ha, AddrProperty *prop) {
+		netaddress na(ha);
+		return addr_is_in(na, prop);
+	}
+
+	addrlist_t *get_addrs(AddrProperty *prop = LocalAddr_P);
+	netaddress *get_first(AddrProperty *p = LocalAddr_P, bool IPv4 = true);
+
+	netaddress *get_src_addr(const netaddress &dest, uint32_t *prefs);
+private:
+	typedef map<AddrProperty *, bool>	propmap_t;
+	typedef RadixTrie<propmap_t>		addr2prop_t;
+
+	iflist_t *interfaces;
+	addr2prop_t prop_trie;
+
+	// Backends for public functions
+	void getifaddrs_iflist(iflist_t &list);
+	bool getifaddrs_is_local(netaddress &na);
+	void getifaddrs_get_addrs(addrlist_t &list);
+
+	void bequeath(addr2prop_t::node *head, AddrProperty *p,
+	    bool add = true);
+	void collect(addr2prop_t::node *head, AddrProperty *p,
+	    addrlist_t &list);
+	addr2prop_t::node *collect_first(addr2prop_t::node *head,
+	    AddrProperty *p);
+};
+
+inline ostream &operator<<(ostream &out, const AddressList::AddrProperty &prop) {
+	return out << *prop.pname;
+}
+
+
+/************************************* inline methods ***********************************/
+
+inline
+size_t
+hostaddress::get_hash() const
+{
+	return (ipv6addr.s6_addr32[0] ^ ipv6addr.s6_addr32[1] ^ ipv6addr.s6_addr32[2] ^ ipv6addr.s6_addr32[3]);
+} // end get_hash
+
+/***** new in hostaddress *****/
+
+
+/** Initialize a hostaddress object.
+ * This calls virtual member set_subtype and therefore sets subtype in all
+ * derived class which overwrite this member function correctly.
+ */
+inline
+hostaddress::hostaddress()
+	: address(IPv6HostAddress),
+	  ipv4flag(false),
+	  outstring(NULL)
+{
+  clear_ip();
+  set_subtype(false);
+} // end constructor hostaddress
+
+
+/** Assign h to this object. */
+inline
+hostaddress&
+hostaddress::operator=(const hostaddress& h) {
+	address::operator=(h);
+	this->set_ip(h);
+	if (outstring)
+	  delete outstring;
+        outstring= 0;
+	return *this;
+} // end operator=
+
+/** Copy constructor for hostaddress objects */
+inline
+hostaddress::hostaddress(const hostaddress& h) :
+  address(h),
+  outstring(NULL)
+{
+  this->set_ip(h);
+
+  //Log(DEBUG_LOG,LOG_NORMAL,"hostaddress","hostaddress constructor called for const hostaddress& h:"); // << h << " outstring:" << static_cast<void*>(outstring) << " h.outstring:" << static_cast<void*>(h.outstring));
+
+} // end copy constructor hostaddress
+
+/** Check if this is an IPv4 address. */
+inline
+bool
+hostaddress::is_ipv4() const {
+	return ipv4flag;
+} // end is_ipv4
+
+/** Check if this is an IPv6 address. */
+inline
+bool
+hostaddress::is_ipv6() const {
+	return (!ipv4flag);
+} // end is_ipv6
+
+/** Check if this is a 6to4 mapped address. */
+inline
+bool
+hostaddress::is_mapped_ip() const
+{
+  return (ipv4flag) ? false : IN6_IS_ADDR_V4MAPPED(ipv6addr.s6_addr);
+} // end is_mapped_ip
+
+inline
+bool
+hostaddress::set_ip(const string& str) { return set_ip(str.c_str()); }
+
+inline
+/** Delete outstring if it exists. */
+hostaddress::~hostaddress() {
+	if (outstring)
+	{
+	  delete[] outstring;
+	  outstring= 0;
+	}
+} // end destructor hostaddress
+
+/** Set IPv4 or IPv6 from string or leave object unchanged.
+ * This changes object type.
+ * @return true on success.
+ */
+inline
+bool
+hostaddress::set_ip(const char *str)
+{
+  return (!str) ? false :
+                 ( strchr(str,':') ? set_ipv6(str) : set_ipv4(str)); 	// which IP version?
+
+} // end set_ipv
+
+
+/** Lookup the host name associated with the current IP address. */
+inline
+string hostaddress::get_host_name(bool *res) const
+{
+  return  ipv4flag ? tsdb::get_hostname(ipv4addr,res) : tsdb::get_hostname(ipv6addr,res);
+} // end get_host_name
+
+/***** inherited from hostaddress *****/
+
+/** Set subtype and IPv4 flag. This does NOT clear the outstring buffer.
+ * Use clear_ip().
+ */
+inline
+void
+appladdress::set_subtype(bool ipv4)
+{
+	ipv4flag = ipv4;
+	subtype = (ipv4) ?  IPv4ApplAddress : IPv6ApplAddress;
+} // end set_subtype
+
+inline
+prefix_length_t netaddress::get_pref_len() const { return prefix_length; }
+
+inline
+size_t netaddress::get_hash() const {
+	return (hostaddress::get_hash() ^ prefix_length);
+} // end get_hash
+
+inline
+int
+netaddress::match_against(const netaddress& na) const
+{
+	// compare prefix lengths
+  return (prefix_length<na.prefix_length) ? -1 : hostaddress::match_against(na);
+} // end match_against
+
+
+inline
+ostream &operator<<(ostream &out, const appladdress &addr) {
+     if (addr.is_mapped_ip()) return out << "[IPv4-mapped address]: "  << addr.get_ip_str() << ":" << (int)addr.get_port() << ", " << addr.get_protocol_name();
+    return out << "[IP address]: " << addr.get_ip_str() << ":" << (int)addr.get_port() << ", " << addr.get_protocol_name();
+}
+
+inline
+ostream &operator<<(ostream &out, const udsaddress &addr) {
+    if (addr.get_socknum()) return out << "[Socketnumber]: " << addr.get_socknum();
+    return out << "[Unix Domain Socket]: " << addr.get_udssocket();
+}
+
+
+
+
+
+
+inline
+size_t udsaddress::get_hash() const {
+    size_t tmp2 = 1;
+	for (unsigned int i = 0; i<uds_socket.size(); i++) {
+	    tmp2 = tmp2 * (int) uds_socket[i];
+	}
+	return (tmp2 ^ socknum);
+} // end get_hash
+
+
+
+} // end namespace protlib
+
+/*********************************** hash functions ***********************************/
+
+namespace __gnu_cxx {
+/// hostaddress hasher
+template <> struct hash<protlib::hostaddress> {
+	inline size_t operator()(const protlib::hostaddress& addr) const { return addr.get_hash(); }
+}; // end hostaddress hasher
+
+/// appladdress hasher
+template <> struct hash<protlib::appladdress> {
+	inline size_t operator()(const protlib::appladdress& addr) const { return addr.get_hash(); }
+}; // end appladdress hasher
+
+/// udsaddress hasher
+template <> struct hash<protlib::udsaddress> {
+	inline size_t operator()(const protlib::udsaddress& addr) const { return addr.get_hash(); }
+}; // end udsaddress hasher
+
+
+
+
+/// netaddress hasher
+template <> struct hash<protlib::netaddress> {
+	inline size_t operator() (const protlib::netaddress& addr) const { return addr.get_hash(); }
+}; // end netaddress hasher
+
+} // end namespace __gnu_cxx
+
+
+namespace std {
+
+/// hostaddress equal_to
+template <> struct equal_to<protlib::hostaddress> {
+	inline bool operator()(const protlib::hostaddress& addr1, const protlib::hostaddress& addr2) const { return addr1.equiv(addr2); }
+}; // end hostaddress equal_to
+
+/// appladdress equal_to
+template <> struct equal_to<protlib::appladdress> {
+	inline bool operator()(const protlib::appladdress& addr1, const protlib::appladdress& addr2) const { return addr1.equiv(addr2); }
+}; // end appladdress equal_to
+
+/// netaddress equal_to
+template <> struct equal_to<protlib::netaddress> {
+	inline bool operator()(const protlib::netaddress& addr1, const protlib::netaddress& addr2) const { return addr1.equiv(addr2); }
+
+}; // end netaddress equal_to
+
+} // end namespace std
+#endif // PROTLIB__ADDRESS_H
Index: /source/ariba/utility/transport/tcpip/protlib/assocdata.h
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/assocdata.h	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/assocdata.h	(revision 5284)
@@ -0,0 +1,104 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file assocdata.h
+/// association data for signaling transport connnections
+/// -- AssocData structure to store data of a signaling associaton
+/// -- i.e., a socket-based signaling transport connection
+/// ----------------------------------------------------------
+/// $Id: assocdata.h 2872 2008-02-18 10:58:03Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/assocdata.h $
+// ===========================================================
+//
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+#ifndef ASSOC_DATA_H
+#define ASSOC_DATA_H
+
+#include "address.h"
+
+namespace protlib {
+
+/**
+  * @ingroup transport
+  * @{
+  */
+
+typedef int socketfd_t; ///< socket type interface
+typedef unsigned int associd_t; /// SCTP lib interface
+
+/// association data, used to keep all necessary information
+/// (socket, peer address, shutdown, touched) about a single connection
+struct AssocData {
+  AssocData(socketfd_t socketfd,
+	    const appladdress& peeraddress,
+	    const appladdress& ownaddress):
+    socketfd(socketfd),
+    assoc(0),
+    peer(peeraddress),
+    ownaddr(ownaddress),
+    thread_ID(0),
+    num_of_out_streams(0),
+    shutdown(false),
+    touched(true)
+  {};
+
+  AssocData(associd_t ass, const appladdress& ap, const appladdress& oa, uint32 streams)
+    : socketfd(0),
+      assoc(ass),
+      peer(ap),
+      ownaddr(oa),
+      thread_ID(0),
+      num_of_out_streams(streams),
+      shutdown(false),
+      touched(true)
+  {};
+
+  AssocData(associd_t ass, const char* apstr, protocol_t proto, port_t port, uint32 streams, bool& res)
+    : socketfd(0),
+      assoc(ass),
+      peer(apstr,proto,port,&res),
+      thread_ID(0),
+      num_of_out_streams(streams),
+      shutdown(false),
+      touched(true)
+  {};
+
+
+  const socketfd_t socketfd; ///< socket of signaling transport connection
+  const associd_t assoc; ///< required for SCTP
+
+  const appladdress peer; ///< address of the signaling peer
+  const appladdress ownaddr; ///< own endpoint address of the signaling connection
+
+  pthread_t thread_ID; ///< related receiver thread
+
+  const uint32 num_of_out_streams; ///< required for SCTP
+
+  // shutdown: connection is being shutdown, shutdown
+  // is not complete yet
+  bool shutdown;
+  // this is required for a second changce algorithm when cleaning up unused connections
+  bool touched;
+}; // end AssocData
+
+//@}
+
+} // end namespace protlib
+#endif
Index: /source/ariba/utility/transport/tcpip/protlib/assocdata_uds.h
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/assocdata_uds.h	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/assocdata_uds.h	(revision 5284)
@@ -0,0 +1,95 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file assocdata_uds.h
+/// association data for Unix Domain transport connnections
+/// -- AssocData structure to store data of a signaling associaton
+/// -- i.e., a socket-based signaling transport connection
+//
+/// ----------------------------------------------------------
+/// $Id: assocdata_uds.h 2872 2008-02-18 10:58:03Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/assocdata_uds.h $
+// ===========================================================
+//
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+
+#ifndef ASSOC_DATA_UDS_H
+#define ASSOC_DATA_UDS_H
+
+#include "address.h"
+
+
+namespace protlib {
+
+/** @ingroup transport
+  * @{
+  */
+
+typedef int socketfd_t; ///< socket type interface
+typedef unsigned int associd_t; /// SCTP lib interface
+
+/// association data, used to keep all necessary information
+/// (socket, peer address, shutdown, touched) about a single connection
+struct AssocDataUDS {
+  AssocDataUDS(socketfd_t socketfd,
+	    const udsaddress& peeraddress,
+	    const udsaddress& ownaddress):
+    socketfd(socketfd),
+    assoc(0),
+    peer(peeraddress),
+    ownaddr(ownaddress),
+    thread_ID(0),
+    num_of_out_streams(0),
+    shutdown(false),
+    touched(true)
+  {};
+
+  AssocDataUDS(associd_t ass, const udsaddress& ap, const udsaddress& oa, uint32 streams)
+    : socketfd(0),
+      assoc(ass),
+      peer(ap),
+      ownaddr(oa),
+      thread_ID(0),
+      num_of_out_streams(streams),
+      shutdown(false),
+      touched(true)
+  {};
+
+  const socketfd_t socketfd; ///< socket of signaling transport connection
+  const associd_t assoc; ///< required for SCTP
+
+  const udsaddress peer; ///< address of the signaling peer
+  const udsaddress ownaddr; ///< own endpoint address of the signaling connection
+
+  pthread_t thread_ID; ///< related receiver thread
+
+  const uint32 num_of_out_streams; ///< required for SCTP
+
+  // shutdown: connection is being shutdown, shutdown
+  // is not complete yet
+  bool shutdown;
+  // this is required for a second changce algorithm when cleaning up unused connections
+  bool touched;
+}; // end AssocDataUDS
+
+//@}
+
+} // end namespace protlib
+#endif
Index: /source/ariba/utility/transport/tcpip/protlib/cleanuphandler.h
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/cleanuphandler.h	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/cleanuphandler.h	(revision 5284)
@@ -0,0 +1,109 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file cleanuphandler.h
+/// preprocessor macros to install cleanup handlers for threads
+/// ----------------------------------------------------------
+/// $Id: cleanuphandler.h 2549 2007-04-02 22:17:37Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/cleanuphandler.h $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+
+/** @ingroup thread
+ *
+ * This header file defines a preprocessor macro to 
+ * install cleanup handlers.
+ *
+ * This cannot be done without macros because the pthread library also uses
+ * macros for cleanup.
+ * References to a common base class of all lockable classes also are not
+ * useful because they are casted to void* and cannot be casted back
+ * correctly after that in all cases, especially when pointers are 
+ * changed while casting. This happens when casting around in a type 
+ * hierarchy.
+ */
+
+#ifndef CLEANUP_HANDLER_H
+#define CLEANUP_HANDLER_H
+
+#include <pthread.h>
+
+namespace protlib { 
+
+/** @addtogroup thread Threads
+ * @{
+ */
+
+/// install cleanup handler
+/** This macro installs a cleanup handler
+ * and does some type casting.
+ * Use uninstall_cleanup(execute) or an apropriate unlock routine to unlock
+ * the mutex and uninstall the handler.
+ * @param f pointer to a cleanup handler routine. 
+ * This is casted to void (*routine)(void *)
+ * @param m cleanup handler argument, normally a pointer to the mutex.
+ * This is casted to void*.
+ */
+#define install_cleanup(f,m) pthread_cleanup_push((void (*)(void *)) f, (void *) m)
+
+/// install cleanup handler for mutex
+/** Calls install_cleanup and uses pthread_mutex_unlock as cleanup handler.
+ * @param m pointer to the mutex.
+ */
+#define install_cleanup_mutex(m) install_cleanup(pthread_mutex_unlock,m)
+
+/// lock mutex and install cleanup handler
+/** @param m mutex
+ */
+#define install_cleanup_mutex_lock(m) install_cleanup_mutex(m) pthread_mutex_lock(m)
+
+/// Lock thread and install cleanup handler
+/** @param ttype class name of thread object
+ * @param tp pointer to thread object
+ */
+#define install_cleanup_thread_lock(ttype,tp) install_cleanup(call_unlock<ttype>,tp) tp->lock()
+
+/// uninstall cleanup handler
+/** This uninstalls a cleanup handler and optionally executes it.
+ * @param exec 0 or 1
+ */
+#define uninstall_cleanup(exec) pthread_cleanup_pop(exec)
+
+/// unlock template
+/** This function calls the unlock method of an object.
+ * @param pobj pointer to the locked object.
+ */
+template <class T> void call_unlock(void* pobj) { 
+	T* t;
+	t = static_cast<T*>(pobj);
+	t->unlock();
+} // end call_unlock<T>
+
+/// call void function
+/** This function calls a function of type void f(void). */
+inline void call_void_fun(void (*f)()) { 
+	f();
+} // end call_void_fun
+
+//@}
+
+} // end namespace protlib
+#endif
Index: /source/ariba/utility/transport/tcpip/protlib/configuration.cpp
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/configuration.cpp	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/configuration.cpp	(revision 5284)
@@ -0,0 +1,604 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file configuration.cpp
+/// A configuration file parser
+/// ----------------------------------------------------------
+/// $Id: configuration.cpp 2549 2007-04-02 22:17:37Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/src/configuration.cpp $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+#include <iostream>
+#include <sstream>
+
+#include "configuration.h"
+
+
+using namespace natfw;
+
+
+// only used internally
+class parse_error : public std::exception {
+  public:
+        parse_error(const std::string &msg) throw () : msg(msg) { }
+	virtual ~parse_error() throw () { }
+
+        std::string get_msg() const throw () { return msg; }
+
+  private:
+        std::string msg;
+};
+
+
+/**
+ * Constructor.
+ */
+configuration::configuration(config_entry rules[]) {
+	for (unsigned i=0; rules[i].type != config_entry::T_END; i++)
+		values[ rules[i].key ] = rules[i];
+}
+
+
+/**
+ * Load a configuration file.
+ *
+ * If there's a parse error or the file can't be opened, a config_error
+ * exception is thrown.
+ *
+ * @param filename the file to load
+ */
+void configuration::load(const std::string &filename) throw (config_error) {
+
+	std::ifstream in(filename.c_str());
+
+	if ( ! in )
+		throw config_error("cannot open file `" + filename + "'");
+
+	try {
+		this->load(in);
+	}
+	catch ( config_error &e ) {
+		in.close();
+		throw;
+	}
+	catch ( ... ) {
+		in.close();
+		throw config_error("unknown exception thrown");
+	}
+
+	in.close();
+}
+
+
+/**
+ * Load configuration data from a stream.
+ *
+ * If there is a parse error, a config_error exception is thrown. This method
+ * will read until end of file. It is up to the caller to close the stream.
+ *
+ * @param in_stream the input stream to read data from
+ */
+void configuration::load(std::istream &in_stream) throw (config_error) {
+	using namespace std;
+
+	for (int line = 1; in_stream; line++) {
+		string buf;
+		string key;
+
+		getline(in_stream, buf);
+
+		stringstream in(buf);
+
+		// skip leading whitespace
+		strip_leading_space(in);
+
+		// skip empty lines and comments
+		if ( in.peek() == -1 || in.peek() == '#' )
+			continue;
+
+		// read the key
+		in >> key;
+		if ( key == "")
+			throw config_error("parse error", line);
+
+		if ( values.find(key) == values.end() )
+			throw config_error("invalid key `" + key + "'", line);
+
+		// skip space between key and '='
+		strip_leading_space(in);
+
+		char c = in.get();
+		if ( c != '=' )
+			throw config_error("parse error", line);
+
+		// skip space between '=' and value
+		strip_leading_space(in);
+
+		// no value for this key, we ignore it altogether
+		if ( in.peek() == -1 )
+			continue;
+
+		try {
+			parse_and_assign(key, in);
+		}
+		catch ( parse_error &e ) {
+			throw config_error(e.get_msg(), line);
+		}
+	}
+
+	if ( ! in_stream.eof() )
+		throw config_error("stream error");
+
+	// check if all required config settings are set.
+	for ( c_iter i = values.begin(); i != values.end(); i++ ) {
+		const config_entry &e = i->second;
+
+		if ( e.required && ! e.defined )
+			throw config_error(
+				"key `" + e.key + "' required but not set");
+	}
+}
+
+
+/**
+ * Write the configuration data to a stream.
+ *
+ * If there is a write error, a config_error exception is thrown. This method
+ * doesn't close the stream after writing. It is up to the caller to do that.
+ *
+ * @param out the output stream to read data from
+ */
+void configuration::dump(std::ostream &out) throw (config_error) {
+	using namespace std;
+
+	out << "# Configuration dump" << endl;
+
+	for ( c_iter i = values.begin(); i != values.end(); i++ ) {
+		const config_entry &e = i->second;
+
+		out << e.key << " = ";
+
+		if ( ! e.defined ) {
+			out << endl;
+			continue;
+		}
+
+		switch ( e.type ) {
+			case config_entry::T_BOOL:
+				out << e.bool_value << endl;
+				break;
+			case config_entry::T_INT:
+				out << e.int_value << endl;
+				break;
+			case config_entry::T_FLOAT:
+				out << e.float_value << endl;
+				break;
+			case config_entry::T_STR:
+				write_string(out, e.str_value);
+				out << endl;
+				break;
+			case config_entry::T_IPv4:
+				out << e.ipv4_value << endl;
+				break;
+			case config_entry::T_IPv6:
+				out << e.ipv6_value << endl;
+				break;
+			case config_entry::T_IPv4_LIST: // fall-through
+			case config_entry::T_IPv6_LIST:
+				dump_address_list(out, e.address_list);
+				out << endl;
+				break;
+			default:
+				assert( false );
+		}
+	}
+}
+
+
+void configuration::dump_address_list(std::ostream &out,
+		const std::list<hostaddress> &addresses) const {
+
+	typedef std::list<hostaddress>::const_iterator addr_iter;
+
+	for ( addr_iter i = addresses.begin(); i != addresses.end(); i++ )
+		out << *i << " ";
+}
+
+
+/**
+ * Test if the configuration contains the given value.
+ *
+ * @param key the name of the key
+ * @return true, if the configuraiton has that key
+ */
+bool configuration::is_defined(const std::string &key) const throw () {
+	c_iter i = values.find(key);
+
+	if ( values.find(key) == values.end() )
+		return false;
+	else
+		return i->second.defined;
+}
+
+
+/**
+ * Get a string configuration value.
+ *
+ * @param key the name of the key
+ * @return the value from the configuration
+ */
+std::string configuration::get_string(const std::string &key) const throw () {
+	c_iter i = values.find(key);
+	assert( i != values.end() );
+	assert( i->second.type == config_entry::T_STR );
+
+	return i->second.str_value;
+}
+
+
+/**
+ * Get a boolean configuration value.
+ *
+ * @param key the name of the key
+ * @return the value from the configuration
+ */
+bool configuration::get_bool(const std::string &key) const throw () {
+	c_iter i = values.find(key);
+	assert( i != values.end() );
+	assert( i->second.type == config_entry::T_BOOL );
+
+	return i->second.bool_value;
+}
+
+
+/**
+ * Get an integer configuration value.
+ *
+ * @param key the name of the key
+ * @return the value from the configuration
+ */
+int configuration::get_int(const std::string &key) const throw () {
+	c_iter i = values.find(key);
+	assert( i != values.end() );
+	assert( i->second.type == config_entry::T_INT );
+
+	return i->second.int_value;
+}
+
+
+/**
+ * Get a floating point configuration value.
+ *
+ * @param key the name of the key
+ * @return the value from the configuration
+ */
+float configuration::get_float(const std::string &key) const throw () {
+	c_iter i = values.find(key);
+	assert( i != values.end() );
+	assert( i->second.type == config_entry::T_FLOAT );
+
+	return i->second.float_value;
+}
+
+
+/**
+ * Get an IPv4 hostaddress configuration value.
+ *
+ * @param key the name of the key
+ * @return the value from the configuration
+ */
+hostaddress configuration::get_ipv4_address(
+		const std::string &key) const throw () {
+
+	c_iter i = values.find(key);
+	assert( i != values.end() );
+	assert( i->second.type == config_entry::T_IPv4 );
+
+	return i->second.ipv4_value;
+}
+
+
+/**
+ * Get an IPv6 hostaddress configuration value.
+ *
+ * @param key the name of the key
+ * @return the value from the configuration
+ */
+hostaddress configuration::get_ipv6_address(
+		const std::string &key) const throw () {
+
+	c_iter i = values.find(key);
+	assert( i != values.end() );
+	assert( i->second.type == config_entry::T_IPv6 );
+
+	return i->second.ipv6_value;
+}
+
+
+/**
+ * Get a list of IPv4 hostaddress objects.
+ *
+ * @param key the name of the key
+ * @return the list of values from the configuration
+ */
+std::list<hostaddress> configuration::get_ipv4_address_list(
+		const std::string &key) const throw () {
+
+	c_iter i = values.find(key);
+	assert( i != values.end() );
+	assert( i->second.type == config_entry::T_IPv4_LIST );
+
+	return i->second.address_list;
+}
+
+
+/**
+ * Get a list of IPv6 hostaddress objects.
+ *
+ * @param key the name of the key
+ * @return the list of values from the configuration
+ */
+std::list<hostaddress> configuration::get_ipv6_address_list(
+		const std::string &key) const throw () {
+
+	c_iter i = values.find(key);
+	assert( i != values.end() );
+	assert( i->second.type == config_entry::T_IPv6_LIST );
+
+	return i->second.address_list;
+}
+
+
+void configuration::strip_leading_space(std::istream &in) const {
+	while ( in && ( in.peek() == ' ' || in.peek() == '\t' ) )
+		in.get();
+}
+
+
+// Parse the given buffer and assign the value to the config entry
+void configuration::parse_and_assign(const std::string &key, std::istream &in) {
+
+	switch ( values[key].type ) {
+		case config_entry::T_BOOL:
+			values[key].bool_value = parse_bool(in);
+			break;
+		case config_entry::T_INT:
+			values[key].int_value = parse_int(in);
+			break;
+		case config_entry::T_FLOAT:
+			values[key].float_value = parse_float(in);
+			break;
+		case config_entry::T_STR:
+			values[key].str_value = parse_string(in);
+			break;
+		case config_entry::T_IPv4:
+			values[key].ipv4_value = parse_ipv4_address(in);
+			break;
+		case config_entry::T_IPv6:
+			values[key].ipv6_value = parse_ipv6_address(in);
+			break;
+		case config_entry::T_IPv4_LIST:
+			values[key].address_list = parse_ipv4_address_list(in);
+			break;
+		case config_entry::T_IPv6_LIST:
+			values[key].address_list = parse_ipv6_address_list(in);
+			break;
+		default:
+			assert( false );
+			throw parse_error("invalid value"); // not reached
+	}
+
+	// no exception thrown until now, so parsing was successful
+	values[key].defined = true;
+}
+
+
+// Write the string to the stream, adding quotation marks and escape sequences
+void configuration::write_string(
+		std::ostream &out, const std::string &str) const {
+
+	std::stringstream stream(str);
+
+	out << '"';
+
+	char c;
+	while ( stream.get(c) ) {
+		switch ( c ) {
+			case '\\':	// fallthrough
+			case '"':	out << '\\' << c; break;
+			default:	out << c;
+		}
+	}
+
+	out << '"';
+}
+
+
+// Matches pattern "[^"]*"\s*
+std::string configuration::parse_string(std::istream &in) const {
+
+	if ( in.get() != '"' )
+		throw parse_error("string doesn't start with a quotation mark");
+
+	bool escape = false;
+	std::string tmp;
+	char c;
+
+	while ( in.get(c) ) {
+		if ( escape ) {
+			if ( c == '\\' || c == '"' )
+				tmp += c;
+			else
+				throw parse_error("invalid escape sequence");
+
+			escape = false;
+		}
+		else {
+			if ( c == '"' )
+				break;
+			else if ( c == '\\' )
+				escape = true;
+			else
+				tmp += c;
+		}
+	}
+
+	// we should be on the closing quotation mark
+	if ( c != '"' )
+		throw parse_error("unterminated string");
+
+	skip_rest_of_line(in);
+
+	return tmp;
+}
+
+
+hostaddress configuration::parse_ipv4_address(std::istream &in) const {
+	std::string word;
+	in >> word;
+
+	bool success;
+	hostaddress addr(word.c_str(), &success);
+
+	if ( success || ! addr.is_ipv4() )
+		return addr;
+	else
+		throw parse_error("invalid IPv4 address");
+
+	skip_rest_of_line(in);
+
+	return addr;
+}
+
+
+hostaddress configuration::parse_ipv6_address(std::istream &in) const {
+	std::string word;
+	in >> word;
+
+	bool success;
+	hostaddress addr(word.c_str(), &success);
+
+	if ( success || ! addr.is_ipv6() )
+		return addr;
+	else
+		throw parse_error("invalid IPv6 address");
+
+	skip_rest_of_line(in);
+
+	return addr;
+}
+
+std::list<hostaddress> configuration::parse_ipv4_address_list(
+		std::istream &in) const {
+
+	std::list<hostaddress> result;
+
+	std::string tmp;
+	while ( in >> tmp ) {
+		bool success;
+		hostaddress addr(tmp.c_str(), &success);
+
+		if ( success && addr.is_ipv4() )
+			result.push_back(addr);
+		else
+			throw parse_error("invalid IPv4 address `" + tmp + "'");
+	}
+
+	return result;
+}
+
+std::list<hostaddress> configuration::parse_ipv6_address_list(
+		std::istream &in) const {
+
+	std::list<hostaddress> result;
+
+	std::string tmp;
+	while ( in >> tmp ) {
+		bool success;
+		hostaddress addr(tmp.c_str(), &success);
+
+		if ( success && addr.is_ipv6() )
+			result.push_back(addr);
+		else
+			throw parse_error("invalid IPv6 address `" + tmp + "'");
+	}
+
+	return result;
+}
+
+int configuration::parse_int(std::istream &in) const {
+	int tmp = -1;
+
+	in >> tmp;
+
+	if ( ! in.good() && ! in.eof() )
+		throw parse_error("parsing integer failed");
+
+	skip_rest_of_line(in);
+
+	return tmp;
+}
+
+
+float configuration::parse_float(std::istream &in) const {
+	float tmp = 0.0;
+
+	in >> tmp;
+
+	if ( ! in.good() && ! in.eof() )
+		throw parse_error("parsing float failed");
+
+	skip_rest_of_line(in);
+
+	return tmp;
+}
+
+
+bool configuration::parse_bool(std::istream &in) const {
+	std::string tmp;
+	bool value;
+
+	in >> tmp;
+
+	if ( tmp == "true" )
+		value = true;
+	else if ( tmp == "false" )
+		value = false;
+	else
+		throw parse_error("parsing boolean failed");
+
+	skip_rest_of_line(in);
+
+	return value;
+}
+
+
+// throw an exception if the rest of the line doesn't only contain whitespace
+void configuration::skip_rest_of_line(std::istream &in) const {
+	char c;
+	while ( in.get(c) ) {
+		if ( c != ' ' && c != '\t' )
+			throw parse_error("junk after value");
+	}
+}
+
+
+// EOF
Index: /source/ariba/utility/transport/tcpip/protlib/configuration.h
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/configuration.h	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/configuration.h	(revision 5284)
@@ -0,0 +1,179 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file configuration.h
+/// Handling of simple (key, value) configuration files
+/// ----------------------------------------------------------
+/// $Id: configuration.h 2549 2007-04-02 22:17:37Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/configuration.h $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+#ifndef NATFW__CONFIG_H
+#define NATFW__CONFIG_H
+
+#include <fstream>
+#include <map>
+#include <list>
+#include <exception>
+
+#include "address.h"
+
+namespace natfw {
+  using protlib::hostaddress;
+
+
+/**
+ * An exception to be thrown if an invalid configuration is read.
+ */
+class config_error : public std::exception {
+  public:
+	config_error(const std::string &msg="Unspecified configuration error",
+			int line=-1) throw () : msg(msg), line(line) { }
+	virtual ~config_error() throw () { }
+
+	std::string get_msg() const throw () { return msg; }
+	int get_line() const throw () { return line; }
+
+  private:
+	std::string msg;
+	int line;
+};
+
+inline std::ostream &operator<<(std::ostream &os, const config_error &err) {
+	if ( err.get_line() > 0 )
+		return os << err.get_msg() << " at line " << err.get_line();
+	else
+		return os << err.get_msg();
+}
+
+
+/**
+ * The specification of a configuration entry.
+ *
+ * This specifies the name of the key, the value type, and optionally an
+ * initial default value.
+ */
+class config_entry {
+  public:
+	enum type_t {
+		T_BOOL, T_INT, T_FLOAT, T_STR, T_IPv4, T_IPv6,
+		T_IPv4_LIST, T_IPv6_LIST, T_END
+	};
+
+	config_entry(std::string key, type_t type, bool required=true)
+		: key(key), type(type), required(required) { }
+
+	config_entry(std::string key, bool value)
+		: key(key), type(T_BOOL), bool_value(value) { }
+
+	config_entry(std::string key, int value)
+		: key(key), type(T_INT), int_value(value) { }
+
+	config_entry(std::string key, float value)
+		: key(key), type(T_FLOAT), float_value(value) { }
+
+	config_entry(std::string key, std::string value)
+		: key(key), type(T_STR), str_value(value) { }
+
+	config_entry() : type(T_END) { }
+
+  private:
+	std::string key;
+	type_t type;
+	bool required;
+	bool defined;
+
+	bool bool_value;
+	int int_value;
+	float float_value;
+	std::string str_value;
+	hostaddress ipv4_value;
+	hostaddress ipv6_value;
+	std::list<hostaddress> address_list; // for both IPv4 and IPv6
+
+	friend class configuration;
+};
+
+
+/**
+ * A class for handling simple configuration files.
+ *
+ * The configuration consists of (key, value) pairs, where both key and value
+ * are strings.
+ *
+ * A configuration file is line-oriented and has the following format:
+ *   [space] key [space] = [space] value [space] EOL
+ *
+ * Value can be a boolean value, an integer, a float, an IP address (either
+ * IPv4 or IPv6), or a string. String values have to be quoted using double
+ * quotes. If a double quote should appear in the string, you have to quote it
+ * using a backslash. A backslash in turn has to be quoted using another
+ * backslash.
+ *
+ * Lines starting with '#' and empty lines are ignored.
+ */
+class configuration {
+  public:
+	configuration(config_entry defaults[]);
+
+	void load(const std::string &filename) throw (config_error);
+	void load(std::istream &in) throw (config_error);
+	void dump(std::ostream &out) throw (config_error);
+
+	bool is_defined(const std::string &key) const throw ();
+
+	std::string get_string(const std::string &key) const throw ();
+	bool get_bool(const std::string &key) const throw ();
+	int get_int(const std::string &key) const throw ();
+	float get_float(const std::string &key) const throw ();
+	hostaddress get_ipv4_address(const std::string &key) const throw ();
+	hostaddress get_ipv6_address(const std::string &key) const throw ();
+
+	std::list<hostaddress> get_ipv4_address_list(
+		const std::string &key) const throw ();
+	std::list<hostaddress> get_ipv6_address_list(
+		const std::string &key) const throw ();
+
+  private:
+	typedef std::map<std::string, config_entry>::const_iterator c_iter;
+	std::map<std::string, config_entry> values;
+
+	void strip_leading_space(std::istream &in) const;
+	void skip_rest_of_line(std::istream &in) const;
+	void parse_and_assign(const std::string &key, std::istream &in);
+
+	bool parse_bool(std::istream &in) const;
+	int parse_int(std::istream &in) const;
+	float parse_float(std::istream &in) const;
+	std::string parse_string(std::istream &in) const;
+	hostaddress parse_ipv4_address(std::istream &in) const;
+	hostaddress parse_ipv6_address(std::istream &in) const;
+	std::list<hostaddress> parse_ipv4_address_list(std::istream &in) const;
+	std::list<hostaddress> parse_ipv6_address_list(std::istream &in) const;
+	void write_string(std::ostream &out, const std::string &str) const;
+	void dump_address_list(std::ostream &out,
+		const std::list<hostaddress> &addresses) const;
+};
+
+
+} // namespace natfw
+
+#endif // NATFW__CONFIG_H
Index: /source/ariba/utility/transport/tcpip/protlib/connectionmap.cpp
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/connectionmap.cpp	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/connectionmap.cpp	(revision 5284)
@@ -0,0 +1,153 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file connectionmap.cpp
+/// stores connection related data
+/// ----------------------------------------------------------
+/// $Id: connectionmap.cpp 2872 2008-02-18 10:58:03Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/src/connectionmap.cpp $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+#include "connectionmap.h"
+#include "logfile.h"
+
+namespace protlib {
+  using namespace log;
+
+/** @ingroup tptcp
+ * @ingroup network
+ * @{
+ */
+
+
+/***** class ConnectionMap *****/
+
+/** @class ConnectionMap connectionmap.h
+    The class ConnectionMap saves all required information about
+    currently existing connections. Its methods allow to check for
+    connections and return, if possible, the data associated
+    with the connection.
+*/
+
+
+/** @returns true if data is not NULL, if there is not already
+ * an entry for data and if  
+ * it is inserted into the internal hash maps.
+ * 
+ */
+bool ConnectionMap::insert(AssocData* assoc) 
+{
+  if (assoc) 
+  {
+    if ( (assoc->socketfd && lookup(assoc->socketfd)) || 
+	 (assoc->assoc && lookup(assoc->assoc)) ||
+	 lookup(assoc->peer)) return false;
+    else 
+    {
+      if (assoc->socketfd)
+	ass2data[assoc->socketfd] = assoc;
+      else
+      if (assoc->assoc)
+	ass2data[assoc->assoc] = assoc;
+      else
+	Log(ERROR_LOG,LOG_NORMAL,"ConnectionMap","insertion failed, both socketfd and associd are 0");
+
+      addr2data[assoc->peer] = assoc;
+      return true;
+    } // end if already in map
+  } else return false;
+} // end insert
+
+/** @returns a pointer to the AssocData object or NULL.
+ * @param socketfd socket file descriptor
+ */
+
+AssocData* ConnectionMap::lookup(socketfd_t socketfd) const 
+{
+	const_ass2data_it_t hit= ass2data.find(socketfd);
+	if (hit!=ass2data.end()) return hit->second;
+	else return NULL;
+} // end lookup
+
+AssocData* ConnectionMap::lookup(associd_t associd) const 
+{
+	const_ass2data_it_t hit= ass2data.find(associd);
+	if (hit!=ass2data.end()) return hit->second;
+	else return NULL;
+} // end lookup
+
+/** @returns a pointer to the AssocData object or NULL.
+ * @param addr IP-adress + port
+ *
+ */
+AssocData* ConnectionMap::lookup(const appladdress& addr) const 
+{
+	const_addr2data_it_t hit= addr2data.find(addr);
+	if (hit!=addr2data.end()) return hit->second;
+	else return NULL;
+} // end lookup
+
+/** @returns true if the AssocData-object with socketfd
+ * could be deleted
+ * @param socketfd socket file descriptor
+ */
+bool ConnectionMap::erase(socketfd_t socketfd) {
+	bool res = true;
+	AssocData* d = lookup(socketfd);
+	if (d) {
+		if (!ass2data.erase(d->socketfd)) res = false;
+		if (!addr2data.erase(d->peer)) res = false;
+		delete d; // AssocData is deleted
+		return res;
+	} else return false;
+} // end erase
+
+/** 
+ * could be deleted
+ * @param associd association id
+ * @returns true if the AssocData-object with associd
+ */
+bool ConnectionMap::erase(associd_t associd) {
+	bool res = true;
+	AssocData* d = lookup(associd);
+	if (d) {
+		if (!ass2data.erase(d->assoc)) res = false;
+		if (!addr2data.erase(d->peer)) res = false;
+		delete d; // AssocData is deleted
+		return res;
+	} else return false;
+} // end erase
+
+/*
+ *
+ */
+void ConnectionMap::clear() {
+	const_ass2data_it_t hit;
+	for (hit=ass2data.begin();hit!=ass2data.end();hit++) {
+		if (hit->second) delete hit->second;
+	} // end for hit
+	ass2data.clear();
+	addr2data.clear();
+} // end clear
+
+
+} // end namespace protlib
+/// @}
Index: /source/ariba/utility/transport/tcpip/protlib/connectionmap.h
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/connectionmap.h	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/connectionmap.h	(revision 5284)
@@ -0,0 +1,105 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file connectionmap.h
+/// maintains connection mapping of application addresses to sockets and vice versa
+/// ----------------------------------------------------------
+/// $Id: connectionmap.h 2549 2007-04-02 22:17:37Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/connectionmap.h $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+#ifndef CONNECTION_MAP_H
+#define CONNECTION_MAP_H
+
+#include "assocdata.h"
+#include <ext/hash_map>
+
+namespace protlib {
+
+/* @class ConnectionMap 
+ * maintains connection mapping of application addresses to sockets and vice versa
+ * @ingroup network
+ * @{
+ */
+class ConnectionMap {
+	public:
+		// a constructor may be needed here in this class
+		/// Insert a new AssocData element into the ConnectionMap
+		bool insert(AssocData* assoc);
+		/// Search for existing connections to this specific socket
+		AssocData* lookup(socketfd_t socketfd) const;
+		/// Search for existing connections to this specific assoc id
+		AssocData* lookup(associd_t associd) const;
+		///Search for existing connections to this address
+		AssocData* lookup(const appladdress& addr) const;
+		/// Erase the AssocData-element associated with this socket
+		bool erase(socketfd_t socketfd);
+		/// Erase the AssocData-element associated with this socket
+		bool erase(associd_t associd);
+		/// Erase the AssocData-element
+		bool erase(AssocData* assoc);
+		/// clear all
+		void clear();
+		/// get number of records
+		size_t get_size() const;
+	private:
+		// this hash_map uses the standard hashfunction on the first entry, int
+		
+		// only typedefs
+		typedef hash_map<socketfd_t ,AssocData*> ass2data_t;
+		typedef ass2data_t::const_iterator const_ass2data_it_t;
+		typedef hash_map<appladdress,AssocData*> addr2data_t;
+		typedef addr2data_t::const_iterator const_addr2data_it_t;
+
+		// internal hashmaps
+		ass2data_t ass2data; ///< map: socket fd to association data
+		addr2data_t addr2data; ///< map: (application) address to association data
+	public:
+		/// connection map iterator
+		typedef const_ass2data_it_t const_it_t;
+		const_it_t begin() const;
+		const_it_t end() const;
+}; // end class ConnectionMap
+
+inline
+size_t 
+ConnectionMap::get_size() const { return ass2data.size(); }
+
+inline
+ConnectionMap::const_it_t ConnectionMap::begin() const {
+	return ass2data.begin();
+} // end begin
+
+inline
+ConnectionMap::const_it_t ConnectionMap::end() const {
+	return ass2data.end();
+} // end end
+
+inline
+bool 
+ConnectionMap::erase(AssocData* assoc) {
+  return assoc ? erase(assoc->socketfd) : false;
+} // end erase
+
+//@}
+
+} // end namespace protlib
+#endif
Index: /source/ariba/utility/transport/tcpip/protlib/connectionmap_uds.cpp
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/connectionmap_uds.cpp	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/connectionmap_uds.cpp	(revision 5284)
@@ -0,0 +1,153 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file connectionmap_uds.cpp
+/// stores network connection related data
+/// ----------------------------------------------------------
+/// $Id: connectionmap_uds.cpp 2872 2008-02-18 10:58:03Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/src/connectionmap_uds.cpp $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+#include "connectionmap_uds.h"
+#include "logfile.h"
+
+namespace protlib {
+  using namespace log;
+
+/** @ingroup tptcp
+ * @ingroup network
+ * @{
+ */
+
+
+/***** class ConnectionMapUDS *****/
+
+/** @class ConnectionMapUDS connectionmap.h
+    The class ConnectionMapUDS saves all required information about
+    currently existing connections. Its methods allow to check for
+    connections and return, if possible, the data associated
+    with the connection.
+*/
+
+
+/** @returns true if data is not NULL, if there is not already
+ * an entry for data and if  
+ * it is inserted into the internal hash maps.
+ * 
+ */
+bool ConnectionMapUDS::insert(AssocDataUDS* assoc) 
+{
+  if (assoc) 
+  {
+    if ( (assoc->socketfd && lookup(assoc->socketfd)) || 
+	 (assoc->assoc && lookup(assoc->assoc)) ||
+	 lookup(assoc->peer)) return false;
+    else 
+    {
+      if (assoc->socketfd)
+	ass2data[assoc->socketfd] = assoc;
+      else
+      if (assoc->assoc)
+	ass2data[assoc->assoc] = assoc;
+      else
+	Log(ERROR_LOG,LOG_NORMAL,"ConnectionMapUDS","insertion failed, both socketfd and associd are 0");
+
+      addr2data[assoc->peer] = assoc;
+      return true;
+    } // end if already in map
+  } else return false;
+} // end insert
+
+/** @returns a pointer to the AssocDataUDS object or NULL.
+ * @param socketfd socket file descriptor
+ */
+
+AssocDataUDS* ConnectionMapUDS::lookup(socketfd_t socketfd) const 
+{
+	const_ass2data_it_t hit= ass2data.find(socketfd);
+	if (hit!=ass2data.end()) return hit->second;
+	else return NULL;
+} // end lookup
+
+AssocDataUDS* ConnectionMapUDS::lookup(associd_t associd) const 
+{
+	const_ass2data_it_t hit= ass2data.find(associd);
+	if (hit!=ass2data.end()) return hit->second;
+	else return NULL;
+} // end lookup
+
+/** @returns a pointer to the AssocDataUDS object or NULL.
+ * @param addr IP-adress + port
+ *
+ */
+AssocDataUDS* ConnectionMapUDS::lookup(const udsaddress& addr) const 
+{
+	const_addr2data_it_t hit= addr2data.find(addr);
+	if (hit!=addr2data.end()) return hit->second;
+	else return NULL;
+} // end lookup
+
+/** @returns true if the AssocDataUDS-object with socketfd
+ * could be deleted
+ * @param socketfd socket file descriptor
+ */
+bool ConnectionMapUDS::erase(socketfd_t socketfd) {
+	bool res = true;
+	AssocDataUDS* d = lookup(socketfd);
+	if (d) {
+		if (!ass2data.erase(d->socketfd)) res = false;
+		if (!addr2data.erase(d->peer)) res = false;
+		delete d; // AssocDataUDS is deleted
+		return res;
+	} else return false;
+} // end erase
+
+/** 
+ * erase an association
+ * @param associd - association identifier
+ * @returns true if the AssocDataUDS-object with associd could be deleted
+ */
+bool ConnectionMapUDS::erase(associd_t associd) {
+	bool res = true;
+	AssocDataUDS* d = lookup(associd);
+	if (d) {
+		if (!ass2data.erase(d->assoc)) res = false;
+		if (!addr2data.erase(d->peer)) res = false;
+		delete d; // AssocDataUDS is deleted
+		return res;
+	} else return false;
+} // end erase
+
+/*
+ *
+ */
+void ConnectionMapUDS::clear() {
+	const_ass2data_it_t hit;
+	for (hit=ass2data.begin();hit!=ass2data.end();hit++) {
+		if (hit->second) delete hit->second;
+	} // end for hit
+	ass2data.clear();
+	addr2data.clear();
+} // end clear
+
+
+} // end namespace protlib
+/// @}
Index: /source/ariba/utility/transport/tcpip/protlib/connectionmap_uds.h
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/connectionmap_uds.h	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/connectionmap_uds.h	(revision 5284)
@@ -0,0 +1,106 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file connectionmap_uds.h
+/// maintains connection mapping of application addresses to 
+/// UNIX domain sockets and vice versa
+/// ----------------------------------------------------------
+/// $Id: connectionmap_uds.h 2549 2007-04-02 22:17:37Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/connectionmap_uds.h $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+#ifndef CONNECTION_MAP_UDS_H
+#define CONNECTION_MAP_UDS_H
+
+#include "assocdata_uds.h"
+#include <ext/hash_map>
+
+namespace protlib {
+
+/* @class ConnectionMap 
+ * maintains connection mapping of application addresses to sockets and vice versa
+ * @ingroup network
+ * @{
+ */
+class ConnectionMapUDS {
+	public:
+		// a constructor may be needed here in this class
+		/// Insert a new AssocDataUDS element into the ConnectionMapUDS
+		bool insert(AssocDataUDS* assoc);
+		/// Search for existing connections to this specific socket
+		AssocDataUDS* lookup(socketfd_t socketfd) const;
+		/// Search for existing connections to this specific assoc id
+		AssocDataUDS* lookup(associd_t associd) const;
+		///Search for existing connections to this address
+		AssocDataUDS* lookup(const udsaddress& addr) const;
+		/// Erase the AssocDataUDS-element associated with this socket
+		bool erase(socketfd_t socketfd);
+		/// Erase the AssocDataUDS-element associated with this socket
+		bool erase(associd_t associd);
+		/// Erase the AssocDataUDS-element
+		bool erase(AssocDataUDS* assoc);
+		/// clear all
+		void clear();
+		/// get number of records
+		size_t get_size() const;
+	private:
+		// this hash_map uses the standard hashfunction on the first entry, int
+		
+		// only typedefs
+		typedef hash_map<socketfd_t ,AssocDataUDS*> ass2data_t;
+		typedef ass2data_t::const_iterator const_ass2data_it_t;
+		typedef hash_map<udsaddress,AssocDataUDS*> addr2data_t;
+		typedef addr2data_t::const_iterator const_addr2data_it_t;
+
+		// internal hashmaps
+		ass2data_t ass2data; ///< map: socket fd to association data
+		addr2data_t addr2data; ///< map: (application) address to association data
+	public:
+		/// connection map iterator
+		typedef const_ass2data_it_t const_it_t;
+		const_it_t begin() const;
+		const_it_t end() const;
+}; // end class ConnectionMapUDS
+
+inline
+size_t 
+ConnectionMapUDS::get_size() const { return ass2data.size(); }
+
+inline
+ConnectionMapUDS::const_it_t ConnectionMapUDS::begin() const {
+	return ass2data.begin();
+} // end begin
+
+inline
+ConnectionMapUDS::const_it_t ConnectionMapUDS::end() const {
+	return ass2data.end();
+} // end end
+
+inline
+bool 
+ConnectionMapUDS::erase(AssocDataUDS* assoc) {
+  return assoc ? erase(assoc->socketfd) : false;
+} // end erase
+
+//@}
+
+} // end namespace protlib
+#endif
Index: /source/ariba/utility/transport/tcpip/protlib/eclock_gettime.c
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/eclock_gettime.c	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/eclock_gettime.c	(revision 5284)
@@ -0,0 +1,78 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file eclock_gettime.c
+/// emulates a clock_gettime call for systems not having it
+/// ----------------------------------------------------------
+/// $Id: eclock_gettime.c 2549 2007-04-02 22:17:37Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/fastqueue/eclock_gettime.c $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+/** @addtogroup fastqueue Fast Queue
+ * @{
+ */
+
+
+
+#include <sys/time.h>
+#include <unistd.h>
+
+/* struct timezone tz = { 0, DST_NONE }; */
+static struct timeval tv;
+typedef int             clockid_t;
+
+/* syntax for clock_gettime:
+   int clock_gettime (clockid_t clock_id, struct timespec *tp);
+
+   to supply it include the following (because of speed):
+   extern int eclock_gettime(struct timespec *tp);
+   #define clock_gettime(clock_id, tspec) eclock_gettime(tspec)
+*/
+
+int eclock_gettime(struct timespec *tp)
+{
+  /* DESCRIPTION
+
+  The clock_gettime function returns the current time (in seconds and
+  nanoseconds) for the specified clock.  The clock_settime function sets the
+  specified clock. The CLOCK_REALTIME clock measures the amount of time
+  elapsed since 00:00:00:00 January 1, 1970 Greenwich Mean Time (GMT), other-
+  wise known as the Epoch. Time values  that fall between two non-negative
+  integer multiples of the resolution are truncated down to the smaller mul-
+  tiple of the resolution.
+
+  */
+  if (gettimeofday(&tv, 0) == 0)
+  {
+#ifdef DEBUG
+    if (tp)
+#endif
+    {
+      tp->tv_sec= tv.tv_sec;
+      tp->tv_nsec= tv.tv_usec*1000;
+      return 0;
+    }
+  }
+  else
+    return -1;
+}
+
+//@}
Index: /source/ariba/utility/transport/tcpip/protlib/fastqueue.c
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/fastqueue.c	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/fastqueue.c	(revision 5284)
@@ -0,0 +1,650 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file fastqueue.c
+/// a simple FIFO queue with mutexes for use with pthreads
+/// ----------------------------------------------------------
+/// $Id: fastqueue.c 2549 2007-04-02 22:17:37Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/fastqueue/fastqueue.c $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+
+/** @addtogroup fastqueue Fast Queue
+ * @{
+ */
+
+/** @file
+ * Fast and thread-safe queue.
+ */
+
+/******************************************************************************
+ * fastqueue.c -- a simple FIFO queue with mutexes for use with pthreads      *
+ * -------------------------------------------------------------------------- *
+ * written by Roland Bless 1995                                               *
+ * all operations enqueue,dequeue are done in O(1) which means constant time  *
+ ******************************************************************************/
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+                       /**** module interface ****/
+#include "fastqueue.h"
+
+                  /*************** defines *****************/
+#define qerr(errnr)      fprintf(stderr,"queue.c: %s\n",queue_errmsg[errnr])
+
+#ifdef __linux__
+
+// not needed for Linux
+//#define pthread_mutexattr_settype pthread_mutexattr_setkind_np
+
+#define PTHREAD_MUTEX_NORMAL PTHREAD_MUTEX_TIMED_NP
+#define PRI_OTHER_MIN  PRI_FG_MIN_NP
+#define PRI_OTHER_MAX  PRI_FG_MAX_NP
+#define PRI_FG_MIN_NP  8
+#define PRI_FG_MAX_NP  15
+
+#define CLOCK_REALTIME 0
+#define NSEC_PER_SEC   1000000000
+extern int eclock_gettime(struct timespec *tp);
+#define clock_gettime(clock_id, tspec) eclock_gettime(tspec)
+
+#elif _DECTHREADS_VERSION < 314126L
+
+#define pthread_mutexattr_settype pthread_mutexattr_settype_np
+#define PTHREAD_MUTEX_NORMAL PTHREAD_MUTEX_NORMAL_NP
+#define PTHREAD_MUTEX_ERRORCHECK PTHREAD_MUTEX_ERRORCHECK_NP
+#endif
+                 /*************** typedefs *****************/
+
+enum {
+       QERR_NONE,
+       QERR_NOMEM,
+       QERR_MUTEXINIT,
+       QERR_MUTEXLOCK,
+       QERR_MUTEXUNLOCK,
+       QERR_MUTEXDESTROY,
+       QERR_QEMPTY,
+       QERR_QINVALID,
+       QERR_QNOTEMPTY,
+       QERR_CONDINIT,
+       QERR_CONDWAIT,
+       QERR_CONDSIGNAL,
+       QERR_CONDDESTROY
+};
+
+const 
+char *const queue_errmsg[]=
+{
+  "all ok",
+  "can't get enough memory",
+  "initializing mutex",
+  "locking mutex",
+  "unlocking mutex",
+  "destroying mutex",
+  "queue empty",
+  "invalid queueobject",
+  "destroying queue - queue not empty",
+  "initializing queue condition variable",
+  "waiting on condition",
+  "signalling condition",
+  "destroying condition"
+};
+
+
+
+queue_t *create_queue(const char* name)
+/* initialization routine for a queue.
+ * returns: NULL if an error occured, or a queue-object which is actually
+ *          a queueheader structure
+ * arguments: none
+ */
+{
+  queue_t *queuehead;
+
+  /* Allocate memory for queue head */
+  if ((queuehead= (queue_t *) malloc(sizeof(queue_t)))!=NULL)
+  {
+    /* Set mutex kind */
+    pthread_mutexattr_init(&queuehead->mutex_attr);
+#ifdef _DEBUG
+    pthread_mutexattr_settype(&queuehead->mutex_attr,PTHREAD_MUTEX_ERRORCHECK);
+#else
+    pthread_mutexattr_settype(&queuehead->mutex_attr,PTHREAD_MUTEX_NORMAL);
+#endif
+    /* use PTHREAD_MUTEX_ERRORCHECK or PTHREAD_MUTEX_ERRORCHECK_NP for testing */
+
+    /* Initialize mutex */
+    if (pthread_mutex_init(&queuehead->mutex, &queuehead->mutex_attr)==0)
+    {
+      /* Create Condition variable for command queue */
+      if (pthread_cond_init(&queuehead->cond, NULL)==0)
+      {
+        queuehead->nr_of_elements= 0UL;
+        queuehead->exp_nr_of_elements= 0UL;
+        queuehead->exp_enabled = 0;
+        queuehead->first_block= (queue_elblock_t *) malloc(sizeof(queue_elblock_t));
+        queuehead->exp_first_block= (queue_elblock_t *) malloc(sizeof(queue_elblock_t));
+        if ((queuehead->first_block == NULL) || (queuehead->exp_first_block == NULL))
+           qerr(QERR_NOMEM);
+        else
+	{
+          queuehead->first_block->read=  0;
+          queuehead->first_block->write= 0;
+          queuehead->first_block->next_block= NULL;          
+          queuehead->last_block= queuehead->first_block;
+          queuehead->exp_first_block->read=  0;
+          queuehead->exp_first_block->write= 0;
+          queuehead->exp_first_block->next_block= NULL;          
+          queuehead->exp_last_block= queuehead->exp_first_block;
+          if (name)
+          {
+            if (strlen(name) <= MAX_QUEUENAME_LENGTH)
+              strcpy(queuehead->name, name);
+            else
+            {
+              memcpy(queuehead->name, name, MAX_QUEUENAME_LENGTH);
+              queuehead->name[MAX_QUEUENAME_LENGTH + 1] = '\0';
+            }
+          }
+          else
+            queuehead->name[0] = '\0';
+          /* Now it's simple to enqueue elements, esp. the first one */
+        }
+//#ifdef QUEUELEN
+        queuehead->queue_maxlength= 0;
+//#endif
+      }
+      else
+        qerr(QERR_CONDINIT);
+    }
+    else /* error during initialize */
+      qerr(QERR_MUTEXINIT);
+  }
+  else
+    qerr(QERR_NOMEM);
+
+  return queuehead;
+}
+
+int enqueue_element_signal(queue_t *queuehead, void *element)
+{
+  return enqueue_element_expedited_signal(queuehead,element,0);
+}
+
+int enqueue_element_expedited_signal(queue_t *queuehead, void *element, int exp)
+/* add a new element into the queue. Memory for the element must be
+ * allocated anywhere else. This routine signals other waiting threads.
+ * returns: -1 if an error occured, or 0 is action could be performed
+ * arguments: pointer to queue_t object, pointer to an element
+ */
+{
+  queue_elblock_t *newelement, *lastblockp;
+
+  if (queuehead==NULL)
+  {
+    qerr(QERR_QINVALID);
+    return -1;
+  }
+
+  if (pthread_mutex_lock(&queuehead->mutex)!=0)
+  {
+    qerr(QERR_MUTEXLOCK);
+    return -1;
+  }
+  /* begin critical section */
+
+  if (exp && queuehead->exp_enabled) exp = 1; else exp = 0;
+  /* Allocate new element structure when necessary */
+  /* Note: queuehead->last_block must always contain a valid value */
+  lastblockp = (exp ? (queuehead->exp_last_block) : (queuehead->last_block));
+  if (lastblockp->write == ELEMENT_BLOCKSIZE)
+  { /* last block is full, so allocate a new block */
+    if ((newelement= (queue_elblock_t *) malloc(sizeof(queue_elblock_t)))==NULL)
+    {
+      qerr(QERR_NOMEM);
+      return -1;
+    }
+
+    /* initialize new structure */
+    newelement->element[0]= element;
+    newelement->read      = 0;
+    newelement->write     = 1;
+    newelement->next_block= NULL;
+    
+    /* append new element to the end */
+    lastblockp->next_block= newelement;
+    /* new element becomes last element */
+    if (exp) queuehead->exp_last_block = newelement; 
+    else queuehead->last_block = newelement; 
+  }
+  else /* last block was not full */
+  { 
+    lastblockp->element[lastblockp->write]= element;
+    lastblockp->write++;
+  }
+  
+  if (exp) queuehead->exp_nr_of_elements++;
+  queuehead->nr_of_elements++;
+//#ifdef QUEUELEN
+    if (queuehead->nr_of_elements > queuehead->queue_maxlength)
+       queuehead->queue_maxlength= queuehead->nr_of_elements;
+//#endif
+  /* Condition should be set while mutex is locked. 
+     Recommended by libc manual.
+  */
+  if (pthread_cond_signal(&queuehead->cond)!=0)
+     qerr(QERR_CONDSIGNAL);
+  /* end critical section */
+  if (pthread_mutex_unlock(&queuehead->mutex)!=0)
+  {
+    qerr(QERR_MUTEXUNLOCK);
+    return -1;
+  }
+  // see above
+//  if (pthread_cond_signal(&queuehead->cond)!=0)
+//     qerr(QERR_CONDSIGNAL);
+
+  return 0;
+}
+
+
+void *dequeue_element_wait(queue_t *queuehead)
+/* wait for the queue to contain an element.
+ * if it contains an element return and remove it.
+ * returns: NULL if an error occured, the pointer to the element otherwise
+ * arguments: pointer to queue_t object
+ */
+{
+  void       *element;
+  queue_elblock_t *blockp;
+  int exp = 0;
+  element= NULL;
+  int retcode= 0;
+
+  if (queuehead != NULL)
+  {
+    /* Wait for an element in the queue */
+    /* Before waiting on a condition, the associated mutex must be locked */
+    if (pthread_mutex_lock(&queuehead->mutex)!=0)
+    {
+      qerr(QERR_MUTEXLOCK); return NULL;
+    }
+
+    while(queuehead->nr_of_elements==0) /* while there is no work to do, wait */
+    { /* for a safe state the predicate must be checked in a loop! */
+      /* cond_wait() unlocks the mutex and might return sometimes without
+         getting a signal! */
+      if ((retcode= pthread_cond_wait(&queuehead->cond, &queuehead->mutex)) != 0)
+      {
+         if (retcode!=EINTR && retcode!=ETIMEDOUT)
+	 {
+	   qerr(QERR_CONDWAIT);
+	 }
+      }
+    }
+
+    /* begin critical section */
+    exp = (queuehead->exp_nr_of_elements!=0);
+    blockp = (exp ? (queuehead->exp_first_block) : (queuehead->first_block));
+    if (blockp != NULL)
+    {
+      /* get the first element */
+      element= blockp->element[blockp->read];
+      blockp->read++;
+
+      if (blockp->next_block == NULL) /* this is the last block */
+      {
+        if (blockp->read == blockp->write) 
+        { /* block is completely dequeued, so reset values */
+          /* the last block always remains allocated! */
+          blockp->read=  0;
+          blockp->write= 0;
+        }
+      }
+      else /* this is not the last block */
+      {
+        /* if block was completely dequeued, remove it */
+        if (blockp->read == ELEMENT_BLOCKSIZE)
+        {
+          if (exp) queuehead->exp_first_block= blockp->next_block;
+          else queuehead->first_block= blockp->next_block;
+          free(blockp);
+        }
+      }
+      if (exp) queuehead->exp_nr_of_elements--;
+      queuehead->nr_of_elements--;
+    }
+    else
+      qerr(QERR_QEMPTY);
+
+    /* end critical section */
+    if (pthread_mutex_unlock(&queuehead->mutex)!=0)
+    {
+      qerr(QERR_MUTEXUNLOCK);
+      return NULL;
+    }
+  }
+  else
+    qerr(QERR_QINVALID);
+
+  return element;
+}
+
+void *dequeue_element_timedwait(queue_t *queuehead, const struct timespec *tspec)
+/* wait for the queue to contain an element.
+ * if it contains an element return and remove it.
+ * returns: NULL if an error occured, the pointer to the element otherwise
+ * arguments: pointer to queue_t object
+ *            tpsec is the time interval to wait (not an absolute time!)
+ */
+{
+  void       *element;
+  queue_elblock_t *blockp;
+  int result;
+  struct timespec abs_tspec;
+  int exp = 0;
+  element= NULL;
+
+  if (queuehead != NULL)
+  {
+    /* Wait for an element in the queue */
+    /* Before waiting on a condition, the associated mutex must be locked */
+    if (pthread_mutex_lock(&queuehead->mutex)!=0)
+    {
+      qerr(QERR_MUTEXLOCK); return NULL;
+    }
+
+    while(queuehead->nr_of_elements==0) /* while there is no work to do, wait */
+    { /* for a safe state the predicate must be checked in a loop! */
+      /* cond_wait() unlocks the mutex and might return sometimes without
+         getting a signal! */
+      clock_gettime(CLOCK_REALTIME, &abs_tspec);
+      abs_tspec.tv_nsec+= tspec->tv_nsec;
+      abs_tspec.tv_sec+= tspec->tv_sec;
+      if (abs_tspec.tv_nsec >= NSEC_PER_SEC)
+      {
+        abs_tspec.tv_nsec%= NSEC_PER_SEC;
+        abs_tspec.tv_sec++;
+      };
+
+      if ((result = pthread_cond_timedwait(&queuehead->cond,
+                                           &queuehead->mutex, &abs_tspec))!=0)
+      {
+	if ( (result != ETIMEDOUT) && (result != EINTR) && (result != EINVAL) ) 
+        {
+	  qerr(QERR_CONDWAIT);
+	} 
+        else 
+        { /* timeout */
+	  if (pthread_mutex_unlock(&queuehead->mutex)!=0) 
+          {
+	    qerr(QERR_MUTEXUNLOCK);
+	    return NULL;
+	  } 
+	  return NULL;
+	}
+      }
+    }
+
+    /* begin critical section */
+    exp = (queuehead->exp_nr_of_elements!=0);
+    blockp = (exp ? (queuehead->exp_first_block) : (queuehead->first_block));
+    if (blockp != NULL)
+    {
+      /* get the first element */
+      element= blockp->element[blockp->read];
+      blockp->read++;
+
+      if (blockp->next_block == NULL) /* this is the last block */
+      {
+        if (blockp->read == blockp->write) 
+        { /* block is completely dequeued, so reset values */
+          /* the last block always remains allocated! */
+          blockp->read=  0;
+          blockp->write= 0;
+        }
+      }
+      else /* this is not the last block */
+      {
+        /* if block was completely dequeued, remove it */
+        if (blockp->read == ELEMENT_BLOCKSIZE)
+        {
+          if (exp) queuehead->exp_first_block= blockp->next_block;
+          else queuehead->first_block= blockp->next_block;
+          free(blockp);
+        }
+      }
+      if (exp) queuehead->exp_nr_of_elements--;
+      queuehead->nr_of_elements--;
+    }
+    else
+      qerr(QERR_QEMPTY);
+
+    /* end critical section */
+    if (pthread_mutex_unlock(&queuehead->mutex)!=0)
+    {
+      qerr(QERR_MUTEXUNLOCK);
+      return NULL;
+    }
+  }
+  else
+    qerr(QERR_QINVALID);
+
+  return element;
+}
+
+int destroy_queue(queue_t *queuehead)
+/* destroys the queue and frees all resources, except the elements!
+ * the queue must be empty to destroy it.
+ * returns: -1 if an error occured, 0 otherwise
+ * arguments: pointer to queue_t object
+ */
+{
+  if (queuehead!=NULL)
+  {
+    /* queue not empty? */
+    if (queuehead->nr_of_elements != 0)
+      qerr(QERR_QNOTEMPTY);
+    else
+    {
+      /* destroy condition variable */
+      if (pthread_cond_destroy(&queuehead->cond)!=0) qerr(QERR_CONDDESTROY);
+      /* destroy mutex */
+      if (pthread_mutex_destroy(&queuehead->mutex)!=0) qerr(QERR_MUTEXDESTROY);
+      
+      pthread_mutexattr_destroy(&queuehead->mutex_attr);
+
+      /* free memory for queuehead */
+#ifdef QUEUELEN
+      fprintf(stderr,"queue.c: length of queue (%s) growed up to %lu elements\n",
+              queuehead->name, queuehead->queue_maxlength);
+#endif      
+      free(queuehead->exp_last_block);
+      free(queuehead->last_block);
+      free(queuehead);
+    }
+
+    return 0;
+  }
+  else
+    qerr(QERR_QINVALID);
+
+  return -1;
+}
+
+void *dequeue_element_nonblocking(queue_t *queuehead)
+/* if queue contains an element return and remove it.
+ * returns: NULL if an error occured or queue was empty, the pointer to
+ * the element otherwise.
+ * arguments: pointer to queue_t object
+ */
+{
+  void       *element;
+  queue_elblock_t *blockp;
+  int exp = 0;
+  element= NULL;
+
+  if (queuehead != NULL)
+  {
+    if (pthread_mutex_lock(&queuehead->mutex)!=0)
+    {
+      qerr(QERR_MUTEXLOCK); return NULL;
+    }
+
+    /* begin critical section */
+
+    if (queuehead->nr_of_elements==0) 
+    { 
+      if (pthread_mutex_unlock(&queuehead->mutex)!=0) qerr(QERR_MUTEXUNLOCK);
+      return NULL;
+    }
+
+    exp = (queuehead->exp_nr_of_elements!=0);
+    blockp = (exp ? (queuehead->exp_first_block) : (queuehead->first_block));
+    if (blockp != NULL)
+    {
+      /* get the first element */
+      element= blockp->element[blockp->read];
+      blockp->read++;
+
+      if (blockp->next_block == NULL) /* this is the last block */
+      {
+        if (blockp->read == blockp->write) 
+        { /* block is completely dequeued, so reset values */
+          /* the last block always remains allocated! */
+          blockp->read=  0;
+          blockp->write= 0;
+        }
+      }
+      else /* this is not the last block */
+      {
+        /* if block was completely dequeued, remove it */
+        if (blockp->read == ELEMENT_BLOCKSIZE)
+        {
+          if (exp) queuehead->exp_first_block= blockp->next_block;
+          else queuehead->first_block= blockp->next_block;
+          free(blockp);
+        }
+      }
+      if (exp) queuehead->exp_nr_of_elements--;
+      queuehead->nr_of_elements--;
+    }
+    else
+      qerr(QERR_QEMPTY);
+
+    /* end critical section */
+    if (pthread_mutex_unlock(&queuehead->mutex)!=0)
+    {
+      qerr(QERR_MUTEXUNLOCK);
+      return NULL;
+    }
+  }
+  else
+    qerr(QERR_QINVALID);
+
+  return element;
+}
+
+unsigned long queue_nr_of_elements(queue_t *queuehead)
+/** Get number fo elements in queue. */
+{
+  unsigned long result = 0;
+
+  if (queuehead != NULL)
+  {
+    if (pthread_mutex_lock(&queuehead->mutex)!=0)
+    {
+      qerr(QERR_MUTEXLOCK);
+      return 0;
+    }
+    /* begin critical section */
+
+    result = queuehead->nr_of_elements; 
+
+    /* end critical section */
+    if (pthread_mutex_unlock(&queuehead->mutex)!=0) qerr(QERR_MUTEXUNLOCK);
+  }
+  else
+    qerr(QERR_QINVALID);
+
+  return result;
+}
+
+int queue_is_expedited_enabled(queue_t *queuehead)
+/** Get exp_enabled flag. */
+{
+  int result = 0;
+
+  if (queuehead != NULL)
+  {
+    if (pthread_mutex_lock(&queuehead->mutex)!=0)
+    {
+      qerr(QERR_MUTEXLOCK);
+      return 0;
+    }
+    /* begin critical section */
+
+    result = queuehead->exp_enabled; 
+
+    /* end critical section */
+    if (pthread_mutex_unlock(&queuehead->mutex)!=0) qerr(QERR_MUTEXUNLOCK);
+  }
+  else
+    qerr(QERR_QINVALID);
+
+  return result;
+}
+
+int queue_enable_expedited(queue_t *queuehead, int exp)
+/** Set exp_enabled flag and return old value. */
+{
+  int result = 0;
+
+  if (queuehead != NULL)
+  {
+    if (pthread_mutex_lock(&queuehead->mutex)!=0)
+    {
+      qerr(QERR_MUTEXLOCK);
+      return 0;
+    }
+    /* begin critical section */
+
+    result = queuehead->exp_enabled; 
+    if (exp) queuehead->exp_enabled = 1;
+    else queuehead->exp_enabled = 0;
+
+    /* end critical section */
+    if (pthread_mutex_unlock(&queuehead->mutex)!=0) qerr(QERR_MUTEXUNLOCK);
+  }
+  else
+    qerr(QERR_QINVALID);
+
+  return result;
+}
+
+//@}
Index: /source/ariba/utility/transport/tcpip/protlib/fastqueue.h
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/fastqueue.h	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/fastqueue.h	(revision 5284)
@@ -0,0 +1,95 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file fastqueue.h
+/// Fast and thread-safe queue to send/receive messages between 
+/// POSIX threads
+/// ----------------------------------------------------------
+/// $Id: fastqueue.h 2872 2008-02-18 10:58:03Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/fastqueue/fastqueue.h $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+/** 
+ * @ingroup fastqueue Fast Queue
+ * @{
+ */
+
+/** @file
+ * Fast and thread-safe queue to send/receive messages between POSIX threads
+ * This can be used as a port for a thread to receive messages (from any thread).
+ * The implementations allows for arbitrary long queues, but queues grow by
+ * element blocks containing ELEMENT_BLOCKSIZE elements. This avoids frequent
+ * malloc/free operations.
+ */
+
+#ifndef QUEUE_TYPE
+#define QUEUE_TYPE
+
+#include <pthread.h>
+
+#define ELEMENT_BLOCKSIZE    64
+#define MAX_QUEUENAME_LENGTH 32
+
+
+/* queue element block type */
+typedef struct queue_elblock_struct
+  {
+    void *element[ELEMENT_BLOCKSIZE];
+    int read, write;
+    struct queue_elblock_struct *next_block;
+  }
+queue_elblock_t;
+
+
+typedef struct queue_struct
+  {
+    pthread_mutex_t mutex;
+    pthread_mutexattr_t mutex_attr;
+    pthread_cond_t cond;
+
+    unsigned long nr_of_elements;
+    unsigned long exp_nr_of_elements;
+    int exp_enabled;
+    queue_elblock_t *first_block;
+    queue_elblock_t *last_block;
+    queue_elblock_t *exp_first_block;
+    queue_elblock_t *exp_last_block;
+//#ifdef QUEUELEN
+    unsigned long queue_maxlength;
+//#endif
+    char name[MAX_QUEUENAME_LENGTH +1];
+  }
+queue_t;
+
+extern queue_t *create_queue (const char *name);
+extern int enqueue_element_signal (queue_t * queuehead, void *element);
+extern int enqueue_element_expedited_signal (queue_t * queuehead, void *element, int exp);
+extern void *dequeue_element_wait (queue_t * queuehead);
+extern void *dequeue_element_timedwait(queue_t *queuehead, const struct timespec *tspec);
+extern int destroy_queue (queue_t * queuehead);
+extern void *dequeue_element_nonblocking(queue_t * queuehead);
+extern unsigned long queue_nr_of_elements(queue_t *queue);
+extern int queue_is_expedited_enabled(queue_t *queue);
+extern int queue_enable_expedited(queue_t *queue, int exp);
+
+#endif
+
+//@}
Index: /source/ariba/utility/transport/tcpip/protlib/fqueue.cpp
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/fqueue.cpp	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/fqueue.cpp	(revision 5284)
@@ -0,0 +1,216 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file fqueue.cpp
+/// wrapper class for fastqueue
+/// ----------------------------------------------------------
+/// $Id: fqueue.cpp 2549 2007-04-02 22:17:37Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/src/fqueue.cpp $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+
+#include "fqueue.h"
+#include "stdio.h"
+#include "logfile.h"
+
+#include <string>
+
+namespace protlib {
+
+/** @addtogroup fastqueue Fast Queue
+ * @{
+ */
+
+  using namespace log;
+
+/**
+ * Constructor.
+ *
+ * Initialize a FastQueue with a queue name and enable/disable expedited
+ * data.
+ *
+ * @param qname the queue's name, or NULL
+ * @param exp if true, expedited data support is enabled
+ */
+FastQueue::FastQueue(const char *qname, bool exp)
+    : queue_name((qname == 0) ? "" : (char*)qname), shutdownflag(false)
+{
+  if ((queue = create_queue(qname)) == NULL)
+  {
+    Log(ERROR_LOG, LOG_ALERT, "FastQueue", "Could not create queue " << queue_name);
+    throw FQError();
+  } else queue_enable_expedited(queue,exp);
+}
+
+
+/**
+ * Add a message to the queue.
+ *
+ * If exp is true and the queue allows expedited data, the message will
+ * pass all normal messages in the queue and thus will be delivered earlier.
+ * If there are other expedited messages in the queue already, it will be
+ * added after the already existing expedited messages.
+ *
+ * This method may fail (and return false) if the queue is in shutdown mode,
+ * there is a problem aquiring locks, or some other threading problem.
+ *
+ * In case the queue is deleted before this message has been removed, this
+ * message is deleted using the delete operator. Because of this, the same
+ * message may only appear once in a queue.
+ * 
+ * @param element a pointer to the message to add
+ * @param exp true if this is expedited data
+ * 
+ * @return true if the element was enqueued successfully
+ */
+bool FastQueue::enqueue(message *element, bool exp)
+{
+  if (shutdownflag) return false;
+  if (enqueue_element_expedited_signal(queue, (void*)element, exp) < 0)
+  {
+    Log(ERROR_LOG, LOG_ALERT, "FastQueue", "Could not enqueue element in queue " << queue_name);
+    return false;
+  }
+  return true;
+}
+
+
+/**
+ * Wait for a message for a given time.
+ *
+ * If no message arrives in the given time period, NULL is returned.
+ *
+ * @param msec the time to wait in milliseconds
+ *
+ * @return the message, or NULL
+ */
+message *FastQueue::dequeue_timedwait(const long int msec)
+{
+  struct timespec tspec = {0,0};
+  tspec.tv_sec = msec/1000;
+  tspec.tv_nsec = (msec%1000)*1000000;
+  return (message*)dequeue_element_timedwait(queue, &tspec);
+}
+
+
+/**
+ * Destructor.
+ * 
+ * Destroys the queue. All messages which are still in the queue are deleted
+ * using the delete operator.
+ */
+FastQueue::~FastQueue()
+{
+  if (queue) 
+  {
+    cleanup();
+    if ((destroy_queue(queue)) < 0)
+    {
+      Log(ERROR_LOG, LOG_ALERT, "FastQueue", "Could not destroy queue " << queue_name);
+    }
+  }
+  DLog("FastQueue", "~FastQueue() - done for queue " << queue_name);
+}
+
+/**
+ * Test if the queue is empty.
+ *
+ * @return true if the queue is empty
+ */
+bool FastQueue::is_empty() const
+{
+  if (queue_nr_of_elements(queue)==0)
+    return true;
+  else
+    return false;
+}
+
+
+/**
+ * Return the number of messages in the queue.
+ *
+ * @return the number of enqueued messages
+ */
+unsigned long FastQueue::size() const
+{
+  return queue_nr_of_elements(queue);
+}
+
+
+/**
+ * Test if expedited message support is enabled.
+ * 
+ * @return true if expedited message support is enabled
+ */
+bool FastQueue::is_expedited_enabled() const
+{
+  if (queue_is_expedited_enabled(queue))
+    return true;
+  else
+    return false;
+}
+
+/**
+ * Enable or disable expedited messages.
+ *
+ * This also returns the previous value of this flag.
+ *
+ * @return true, if expedited messages were previously enabled, false otherwise
+ */
+bool FastQueue::enable_expedited(bool exp)
+{
+  if (queue_enable_expedited(queue,exp))
+    return true;
+  else
+    return false;
+}
+
+
+/**
+ * Disable enqueueing of new messages.
+ *
+ * A queue in shutdown mode does not accept messages any more.
+ */
+void FastQueue::shutdown() { shutdownflag = true; }
+
+
+/**
+ * Put queue into shutdown mode and delete all stored messages..
+ *
+ * @return the number of messages that were in the queue
+ */
+unsigned long FastQueue::cleanup()
+{
+  unsigned long count = 0;
+  message* m = NULL;
+  shutdownflag = true;
+  while (!is_empty())
+    if ((m = dequeue(false))) {
+      delete m;
+      m = NULL;
+      count++;
+    }
+  return count;
+}
+
+//@}
+
+} // end namespace protlib
Index: /source/ariba/utility/transport/tcpip/protlib/fqueue.h
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/fqueue.h	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/fqueue.h	(revision 5284)
@@ -0,0 +1,148 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file fqueue.h
+/// a wrapper class for fastqueue C implementation
+/// ----------------------------------------------------------
+/// $Id: fqueue.h 2549 2007-04-02 22:17:37Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/fqueue.h $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+
+/** @ingroup fastqueue
+ *
+ */
+
+#ifndef __FQUEUE_H__
+#define __FQUEUE_H__
+
+#include <string>
+
+#include "protlib_types.h"
+#include "messages.h"
+
+extern "C" {
+#include"fastqueue.h"
+}
+
+namespace protlib {
+
+/** @addtogroup fastqueue Fast Queue
+ * @{
+ */
+
+// declared in messages.h
+class message;
+
+
+/** 
+ * A fast message queue.
+ *
+ * This is a fast and thread-safe message queue with expedited data
+ * support. It is an object oriented wrapper around fastqueue.c.
+ * The queue grows dynamically and has no built-in entry limit.
+ */
+class FastQueue {
+public:
+	/// FastQueue error
+	class FQError{};
+	/// constructor
+	FastQueue(const char *qname = 0, bool exp = false);
+	/// destructor
+	~FastQueue();
+	/// enqueue message
+	bool enqueue(message *element, bool exp = false);
+	/// dequeue message
+	message *dequeue(bool blocking = true);
+	/// dequeue message, timed wait
+	message *dequeue_timedwait(const struct timespec &tspec);
+	/// dequeue message, timed wait
+	message *dequeue_timedwait(const long int msec);
+	/// is queue empty
+	bool is_empty() const;
+	/// get number of enqueued messages
+	unsigned long size() const;
+	/// is expedited data support enabled
+	bool is_expedited_enabled() const;
+	/// enable/disable expedited data
+	bool enable_expedited(bool exp);
+	/// shutdown queue, do not accept messages
+	void shutdown();
+	/// delete stored messages
+	unsigned long cleanup();
+	/// Return the name of the queue.
+	const char* get_name() const { return queue_name.c_str(); }
+private:
+	/// C fastqueue
+	queue_t *queue;
+	/// name of the queue, also stored in the queue_t
+	string queue_name;
+	/// accept or reject messages
+	bool shutdownflag;
+};
+
+
+/**
+ * Remove the first message from the queue.
+ *
+ * Messages are removed in the same order they were added to the queue (FIFO).
+ * If the expedited messages feature is enabled, there's an exception to
+ * this rule: Expedited messages are always removed before all other messages.
+ * The FIFO condition still holds among expedited messages, however.
+ *
+ * If blocking is set, wait infinitely for a message. If set to false,
+ * return immediately if the queue is empty. In this case, NULL is returned.
+ *
+ * @param blocking if true, block until a message arrives
+ *
+ * @return the message, or NULL
+ */
+inline
+message *
+FastQueue::dequeue(bool blocking)
+{
+  return static_cast<message*>(blocking ? 
+			       dequeue_element_wait(queue) :
+			       dequeue_element_nonblocking(queue));
+}
+
+
+/**
+ * Wait for a message for a given time.
+ *
+ * If no message arrives in the given time period, NULL is returned.
+ *
+ * @param tspec the time to wait
+ *
+ * @return the message, or NULL
+ */
+inline
+message *
+FastQueue::dequeue_timedwait(const struct timespec& tspec)
+{
+  return (message*)dequeue_element_timedwait(queue, &tspec);
+}
+
+//@}
+
+} // end namespace protlib
+
+#endif 
Index: /source/ariba/utility/transport/tcpip/protlib/ie.cpp
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/ie.cpp	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/ie.cpp	(revision 5284)
@@ -0,0 +1,696 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file ie.cpp
+/// information elements for the protocol, IE manager singleton
+/// ----------------------------------------------------------
+/// $Id: ie.cpp 2549 2007-04-02 22:17:37Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/src/ie.cpp $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+
+/** @ingroup ie
+ * This file defines the base class of all information elements, the
+ * information elements for the GIST protocol and an IE manager singleton
+ * object.
+ * Although the IEs are closely related to the structure of GIST messages,
+ * they may be used in other contexts as well because of the coding shemes.
+ */
+
+#include "ie.h"
+#include "logfile.h"
+
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <sstream>
+#include <iomanip>
+
+namespace protlib {
+  using namespace log;
+
+
+
+/** @addtogroup ie Information Elements
+ * @{
+ */
+
+/***** class IE *****/
+
+/** Constructor. Sets category of IE. */
+IE::IE(uint16 category) : category(category) {}
+
+IE::IE(const IE& n) : category(n.category) {}
+
+/** Get the category of the IE. */
+uint16 IE::get_category() const {
+	return category;
+} // end get_category
+
+/** Check arguments of IE deserialization member functions.
+ * Additionally, bread is set to 0.
+ */ 
+bool IE::check_deser_args(coding_t cod, IEErrorList& errorlist, uint32 &bread) const {
+	bread = 0;
+	// check coding
+	if (!supports_coding(cod)) {
+	  Log(ERROR_LOG,LOG_NORMAL, "IE", "IE::check_deser_args(): IE " << get_ie_name() << " does not support coding " << cod );
+	  catch_bad_alloc(errorlist.put(new IEError(IEError::ERROR_CODING)));
+	  return false;
+	} // end if cod
+	return true;
+} // end check_deser_args()
+
+/** Check arguments of IE serialization member functions.
+ * Additionally, wbytes is set to 0.
+ */ 
+void IE::check_ser_args(coding_t cod, uint32 &wbytes) const {
+	wbytes = 0;
+	// check IE state
+	if (!check()) {
+		IEError err(IEError::ERROR_INVALID_STATE);
+		Log(ERROR_LOG,LOG_NORMAL, "IE", "IE::check_ser_args() for IE " << get_ie_name() << ", error: " << err.getstr());
+		throw err;
+	} // end if !check()
+	// check coding
+	if (!supports_coding(cod)) {
+		IEError err(IEError::ERROR_CODING);
+		Log(ERROR_LOG,LOG_NORMAL, "IE", "IE::check_ser_args() for IE " << get_ie_name() << ", error: " << err.getstr() << ", coding: " << cod);
+		throw err;
+	} // end if cod
+	return;
+} // end check_ser_args()
+
+
+/** Print the content of the IE, default behaviour is to print its name.
+ * Level and indent control how much space is inserted after a newline.
+ * If name points to a string, this string is printed before the
+* get_ie_name().
+ */
+ostream& IE::print(ostream& os, uint32 level, const uint32 indent, const char* name) const {
+	os<<setw(level*indent)<<"";
+	if (name && (*name!=0)) os<<name<<" ";
+	os<<"<"<<get_ie_name()<<">";
+	return os;
+} // end print
+
+istream& IE::input(istream& is, bool istty, uint32 level, const uint32 indent, const char* name) {
+  Log(ERROR_LOG,LOG_NORMAL, "IE", "IE " << get_ie_name() << "::input not yet implemented");
+  if (istty) {
+    cout<<setw(level*indent)<<"";
+    if (name && (*name!=0)) cout<<name<<" ";
+    cout<<"<"<<get_ie_name()<<">: Input not yet implemented."<<endl;
+  } // end if istty
+  return is;
+} // end input
+
+/** Print the IE to a string using print() and stringstream. */
+string IE::to_string(const char* name) const {
+	ostringstream os;
+	print(os,0,3,name);
+	return os.str();
+} // end to_string
+
+/** Log and throw a nomem_error */
+void IE::throw_nomem_error() const {
+	try {
+	  Log(ERROR_LOG,LOG_CRIT, "IE", "Not enough memory for IE " << get_ie_name());
+	} catch(...) {}
+	throw IEError(IEError::ERROR_NO_MEM);
+} // end throw_nomem_error
+
+/** Set all pointers to external data to NULL.
+ * By default this does nothing because there are no pointers.
+ */
+void IE::clear_pointers() {}
+
+
+/***** class IEError *****/
+
+/// IEError strings
+const char* IEError::err_str[] = {
+	"Error while registering IE. Either pointer to IE is NULL or registered IE already.",
+	"IE coding scheme is not supported by this function.",
+	"IE category is not supported by this function or in the applied coding scheme.",
+	"IE Manager instance does not exist (possible mem alloc problem?)",
+	"NetMsg too short for (de)serialization.",
+	"IE is in invalid state.",
+	"Wrong/unexpected IE type.",
+	"Wrong/unexpected IE subtype.",
+	"Wrong IE length.",
+	"Not enough memory to allocate IE.",
+	"Too big for this protocol implementation.",
+	"Unknown error code for this error class.",
+	"Wrong or unknown protocol version.",
+	"Unexpected object",
+	"PDU syntax error",
+	"PDU Object set failed (wrong index)",
+	"Protocol Specific Error"
+};
+
+
+/**
+ * Constructor.
+ *
+ * Initialize an IEError object by setting the error code.
+ *
+ * @warning Don't instantiate IEError. Use a child class instead!
+ *
+ * @param error the kind of error this exception represents
+ */
+IEError::IEError(error_t error) : ProtLibException(err_str[error]), err(error) {
+	// nothing to do
+}
+
+
+IEError::IEError(std::string msg) throw ()
+		: ProtLibException(msg), err(ERROR_UNKNOWN_ERRORCODE) {
+
+	// nothing to do
+}
+
+
+/**
+ * Destructor.
+ *
+ * This has only been defined to prevent compiler warnings.
+ */
+IEError::~IEError() throw () {
+	// nothing to do
+}
+
+
+/**
+ * Returns an error message.
+ *
+ * Note: what() returns more useful messages.
+ *
+ * @return the error message
+ */
+const char* IEError::getstr() const {
+	return err_str[err];
+}
+
+
+/***** class PDUSyntaxError *****/
+
+/**
+ * Constructor.
+ *
+ * @deprecated This constructor shouldn't be used for new code.
+ *
+ * @param msg an error message describing the problem
+ */
+PDUSyntaxError::PDUSyntaxError(const char* msg)
+		: IEError(IEError::ERROR_PDU_SYNTAX),
+		  coding(coding), category(0), type(0), subtype(0),
+		  errorpos(0), message(msg) {
+
+	ostringstream ost;
+	ost << "[coding " << coding << ", cat " << category << ", type " << type
+		<< ", subtype " << subtype << "] " << message;
+
+	error_msg = ost.str();
+}
+
+
+/**
+ * Constructor.
+ *
+ * @param coding the protocol version
+ * @param category the IE's category
+ * @param type the IE's type
+ * @param subtype the IE's subtype
+ * @param pos the position in the NetMsg at which the problem was discovered
+ * @param msg a message describing the problem
+ */
+PDUSyntaxError::PDUSyntaxError(IE::coding_t coding, uint16 category,
+		uint16 type, uint16 subtype, uint32 pos, const char *msg)
+		: IEError(IEError::ERROR_PDU_SYNTAX),
+		  coding(coding), category(category), type(type),
+		  subtype(subtype), errorpos(pos), message(msg) {
+
+	ostringstream ost;
+	ost << "[coding " << coding << ", cat " << category << ", type " << type
+		<< ", subtype " << subtype << "] " << message;
+
+	error_msg = ost.str();
+}
+
+
+/***** class IEMsgTooShort *****/
+
+/**
+ * Constructor.
+ *
+ * @param coding the protocol version
+ * @param category the IE's category
+ * @param pos the position in the NetMsg at which the problem was discovered
+ */
+IEMsgTooShort::IEMsgTooShort(IE::coding_t coding, uint16 category, uint32 pos) 
+		: IEError(ERROR_MSG_TOO_SHORT),
+		  coding(coding), category(category), errorpos(pos) {
+
+	ostringstream ost;
+	ost << "[coding " << coding << ", cat " << category
+		<< ", pos" << errorpos << IEError::getstr();
+
+	error_msg = ost.str();
+}
+
+
+/***** class IEWrongVersion *****/
+
+/**
+ * Constructor.
+ *
+ * @param coding the protocol version
+ * @param category the IE's category
+ * @param pos the position in the NetMsg at which the problem was discovered
+ */
+IEWrongVersion::IEWrongVersion(IE::coding_t coding, uint16 category, uint32 pos)
+		: IEError(ERROR_WRONG_VERSION),
+		  coding(coding), category(category), errorpos(pos) {
+
+	ostringstream ost;
+	ost << "[coding " << coding << ", cat " << category
+		<< ", pos" << errorpos << IEError::getstr();
+
+	error_msg = ost.str();
+}
+
+
+/***** class IEWrongType *****/
+
+/**
+ * Constructor.
+ *
+ * @deprecated This constructor should not be used for new code.
+ *
+ * @param coding the protocol version
+ * @param category the IE's category
+ * @param pos the position in the NetMsg at which the problem was discovered
+ */
+IEWrongType::IEWrongType(IE::coding_t coding, uint16 category, uint32 pos) 
+		: IEError(ERROR_WRONG_TYPE), coding(coding),
+		  category(category), type(0), errorpos(pos) {
+
+	ostringstream ost;
+	ost << "[coding " << coding << ", cat " << category << ", type " << type
+		<< ", pos" << errorpos << IEError::getstr();
+
+	error_msg = ost.str();
+}
+
+
+/**
+ * Constructor.
+ *
+ * @param coding the protocol version
+ * @param category the IE's category
+ * @param type the IE's type
+ * @param pos the position in the NetMsg at which the problem was discovered
+ */
+IEWrongType::IEWrongType(IE::coding_t coding, uint16 category, uint16 type,
+		uint32 pos) 
+		: IEError(ERROR_WRONG_TYPE), coding(coding),
+		  category(category), type(type), errorpos(pos) {
+
+	ostringstream ost;
+	ost << "[coding " << coding << ", cat " << category << ", type " << type
+		<< ", pos" << errorpos << IEError::getstr();
+
+	error_msg = ost.str();
+}
+
+
+/***** class IEWrongSubtype *****/
+
+/**
+ * Constructor.
+ *
+ * @deprecated This constructor should not be used for new code.
+ *
+ * @param coding the protocol version
+ * @param category the IE's category
+ * @param type the IE's type
+ * @param pos the position in the NetMsg at which the problem was discovered
+ */
+IEWrongSubtype::IEWrongSubtype(IE::coding_t coding, uint16 category,
+		uint16 type, uint32 pos) 
+		: IEError(ERROR_WRONG_SUBTYPE), coding(coding),
+		  category(category), type(type), subtype(0), errorpos(pos) {
+
+	ostringstream ost;
+	ost << "[coding " << coding << ", cat " << category << ", type " << type
+		<< ", subtype " << subtype << ", pos" << errorpos
+		<< IEError::getstr();
+
+	error_msg = ost.str();
+}
+
+
+/**
+ * Constructor.
+ *
+ * @param coding the protocol version
+ * @param category the IE's category
+ * @param type the IE's type
+ * @param subtype the IE's subtype
+ * @param pos the position in the NetMsg at which the problem was discovered
+ */
+IEWrongSubtype::IEWrongSubtype(IE::coding_t coding, uint16 category,
+		uint16 type, uint16 subtype, uint32 pos) 
+		: IEError(ERROR_WRONG_SUBTYPE),
+		  coding(coding), category(category), type(type),
+		  subtype(subtype), errorpos(pos) {
+
+	ostringstream ost;
+	ost << "[coding " << coding << ", cat " << category << ", type " << type
+		<< ", subtype " << subtype << ", pos" << errorpos
+		<< IEError::getstr();
+
+	error_msg = ost.str();
+}
+
+
+/***** class IEWrongLength *****/
+
+/**
+ * Constructor.
+ *
+ * The category, type and subtype parameters refer to the IE throwing the
+ * exception.
+ *
+ * @param coding the protocol version
+ * @param category the IE's category
+ * @param type the IE's type
+ * @param subtype the IE's subtype
+ * @param pos the position in the NetMsg at which the problem was discovered
+ */
+IEWrongLength::IEWrongLength(IE::coding_t coding, uint16 category, uint16 type,
+		uint16 subtype, uint32 pos) 
+		: IEError(ERROR_WRONG_LENGTH),
+		  coding(coding), category(category), type(type),
+		  subtype(subtype), errorpos(pos) {
+
+	ostringstream ost;
+	ost << "[coding " << coding << ", cat " << category << ", type " << type
+		<< ", subtype " << subtype << ", pos" << errorpos
+		<< IEError::getstr();
+
+	error_msg = ost.str();
+}
+
+
+/***** class IETooBigForImpl *****/
+
+/**
+ * Constructor.
+ *
+ * @param coding the protocol version
+ * @param category the IE's category
+ * @param pos the position in the NetMsg at which the problem was discovered
+ */
+IETooBigForImpl::IETooBigForImpl(IE::coding_t coding, uint16 category,
+		uint32 pos) 
+		: IEError(ERROR_TOO_BIG_FOR_IMPL),
+		  coding(coding), category(category), errorpos(pos) {
+
+	ostringstream ost;
+	ost << "[coding " << coding << ", cat " << category
+		<< ", pos" << errorpos << IEError::getstr();
+
+	error_msg = ost.str();
+}
+
+
+/***** class IEProtocol *****/
+
+/**
+ * Constructor.
+ *
+ * @param coding the protocol version
+ * @param category the IE's category
+ * @param pos the position in the NetMsg at which the problem was discovered
+ */
+IEProtocolSpecific::IEProtocolSpecific(IE::coding_t coding, uint16 category,
+		uint32 pos) 
+		: IEError(ERROR_PROT_SPECIFIC),
+		  coding(coding), category(category), errorpos(pos) {
+
+	ostringstream ost;
+	ost << "[coding " << coding << ", cat " << category
+		<< ", pos" << errorpos << IEError::getstr();
+
+	error_msg = ost.str();
+}
+
+
+/***** class IEErrorList *****/
+
+/** Insert IE Error into list. */
+void IEErrorList::put(IEError* iee) {
+	if (iee) queue.push_front(iee);
+} // end put
+
+/** Get and remove IE Error from the list. 
+ * Returns NULL if list is empty.
+ */
+IEError* IEErrorList::get() {
+	register IEError* iee;
+	if (queue.empty()) return NULL;
+	else {
+		iee = queue.back();
+		queue.pop_back();
+		return iee;
+	} // end if
+} // end get
+
+/** Is the IE error list empty? */
+bool IEErrorList::is_empty() const {
+	return queue.empty();
+} // end is_empty
+
+/** clear IE error list and destroy all stored IE error objects. */
+void IEErrorList::clear() {
+	queueit_t qit;
+	// delete IEError objects in queue
+	for (qit=queue.begin();qit!=queue.end();++qit)
+		if (*qit) delete *qit;
+	// clear queue
+	queue.clear();		
+} // end clear
+
+/** Destroy IEError list and all IEError objects in it. */
+IEErrorList::~IEErrorList() {
+	if (!queue.empty()) {
+	  Log(DEBUG_LOG,LOG_CRIT, "IE", "Destroying non-empty IEErrorList, deleting IEError objects.");
+	  clear();
+	} // end if not empty
+} // end ~IEErrorList
+
+
+/***** class IEManager *****/
+
+
+/**
+ * Constructor.
+ */
+IEManager::IEManager() {
+	// nothing to do
+}
+
+
+/**
+ * Destructor.
+ *
+ * All registered IEs are deleted.
+ */
+IEManager::~IEManager() {
+	// iterator shortcuts
+	typedef category_map_t::const_iterator c_iter;
+
+	/*
+	 * Walk through all registered IEs and delete them.
+	 */
+	int num_deleted = 0;
+
+	for (c_iter i = registry.begin(); i != registry.end(); i++) {
+		IE *ie = i->second;
+
+		if ( ie != NULL ) {
+			delete ie;
+			num_deleted++;
+		}
+	}
+
+	DLog("IEManager", "Deleted " << num_deleted << " IEs");
+}
+
+
+/** 
+ * Register an Information Element.
+ *
+ * Make the IE object passed as the argument register itself with this
+ * IEManager. See IE's register_ie() method for the rules.
+ *
+ * This method exists for convenience only, please see the other register_ie()
+ * method for details.
+ *
+ * @param ie pointer to IE (NULL is not allowed)
+ */
+void IEManager::register_ie(const IE* ie) {
+	if ( ie == NULL )
+		throw IEError(IEError::ERROR_REGISTER);
+
+	return ie->register_ie(this);
+}
+
+
+/**
+ * Register an Information Element.
+ *
+ * Register an IE for the given category, type and subtype. It is not allowed
+ * to register more than one IE for a (category, type, subtype) triple.
+ *
+ * It is @em very important that each IE instance is registered only once.
+ * If a class can handle multiple (category, type, subtype) triples, one
+ * instance per triple has to be registered.
+ * 
+ * There is no way to unregister an IE. All registered IEs will be deleted
+ * by IEManager's destructor.
+ *
+ * @param category category of the IE
+ * @param type IE type
+ * @param subtype IE subtype
+ * @param ie the IE to register (NULL is not allowed)
+ */
+void IEManager::register_ie(uint16 category, uint16 type, uint16 subtype,
+		const IE* ie) {
+
+	// for logging
+	ostringstream triple;
+	triple << "(" << category << ", " << type << ", " << subtype << ")";
+
+	if ( ie == NULL )
+		throw IEError(IEError::ERROR_REGISTER);
+
+	IE_Key key(category, type, subtype);
+
+	// don't allow overwriting
+	if ( registry[key] != NULL ) {
+		ERRLog("IEManager",
+			"An IE is already " << "registered for " << triple);
+		return;
+	}
+
+
+	try {
+		registry[key] = const_cast<IE *>(ie);
+	}
+	catch ( ... ) {
+		ERRLog("IEManager", "Cannot register IE for " << triple);
+
+		throw IEError(IEError::ERROR_REGISTER);
+	}
+
+	// We made it so far, this means success.
+	DLog("IEManager",
+		"Registered IE " << ie->get_ie_name() << " for " << triple);
+}
+
+
+/**
+ * Create a new instance.
+ *
+ * Creates a new instance using the appropriate registered IE. The definition
+ * of @em appropriate depends on lookup_ie().
+ *
+ * Note that some old IEManager child classes called this method lookup().
+ * This old lookup() method should not be confused with lookup_ie().
+ *
+ * @param category category of the IE
+ * @param type IE type
+ * @param subtype IE subtype
+ * @return a new instance, or NULL if no matching IE is found
+ */
+IE *IEManager::new_instance(uint16 category, uint16 type, uint16 subtype) {
+	IE *ie = lookup_ie(category, type, subtype);
+
+	if ( ie )
+		return ie->copy();
+	else
+		return NULL;
+}
+
+
+/**
+ * Return a registered IE.
+ *
+ * Returns a registered IE instance. It does @em not create a new instance,
+ * it is really an instance you registered earlier. Use new_instance() if
+ * you need new instances!
+ *
+ * This method is an extension point that can be used, for example, to return
+ * "default" IEs if no matching IE is found in the registry.
+ *
+ * @param category category of the IE
+ * @param type IE type
+ * @param subtype IE subtype
+ * @return a registered instance, or NULL if no matching IE is found
+ */
+IE *IEManager::lookup_ie(uint16 category, uint16 type, uint16 subtype) {
+	return registry[IE_Key(category, type, subtype)];
+}
+
+
+/**
+ * Throw an exception and log it.
+ */
+void IEManager::throw_nomem_error() const {
+	try {
+		ERRLog("IEManager", "Out of memory.");
+	}
+	catch ( ... ) {
+		// There's no way to handle this!
+	}
+
+	throw IEError(IEError::ERROR_NO_MEM);
+}
+
+
+/***** operator<< and >> *****/
+
+/** Print the given IE to the ostream using level=0 and indent=3. */
+ostream& operator<<(ostream& os, const IE& ie) {
+	ie.print(os,0,3);
+	return os;
+} // end operator<<
+
+istream& operator>>(istream& is, IE& ie) {
+	ie.input(is,isatty(0),0,3);
+	return is;
+} // end operator>>
+
+//@}
+
+} // end namespace protlib
Index: /source/ariba/utility/transport/tcpip/protlib/ie.h
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/ie.h	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/ie.h	(revision 5284)
@@ -0,0 +1,500 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file ie.h
+/// Basic information elements (PDUs and PDU objects)
+/// ----------------------------------------------------------
+/// $Id: ie.h 2549 2007-04-02 22:17:37Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/ie.h $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+
+/** @ingroup ie
+ * @todo Use objectpool by deriving classes from class poolobject and
+ * linking executables against objectpool.o or including objectpool.o into
+ * libie.a.
+ *
+ * This header file defines the base class of all information elements, the
+ * information elements for the protocol and an IE manager object.
+ *
+ * For performance only pointers are exchanged. The copy member function is
+ * the way to duplicate an IE. It does much the same as a copy constructor
+ * but returns not the IE but a pointer to it. If the IE contains pointers,
+ * their target objects are copied too.
+ */
+
+#ifndef _PROTLIB__IE_H_
+#define _PROTLIB__IE_H_
+
+#include <ext/hash_map>
+#include <deque>
+#include <string>
+#include <iostream>
+#include <map>
+
+#include "protlib_types.h"
+#include "network_message.h"
+
+namespace protlib {
+
+
+
+/** @addtogroup ie Information Elements
+ * @{
+ */
+
+/// Catch bad_alloc and call throw_nomem_error
+#define catch_bad_alloc(x) try { x; } catch(bad_alloc) { throw_nomem_error(); }
+
+// forward declarations
+class IEManager;
+class IEErrorList;
+class IEError;
+
+/** Abstract Information Element (IE) interface
+ */
+class IE {
+public:
+	virtual ~IE() { }
+
+	friend class IEManager;
+	/// IE coding sheme
+	/** All coding shemes have to be listed here. Each IE should support at
+	 * least one listed coding sheme. This is used when serializing or
+	 * deserializing from a NetMsg object to (de)code the IE in the right way.
+	 * Note that coding schemes and protocol version are not the same.
+	 * There could also be a coding sheme to (de)code IEs e.g. for router
+	 * configuration.
+	 */
+	enum coding_t {
+	  nslp_v1     = 1,
+	  protocol_v1 = 1,
+	  protocol_v2 = 2,
+	  nslp_v2     = 3,
+	  nslp_v2_yoda = 4
+	}; // end coding_t
+protected:
+	/// contructor
+	IE(uint16 category);
+	/// copy constructor
+	IE(const IE& n);
+public:
+	/// get a new instance of the IE
+	virtual IE* new_instance() const = 0;
+	/// copy an IE
+	virtual IE* copy() const = 0;
+	/// deserialization
+	virtual IE* deserialize(NetMsg& msg, coding_t coding, IEErrorList& errorlist, uint32& bread, bool skip = true) = 0;
+	/// serialize
+	virtual void serialize(NetMsg& msg, coding_t coding, uint32& wbytes) const = 0;
+protected:
+	/// check arguments for deserialization
+	bool check_deser_args(coding_t cod, IEErrorList& errorlist, uint32 &bread) const;
+	/// check arguments for serialization
+	void check_ser_args(coding_t cod, uint32 &wbytes) const;
+public:
+	/// IE consistency check
+	virtual bool check() const = 0;
+	/// check if IE supports coding sheme
+	virtual bool supports_coding(coding_t c) const = 0;
+	/// IE serialized size
+	virtual size_t get_serialized_size(coding_t coding) const = 0;
+	/// get category
+	uint16 get_category() const;
+	/// equality
+	virtual bool operator==(const IE& ie) const = 0;
+	/// not equal
+	inline bool operator!=(const IE& ie) const { return (!(*this==ie)); }
+	/// get IE name
+	/** This is mainly for error reporting. */
+	virtual const char* get_ie_name() const = 0;
+	/// print to a ostream
+	virtual ostream& print(ostream& os, uint32 level, const uint32 indent, const char* name = NULL) const;
+	/// get a string representing the IE content
+	string to_string(const char* name = 0) const;
+	/// input from an istream
+	/** Attention: No checking, no warnings. This is ONLY for testing. */
+	virtual istream& input(istream& is, bool istty, uint32 level, const uint32 indent, const char* name = NULL);
+	/// clear all pointer fields
+	virtual void clear_pointers();
+protected:
+	/// register this IE
+	virtual void register_ie(IEManager *iem) const = 0;
+	/// IE category
+	const uint16 category;
+	/// throw a NO_MEM exception
+	void throw_nomem_error() const;
+}; // end class IE
+
+
+
+/**
+ * IE Error base class.
+ *
+ * This is the base for all exceptions thrown during serialize() and
+ * deserialize().
+ *
+ * @warning New code should use the exceptions derived from this class.
+ * This class should be abstract but isn't for compatibility reasons.
+ */
+class IEError : public ProtLibException {
+  public:
+	/// IE error code - common parsing errors
+	enum error_t {
+		ERROR_REGISTER,
+		ERROR_CODING,
+		ERROR_CATEGORY,
+		ERROR_NO_IEMANAGER,
+		ERROR_MSG_TOO_SHORT,
+		ERROR_INVALID_STATE,
+		ERROR_WRONG_TYPE,
+		ERROR_WRONG_SUBTYPE,
+		ERROR_WRONG_LENGTH,
+		ERROR_NO_MEM,
+		ERROR_TOO_BIG_FOR_IMPL,
+		ERROR_UNKNOWN_ERRORCODE,
+		ERROR_WRONG_VERSION,
+		ERROR_UNEXPECTED_OBJECT,
+		ERROR_PDU_SYNTAX,
+		ERROR_OBJ_SET_FAILED,
+		ERROR_PROT_SPECIFIC
+	}; // end error_t
+
+	const error_t err;
+
+	IEError(error_t e);
+	virtual ~IEError() throw ();
+
+	virtual const char *getstr() const;
+
+  protected:
+	IEError(std::string msg) throw ();
+
+  private:
+	static const char* err_str[];
+};
+
+
+/**
+ * Syntax error during deserialization.
+ *
+ * This exception is thrown if a syntax error is detected during
+ * deserialization.
+ */
+class PDUSyntaxError : public IEError {
+  public:
+	PDUSyntaxError(const char* msg); // deprecated!
+	PDUSyntaxError(IE::coding_t coding, uint16 category, uint16 type,
+			uint16 subtype, uint32 pos, const char *msg = "");
+	virtual ~PDUSyntaxError() throw () { }
+
+	const IE::coding_t coding;
+	const uint16 category;
+	const uint16 type;
+	const uint16 subtype;
+	const uint32 errorpos;
+	const string message;
+};
+
+
+/**
+ * NetMsg is too short to serialize/deserialize.
+ *
+ * This exception is typically thrown if a NetMsg ended unexpectedly
+ * which indicates a truncated message. It may also be thrown if a
+ * NetMsg is too short to hold a serialized IE object.
+ */
+class IEMsgTooShort : public IEError {
+  public:
+	IEMsgTooShort(IE::coding_t coding, uint16 category, uint32 pos);
+	virtual ~IEMsgTooShort() throw () { }
+
+	const IE::coding_t coding;
+	const uint16 category;
+	const uint32 errorpos;
+};
+
+
+/**
+ * Wrong protocol version.
+ *
+ * This exception is thrown in case of a version conflict, like a
+ * deserialize() method not being able to handle a coding.
+ */
+class IEWrongVersion : public IEError {
+  public:
+	IEWrongVersion(IE::coding_t coding, uint16 category, uint32 pos);
+	virtual ~IEWrongVersion() throw () { }
+
+	const IE::coding_t coding;
+	const uint16 category;
+	const uint32 errorpos;
+};
+
+
+/**
+ * Invalid IE type.
+ *
+ * Typically thrown if deserialize() fails because there is no matching IE
+ * registered with the IEManager.
+ */
+class IEWrongType : public IEError {
+  public:
+	// The first constructor is deprecated!
+	IEWrongType(IE::coding_t coding, uint16 category, uint32 pos);
+	IEWrongType(IE::coding_t coding, uint16 category, uint16 type,
+			uint32 pos);
+	virtual ~IEWrongType() throw () { }
+
+	const IE::coding_t coding;
+	const uint16 category;
+	const uint16 type;
+	const uint32 errorpos;
+};
+
+
+/**
+ * Invalid IE subtype.
+ *
+ * Typically thrown if deserialize() fails because there is no matching IE
+ * registered with the IEManager.
+ */
+class IEWrongSubtype : public IEError {
+  public:
+	// The first constructor is deprecated!
+	IEWrongSubtype(IE::coding_t coding, uint16 category, uint16 type,
+			uint32 pos);
+	IEWrongSubtype(IE::coding_t coding, uint16 category, uint16 type,
+			uint16 subtype, uint32 pos);
+	virtual ~IEWrongSubtype() throw () { }
+
+	const IE::coding_t coding;
+	const uint16 category;
+	const uint16 type;
+	const uint16 subtype;
+	const uint32 errorpos;
+};
+
+
+/**
+ * An invalid length field was read.
+ *
+ * This exception is thrown if a length field inside a NetMsg has a wrong
+ * length (either too long or too short, but makes no sense). Note that
+ * this overlaps with IEMsgTooShort in some cases.
+ */
+class IEWrongLength : public IEError {
+  public:
+	IEWrongLength(IE::coding_t coding, uint16 category, uint16 type,
+			uint16 subtype, uint32 pos);
+	virtual ~IEWrongLength() throw () { }
+
+	const IE::coding_t coding;
+	const uint16 category;
+	const uint16 type;
+	const uint16 subtype;
+	const uint32 errorpos;
+};
+
+
+/**
+ * Some entity is too big for this implementation.
+ *
+ * This exception is thrown if an operation can't be performed because
+ * of some implementation limit.
+ */
+class IETooBigForImpl : public IEError {
+  public:
+	IETooBigForImpl(IE::coding_t coding, uint16 category, uint32 pos);
+	virtual ~IETooBigForImpl() throw () { }
+
+	const IE::coding_t coding;
+	const uint16 category;
+	const uint32 errorpos;
+};
+
+
+/**
+ * Protocol Specific Error
+ *
+ * This exception is thrown if a protocol specific error
+ * occurred.
+ */
+class IEProtocolSpecific : public IEError {
+  public:
+	IEProtocolSpecific(IE::coding_t coding, uint16 category, uint32 pos);
+	virtual ~IEProtocolSpecific() throw () { }
+
+	const IE::coding_t coding;
+	const uint16 category;
+	const uint32 errorpos;
+};
+
+
+/// IE error list
+/** This represents a list of IE errors. */
+class IEErrorList {
+public:
+	/// put an IEError on the list
+	void put(IEError* iee);
+	/// get and remove next IEError
+	IEError* get();
+	/// is list empty
+	bool is_empty() const;
+	/// clear list
+	void clear();
+	/// destructor
+	~IEErrorList();
+private:
+	/// internal queue type
+	typedef deque<IEError*> queue_t;
+	/// queue iterator type
+	typedef queue_t::iterator queueit_t;
+	/// IEError storage
+	queue_t queue;
+}; // end IEErrorList
+
+
+/**
+ * Represents a (category, type, subtype) tuple.
+ *
+ * Used internally by IEManager.
+ */
+class IE_Key {
+  public:
+	inline IE_Key(uint16 category, uint16 type, uint16 subtype)
+		: category(category), type(type), subtype(subtype) { }
+
+	inline bool operator==(const IE_Key &other) const {
+		return category == other.category && type == other.type
+			&& subtype == other.subtype;
+	}
+
+	inline uint16 get_category() const { return category; }
+	inline uint16 get_type() const { return type; }
+	inline uint16 get_subtype() const { return subtype; }
+
+  private:
+	uint16 category;
+	uint16 type;
+	uint16 subtype;
+};
+
+struct hash_IE_Key {
+	inline size_t operator()(const protlib::IE_Key &k) const {
+		return (k.get_category() << 16)
+			| ( k.get_type() ^ k.get_subtype() );
+	}
+};
+
+
+/** 
+ * A registry and factory for IEs.
+ *
+ * Each IE has to register at the IE Manager. The IEManager then provides
+ * methods to deserialize IEs from or serialize IEs to a NetMsg object.
+ * IEManager is abstract and thus can't be instantiated.
+ *
+ * In contrast to earlier implementations, IEManager itself is no longer a
+ * singleton. Inheriting from singletons is a tricky business in C++ (and
+ * much easier in Java) because static methods can't be virtual. Because
+ * of this, multiple badly implemented child classes were unable to coexist
+ * in a single program.
+ *
+ * The following has to be done in each protocol to use IEManager and
+ * create a protocol-specific singleton (called PROT_IEManager):
+ *
+ *   - Inherit from IEManager.
+ *   - Make the constructor private.
+ *   - Provide a "private: static PROT_IEManager *inst" attribute.
+ *   - Provide a "public: static PROT_IEManager *instance()" method.
+ *   - Provide a "public: static void clear()" method.
+ *   - Define your own category_t with categories appropriate for your protocol.
+ * 
+ * An example implementation can be found in the QSPEC code. Please note that
+ * old code (r286 and earlier) won't compile because of interface changes.
+ * The ability to register "default" IEs that are returned if no more specific
+ * IE is found has been removed because it depended on coding_t. If derived
+ * IEManagers need this functionality, they have to override lookup_ie().
+ * 
+ */
+class IEManager {
+
+  public:
+	virtual ~IEManager();
+
+	virtual void register_ie(const IE *ie);
+	virtual void register_ie(uint16 category, uint16 type, uint16 subtype,
+			const IE *ie);
+
+	virtual IE *new_instance(uint16 category, uint16 type, uint16 subtype);
+
+	virtual void serialize(IE &ie, NetMsg &msg, IE::coding_t coding,
+			uint32 &bytes_written) const;
+
+	virtual IE *deserialize(NetMsg &msg, uint16 category,
+			IE::coding_t coding, IEErrorList& errorlist,
+			uint32 &bytes_read, bool skip = true) = 0;
+
+  protected:
+	IEManager();
+
+	virtual IE *lookup_ie(uint16 category, uint16 type, uint16 subtype);
+
+	virtual void throw_nomem_error() const;
+
+  private:
+	typedef hash_map<IE_Key, IE *, hash_IE_Key> category_map_t;
+
+	category_map_t registry;
+};
+
+
+/** This mainly calls the serialize member function of the given IE.
+ * @param ie pointer to an IE
+ * @param msg NetMsg object that will hold the serialized IE.
+ * @param coding IE coding sheme
+ * @param wbytes number of output bytes
+ */
+inline
+void IEManager::serialize(IE& ie, NetMsg& msg, IE::coding_t coding, uint32& wbytes) const {
+	ie.serialize(msg,coding,wbytes);
+} // end serialize
+
+
+/// print an IE to an ostream
+ostream& operator<<(ostream& os, const IE& ie);
+
+/// input operator
+istream& operator>>(istream& is, IE& ie);
+
+/// round uint32 up
+/** Adds up the given uint32 to fit a 32-bit or 4-byte border. */
+inline uint32 round_up4(uint32 i) {
+	if (i%4) i = i-(i%4)+4;
+	return i;
+} // end round_up4
+
+//@}
+
+} // end namespace protlib
+
+#endif // _PROTLIB__IE_H_
Index: /source/ariba/utility/transport/tcpip/protlib/llhashers.h
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/llhashers.h	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/llhashers.h	(revision 5284)
@@ -0,0 +1,59 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file llhashers.h
+/// hash functions for long longs
+/// ----------------------------------------------------------
+/// $Id: llhashers.h 2872 2008-02-18 10:58:03Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/llhashers.h $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+
+#ifndef PROTLIB_LL_HASHERS_H
+#define PROTLIB_LL_HASHERS_H
+
+
+/** @addtogroup hashers Hash function objects
+ *
+ * This file contains definitions of hash functions 
+ * for long long (64 bit integers)
+ *
+ * @{
+ */
+
+namespace __gnu_cxx {
+
+/// long long int hasher
+template <> struct hash<long long> {
+	inline size_t operator()(long long i) const { return (size_t)i; }
+}; // end long long hasher
+
+/// unsigned long long int hasher
+template <> struct hash<unsigned long long> {
+	inline size_t operator()(unsigned long long i) const { return (size_t)i; }
+}; // end unsigned long long hasher
+
+} // end namespace __gnu_cxx
+
+
+//@}
+
+#endif
Index: /source/ariba/utility/transport/tcpip/protlib/logfile.cpp
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/logfile.cpp	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/logfile.cpp	(revision 5284)
@@ -0,0 +1,187 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file logfile.cpp
+/// Implementation of a logging stream
+/// ----------------------------------------------------------
+/// $Id: logfile.cpp 2549 2007-04-02 22:17:37Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/src/logfile.cpp $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+#include "logfile.h"
+#include <iostream>
+#include <iomanip>
+#include <new>
+
+#include <time.h>
+#include <sys/time.h> // gettimeofday
+
+namespace protlib {
+
+using namespace std;
+
+  namespace log {
+
+const char *const ANSIcolorcode[]= {
+  "[0m",  // clear, off; reset; clears all colors and styles (to white on black)
+  "[1m",  // bold_on		
+  "[3m",  // italics_on	
+  "[4m",  // underline_on	
+  "[7m",  // inverse_on	
+  "[9m",  // strikethrough_on	
+  "[22m", // bold_off		
+  "[23m", // italics_off	
+  "[24m", // underline_off	
+  "[27m", // inverse_off	
+  "[29m", // strikethrough_off
+  "[30m", // black  		
+  "[31m", // red    		
+  "[32m", // green  		
+  "[33m", // yellow 		
+  "[34m", // blue   		
+  "[35m", // magenta		
+  "[36m", // cyan   		
+  "[37m", // white  		
+  "[39m", // default		
+  "[40m", // bg_black  	
+  "[41m", // bg_red    	
+  "[42m", // bg_green  	
+  "[43m", // bg_yellow 	
+  "[44m", // bg_blue   	
+  "[45m", // bg_magenta	
+  "[46m", // bg_cyan   	
+  "[47m", // bg_white  	
+  "[49m"  // bg_default       
+};
+
+const char* color[num_colors+1];
+
+const char *const logclass_str[]=
+{
+  " ZERO  ",
+  "*ERROR*",
+  "WARNING",
+  " EVENT ",
+  " INFO  ",
+  " DEBUG ",
+  " EXPERT"
+};
+
+
+const char *const logseveritylevel_str[]=
+  {
+    "EMERG ",
+    "ALERT ",
+    "CRITIC",
+    "LEVEL3",
+    "NORMAL",
+    "LEVEL5",
+    "LEVEL6",
+    "LEVEL7",
+    "UNIMP ",
+    "LEVEL9",
+    "LEVELA",
+    "LEVELB",
+    "LEVELC",
+    "LEVELD",
+    "LEVELE",
+    "-ALL- "
+  };
+
+
+/** set logging destination to new filename
+ * @return true if logfile could be opened for given name
+ */
+bool
+logfile::set_dest(const char* filename, bool quiet)
+{
+  // lock everything
+  pthread_mutex_lock(&logmutex); 
+
+  if (logstream && !quiet)
+  {
+//     (*logstream) << color[blue] << timenow() << '[' << getpid() << "] Redirecting Log output to \"" << filename << '\"' << endl;
+//     (*logstream) << color[blue] << timenow() 
+// 		 << '[' << getpid() << "] <<<<<<<<<<<<<<<<<<<<<<<< *** LOG  STOP *** <<<<<<<<<<<<<<<<<<<<<<<<" 
+// 		 << color[off] << endl;
+  }
+
+  // delete old stream
+  if (logstream!= &cout)
+    delete logstream;
+
+  // allocate new stream
+  if (strlen(filename))
+    logstream= new(nothrow) ofstream(filename);
+  else
+    logstream= &cout;
+
+  pthread_mutex_unlock(&logmutex); 
+
+  if (!logstream)
+  {
+    cerr << "Could not open logfile " << filename << endl;
+    return false;
+  }
+  else
+  {
+//     (*logstream) << color[blue] << timenow() 
+// 		 << '[' << getpid() << "] >>>>>>>>>>>>>>>>>>>>>>>> *** LOG START *** >>>>>>>>>>>>>>>>>>>>>>>>" 
+// 		 << color[off] << endl;
+  }
+  return true;
+}
+
+
+ostream&
+logfile::logstart(logclass_t logclass, loglevel_t severity_level, 
+		  const string& modname,
+		  const char* file, 
+		  const char* func, 
+		  int line)
+{  
+  // lock logstream for writing, must be unlocked by logfile.end()
+  int mtxlck_ret= 0;
+  if ( (mtxlck_ret= pthread_mutex_lock(&logmutex)) )
+  {
+    cerr << color[red] << "logfile::logstart() ERROR while locking mutex - return code:" << mtxlck_ret << "/" << strerror(mtxlck_ret) << endl;
+  }
+
+  if ( logstream )
+  {
+    (*logstream) << (logclass==ERROR_LOG ? color[bold_on] : "")
+                 << (logclass==WARNING_LOG ? color[magenta] : 
+		     (logclass==ERROR_LOG ? color[red] : color[off])
+		    )
+                 << timenow()
+		 << '-' << getpid() << (logclass!=ERROR_LOG ? '-' : '*')
+		 << color[bold_on] << logclass_str[logclass>>4] << (logclass==ERROR_LOG ? color[bold_on] : color[bold_off])
+		 << (logclass!=ERROR_LOG ? '/' : '*') << hex << severity_level << dec
+		 << ": " << color[bold_on] << left << setfill(' ') << setw(15) << modname << color[bold_off] << right << " " << color[off];
+  }
+  
+  return (*logstream);
+}
+
+
+  } // end namespace log
+
+} // end namespace protlib
Index: /source/ariba/utility/transport/tcpip/protlib/logfile.h
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/logfile.h	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/logfile.h	(revision 5284)
@@ -0,0 +1,386 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file logfile.h
+/// Implementation of a logging stream
+/// ----------------------------------------------------------
+/// $Id: logfile.h 2549 2007-04-02 22:17:37Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/logfile.h $
+// ===========================================================
+//
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+#ifndef _logfile_h_
+#define _logfile_h_
+
+
+#define _NO_LOGGING
+
+#include <fstream> // file stream
+#include <iostream>
+
+#include <string.h>
+#include <pthread.h>
+#include <sys/time.h>
+#include <stdio.h> // sprintf
+#include <unistd.h> // getpid
+
+#include "protlib_types.h"
+
+namespace protlib {
+
+  using namespace std;
+/** @addtogroup log Logging
+ * @{
+ */
+
+namespace log {
+
+    static const pthread_mutex_t initlogmutex=
+#ifdef _DEBUG
+  // PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; // use this for debugging, it will return errors on potential deadlock situations
+  PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+#else // should be recursive mutex because sometimes error log output sometimes occurs
+  // while objects contents are logged
+  PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; // PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+#undef ERROR_LOG
+#undef WARNING_LOG
+#undef EVENT_LOG
+#undef INFO_LOG
+#undef DEBUG_LOG
+#undef LOG_TYPES
+
+#undef LOG_ALL
+#undef LOG_EMERG
+#undef LOG_ALERT
+#undef LOG_CRIT
+#undef LOG_NORMAL
+#undef LOG_UNIMP
+
+
+enum logclass_t
+{
+  ERROR_LOG= 0x10,
+  WARNING_LOG= 0x20,
+  EVENT_LOG= 0x30,
+  INFO_LOG=  0x40,
+  DEBUG_LOG= 0x50,
+  EVERY_LOG= 0xF0,
+  LOG_TYPES= 5
+};
+
+
+enum loglevel_t
+{
+  LOG_EMERG=  0,
+  LOG_ALERT=  1,
+  LOG_CRIT=   2,
+  LOG_NORMAL= 4,
+  LOG_UNIMP=  8,
+  LOG_ALL=   15
+};
+
+// colors
+
+enum color_t
+{
+clear,
+bold_on,
+italics_on,
+underline_on,
+inverse_on,
+strikethrough_on,
+bold_off,
+italics_off,
+underline_off,
+inverse_off,
+strikethrough_off,
+black,
+red,
+green,
+yellow,
+blue,
+magenta,
+cyan,
+white,
+fg_default,
+bg_black,
+bg_red,
+bg_green,
+bg_yellow,
+bg_blue,
+bg_magenta,
+bg_cyan,
+bg_white,
+bg_default,
+num_colors,
+off=0};
+
+extern const char* color[];
+extern const char *const ANSIcolorcode[];
+
+
+#define  ERRLog(mname, logstring) Log(ERROR_LOG, LOG_NORMAL, mname, logstring)
+#define  ERRCLog(mname, logstring) Log(ERROR_LOG, LOG_CRIT, mname, logstring)
+#define  EVLog(mname, logstring) Log(EVENT_LOG, LOG_NORMAL, mname, logstring)
+#define  WLog(mname, logstring) Log(WARNING_LOG, LOG_NORMAL, mname, logstring)
+#define  ILog(mname, logstring) Log(INFO_LOG, LOG_NORMAL, mname, logstring)
+#define  DLog(mname, logstring) Log(DEBUG_LOG, LOG_NORMAL, mname, logstring)
+
+
+#ifndef _NO_LOGGING
+
+// Log(lclass, llevel, mname, logstring)
+// lclass: logclass, llevel: severitylevel, mname: module or methodname,
+// logstring: things to log in stream notation
+#define  Log(lclass, llevel, mname, logstring) do {			\
+  if ( protlib::log::DefaultLog.should_log(lclass, llevel) ) {		\
+    using protlib::log::DefaultLog;					\
+    DefaultLog.logstart(lclass, llevel, mname) << logstring;		\
+    DefaultLog.logend();						\
+  }									\
+} while ( false )
+
+#define  LogS(lclass, llevel, mname, logstring) do {			\
+  if ( protlib::log::DefaultLog.should_log(lclass, llevel) ) {		\
+    protlib::log::DefaultLog.logstart(lclass, llevel, mname,		\
+	__FILE__, __FUNCTION__, __LINE__) << logstring;			\
+    protlib::log::DefaultLog.logend();					\
+  }									\
+} while ( false )
+
+#else
+
+#define  Log(logclass, loglevel, mname, logstring)
+#define  LogS(logclass, loglevel, mname, logstring)
+
+#endif
+
+class logfile
+{
+ private:
+  ostream* logstream;
+  pthread_mutex_t logmutex;
+
+  unsigned char logfilter[LOG_TYPES];
+
+  bool usecolors;
+  bool quiet_start;
+
+  const char* timenow();
+
+ public:
+
+  logfile(const char* filename="", bool usecolors= true, bool quietstart=false);
+  ~logfile();
+
+  bool set_dest(const char* filename, bool quiet=false);
+  void set_filter(logclass_t logclass, uint8 severitylevel);
+  bool should_log(logclass_t logclass, loglevel_t severitylevel);
+
+
+  ostream& logstart(logclass_t logclass, loglevel_t severity_level,
+		    const string& modname,
+		    const char* file="",
+		    const char* func="",
+		    int line=0);
+  void coloron() { usecolors=true; for (int i= 0; i<num_colors; i++) {color[i]= ANSIcolorcode[i]; } }
+  void coloroff() { usecolors=false; for (int i= 0; i<num_colors; i++) {color[i]= ""; } }
+
+  void logend();
+}; // end class logfile
+
+extern
+
+inline
+logfile::logfile(const char* filename,  bool usecolors, bool quietstart)
+  : logstream(0),
+    logmutex(initlogmutex),
+    usecolors(usecolors),
+    quiet_start(quietstart)
+{
+  for (int i= 0; i< LOG_TYPES; i++)
+    logfilter[i]= LOG_ALL;
+
+  if (strlen(filename))
+    logstream= new(nothrow) ofstream(filename);
+  else
+    logstream= &cout;
+
+  if (!logstream)
+  {
+    cerr << "Could not open logfile " << filename << endl;
+  }
+  else
+  {
+    pthread_mutex_lock(&logmutex);
+
+    // if enable colors, use ANSI code,
+    // if disable colors, so replace all strings with "";
+    for (int i= 0; i<num_colors; i++)
+    {
+      color[i]= (usecolors ? ANSIcolorcode[i] : "");
+    }
+
+    if (!quiet_start && logstream)
+    {
+//       (*logstream) << color[blue] << timenow()
+// 		   << '[' << getpid() << "] >>>>>>>>>>>>>>>>>>>>>>>> *** LOG START *** >>>>>>>>>>>>>>>>>>>>>>>>"
+// 		   << color[off] << endl;
+    }
+    pthread_mutex_unlock(&logmutex);
+  }
+}
+
+
+inline
+logfile::~logfile()
+{
+  if (logstream)
+  {
+    pthread_mutex_lock(&logmutex);
+
+    if ( ! quiet_start )
+// 	(*logstream) << color[blue] << timenow() << '[' << getpid()
+// 	<< "] <<<<<<<<<<<<<<<<<<<<<<<< *** LOG  STOP *** <<<<<<<<<<<<<<<<<<<<<<<<"
+// 	<< color[off] << endl;
+    pthread_mutex_unlock(&logmutex);
+
+    // destroy mutex
+    pthread_mutex_destroy(&logmutex);
+
+    // delete if allocated stream
+    if (logstream!= &cout)
+      delete logstream;
+
+    logstream= 0;
+  }
+}
+
+
+
+inline
+void
+logfile::set_filter(logclass_t logclass, uint8 severity_level)
+{
+  uint8 logclass_index= (logclass>>4)-1;
+  if (logclass_index < LOG_TYPES)
+    logfilter[logclass_index]=  severity_level;
+}
+
+inline
+bool
+logfile::should_log(logclass_t logclass, loglevel_t severity_level)
+{
+  return severity_level <= logfilter[(logclass>>4)-1];
+}
+
+
+/**
+ * returns current time in static char array
+ * @return pointer to static character array that contains current time
+ */
+inline
+const char* logfile::timenow()
+{
+  static time_t t;
+  static struct timeval now;
+  static char timestr[32]= "";
+  static char msecstr[6];
+
+  gettimeofday(&now,NULL);
+  t= now.tv_sec;
+  strftime(timestr, sizeof(timestr)-sizeof(msecstr), "%Y-%m-%d %H:%M:%S.", localtime(&t));
+  snprintf(msecstr,sizeof(msecstr),"%03lu",now.tv_usec/1000UL);
+  strcat(timestr,msecstr);
+  return timestr;
+}
+
+inline
+void logfile::logend()
+{
+  if (logstream)
+  {
+    (*logstream) << color[off] << endl;
+  }
+
+  pthread_mutex_unlock(&logmutex);
+}
+
+
+extern logfile& DefaultLog;
+//@}
+
+} // end namespace log
+
+} // end namespace protlib
+
+
+
+
+
+/**
+ * returns current time in static char array
+ * @return pointer to static character array that contains current time
+ */
+inline
+const char* log_timenow(char* module, char* event)
+{
+
+    //static pthread_mutex_t timestampmutex= PTHREAD_MUTEX_INITIALIZER;
+
+
+
+    //pthread_mutex_lock(&timestampmutex);
+
+
+    static time_t t;
+    //static struct timeval now;
+    static char timestr[128]= "";
+    //static char msecstr[8];
+
+    struct timespec tp;
+
+    clock_gettime(CLOCK_REALTIME, &tp);
+
+    //gettimeofday(&now,NULL);
+    t= tp.tv_sec;
+
+    //bringing down the range to under 1 hour
+    //write out microseconds
+
+    //printf("%ld\n", tp.tv_nsec);
+    //printf("%ld\n", t % 3600);
+
+    sprintf(timestr, "%05ld%06ld - ", t % 3600, tp.tv_nsec/1000L);
+    //snprintf(msecstr,sizeof(msecstr),"%06lu",tp.tv_nsec/1000000UL);
+    strcat(timestr,module);
+    strcat(timestr," - ");
+    strcat(timestr,event);
+
+    //pthread_mutex_unlock(&timestampmutex);
+
+    return timestr;
+}
+
+
+
+#endif
Index: /source/ariba/utility/transport/tcpip/protlib/messages.cpp
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/messages.cpp	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/messages.cpp	(revision 5284)
@@ -0,0 +1,205 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file messages.cpp
+/// These messages are sent internally between threads (modules)
+/// ----------------------------------------------------------
+/// $Id: messages.cpp 3013 2008-05-15 16:12:27Z roehricht $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/src/messages.cpp $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+/** @ingroup messages
+ * These messages are sent internally between threads (modules).
+ */
+
+#include "messages.h"
+//#include "context.h"
+#include "queuemanager.h"
+#include "cleanuphandler.h"
+#include "threadsafe_db.h"
+
+namespace protlib {
+
+/** @addtogroup messages Internal Messages
+ * @{
+ */
+
+/***** class message *****/
+
+/** This array contains printable names of messages sources. */
+const char* const message::qaddr_string[] = {
+	"UNKNOWN",
+	"TransportProtocol",
+	"TimerModule",
+	"Coordination (ext)",	// external
+	"Coordination (int)",	// internal
+	"Signaling",
+	"Policy",
+	"ResourceModule",
+	"Routing",
+	"Accounting",
+	"RouterConfiguration",
+	"TPoverSCTP",
+	"TPoverTCP",
+	"TPoverTLS_TCP",
+	"TPoverUDP",
+	"TPoverQueryEncapsulation",
+	"QNSLP-TimerProc",
+	"QNSLP-Coordinator",
+	"QNSLP-Signaling",
+	"APPL-QNSLP-Signaling",
+	"QNSLP-APPL-Signaling",
+	"GUI",
+	"API-0",
+	"API-1",
+	"API-2",
+	"API-3",
+	"API-4",
+	"API-5",
+	"API-6",
+	"API-7",
+	"API Wrapper Input (from TP)",
+	"TPoverUDS",
+	"QoS NSLP Client API over UDS",
+	"(INVALID)"
+}; // end qaddr_string
+
+/** This array contains printable names of message types. */
+const char* const message::type_string[] = {
+	"TPMsg",
+	"TimerMsg",
+	"SignalingMsg",
+	"ContextMsg",
+	"InfoMsg",
+	"RoutingMsg",
+	"APIMsg"
+}; // end type_string
+
+/** Set message type, source ID and source queue.
+ * Set message ID to id if possible, otherwise generate a new ID.
+ */
+message::message(type_t t, qaddr_t s, id_t id) 
+: type(t), source(s) {
+	if ((!id) || (!set_id(id))) new_id();
+} // end constructor
+
+/** Destructor does nothing for this class. */
+message::~message() {}
+
+message::id_t message::get_id() const { return msg_id; }
+
+message::id_t message::set_id(id_t id) {
+	if (!id) {
+		new_id();
+		return 0;
+	} else {
+		msg_id = id;
+		return id;
+	} // end if id
+} // end set_id
+
+/** Generate an unused ID. */
+message::id_t message::new_id() {
+	msg_id = 0;
+	while (!msg_id) msg_id = tsdb::get_new_id64();;
+	return msg_id;
+} // end new_id
+
+/** Get the message type. */
+message::type_t message::get_type() const { return type; }
+
+FastQueue* message::get_source_queue() const {
+	return QueueManager::instance()->get_queue(source);
+} // end get_source_queue
+
+message::qaddr_t message::get_source() const {
+	return source;
+} // end get_source
+
+/** Set source ID and return old value. */
+message::qaddr_t message::set_source(qaddr_t s) {
+	register qaddr_t os = source;
+	source = s;
+	return os;
+} // end set_source
+
+/** Returns a pointer to a string containing a printable name of the message 
+ * source.
+ */
+const char* message::get_qaddr_name() const {
+	return qaddr_string[source];
+} // end get_source_name
+
+/** Get the name of the given source. */
+const char* message::get_qaddr_name(qaddr_t s) {
+	return qaddr_string[s];
+} // end get_source_name
+
+/** Send this message to destqueue.
+ * @returns false if destqueue is NULL or queue does not accept the message.
+ */
+bool message::send(qaddr_t src, FastQueue* destqueue, bool exp) {
+	if (!destqueue) return false;
+	source = src;
+	return destqueue->enqueue(this,exp);
+} // end send
+
+/** Send this message.
+ * @returns false if destination queue cannot be found or queue does not accept the message.
+ */
+bool message::send(qaddr_t src, qaddr_t dest, bool exp) {
+	FastQueue* destqueue = QueueManager::instance()->get_queue(dest);
+	if (!destqueue) return false;
+	source = src;
+	return destqueue->enqueue(this,exp);
+} // end send
+
+/** Send this message.
+ * @returns false if destination queue cannot be found or queue does not accept the message.
+ */
+bool message::send_to(qaddr_t dest, bool exp) {
+	FastQueue* destqueue = QueueManager::instance()->get_queue(dest);
+	if (destqueue) return destqueue->enqueue(this,exp);
+	else return false;
+} // end send_to
+
+bool message::send_to(FastQueue* destqueue, bool exp) {
+	if (destqueue) return destqueue->enqueue(this,exp);
+	else return false;
+} // end send_to
+
+/** Send back this message.
+ * @returns false if destination queue cannot be found or queue does not accept the message.
+ */
+bool message::send_back(qaddr_t from, bool exp) {
+	FastQueue* destqueue = QueueManager::instance()->get_queue(source);
+	if (!destqueue) return false;
+	source = from;
+	return destqueue->enqueue(this,exp);
+} // end send_back
+
+/** Set all pointer fields to NULL. */
+void message::clear_pointers() {}
+
+
+//@}
+
+} // end namespace protlib
Index: /source/ariba/utility/transport/tcpip/protlib/messages.h
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/messages.h	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/messages.h	(revision 5284)
@@ -0,0 +1,192 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file messages.h
+/// internal messages sent between modules and other components
+/// ----------------------------------------------------------
+/// $Id: messages.h 3013 2008-05-15 16:12:27Z roehricht $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/messages.h $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+
+/** @ingroup messages
+ * @file
+ * These messages are sent between modules and other DRM components.
+ */
+
+#ifndef _PROTLIB__MESSAGE_H_
+#define _PROTLIB__MESSAGE_H_
+
+#include <pthread.h>
+#include <ext/hash_set>
+
+#include "protlib_types.h"
+#include "fqueue.h"
+
+namespace protlib {
+
+/** @addtogroup messages Internal Messages
+ * @{
+ */
+
+// class FastQueue is declared in fqueue.h
+class FastQueue;
+
+// class Context is declared in context.h
+class Context;
+
+/// internal messages
+/** Base class of all internal drm messages passed between modules. */
+class message {
+public:
+	/// message type
+	/** Each subclass of class message has its own unique type. */
+	enum type_t {
+		type_transport,
+		type_timer,
+		type_signaling,
+		type_context,
+		type_info,
+		type_routing,
+		type_API
+	}; // end type_t
+
+	/// source ID
+	/** Identifies the module which sent the message.
+	 *  If you add an id here, please add also the corresponding string in qaddr_string
+	 */
+	enum qaddr_t {
+		qaddr_unknown, // used as return value in NSLPtable.get_address() if there is no address found
+		qaddr_transport,
+		qaddr_timer,
+		qaddr_coordination,
+		qaddr_coordination_internal,
+		qaddr_signaling,
+		qaddr_policy,
+		qaddr_resource,
+		qaddr_routing,
+		qaddr_accounting,
+		qaddr_router_config,
+		qaddr_tp_over_sctp,
+		qaddr_tp_over_tcp,
+		qaddr_tp_over_tls_tcp,
+		qaddr_tp_over_udp,
+		qaddr_tp_queryencap,
+		qaddr_qos_nslp_timerprocessing,
+		qaddr_qos_nslp_coordination,
+		qaddr_qos_nslp_signaling,
+		qaddr_appl_qos_signaling,
+		qaddr_qos_appl_signaling,
+		qaddr_gui,
+		qaddr_api_0,
+		qaddr_api_1,
+		qaddr_api_2,
+		qaddr_api_3,
+		qaddr_api_4,
+		qaddr_api_5,
+		qaddr_api_6,
+		qaddr_api_7,
+		qaddr_api_wrapper_input,
+		qaddr_tp_over_uds,
+		qaddr_uds_appl_qos	// receives messages from an external client via UDS
+	}; // end qaddr_t
+
+	/// message ID
+	/** Each message has an ID.
+	 * Message IDs are not unique, you can use the same ID e.g. for request
+	 * and response. You cannot use an unused message ID, you can just reuse
+	 * an already used ID. ID 0 sets an unused ID.
+	 * Since id_t is 64-bit long, you can send 10^10 messages per seconds
+	 * for over 30 years without reusing an ID.
+	 */
+	typedef gp_id_t id_t;
+	/// constructor
+	message(type_t t, qaddr_t s = qaddr_unknown, id_t id = 0);
+	/// destructor
+	virtual ~message();
+	/// get ID
+	id_t get_id() const;
+	/// set ID or generate a new one
+	id_t set_id(id_t id);
+	/// get new ID
+	id_t new_id();
+	/// get message type
+	type_t get_type() const;
+	/// get source module queue
+	FastQueue *get_source_queue() const;
+	/// get source ID
+	qaddr_t get_source() const;
+	/// set source ID
+	qaddr_t set_source(qaddr_t s);
+	/// get name of message source
+	const char* get_qaddr_name() const;
+	/// get source name
+	static const char* get_qaddr_name(qaddr_t s);
+	/// get name of message type
+	const char* get_type_name() const { return type_string[type]; }
+	/// get type name
+	static const char* get_type_name(type_t t) { return type_string[t]; }
+	/// send the message to a queue
+	bool send(qaddr_t src, FastQueue* destqueue, bool exp = false);
+	/// send the message
+	bool send(qaddr_t src, qaddr_t dest, bool exp = false);
+	// @{
+	/// send the message to dest
+	bool send_to(qaddr_t dest, bool exp = false);
+	bool send_to(FastQueue* destqueue, bool exp = false);
+	// @}
+	/// send the message back
+	bool send_back(qaddr_t from, bool exp = false);
+	//@{
+	/// send or delete the message
+	void send_or_delete(qaddr_t src, qaddr_t dest, bool exp = false) {	if (!send(src,dest,exp)) delete this; }
+	void send_to_or_delete(qaddr_t dest, bool exp = false) { if (!send_to(dest,exp)) delete this; }
+	void send_back_or_delete(qaddr_t src, bool exp = false) { if (!send_back(src,exp)) delete this; }
+	//@}
+	/// clear all pointers
+	virtual void clear_pointers();
+private:
+	const type_t type;
+	qaddr_t source;
+	id_t msg_id;
+ 	/// printable message source names
+	static const char* const qaddr_string[];
+ 	/// printable message typee names
+	static const char* const type_string[];
+}; // end class message
+
+
+
+//@}
+
+} // end namespace protlib
+
+namespace __gnu_cxx {
+
+/// message pointer hasher
+/** Hash value is the address of the object pointed to. */
+template <> struct hash<protlib::message*> {
+	inline size_t operator()(protlib::message* m) const { return (size_t)m; }
+}; // end msgp_hash
+
+} // end namespace __gnu_cxx
+
+#endif // _PROTLIB__MESSAGE_H_
Index: /source/ariba/utility/transport/tcpip/protlib/network_message.cpp
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/network_message.cpp	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/network_message.cpp	(revision 5284)
@@ -0,0 +1,672 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file network_message.cpp
+/// generic class for network messages represented as byte stream
+/// ----------------------------------------------------------
+/// $Id: network_message.cpp 3247 2008-07-28 20:54:54Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/src/network_message.cpp $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+/** @ingroup networkmsg
+ * This is a generic class for network messages,
+ * represented as a byte stream (buffer containing bytes).
+ */
+
+#include <netinet/in.h> 
+#include <string.h>
+#include <cctype>
+#include <fstream>
+#include <ostream>
+#include <sstream>
+#include <iomanip>
+
+#include "network_message.h"
+
+#include "logfile.h" // only required for color definitions
+
+namespace protlib {
+
+
+  using namespace protlib::log;
+/** @addtogroup networkmsg Network Messages
+ * @{
+ */
+
+/** @param e error code */
+NetMsgError::NetMsgError(error_t e) : err(e) {}
+
+const char* NetMsgError::getstr() const { return errstr[err]; }
+
+/** NetMsg error strings */
+const char* const NetMsgError::errstr[] = 
+{
+    "Network message too long.",
+    "Not enough memory to allocate network message.",
+    "Operation not valid because of pointer position in NetMsg buffer.",
+    "NULL pointer argument in call to NetMsg constructor.",
+    "Invalid start offset.",
+    "NetMsg buffer too short.",
+    "Invalid buffer size: zero"
+}; // end network message error strings
+
+/** Maximum size of a network message. This is set to 128000 to prevent
+ * very large messages.
+ */
+const uint32 NetMsg::max_size = 128000;
+
+/** Creates a network message object of the desired size if possible.
+ * @param s buffer size.
+ */
+NetMsg::NetMsg(uint32 s) {
+  if (s>max_size) throw NetMsgError(NetMsgError::ERROR_TOO_LONG);
+  if (s==0) throw NetMsgError(NetMsgError::ERROR_INVALID_BUFSIZE);
+  buf = new(nothrow) uchar[s];
+  if (!buf) throw NetMsgError(NetMsgError::ERROR_NO_MEM);
+  memset(buf,0,s);
+  buf_len = s;
+  pos = buf;
+  buf_end = buf+(s-1);
+} // end constructor
+
+/** Creates a network message object of the desired size if possible.
+ * @param b pointer to a buffer to initialize the NetMsg.
+ * @param s buffer size
+ * @param copy copy the buffer or use the buffer without copying.
+ */
+NetMsg::NetMsg(uchar *b, uint32 s, bool copy) {
+  if (s>max_size) throw NetMsgError(NetMsgError::ERROR_TOO_LONG);
+  if (s==0) throw NetMsgError(NetMsgError::ERROR_INVALID_BUFSIZE);
+  if (copy) {
+    buf = new(nothrow) uchar[s];
+    if (!buf) throw NetMsgError(NetMsgError::ERROR_NO_MEM);
+    memcpy(buf,b,s);
+  } else {
+    buf=b;
+    if (!buf) throw NetMsgError(NetMsgError::ERROR_NULL_POINTER);
+  } // end if copy
+  buf_len = s;
+  pos = buf;
+  buf_end = buf+(s-1);
+} // end constructor
+
+NetMsg::NetMsg(const NetMsg& n) {
+  buf_len = n.buf_len;
+  if (buf_len == 0)
+    throw NetMsgError(NetMsgError::ERROR_INVALID_BUFSIZE);
+
+  buf = new(nothrow) uchar[buf_len];
+  if (!buf) throw NetMsgError(NetMsgError::ERROR_NO_MEM);
+  memcpy(buf,n.buf,buf_len);
+  pos = buf+(n.pos-n.buf);
+  buf_end = buf+(buf_len-1);
+} // end copy constructor
+
+/** Frees the message buffer. */
+NetMsg::~NetMsg() {
+  if (buf) { delete[] buf; buf= 0; }
+} // end destructor
+
+/** @return the size of the network message buffer. */
+uint32 NetMsg::get_size() const {
+   return buf_len;
+} // end get_size
+
+/** Returns the number of bytes left, that is the number of bytes from the 
+ * current position to the end of the buffer.
+ */
+uint32 NetMsg::get_bytes_left() const {
+  if (buf<=pos) 
+  {
+    if (pos<=buf_end) 
+      return (buf_end-pos)+1; 
+    else 
+      return 0;
+  } 
+  else /// should never happen
+    throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
+} // end get_size
+
+/** Returns the offset of the buffer pointer. 
+ * Note that an offset of buf_len means that the pointer is one byte behind
+ * the end of the buffer. This means that you reached the buffer end.
+ * This leads to a get-pos result of buf_len.
+ */
+uint32 NetMsg::get_pos() const {
+  if ((buf<=pos) && (pos<=(buf_end+1))) 
+    return (pos-buf);
+  else 
+    throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
+} // end get_pos
+
+/** Move pointer to the given offset. 
+ * @param p pointer offset 
+ * @note if p==buf_len then the pointer is one byte behind the buffer end.
+ * This is correct and signals that all data has been read from the buffer.
+ */
+NetMsg& NetMsg::set_pos(uint32 p) {
+  if (p<=buf_len) 
+  {
+    pos = buf+p;
+    return *this;
+  } 
+  else 
+    throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
+} // end set_pos
+
+/** Move pointer relative to current position.
+ * @param rp offset relative to current position. 
+ */
+NetMsg& NetMsg::set_pos_r(int32 rp) 
+{
+  if (((pos+rp)>=buf) && ((pos+rp)<=(buf_end+1))) {
+    pos += rp;
+  } 
+  else 
+    throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
+  return *this;
+} // end set_pos_r
+
+/** Set current position to buffer start. */
+NetMsg& NetMsg::to_start() {
+  pos=buf;
+  return *this;
+} // end to_start
+
+/** Copy n bytes into NetMsg buffer.
+ * @param b source
+ * @param n number of bytes to copy
+ */
+uint32 NetMsg::copy_from(const uchar *b, uint32 n) {
+  return copy_from(b,0,n);
+} // end copy_from
+
+/** Copy bytes into NetMsg buffer.
+ * @param b source
+ * @param start offset of first byte to copy
+ * @param n number of bytes to copy
+ */
+uint32 NetMsg::copy_from(const uchar *b, uint32 start, uint32 n) {
+  if ((n+start)>buf_len) throw NetMsgError(NetMsgError::ERROR_TOO_SHORT);
+  // TH: I BELIEVE THIS IS WRONG !!
+  //memmove(buf,b+start,n);
+  memmove(buf+start,b,n);
+  return n;
+} // end copy_from
+
+/** Copy n bytes from NetMsg buffer into b. If the NetMsg buffer is smaller
+ * than n, less bytes are copied. 
+ * @param b destination buffer
+ * @param n number of bytes to be copied
+ * @return number of copied bytes
+ */
+uint32 NetMsg::copy_to(uchar *b, uint32 n) const {
+  try {
+    return copy_to(b,0,n);
+  } catch(NetMsgError& e) {
+    // ERROR, should not happen
+  } // end try-catch
+  return 0;
+} // end copy_to
+
+/** Copy n bytes from NetMsg buffer into b. If the NetMsg buffer is smaller
+ * than n, less bytes are copied. 
+ * @param b destination buffer
+ * @param start offset into NetMsg buffer
+ * @param n number of bytes to be copied
+ * @return number of copied bytes
+ */
+uint32 NetMsg::copy_to(uchar *b, uint32 start, uint32 n) const {
+  if (start>=buf_len) throw NetMsgError(NetMsgError::ERROR_INVALID_START_OFFSET);
+  if ((n+start)>buf_len) n=buf_len-start;
+  memmove(b,buf+start,n);
+  return n;
+} // end copy_to
+
+/** returns a pointer to the NetMsg buffer. */
+uchar* NetMsg::get_buffer() const {
+	return buf;
+} // end get_buffer
+
+
+
+/** Decode an uint8 integer.
+ * @param move determines if current position in buffer is changed or not.
+ */
+uint8 NetMsg::decode8(bool move) {
+  register uint8 i;
+  if (pos<=buf_end) 
+  {
+    i = *pos;
+    if (move) pos+=1;
+  } 
+  else 
+    throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
+  
+  return i;
+} // end decode uint8
+
+/** Decode an uint16 integer.
+ * @param move determines if current position in buffer is changed or not.
+ */
+uint16 NetMsg::decode16(bool move) {
+  register uint16 i;
+  if ((pos+1)<=buf_end) {
+    i = ntohs(*((uint16*)pos));
+    if (move) pos+=2;
+  } 
+  else 
+    throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
+  return i;
+} // end decode uint16
+
+/** Decode an uint32 integer.
+ * @param move determines if current position in buffer is changed or not.
+ */
+uint32 NetMsg::decode32(bool move) {
+  register uint32 i;
+  if ((pos+3)<=buf_end) {
+    i = ntohl(*((uint32*)pos));
+    if (move) pos+=4;
+  } 
+  else 
+    throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
+  return i;
+} // end decode uint32
+
+/** Decode an uint64 integer.
+ * @param move determines if current position in buffer is changed or not.
+ */
+uint64 NetMsg::decode64(bool move) {
+  uint64 hi = 0;
+  uint64 lo = 0;
+  uint64 res = 0;
+  uint32* p = (uint32*)pos;
+  if ((pos+7)<=buf_end) {
+    hi = ntohl(*p);
+    lo = ntohl(*(p+1));
+    res = (hi<<32)+lo;
+    if (move) pos+=8;
+  } else throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
+  return res;
+} // end decode uint64
+
+/** Decode an uint128 integer.
+ * @param move determines if current position in buffer is changed or not.
+ */
+uint128 NetMsg::decode128(bool move) {
+  uint32 word1, word2, word3, word4;
+  uint128 res;
+  word1 = NetMsg::decode32();
+  word2 = NetMsg::decode32();
+  word3 = NetMsg::decode32();
+  word4 = NetMsg::decode32();
+  res.w1 = word1;
+  res.w2 = word2;
+  res.w3 = word3;
+  res.w4 = word4;
+
+  return res;
+} // end decode uint128
+
+/** Encode an uint8 integer.
+ * @param i an uint8
+ * @param move determines if current position in buffer is changed or not.
+ */
+void NetMsg::encode8(uint8 i, bool move) {
+  if (pos<=buf_end) {
+    *pos = i;
+    if (move) pos+=1;
+  } else throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
+} // end encode uint8
+
+/** Encode an uint16 integer.
+ * @param i an uint16
+ * @param move determines if current position in buffer is changed or not.
+ */
+void NetMsg::encode16(uint16 i, bool move) {
+  if ((pos+1)<=buf_end) {
+    *((uint16*)pos) = htons(i);
+    if (move) pos+=2;
+  } else throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
+} // end encode uint16
+
+/** Encode an uint32 integer.
+ * @param i an uint32
+ * @param move determines if current position in buffer is changed or not.
+ */
+void NetMsg::encode32(uint32 i, bool move) {
+  if ((pos+3)<=buf_end) {
+    *((uint32*)pos) = htonl(i);
+    if (move) pos+=4;
+  } else throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
+} // end encode uint32
+
+/** Encode an uint64 integer.
+ * @param i an uint64
+ * @param move determines if current position in buffer is changed or not.
+ */
+void NetMsg::encode64(uint64 i, bool move) {
+	uint32 hi = 0;
+	uint32 lo = 0;
+	uint32* p = (uint32*)pos;
+	if ((pos+7)<=buf_end) {
+		lo = i;
+		hi = (i>>32);
+		*p = htonl(hi);
+		*(p+1) = htonl(lo);
+		if (move) pos+=8;
+	} else throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
+} // end encode uint64
+
+/** Encode an uint128 integer.
+ * @param i an uint128
+ * @param move determines if current position in buffer is changed or not.
+ */
+void NetMsg::encode128(uint128 i, bool move) {
+  encode32(i.w1);
+  encode32(i.w2);
+  encode32(i.w3);
+  encode32(i.w4);
+} // end encode uint128
+
+/** Decode uchars.
+ * @param c pointer to uchar array
+ * @param len uchar array size
+ * @param move determines if current position in buffer is changed or not.
+ */
+void NetMsg::decode(uchar *c, uint32 len, bool move) {
+  if ((pos+(len-1))<=buf_end) {
+    memmove(c,pos,len);
+    if (move) pos+=len;
+  } else throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
+} // end decode uchars
+
+/** Encode uchars.
+ * @param c pointer to uchar array
+ * @param len uchar array size
+ * @param move determines if current position in buffer is changed or not.
+ */
+void NetMsg::encode(const uchar *c, uint32 len, bool move) {
+  if ((pos+(len-1))<=buf_end) {
+    memmove(pos,c,len);
+    if (move) pos+=len;
+  } else throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
+} // end encode uchars
+
+/** Decode string.
+ * @param s string reference
+ * @param len number of bytes to decode
+ * @param move determines if current position in buffer is changed or not.
+ * @return string length.
+ */
+uint32 NetMsg::decode(string& s, uint32 len, bool move) {
+  if (len==0) {
+    s.clear();
+    return 0;
+  } else if ((pos+(len-1))<=buf_end) {
+    s.clear();
+    s.assign((const char*)pos,0,len);
+    if (move) pos+=len;
+    return s.length();
+  } else throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
+} // end decode string
+
+/** Encode string.
+ * @param s string reference
+ * @param move determines if current position in buffer is changed or not.
+ */
+uint32 NetMsg::encode(const string& s, bool move) {
+  uint32 len = s.length();
+  if ((pos+(len-1))<=buf_end) {
+    memmove(pos,s.c_str(),len);
+    if (move) pos+=len;
+    return len;
+  } else throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
+} // end encode string
+
+/** Decode an IPv4 address. 
+ * @param in reference to in_addr
+ * @param move determines if current position in buffer is changed or not.
+ */
+void NetMsg::decode(struct in_addr& in, bool move) {
+  //in.s_addr = decode32(move);
+  if ((pos+3)<=buf_end) {
+    in.s_addr = *((uint32*)pos);
+    if (move) pos+=4;
+  } 
+  else 
+    throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
+} // end decode(in_addr)
+
+/** Encode an IPv4 address. 
+ * @param in reference to const in_addr
+ * @param move determines if current position in buffer is changed or not.
+ */
+void NetMsg::encode(const struct in_addr& in, bool move) {
+  //encode32(in.s_addr,move);
+  if ((pos+3)<=buf_end) {
+    *((uint32*)pos) = in.s_addr;
+    if (move) pos+=4;
+  } else throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
+} // end encode(in_addr)
+
+/** Decode an IPv6 address. 
+ * @param in reference to in6_addr
+ * @param move determines if current position in buffer is changed or not.
+ */
+void NetMsg::decode(struct in6_addr& in, bool move) {
+  if ((pos+15)<=buf_end) {
+    memmove(in.s6_addr,pos,16);
+    if (move) pos+=16;
+  } else throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
+} // end decode(in6_addr)
+
+/** Encode an IPv6 address. 
+ * @param in reference to const in6_addr
+ * @param move determines if current position in buffer is changed or not.
+ */
+void NetMsg::encode(const struct in6_addr& in, bool move) {
+  if ((pos+15)<=buf_end) {
+    memmove(pos,in.s6_addr,16);
+    if (move) pos+=16;
+  } else throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
+} // end encode(in6_addr)
+
+
+
+
+
+
+/** Truncates the buffer at the current position and sets the current
+ * position to buffer start.
+ * @return new buffer size.
+ */
+uint32 NetMsg::truncate() {
+  if ((pos>=buf) && (pos<=(buf_end+1))) {
+    buf_len = (pos-buf);
+    buf_end = pos-1;
+    to_start();
+  } else {
+    throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
+  } // end if buf
+  return buf_len;
+} // end truncate
+
+/** Truncates the buffer at given offset. */
+uint32 NetMsg::truncate(uint32 t) {
+  set_pos(t);
+  return truncate();
+} // end truncate
+
+/** Set padding bytes to 0.
+ * @param len padding length
+ * @param move determines if current position in buffer is changed or not.
+ */
+void NetMsg::padding(uint32 len, bool move) {
+  if (len==0) return;
+  else if ((pos+(len-1))<=buf_end) {
+    memset(pos,0,len);
+    if (move) pos+=len;
+  } else throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
+} // end padding
+
+/** Two network messages are equal if their buffers and states are equal. */
+bool NetMsg::operator==(const NetMsg& n) const 
+{
+  // buffer size equal
+  if (buf_len==n.buf_len) 
+  {
+    // empty buffers are considered equal
+    if ((buf==NULL) && (n.buf==NULL)) 
+      return true; 
+    else 
+    if (buf && n.buf) 
+    {
+      // compare buffer content 
+      if (memcmp(buf,n.buf,buf_len)==0) 
+      {
+	// last check: position must be equal
+	return ((pos-buf)==(n.pos-n.buf));
+      } 
+      else 
+	return false;
+    } 
+    else 
+      return false;
+  } 
+  else 
+    return false;
+} // end operator==
+
+/** Decode NetMsg.
+ * @param m NetMsg reference
+ * @param move determines if current position in buffer is changed or not.
+ */
+void NetMsg::decode(NetMsg& m, bool move) {
+  uint32 len = m.get_size();
+  if ((pos+(len-1))<=buf_end) {
+    // copy buffer
+    m.to_start();
+    memmove(m.buf,pos,len);
+    if (move) pos+=len;
+  } else throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
+} // end decode NetMsg
+
+/** Encode NetMsg.
+ * @param m NetMsg reference
+ * @param len length of data to encode
+ * @param move determines if current position in buffer is changed or not.
+ */
+void NetMsg::encode(const NetMsg& m, uint32 len, bool move) {
+  if ((pos+(len-1))<=buf_end) {
+    memmove(pos,m.buf,len);
+    if (move) pos+=len;
+  } else throw NetMsgError(NetMsgError::ERROR_INVALID_POS);
+} // end encode NetMsg
+
+
+/** hex of dump buffer contents
+ * if startpos is 0, the beginning of the buffer is used
+ */
+ostream& 
+NetMsg::hexdump(ostream& os, uchar *startpos, uint32 length) const
+{
+  if (length==0) 
+    length=buf_len;
+
+  if (startpos == 0)
+    startpos= buf;
+
+  ios_base::fmtflags flags = os.flags();	// save stream flags
+
+  os << color[blue] << "[dump: start=" << static_cast<void *>(startpos) << ", length:" << length;
+  if (startpos > buf_end)
+    return os << "ERROR: start position behind last buffer byte ]" << color[clear] << endl;
+  else
+  if (startpos < buf)
+    return os << "ERROR: start position before first buffer byte ]" << color[clear] << endl;
+
+  os << endl;
+ 
+  while ( length > 0 && startpos <= buf_end )
+  {
+    os << setw(4) << startpos-buf << ": ";
+
+    // alphanumeric characters are printed directly
+    for (uint8 index=0; index <= 3; index++) {
+	if ( startpos+index <= buf_end ) {
+	    uchar c = *(startpos+index);
+	    os << ( isalnum(c) ? static_cast<char>(c) : '.');
+	}
+	else
+	    os << ' ';
+    }
+
+    os << " : " << hex << noshowbase;
+
+    // dump hex numbers
+    for (uint8 index=0; index <= 3; index++) {
+	if ( startpos+index <= buf_end )
+	    os << setw(2) << setfill('0')
+		<< static_cast<unsigned short>(*(startpos+index)) << ' ';
+	else
+	    os << "   ";
+    }
+
+    os << setfill(' ') << "       ";
+
+    // print in base 2
+    for (uint8 index=0; index <= 3 && (startpos+index <= buf_end); index++)
+    {
+	unsigned short val = static_cast<unsigned short>(*(startpos+index));
+
+	for (int i=7; i >= 0; i--)
+	    os << ((val >> i) & 1);
+
+	os << ' ';
+    }
+
+    startpos += 4;
+    length = ( length >= 4 ) ? length-4 : 0;
+
+    // reset formatting
+    os.width(0);
+    os << dec << setfill(' ') << endl;
+  }
+
+  os.setf(flags);		// reset stream flags
+
+  return os << ']' << color[clear] << endl;
+}
+
+ostream& operator<<(ostream& os, NetMsg& msg)
+{ 
+ 
+  ostringstream hexdumpstr;
+  msg.hexdump(hexdumpstr);
+  return os << hexdumpstr.str();
+  
+}
+
+//@}
+
+} // end namespace protlib
Index: /source/ariba/utility/transport/tcpip/protlib/network_message.h
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/network_message.h	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/network_message.h	(revision 5284)
@@ -0,0 +1,182 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file network_message.h
+/// generic class for network messages (PDUs coming from/going to network)
+/// ----------------------------------------------------------
+/// $Id: network_message.h 3247 2008-07-28 20:54:54Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/network_message.h $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+
+/** @ingroup networkmsg
+ *
+ * This is a generic class for network messages. 
+ * A network message consists of a number of bytes.
+ * There are no access member functions. So the user has full control over
+ * the buffer.
+ */
+ 
+#ifndef _PROTLIB__NETWORK_MESSAGE_H_
+#define _PROTLIB__NETWORK_MESSAGE_H_
+
+#include <netinet/in.h>
+#include <string>
+#include <ostream>
+
+#include "protlib_types.h"
+
+namespace protlib {
+
+/** @addtogroup networkmsg Network Messages
+ * @ingroup network
+ * @{
+ */
+
+class NetMsgError : public ProtLibException {
+public:
+	enum error_t {
+		ERROR_TOO_LONG,
+		ERROR_NO_MEM,
+		ERROR_INVALID_POS,
+		ERROR_NULL_POINTER,
+		ERROR_INVALID_START_OFFSET,
+		ERROR_TOO_SHORT,
+		ERROR_INVALID_BUFSIZE
+	};
+	NetMsgError(error_t e);
+	const char * getstr() const;
+	virtual const char *what() const throw() { return getstr(); }
+	const error_t err;
+private:
+	static const char* const errstr[];
+}; // end NetMsgError
+
+/// network message
+/** This class is used to exchange data between signalling and transport
+* protocol.
+*/
+class NetMsg {
+public:
+	static const uint32 max_size;
+	/// constructor
+	NetMsg(uint32 s);
+	/// constructor
+	NetMsg(uchar *b, uint32 s, bool copy = true);
+	/// copy constructor
+	NetMsg(const NetMsg& n);
+	/// destructor
+	~NetMsg();
+	/// get buffer size
+	uint32 get_size() const;
+	/// get bytes left until buffer ends
+	uint32 get_bytes_left() const;
+	/// get pointer offset
+	uint32 get_pos() const;
+	/// move pointer to offset
+	NetMsg& set_pos(uint32 p);
+	/// move pointer relative
+	NetMsg& set_pos_r(int32 rp);
+	/// set pointer to beginning
+	NetMsg& to_start();
+	/// copy into NetMsg buffer
+	uint32 copy_from(const uchar *b, uint32 n);
+	/// copy into NetMsg buffer
+	uint32 copy_from(const uchar *b, uint32 start, uint32 end);
+	/// copy from NetMsg buffer
+	uint32 copy_to(uchar *b, uint32 n) const;
+	/// copy from NetMsg buffer
+	uint32 copy_to(uchar *b, uint32 start, uint32 n) const;
+	/// get pointer to buffer
+	uchar* get_buffer() const;
+	/// decode uint8
+	uint8 decode8(bool move = true);
+	/// decode uint16
+	uint16 decode16(bool move = true);
+	/// decode uint32
+	uint32 decode32(bool move = true);
+	/// decode uint64
+	uint64 decode64(bool move = true);
+	/// decode uint128
+	uint128 decode128(bool move = true);
+	/// encode uint8
+	void encode8(uint8 i, bool move = true);
+	/// encode uint16
+	void encode16(uint16 i, bool move = true);
+	/// encode uint32
+	void encode32(uint32 i, bool move = true);
+	/// encode uint64
+	void encode64(uint64 i, bool move = true);
+	/// encode uint128
+	void encode128(uint128 i, bool move = true);
+	/// decode uchars
+	void decode(uchar *c, uint32 len, bool move = true);
+	/// encode uchars
+	void encode(const uchar *c, uint32 len, bool move = true);
+	/// decode string
+	uint32 decode(string& s, uint32 len, bool move = true);
+	/// encode string
+	uint32 encode(const string& s, bool move = true);
+	/// decode IPv4
+	void decode(struct in_addr& in, bool move = true);
+	/// encode IPv4
+	void encode(const struct in_addr& in, bool move = true);
+	/// decode IPv6
+	void decode(struct in6_addr& in, bool move = true);
+	/// encode IPv6
+	void encode(const struct in6_addr& in, bool move = true);
+        /// truncate buffer
+	uint32 truncate();
+	/// truncate buffer
+	uint32 truncate(uint32 t);
+	/// apply padding
+	void padding(uint32 len, bool move = true);
+	/// test for equality
+	bool operator==(const NetMsg& n) const;
+	/// encode a NetMsg into this NetMsg
+	void encode(const NetMsg& m, uint32 len, bool move = true);
+	/// decode a NetMsg from this NetMsg
+	void decode(NetMsg& m, bool move = true);
+	/// print a raw hexdump of the buffer
+	ostream& hexdump(ostream& os, uchar *startpos=0, uint32 length=0) const;
+
+private:
+	/// buffer for data
+	uchar *buf;
+	/// buffer size
+	uint32 buf_len;     
+	/// current reading/writing position
+	uchar *pos;
+	/// buffer end
+	/** Ponter to the last byte of the buffer. */	
+	uchar *buf_end;
+};
+
+inline std::ostream &operator<<(std::ostream &out, const NetMsg &msg) {
+	msg.hexdump(out);
+	return out;
+}
+
+//@}
+
+} // namespace protlib
+
+#endif // _PROTLIB__NETWORK_MESSAGE_H_
Index: /source/ariba/utility/transport/tcpip/protlib/protlib_types.h
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/protlib_types.h	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/protlib_types.h	(revision 5284)
@@ -0,0 +1,170 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file protlib_types.h
+/// This file contains various typedefs
+/// ----------------------------------------------------------
+/// $Id: protlib_types.h 3064 2008-07-02 08:05:18Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/protlib_types.h $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+// ----------------------------------------*- mode: C++; -*--
+// protlib_types.h - various typedefs
+// ----------------------------------------------------------
+// $Id: protlib_types.h 3064 2008-07-02 08:05:18Z bless $
+// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/protlib_types.h $
+// ==========================================================
+//                      
+// (C)opyright, all rights reserved by
+// - Institute of Telematics, University of Karlsruhe (TH)
+// ==========================================================
+
+/**
+ * @ingroup types
+ *
+ */
+
+#ifndef PROTLIB__TYPES_H
+#define PROTLIB__TYPES_H
+
+#include <iostream>
+#include <fstream>
+#include <exception>
+
+#include <cassert>
+
+#include <netinet/in.h> // required for IPPROTO constants
+
+#include <sys/types.h>
+
+// What's this used for? If if it's not needed, please delete it.
+#define _THREADS
+
+
+namespace protlib {
+  using namespace std;
+  using namespace __gnu_cxx;
+
+/**
+ * @addtogroup types Type Definitions
+ * @{
+ */
+ 
+/**
+ * The abstract base class for all exceptions thrown by protlib.
+ */
+class ProtLibException : public std::exception {
+  public:
+	virtual ~ProtLibException() throw() { }
+
+	/**
+	 * Get a printable string representation of the error.
+	 *
+	 * @warning Note that the data this pointer refers to still belongs
+	 * to the exception object. It is only valid as long as the exception
+	 * object exists.
+	 *
+	 * @return the error message
+	 */
+	virtual const char *what() const throw() { return error_msg.c_str(); }
+
+	/**
+	 * Deprecated: Use what() instead.
+	 */
+	virtual const char *getstr() const { return what(); }
+
+
+  protected:
+	ProtLibException() throw() { }
+	ProtLibException(std::string msg) throw() : error_msg(msg) { }
+
+	std::string error_msg;
+};
+
+inline ostream& operator<<(ostream& os, const ProtLibException &err) {
+	return os << err.what();
+}
+
+
+typedef unsigned char       uchar;
+
+typedef char                int8;
+typedef unsigned char       uint8;
+
+typedef short int           int16;
+typedef unsigned short int  uint16;
+
+// the following types depend on the platform
+// since types.h tries to figure out the correct sizes already
+// we will not replicate the stuff here. Note that on 64-bit
+// platforms usually int == 32-bit, long == 64-bit
+
+typedef int32_t             int32;
+typedef u_int32_t           uint32;
+
+typedef int64_t             int64;
+typedef u_int64_t           uint64;
+
+
+class uint128 {
+public:
+	uint32 w1;
+	uint32 w2;
+	uint32 w3;
+	uint32 w4;
+  uint128() : w1(0),w2(0),w3(0),w4(0) {};
+  uint128(uint32 w1, uint32 w2, uint32 w3, uint32 w4) : w1(w1),w2(w2),w3(w3),w4(w4) {}; 
+  bool operator==(const uint128& val) const { return w1==val.w1 && w2==val.w2 && w3==val.w3 && w4==val.w4; }
+};
+
+
+/// Network prefix length.
+typedef uint8 prefix_length_t;
+
+/// Protocol number, as it is given in an IP header.
+typedef uint8 protocol_t;
+
+/** these are pseudo protocol IDs in order to being able to perform
+ * multiplexing based on on address object alone
+ * currently used for Query encapsulation and TLS/TCP
+ * this should be changed in the future, probably by using an additional
+ * attribute in the appladdress object 
+ **/
+const protocol_t prot_tls_tcp    = 254;
+const protocol_t prot_query_encap= 255;
+const protocol_t prot_tcp        = IPPROTO_TCP;
+const protocol_t prot_udp        = IPPROTO_UDP;
+const protocol_t prot_sctp       = IPPROTO_SCTP;
+
+/// Port number, as given in TCP or UDP headers.
+typedef uint16 port_t;
+
+/// A general purpose ID type.
+typedef uint64 gp_id_t;
+
+/// Catch everything, do nothing.
+#define catch_all(x) try { x; } catch(...) { }
+
+// @}
+
+} // namespace protlib
+
+#endif // PROTLIB__TYPES_H
Index: /source/ariba/utility/transport/tcpip/protlib/queuemanager.cpp
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/queuemanager.cpp	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/queuemanager.cpp	(revision 5284)
@@ -0,0 +1,212 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file queuemanager.cpp
+/// queuemanager which records queues and message source IDs
+/// ----------------------------------------------------------
+/// $Id: queuemanager.cpp 2774 2007-08-08 12:32:08Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/src/queuemanager.cpp $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+/** @ingroup queuemanager
+ *
+ */
+#include <stdexcept>
+
+#include "queuemanager.h"
+#include "logfile.h"
+
+namespace protlib { 
+
+/** @addtogroup queuemanager Queue Manager
+ * \ingroup fastqueue
+ * @{
+ */
+
+using namespace log;
+
+/***** class QueueManagerError *****/
+
+QueueManagerError::QueueManagerError(error_t e) : err(e) {}
+
+const char* QueueManagerError::getstr() const { return errstr[err]; }
+
+const char* const QueueManagerError::errstr[] = {
+	"Unable to create QueueManager.",
+	"Cannot register FastQueue. No memory or registered queue more than once."
+}; // end errstr
+
+/***** class QueueManager *****/
+
+/** Return QueueManager singleton. */
+QueueManager* QueueManager::instance() {
+	if (!inst) {
+		// try to create singleton
+		inst = new(nothrow) QueueManager();
+		if (!inst) {
+		  Log(INFO_LOG,LOG_NORMAL, "QueueManager" ,"Cannot created QueueManager singleton.");
+		  throw QueueManagerError(QueueManagerError::ERROR_NO_QUEUE_MANAGER);
+		} else {
+		  Log(DEBUG_LOG,LOG_NORMAL, "QueueManager", "Just created QueueManager singleton.");
+		} // end if not inst
+	} // end if not inst
+	return inst;
+} // end QueueManager
+
+/**
+ * Delete the QueueManager singleton object.
+ *
+ * After a call to clear references to that object become invalid and must
+ * be updated by a call to instance().
+ */
+void QueueManager::clear() {
+
+	if (inst) {
+		QueueManager *tmp = inst;
+		inst = 0;
+		DLog("QueueManager", "Destroying QueueManager singleton ...");
+		delete tmp;
+	}
+
+	DLog("QueueManager", "The QueueManager singleton has been destroyed");
+}
+
+
+/**
+ * Register a queue.
+ *
+ * This registers a FastQueue for the given message source ID with the
+ * QueueManager.
+ *
+ * The registered queue (and all its entries) is deleted as soon as the
+ * QueueManager is deleted. Because of this, a queue may only be registered
+ * once.
+ *
+ * @param fq pointer to an already allocated fastqueue 
+ * @param s  message source ID
+ */
+void QueueManager::register_queue(FastQueue* fq, message::qaddr_t s) {
+  pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
+  // expand array if necessary
+  if (((uint32)s)>=queue_arr.capacity()) {
+    Log(DEBUG_LOG,LOG_NORMAL, "QueueManager", "expanding queue array from " << s << " to " << s+5);
+    // get more memory
+    queue_arr.reserve(s+5);
+    while (queue_arr.size()<queue_arr.capacity()) queue_arr.push_back(NULL);
+  } // end get more memory
+  
+  if (queue_arr[s]) 
+  {
+    // queue already exists
+    Log(ERROR_LOG,LOG_CRIT, "QueueManager", "A queue for " << s << " is already  registered");
+    throw QueueManagerError(QueueManagerError::ERROR_REGISTER);
+  } // end if queue exists
+  else 
+  {
+    // register queue
+    if (fq)
+    {
+      queue_arr[s] = fq;
+    }
+    else
+    {
+      Log(ERROR_LOG,LOG_CRIT, "QueueManager", "Cannot register queue for " << s);
+      throw QueueManagerError(QueueManagerError::ERROR_REGISTER);
+    }
+  } // end else no queue exists
+  pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
+} // end register_queue
+
+
+void 
+QueueManager::unregister_queue(message::qaddr_t s) 
+{
+  pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
+  try {
+	  queue_arr.at(s) = 0;
+  }
+  catch ( std::out_of_range ) {
+	/*
+	 * Nothing to do, queue has probably already been unregistered,
+	 * probably by calling QueueManager::clear().
+	 */
+  }
+  pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
+}
+
+FastQueue* QueueManager::get_queue(message::qaddr_t s) const {
+	FastQueue* fq = NULL;
+	pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
+	if (((uint32)s)<queue_arr.size()) {
+		fq = queue_arr[s];
+	} else {
+		fq = NULL;
+	} // end if
+	pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
+	return fq;
+} // end get
+
+QueueManager* QueueManager::inst = NULL;
+
+/**
+ * Constructor.
+ */
+QueueManager::QueueManager() : queue_arr(QueueManager::INITIAL_ARRAY_SIZE) {
+	pthread_mutexattr_t mutex_attr;
+
+	pthread_mutexattr_init(&mutex_attr);
+
+#ifdef _DEBUG
+	pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK);
+#else
+	pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_NORMAL);
+#endif
+
+	pthread_mutex_init(&mutex, &mutex_attr);
+
+	pthread_mutexattr_destroy(&mutex_attr); // doesn't affect mutex
+}
+
+
+/**
+ * Destructor.
+ *
+ * Delete this object and all FastQueue objects that are still registered.
+ */
+QueueManager::~QueueManager() {
+
+	pthread_mutex_lock(&mutex);
+
+	// count queues which are still registered
+	for ( qm_array_it_t i = queue_arr.begin(); i != queue_arr.end(); i++) 
+		if ( *i != 0 )
+			WLog("QueueManager",
+				"~QueueManager(): queue " << (*i)->get_name()
+				<< " has not been unregistered");
+
+	pthread_mutex_unlock(&mutex);
+
+	pthread_mutex_destroy(&mutex);
+}
+
+//@}
+
+} // end namespace protlib
Index: /source/ariba/utility/transport/tcpip/protlib/queuemanager.h
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/queuemanager.h	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/queuemanager.h	(revision 5284)
@@ -0,0 +1,121 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file queuemanager.h
+/// This is the queuemanager which records queues and message source IDs
+/// ----------------------------------------------------------
+/// $Id: queuemanager.h 2549 2007-04-02 22:17:37Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/queuemanager.h $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+/** @ingroup queuemanager
+ *
+ * This is the queuemanager which records queues and message source IDs.
+ */
+
+#ifndef QUEUE_MANAGER_H
+#define QUEUE_MANAGER_H
+
+#include "protlib_types.h"
+#include "cleanuphandler.h"
+
+#include <vector>
+
+#include "fqueue.h"
+#include "messages.h"
+
+namespace protlib { 
+
+/** @addtogroup queuemanager Queue Manager
+ * \ingroup fastqueue
+ * @{
+ */
+
+/// QueueManager errors
+class QueueManagerError : public ProtLibException {
+public:
+	/// error codes
+	enum error_t {
+		ERROR_NO_QUEUE_MANAGER,
+		ERROR_REGISTER
+	}; // end error_t
+	const error_t err;
+	/// constructor
+	QueueManagerError(error_t e);
+	virtual const char* getstr() const;
+	virtual const char *what() const throw() { return getstr(); }
+private:
+	/// QueueManager error strings
+	static const char* const errstr[];
+}; // end class QueueManagerError
+
+
+/**
+ * The Queue Manager singleton.
+ *
+ * The QueueManager manages several FastQueue objects. A queue is registered
+ * with the manager using a simple (key, value) scheme. The key is of type
+ * message:qaddr_t, and the value is a FastQueue object.
+ *
+ * You can send messages to a registered queue using the message::send_to(dest)
+ * method, where dest has to be the message::qaddr_t which has been used for
+ * registering the queue.
+ *
+ * This class is used as a singleton, so there will usually be only one
+ * object of this class.
+ */
+class QueueManager {
+public:
+	/// return QueueManager singleton instance
+	static QueueManager* instance();
+	/// clear QueueManager 
+	static void clear();
+	/// register a queue
+	void register_queue(FastQueue* fq, message::qaddr_t s);
+	/// deregister a queue
+	void unregister_queue(message::qaddr_t s);
+
+	/// get queue
+	FastQueue* get_queue(message::qaddr_t s) const;
+private:
+	/// QueueManager instance
+	static QueueManager* inst;
+	/// constructor
+	QueueManager();
+	/// Destruktor
+	~QueueManager();
+	/// QueueManager array
+	typedef vector<FastQueue*> qm_array_t;
+	/// QueueManager array iterator
+	typedef qm_array_t::iterator qm_array_it_t;
+	/// array
+	qm_array_t queue_arr;
+	/// locking
+	mutable pthread_mutex_t mutex;
+
+	static const size_t INITIAL_ARRAY_SIZE = 128;
+};
+
+//@}
+
+} // end namespace protlib
+
+#endif
Index: /source/ariba/utility/transport/tcpip/protlib/setuid.cpp
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/setuid.cpp	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/setuid.cpp	(revision 5284)
@@ -0,0 +1,172 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file setuid.cpp
+/// Change effective user ID in a thread-safe way.
+/// ----------------------------------------------------------
+/// $Id: setuid.cpp 2549 2007-04-02 22:17:37Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/src/setuid.cpp $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+/** @ingroup tssetuid
+ *
+ * Thread-safe setuid support for linux. 
+ * Change effective user ID in a thread-safe way.
+ *
+ * tsdb::init() must be called before calling setuid::init().
+ */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include "setuid.h"
+#include "threadsafe_db.h"
+#include "cleanuphandler.h"
+#include "logfile.h"
+
+
+namespace protlib { 
+
+/** @addtogroup tssetuid Thread-safe setuid program support
+ * @{
+ */
+
+  using namespace log;
+
+void setuid::init() {
+	if (is_init) {
+	  Log(ERROR_LOG,LOG_CRIT, "setuid", "Tried to initialize setuid although already initialized.");
+	} else {
+		pthread_mutex_init(&mutex,NULL);
+		count = 0;
+		file_userid = ::geteuid();
+		real_userid = ::getuid();
+		is_setuid = (real_userid!=file_userid);
+		file_username = tsdb::get_username(file_userid);
+		real_username = tsdb::get_username(real_userid);
+		is_init = true;
+		if (is_setuid) {
+		  Log(INFO_LOG,LOG_CRIT, "setuid", "Setuid-bit is set, euid is " << file_userid << " " << file_username << ", realuid is " << real_userid << " " << real_username << ". Turning off setuid as soon as possible");
+		  count = 1;
+		  off();
+		} else {
+		  Log(INFO_LOG,LOG_CRIT, "setuid", "Setuid-bit is not set or euid and ruid are equal. setuid::on() and setuid::off() will do nothing");
+		} // end if is_setuid
+	} // end if is_init
+} // end init
+
+void setuid::end() {
+	if (is_init) {
+		is_init = false;
+		pthread_mutex_destroy(&mutex);
+		count = 0;
+		// turn off setuid
+		if (is_setuid) {
+		  Log(INFO_LOG,LOG_CRIT, "setuid", "setuid::end() turn off setuid. Switching (maybe permamently) to " << real_userid << " " << real_username << " using setuid()");
+		  ::setuid(real_userid);
+		} // end if is_setuid
+	} else {
+	  Log(ERROR_LOG,LOG_CRIT, "setuid", "Tried to end setuid although not initialized.");
+	} // end if is_init
+} // end end
+
+void setuid::on() {
+	if (is_setuid) {
+		if (is_init) {
+			pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
+			if (count==0) {
+			  Log(INFO_LOG,LOG_CRIT, "setuid", "setuid::on(): setting euid to " << file_userid << " " << file_username);
+			  int status;
+                          #ifdef _POSIX_SAVED_IDS
+			  status = seteuid(file_userid);
+				#else
+					status = setreuid(real_userid,file_userid);
+				#endif
+				if (status<0) {
+				  Log(ERROR_LOG,LOG_ALERT, "setuid", "setuid::on(): error " << strerror(errno));
+				} else count++;
+			} else {
+			  Log(INFO_LOG,LOG_CRIT, "setuid", "setuid::on(): setuid already on");
+			  count++;
+			} // end if count
+			pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
+		} else {
+		  Log(ERROR_LOG,LOG_CRIT, "setuid", "Tried to use setuid although not initialized.");
+		} // end if is_init
+	} // end if is_setuid
+} // end on
+
+void setuid::off() {
+	if (is_setuid) {
+		if (is_init) {
+			pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
+			if (count==1) {
+				int status;
+				#ifdef _POSIX_SAVED_IDS
+					status = seteuid(real_userid);
+				#else
+					status = setreuid(file_userid,real_userid);
+				#endif
+				if (status<0) {
+				  Log(ERROR_LOG,LOG_ALERT, "setuid", "setuid::off(): error " << strerror(errno));
+				} else {
+				  count = 0;
+				  Log(INFO_LOG,LOG_CRIT, "setuid", "setuid::off(): set euid to " << real_userid << " " << real_username);
+				} // end if count
+			} else if (count==0) {
+			  Log(INFO_LOG,LOG_CRIT, "setuid", "setuid::off(): setuid already off");
+			} else {
+			  Log(INFO_LOG,LOG_CRIT, "setuid", "setuid::off(): setuid still on");
+			  count--;
+			} // end if count
+			pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
+		} else {
+		  Log(ERROR_LOG,LOG_CRIT, "setuid", "Tried to use setuid although not initialized.");
+		} // end if is_init
+	} // end if is_setuid
+} // end off
+
+bool setuid::is_init = false;
+
+pthread_mutex_t setuid::mutex =
+#ifdef _DEBUG
+    PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
+#else
+    PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+uint32 setuid::count = 0;
+
+uid_t setuid::file_userid = 65534;
+
+string setuid::file_username = "nobody";
+
+uid_t setuid::real_userid = 65534;
+
+string setuid::real_username = "nobody";
+
+bool setuid::is_setuid = true; // important!
+
+//@}
+
+} // end namespace protlib
Index: /source/ariba/utility/transport/tcpip/protlib/setuid.h
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/setuid.h	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/setuid.h	(revision 5284)
@@ -0,0 +1,94 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file setuid.h
+/// Change effective user ID in a thread-safe way
+/// ----------------------------------------------------------
+/// $Id: setuid.h 2549 2007-04-02 22:17:37Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/setuid.h $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+/** @ingroup tssetuid
+ *
+ * Thread-safe setuid support for linux. 
+ * Change effective user ID in a thread-safe way.
+ *
+ * tsdb::init() must be called before calling setuid::init().
+ */
+
+#ifndef THREADSAFE_SETUID_H
+#define THREADSAFE_SETUID_H
+
+#include <sys/types.h>
+#include <pthread.h>
+#include <string>
+
+#include "protlib_types.h"
+#include "cleanuphandler.h"
+
+namespace protlib { 
+
+/** @addtogroup tssetuid Thread-safe setuid program support
+ * @{
+ */
+
+/// Thread-safe setuid
+/** This class provieds class methods for changing the effective user ID of
+ * the current process.
+ */
+class setuid {
+public:
+	/// initialize setuid 
+	static void init();
+	/// cleanup setuid resources
+	static void end();
+	/// turn on setuid mode
+	static void on();
+	/// turn off setuid mode
+	static void off();
+private:
+	/// init state
+	static bool is_init;
+	/// setuid mutex
+	static pthread_mutex_t mutex;
+	/// setuid counter
+	static uint32 count;
+	/// file user ID
+	static uid_t file_userid;
+	/// file user name
+	static string file_username;
+	/// real user ID
+	static uid_t real_userid;
+	/// real user name
+	static string real_username;
+	/// are we using setuid?
+	static bool is_setuid;
+}; // end class setuid
+
+/// Turn on setuid mode and install cleanup handler.
+#define BEGIN_SETUID_MODE protlib::setuid::on(); install_cleanup(call_void_fun,protlib::setuid::off)
+#define END_SETUID_MODE uninstall_cleanup(1)
+
+//@}
+
+} // end namespace protlib
+
+#endif
Index: /source/ariba/utility/transport/tcpip/protlib/testqueue.c
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/testqueue.c	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/testqueue.c	(revision 5284)
@@ -0,0 +1,85 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file testqueue.c
+/// Testing fastqueue.
+/// ----------------------------------------------------------
+/// $Id: testqueue.c 2872 2008-02-18 10:58:03Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/fastqueue/testqueue.c $
+// ===========================================================
+//
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+
+/**
+ * @ingroup fastqueue
+ * @{
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <pthread.h> /* Headers for POSIX-Threads */
+#include <time.h>    /* needed for getting Timestamps */
+
+#include "fastqueue.h"
+
+#define error_check(status,string) \
+        if (status==-1) perror(string);
+
+#define MAXELEMENTS 10000
+
+                         /*** global variables ***/
+pthread_t       producer_thread,             /* Thread Objects (sim. to TCB) */
+                consumer_thread;
+
+float           queuetime, porttime;
+
+
+/** both queues must be created before monitor tasks are started **/
+queue_t       *consumer_cmdq;     /** queue for consumertask **/
+struct timespec ts_start,ts_end;
+int status;              /* Hold status from pthread_ calls */
+
+void *producertask(void * argp)
+{
+  long i;
+  fprintf(stderr,"QUEUETEST started. Please wait.\n");
+  clock_gettime(CLOCK_REALTIME,&ts_start);
+  for (i=1; i<=MAXELEMENTS; i++)
+      enqueue_element_signal(consumer_cmdq, (void *) i);
+
+  return NULL;
+}
+
+void *consumertask(void * argp)
+{
+  long j;
+  /** test queue **/
+  while ((j= (int) dequeue_element_wait(consumer_cmdq))<MAXELEMENTS);
+
+  clock_gettime(CLOCK_REALTIME,&ts_end);
+  queuetime= ts_end.tv_sec-ts_start.tv_sec +
+             (ts_end.tv_nsec-ts_start.tv_nsec)*1E-9;
+  fprintf(stderr,"QUEUETEST stopped (%d elements): %gs\n",MAXELEMENTS,queuetime);
+  return NULL;
+}
+
+/**** end of source ****/
+
+//@}
Index: /source/ariba/utility/transport/tcpip/protlib/threads.cpp
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/threads.cpp	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/threads.cpp	(revision 5284)
@@ -0,0 +1,315 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file threads.cpp
+/// A Thread class for POSIX threads
+/// ----------------------------------------------------------
+/// $Id: threads.cpp 2872 2008-02-18 10:58:03Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/src/threads.cpp $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+
+#include <sys/time.h>
+
+#include "threads.h"
+
+
+namespace protlib {
+   using namespace log;
+
+/** @addtogroup thread Threads
+ * @{
+ */
+
+
+/** This is the default sleep time and can be used as default value in
+ * constructors.
+ */
+uint32 ThreadParam::default_sleep_time = 5;
+
+
+/**
+ * Initializes a ThreadParam object with a default wait time and a 
+ * a thread (group) name string.
+ *
+ * @param wait wait time between stopping and aborting the thread inside
+ *    ThreadStarter::abort_processing
+ * @param n name of the threads.
+ * @param minc minimal number of threads
+ * @param maxc maximal number of threads
+ */
+ThreadParam::ThreadParam(uint32 wait, const char *n, uint32 minc, uint32 maxc) 
+		: sleep_time(wait), name(n ? n : "UNKNOWN"),
+		  min_count(minc), max_count(maxc) {
+
+	  assert( minc > 0 );
+	  assert( maxc >= minc );
+}
+
+
+/**
+ * Constructor.
+ *
+ * @param p thread parameters
+ * @param create_queue if true, create one internal queue
+ * @param exp_allow if true, allow reception of expedited messages on the queue
+ */
+Thread::Thread(const ThreadParam &p, bool create_queue, bool exp_allow)
+	: running_threads(0), started_threads(0), state(STATE_INIT), tparam(p),
+	  fq(create_queue ? new FastQueue(p.name.c_str(), exp_allow) : 0) {
+
+	pthread_mutexattr_t mutex_attr;
+
+	pthread_mutexattr_init(&mutex_attr);
+
+#ifdef _DEBUG
+	pthread_mutexattr_settype(&mutex_attr,PTHREAD_MUTEX_ERRORCHECK);
+#else
+	pthread_mutexattr_settype(&mutex_attr,PTHREAD_MUTEX_NORMAL);
+#endif
+
+	pthread_mutex_init(&mutex, &mutex_attr);
+	pthread_cond_init(&cond,NULL);
+
+	pthread_mutexattr_destroy(&mutex_attr);
+}
+
+
+/**
+ * Destructor.
+ *
+ * Currently throws an exception if there are still running threads.
+ */
+Thread::~Thread() {
+	if ( get_running_threads() )
+		throw ThreadError(ThreadError::ERROR_STILL_RUNNING);
+
+	delete fq; // delete queue, no-op if fq is NULL
+
+	pthread_cond_destroy(&cond);
+	pthread_mutex_destroy(&mutex);
+}
+
+
+/**
+ * Called for each thread when processing is started.
+ *
+ * The thread must not be locked because this is done inside this method.
+ * Cancellation is enabled and set to synchronous mode. So you only need to
+ * install cleanup handlers when there is a cancellation point between
+ * calls to lock() and unlock().
+ */
+void *Thread::start_processing() {
+
+	lock();
+
+	switch (state) {
+		case STATE_INIT: 
+			state=STATE_RUN;
+			break;
+		case STATE_RUN:
+			break;
+		case STATE_STOP:
+		case STATE_ABORT:
+			unlock();
+			return NULL;
+	}
+
+	inc_running_threads();
+	inc_started_threads();
+
+	int thread_num = get_started_threads();
+
+	unlock();
+
+	/*
+	 * Catch exceptions for logging, but don't rethrow them as this would
+	 * lead to undefined behaviour (probably crashing the ThreadStarter).
+	 *
+	 * All exceptions should be handled in main_loop(), it is a programming
+	 * error if they are propagated up to this point!
+	 */
+	try {
+		main_loop(thread_num);
+	}
+	catch ( ProtLibException &e ) {
+		ERRLog("Threads", "Unhandled ProtLibException in thread "
+			<< tparam.name << ", num " << thread_num << ", error ["
+			<< e.getstr() << ']');
+	}
+	catch ( bad_alloc & ) {
+		ERRLog("Threads", tparam.name << ", num " << thread_num
+			<< ": [out of memory]");
+	}
+	catch ( ... ) {
+		ERRLog("Threads", "Unhandled non-ProtLibException in thread "
+			<< tparam.name << ", num " << thread_num);
+	}
+
+	lock();
+	dec_running_threads();
+	unlock();
+
+	return NULL;
+}
+
+
+/**
+ * Called when the thread is asked to stop processing.
+ *
+ * The thread object may do some cleanup or work on until it has completed
+ * a task.
+ *
+ * @param do_lock if true the thread mutex is used
+ */
+void Thread::stop_processing(bool do_lock) {
+	if ( do_lock )
+		lock();
+
+	if (state==STATE_RUN) {
+		state = STATE_STOP;
+		signal_cond();
+	}
+
+	if ( do_lock )
+		unlock();
+}
+
+
+/**
+ * This is called just before a running thread is killed.
+ *
+ * @param do_lock if true the thread mutex is used
+ */
+void Thread::abort_processing(bool do_lock) {
+	if ( do_lock )
+		lock();
+
+	if ( state == STATE_RUN  ||  state == STATE_STOP ) {
+		state = STATE_ABORT;
+		signal_cond();
+	}
+
+	if ( do_lock )
+		unlock();
+}
+
+
+/**
+ * Checks whether there is still a running thread. 
+ *
+ * @param do_lock if true the thread mutex is used
+ */
+bool Thread::is_running(bool do_lock) {
+
+	if ( do_lock )
+		lock();
+
+	bool res = ( get_running_threads() > 0 );
+
+	if ( do_lock )
+		unlock();
+
+	return res;
+}
+
+
+/**
+ * Wait for the condition.
+ *
+ * @param sec relative time (seconds)
+ * @param nsec relative time (nanoseconds)
+ * @return 0, ETIMEDOUT or EINTR.
+ */
+int Thread::wait_cond(int32 sec, int32 nsec) {
+	struct timeval tv;
+	struct timespec ts;
+
+	if ( sec < 0 )
+		sec = 0;
+	if ( nsec < 0 )
+		nsec = 0;
+
+	gettimeofday(&tv, NULL);
+	ts.tv_sec = tv.tv_sec+sec;
+	ts.tv_nsec = tv.tv_usec*1000+nsec;
+
+	// TODO: This is weird.
+	while ( ts.tv_nsec > 1000000000) {
+		ts.tv_sec++;
+		ts.tv_nsec -= 1000000000;
+	}
+
+	if ( ts.tv_sec < 0 )
+		ts.tv_sec = 0;
+	if ( ts.tv_nsec < 0 )
+		ts.tv_nsec = 0;
+
+	return pthread_cond_timedwait(&cond, &mutex, &ts);
+}
+
+
+/**
+ * Returns the thread's state.
+ *
+ * @param do_lock if true the thread mutex is used
+ * @return the thread's current state
+ *
+ * @see enum state_t for more information on what a thread state is.
+ */
+Thread::state_t Thread::get_state(bool do_lock) {
+	if ( do_lock )
+		lock();
+
+	state_t s = state;
+
+	if ( do_lock )
+		unlock();
+
+	return s;
+}
+
+/// get time of day as timespec
+void Thread::get_time_of_day(struct timespec& ts) {
+	struct timeval tv;
+	gettimeofday(&tv,NULL);
+	ts.tv_sec = tv.tv_sec;
+	ts.tv_nsec = tv.tv_usec*1000;
+}
+
+const char* ThreadError::getstr() const {
+	return errstr[(int)err];
+}
+
+const char* const ThreadError::errstr[] = {
+	"Cannot create POSIX Threads.",
+	"Thread is running.",
+	"Thread is going to stop.",
+	"Thread is aborting.",
+	"Still running threads left.",
+	"ThreadStarter is not initialized correctly."
+	"Internal ThreadStarter or Thread error.",
+	"Thread has not been started yet."
+};
+
+//@}
+
+} // end namespace protlib
Index: /source/ariba/utility/transport/tcpip/protlib/threads.h
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/threads.h	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/threads.h	(revision 5284)
@@ -0,0 +1,567 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file threads.h
+/// Thread support functions (classes thread and threadstarter) based on POSIX threads
+/// ----------------------------------------------------------
+/// $Id: threads.h 2549 2007-04-02 22:17:37Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/threads.h $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+
+/**
+ * Classes to support multi-threaded programming.
+ *
+ * @ingroup thread
+ *
+ * A Thread module class must inherit from Thread. Several instances may run
+ * simultaneously but they share exactly one module object. So you must take
+ * care of this fact when writing the module code and use locks accordingly.
+ *
+ * Use lock(), unlock(), wait_cond() and signal_cond() the way you would use
+ * the corresponding POSIX thread functions.
+ *
+ * Use the ThreadStarter template class to create threads.
+ */
+
+#ifndef PROTLIB__THREADS_H
+#define PROTLIB__THREADS_H
+
+#include <pthread.h>
+#include <signal.h>
+#include <sys/times.h>
+#include <string>
+
+#include "protlib_types.h"
+#include "logfile.h"
+#include "fqueue.h"
+
+namespace protlib {
+  using namespace log;
+
+/** @addtogroup thread Threads
+ * @{
+ */
+
+
+/**
+ * Call the method start_processing of a Thread instance.
+ *
+ * @param thread_object a Thread instance
+ */
+template <class T> void *thread_starter(void *thread_object) {
+
+	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+	pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
+
+	(static_cast<T*>(thread_object))->start_processing();
+	return NULL;
+}
+
+
+/**
+ * Base class for thread object parameters.
+ *
+ * This is used by ThreadStarter to extract and store overall data like the
+ * sleep time and is also accessible to the thread object.
+ */
+class ThreadParam {
+  public:
+	ThreadParam();
+	ThreadParam(uint32 wait, const char* name,
+		uint32 minc=1, uint32 maxc=(uint32)-1);
+
+	static uint32 default_sleep_time;
+	/// sleep time
+	const uint32 sleep_time;
+	const std::string name;
+	/// minimum thread count
+	const uint32 min_count;
+	/// maximum thread count
+	const uint32 max_count;
+};
+
+
+/**
+ * This exception will be thrown if there is some trouble with threading.
+ */
+class ThreadError : public ProtLibException {
+  public:
+	enum error_t {
+		ERROR_THREAD_CREATION, ERROR_RUNNING, ERROR_STOPPING,
+		ERROR_ABORTING, ERROR_STILL_RUNNING, ERROR_UNINITIALIZED,
+		ERROR_INTERNAL, ERROR_NOT_STARTED
+	};
+
+	ThreadError(error_t e) : err(e) { }
+	virtual ~ThreadError() throw () { }
+
+	virtual const char* getstr() const;
+	virtual const char *what() const throw() { return getstr(); }
+	const error_t err;
+
+  protected:
+	static const char* const errstr[];
+};
+
+
+/**
+ * Abstract interface for thread modules.
+ *
+ * Don't confuse this Thread class with POSIX threads. A Thread class only
+ * provides a main_loop method which will be executed by one or more POSIX
+ * threads simultaneously. The Thread instance provides a central point for
+ * all those POSIX threads to store data. Don't forget to lock() the Thread
+ * instance to avoid race conditions if you want to access and/or modify
+ * the data.
+ */
+class Thread {
+  public:
+	Thread(const ThreadParam& p,
+		bool create_queue=true, bool exp_allow=true);
+	virtual ~Thread();
+
+	void *start_processing();
+	void stop_processing(bool do_lock=true);
+	void abort_processing(bool do_lock=true);
+
+	bool is_running(bool do_lock=true);
+
+	virtual void main_loop(uint32 thread_num) = 0;
+
+	void lock();
+	void unlock();
+
+	void signal_cond();
+	void broadcast_cond();
+	void wait_cond();
+	int wait_cond(const struct timespec& ts);
+	int wait_cond(int32 sec, int32 nsec=0);
+
+	/**
+	* State of a thread.
+	*
+	* The state of a thread does not really tell whether there are threads
+	* active or not. It only represents a state in the life cycle of a 
+	* thread object.
+	*/
+	enum state_t {
+		STATE_INIT, STATE_RUN, STATE_STOP, STATE_ABORT
+	};
+
+	state_t get_state(bool do_lock=true);
+	FastQueue* get_fqueue() { return fq; }
+
+	static void get_time_of_day(struct timespec& ts);
+
+  private:
+	/// This counter records the number of threads running on this object.
+	uint32 running_threads;
+
+	/// This counter records the number of started threads.
+	uint32 started_threads;
+
+	/** 
+	* Thread-global mutex.
+	*
+	* This mutex is used to lock the thread object when data common to all
+	* threads on this object is modified.
+	*/
+	pthread_mutex_t mutex;
+
+	/// thread object condition
+	pthread_cond_t cond;
+
+	/// thread state
+	state_t state;
+
+	/// Thread parameters.
+	const ThreadParam tparam;
+
+	/// The input queue where threads can get messages from.
+	FastQueue* fq;
+
+	void inc_running_threads();
+	void dec_running_threads();
+	uint32 get_running_threads() const;
+	void inc_started_threads();
+	uint32 get_started_threads() const;
+};
+    
+
+inline void Thread::lock() {
+	if ( pthread_mutex_lock(&mutex) != 0 ) {
+		ERRLog(tparam.name, "Error while locking mutex");
+	}
+}
+
+inline void Thread::unlock() {
+	int ret = pthread_mutex_unlock(&mutex);
+	assert( ret == 0 );
+}
+
+inline void Thread::signal_cond() {
+	pthread_cond_signal(&cond);
+}
+
+inline void Thread::broadcast_cond() {
+	pthread_cond_broadcast(&cond);
+}
+
+inline void Thread::wait_cond() {
+	pthread_cond_wait(&cond,&mutex);
+}
+
+
+/**
+ * @param ts absolute time
+ * @return 0, ETIMEDOUT or EINTR.
+ */
+inline int Thread::wait_cond(const struct timespec& ts) {
+	return pthread_cond_timedwait(&cond, &mutex, &ts);
+}
+
+
+inline void Thread::inc_running_threads() {
+	running_threads++;
+}
+
+inline void Thread::dec_running_threads() {
+	assert( running_threads > 0 );
+	running_threads--;
+}
+
+inline uint32 Thread::get_running_threads() const {
+	return running_threads;
+}
+
+inline void Thread::inc_started_threads() {
+	started_threads++;
+}
+
+inline uint32 Thread::get_started_threads() const {
+	return started_threads;
+}
+
+
+/**
+ * A template class used to start threads.
+ *
+ * Note that the ThreadStarter template class is not thread-safe yet, so it
+ * may only be accessed by one thread at a time.
+ */
+template <class T, class TParam> class ThreadStarter {
+  public:
+	ThreadStarter(uint32 count, const TParam& param);
+	~ThreadStarter();
+
+	void start_processing();
+	void stop_processing();
+	bool sleepuntilstop();		// deprecated!
+	void wait_until_stopped();
+	void abort_processing(bool kill=false);
+
+	/// get a pointer to the thread object
+	inline T *get_thread_object() { return &thread_object; }
+
+	/// Are all threads finished: TODO
+	inline bool is_running() const { return thread_object.is_running(); }
+
+  private:
+	/// The Thread object on which the threads run.
+	T thread_object;
+
+	/// For debugging, the name of the thread as given by TParam.
+	const TParam thread_param;
+
+	/// Contains the handles of all pthreads that we created.
+	std::vector<pthread_t> pthreads;
+};
+
+
+/**
+ * Constructor.
+ *
+ * @param count the number of threads to start
+ * @param param thread parameters
+ */
+template <class T, class TParam>
+ThreadStarter<T, TParam>::ThreadStarter(uint32 count, const TParam& param)
+		: thread_object(param), thread_param(param), pthreads(count) {
+
+	// TODO: fix all Thread subclasses that use an invalid count!
+	if ( count < param.min_count )
+		count = param.min_count;
+	else if ( count > param.max_count )
+		count = param.max_count;
+
+	assert( count >= param.min_count && count <= param.max_count );
+
+	pthreads.resize(count); // TODO: remove
+}
+
+
+/**
+ * Destructor.
+ *
+ * This cancels all running threads if there are still some.
+ */
+template <class T, class TParam> ThreadStarter<T, TParam>::~ThreadStarter() {
+
+	if ( thread_object.is_running() ) {
+		catch_all(stop_processing());
+		sleepuntilstop();
+		catch_all(abort_processing(true));
+	}
+}
+
+
+/**
+ * Start the threads.
+ */
+template <class T, class TParam>
+void ThreadStarter<T, TParam>::start_processing() {
+
+	thread_object.lock();
+
+	/*
+	 * Check if this is a fresh Thread. If it is or was already running,
+	 * we have detected a programming error.
+	 */
+	if ( thread_object.is_running(false) ) {
+		thread_object.unlock();
+
+		ERRLog("Threads", "start_processing(): " << thread_param.name
+			<< " is already running");
+
+		throw ThreadError(ThreadError::ERROR_INTERNAL);
+	}
+
+
+	/*
+	 * Create the requested number of threads.
+	 */
+	int res;
+	pthread_attr_t attr;
+	pthread_attr_init(&attr);
+	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+	for (unsigned i = 0; i < pthreads.size(); i++) {
+		// Create a posix thread. It will start running immediately.
+		res = pthread_create(&pthreads[i], &attr,
+					&thread_starter<T>, &thread_object);
+
+		if ( res != 0 ) {
+			thread_object.unlock();
+			ERRLog("Threads", "pthread_create() failed starting a "
+				<< "thread for " << thread_param.name);
+
+			throw ThreadError(ThreadError::ERROR_THREAD_CREATION);
+		}
+	}
+
+	ILog("Threads", pthreads.size() << " " << thread_param.name
+		<< " thread(s) sucessfully created");
+
+	pthread_attr_destroy(&attr); // has no effect on the created threads
+
+	thread_object.unlock();
+}
+
+
+/**
+ * Ask all threads to stop (politely).
+ */
+template <class T, class TParam>
+void ThreadStarter<T, TParam>::stop_processing() {
+
+	thread_object.lock();
+
+	typename T::state_t state = thread_object.get_state(false);
+
+	switch (state) {
+
+	  case T::STATE_INIT:
+		thread_object.unlock();
+		DLog("Threads", "Thread " << thread_param.name
+			<< " has not been started yet.");
+		throw ThreadError(ThreadError::ERROR_NOT_STARTED);
+		break;
+
+	  case T::STATE_RUN:
+		thread_object.stop_processing(false);
+		thread_object.unlock();
+
+		ILog("Threads", "Thread(s) "
+			<< thread_param.name << " asked to stop");
+		break;
+
+	  case T::STATE_STOP:
+		thread_object.unlock();
+		DLog("Threads", "Thread(s) "
+			<< thread_param.name << " is already in state stop.");
+		throw ThreadError(ThreadError::ERROR_STOPPING);
+		break;
+
+	  case T::STATE_ABORT:
+		//thread_object.unlock();
+		DLog("Threads", "Thread "
+			<< thread_param.name << " is in state abort.");
+		//throw ThreadError(ThreadError::ERROR_ABORTING);
+		break;
+
+	  default:
+		assert( false ); // unknown state
+
+	}
+}
+
+
+/**
+ * Wait for the thread to stop running (DEPRECATED).
+ *
+ * Sleeps until all threads have stopped running but not longer than
+ * sleep_time seconds.
+ *
+ * This method is deprecated because it suffers from a race condition:
+ * If none of the pthreads created in start_processing() has been run yet,
+ * then this method returns immediately. Use wait_until_stopped() instead.
+ *
+ * @return true if the threads have stopped
+ *
+ * @see ThreadParam
+ */
+template <class T, class TParam>
+bool ThreadStarter<T, TParam>::sleepuntilstop() {
+	
+	for (uint32 i = 0; thread_object.is_running()
+			&& i < thread_param.sleep_time; i++)
+		sleep(1);
+
+	return ( thread_object.is_running() ? false : true );
+}
+
+
+/**
+ * Wait until all threads have stopped running.
+ *
+ * Threads that haven't been running yet (state IDLE) are not considered
+ * as stopped!
+ */
+template <class T, class TParam>
+void ThreadStarter<T, TParam>::wait_until_stopped() {
+
+	DLog("Threads",
+		"Waiting for Thread " << thread_param.name << " to stop");
+
+	Thread::state_t state = thread_object.get_state(false);
+
+	while ( state == Thread::STATE_INIT || thread_object.is_running() ) {
+		sleep(1);
+		state = thread_object.get_state(false);
+	}
+
+	DLog("Threads", "Thread " << thread_param.name << " has stopped");
+}
+
+
+/**
+ * Stop and kill the threads.
+ *
+ * @param kill kill the threads if they do not stop. 
+ */
+template <class T, class TParam>
+void ThreadStarter<T, TParam>::abort_processing(bool kill) {
+
+	thread_object.lock();
+
+	switch ( thread_object.get_state(false) ) {
+
+	  case T::STATE_INIT:
+		thread_object.unlock();
+		DLog("Threads", "Thread "
+			<< thread_param.name << " has not been started yet.");
+		throw ThreadError(ThreadError::ERROR_NOT_STARTED);
+		break;
+
+	  case T::STATE_ABORT: 
+		if ( ! kill ) {
+			//thread_object.unlock();
+			DLog("Threads", "Thread " << thread_param.name
+				<< " is already in state abort.");
+
+			//throw ThreadError(ThreadError::ERROR_ABORTING);
+		}
+		break;
+
+	  default:
+		break;
+	}
+
+	if ( thread_object.is_running(false) ) {
+		thread_object.stop_processing(false); 
+		// unlock and sleep so the threads have a chance to stop.
+		thread_object.unlock();
+		sleepuntilstop();
+		thread_object.lock();
+	}
+
+	thread_object.abort_processing(false);
+
+	// unlock and let the thread abort
+	thread_object.unlock();
+	sleepuntilstop();
+	thread_object.lock();
+
+	if ( thread_object.is_running(false) ) {
+		// unlock and maybe kill
+		thread_object.unlock();
+		if (kill) {
+			for (unsigned i = 0; i < pthreads.size(); i++) 
+				pthread_cancel( pthreads[i] );
+
+			sleepuntilstop();
+
+			for (unsigned i = 0; i < pthreads.size(); i++) 
+				pthread_kill(pthreads[i], 9);
+
+			ILog("Threads", pthreads.size() << " thread(s) "
+				<< thread_param.name << " killed");
+		} else {
+			ILog("Threads", pthreads.size() << " thread(s) "
+				<< thread_param.name << " refused to abort");
+
+			throw ThreadError(ThreadError::ERROR_STILL_RUNNING);
+		}
+
+	} else {
+		thread_object.unlock();
+		ILog("Threads", pthreads.size() << " thread(s) "
+			<< thread_param.name << " have terminated");
+	}
+}
+
+
+//@}
+
+} // namespace protlib
+
+#endif // PROTLIB__THREADS_H
Index: /source/ariba/utility/transport/tcpip/protlib/threadsafe_db.cpp
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/threadsafe_db.cpp	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/threadsafe_db.cpp	(revision 5284)
@@ -0,0 +1,358 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file threadsafe_db.cpp
+/// Thread-safe access for some resolving functions (netdb)...
+/// ----------------------------------------------------------
+/// $Id: threadsafe_db.cpp 2872 2008-02-18 10:58:03Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/src/threadsafe_db.cpp $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+/** @ingroup netdb
+ *
+ * As the reentrant functions for netdb access seem not portable, I decided to 
+ * write some wrappers for those functions I need. This is not 
+ * object-oriented because the NetDB would be another singleton object and
+ * I only want some wrapper functions.
+ */
+
+#include <netdb.h>
+#include <pwd.h>
+#include <netinet/in.h>
+#include <cerrno>
+
+#include "threadsafe_db.h"
+#include "cleanuphandler.h"
+#include "logfile.h"
+
+namespace protlib { 
+
+/** @addtogroup netdb Thread-safe DB
+ * @{
+ */
+
+  using namespace log;
+
+bool tsdb::is_init = false;
+bool tsdb::resolvenames = true;
+pthread_mutex_t tsdb::mutex = 
+#ifdef _DEBUG
+    PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
+#else
+    PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+
+uint32 tsdb::id32 = 1;
+uint64 tsdb::id64 = 1;
+
+protocol_t tsdb::udp_id= 17;
+protocol_t tsdb::tcp_id= 6;
+protocol_t tsdb::sctp_id= 132;
+
+
+void 
+tsdb::init(bool noresolving) 
+{
+  if (is_init) 
+  {
+    Log(ERROR_LOG,LOG_NORMAL, "Threadsafe_DB", "Tried to initialize tstdb although already initialized.");
+  } else 
+  {
+    pthread_mutex_init(&mutex,NULL);
+    is_init = true;
+
+    // initialize frequently used protocol constants
+    udp_id= tsdb::getprotobyname("udp");
+    tcp_id= tsdb::getprotobyname("tcp");
+    sctp_id= tsdb::getprotobyname("sctp");
+
+    resolvenames=!noresolving;
+    if (!resolvenames) 
+      Log(INFO_LOG,LOG_NORMAL,"Threadsafe_DB"," ** Disabled reverse name lookups - addresses will not be resolved to names **");
+  } // end if is_init
+} // end init
+  
+void tsdb::end() {
+	if (is_init) {
+		is_init = false;
+		pthread_mutex_destroy(&mutex);
+	} else {
+	  Log(ERROR_LOG,LOG_NORMAL, "Threadsafe_DB", "Tried to end tstdb although not initialized.");
+	} // end if is_init
+} // end end
+
+uint32 tsdb::get_new_id32() {
+	uint32 res = 0;
+	if (is_init) {
+		pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
+		res = id32++;
+		pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
+	} else {
+	  Log(ERROR_LOG,LOG_NORMAL, "Threadsafe_DB", "Tried to access tsdb although not initialized.");
+	} // end if is_init
+	return res;
+} // end get_new_id32
+
+uint64 tsdb::get_new_id64() {
+	uint64 res = 0;
+	if (is_init) {
+		pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
+		res = id64++;
+		pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
+	} else {
+	  Log(ERROR_LOG,LOG_NORMAL, "Threadsafe_DB", "Tried to access tsdb although not initialized.");
+	} // end if is_init
+	return res;
+} // end get_new_id64
+
+string tsdb::getprotobynumber(protocol_t proto, bool *res) {
+	string str;
+	if (is_init) 
+	{
+		pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
+		struct protoent* entry = ::getprotobynumber(proto);
+
+		if (res) *res = (entry!=NULL);
+		if (entry) 
+		  str = entry->p_name;
+		else 
+		  str = "UNKNOWN";
+
+		pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
+	} 
+	else 
+	{
+	  Log(ERROR_LOG,LOG_NORMAL, "Threadsafe_DB", "Tried to access tsdb although not initialized.");
+	  if (res) *res = false;
+	  str = "";
+	} // end if is_init
+	return str;
+} // end getprotobynumber
+
+protocol_t tsdb::getprotobyname(const string &pname, bool *res) {
+	return getprotobyname(pname.c_str(),res);
+} // end getprotobyname
+
+protocol_t tsdb::getprotobyname(const char* pname, bool *res) {
+	register protocol_t pnum;
+	struct protoent* entry = NULL;
+	if (is_init) {
+		pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
+		if (pname) entry = ::getprotobyname(pname);
+		if (res) *res = (entry!=NULL);
+		if (entry) pnum = entry->p_proto;
+		else pnum = 0;
+		pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
+	} else {
+	  Log(ERROR_LOG,LOG_NORMAL, "Threadsafe_DB", "Tried to access tsdb although not initialized.");
+	  if (res) *res = false;
+	  pnum = 0;
+	} // end if is_init
+	return pnum;
+} // end getprotobyname
+
+string tsdb::get_username(uid_t uid, bool *res) {
+	string str;
+	if (is_init) {
+		pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
+		struct passwd* entry = ::getpwuid(uid);
+		if (res) *res = (entry!=NULL);
+		if (entry) str = entry->pw_name;
+		else str = "UNKNOWN";
+		pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
+	} else {
+	  Log(ERROR_LOG,LOG_NORMAL, "Threadsafe_DB", "Tried to access tsdb although not initialized.");
+	  if (res) *res = false;
+	  str = "";
+	} // end if is_init
+	return str;
+} // end get_username
+
+uid_t tsdb::get_userid(const char* uname, bool *res) {
+	register uid_t uid;
+	struct passwd* entry = NULL;
+	if (is_init) {
+		pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
+		if (uname) entry = ::getpwnam(uname);
+		if (res) *res = (entry!=NULL);
+		if (entry) uid = entry->pw_uid;
+		else uid = 0;
+		pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
+	} else {
+	  Log(ERROR_LOG,LOG_NORMAL, "Threadsafe_DB", "Tried to access tsdb although not initialized.");
+	  if (res) *res = false;
+	  uid = 0;
+	} // end if is_init
+	return uid;
+} // end get_userid
+
+uid_t tsdb::get_userid(const string& uname, bool *res) {
+	return get_userid(uname.c_str(),res);
+} // end get_userid
+
+string tsdb::get_portname(port_t port, protocol_t prot, bool *res) {
+	string str;
+	if (is_init) {
+		bool tmpres = true;
+		string pname = getprotobynumber(prot,&tmpres);
+		if (tmpres) {
+			pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
+			struct servent* entry = ::getservbyport(htons(port),pname.c_str());
+			if (res) *res = (entry!=NULL);
+			if (entry) str = entry->s_name;
+			else str = "UNKNOWN";
+			pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
+		} else {
+			if (res) *res = false;
+			str = "UNKNOWN";
+		} // end if tmpres
+	} else {
+	  Log(ERROR_LOG,LOG_NORMAL, "Threadsafe_DB", "Tried to access tsdb although not initialized.");
+	  if (res) *res = false;
+	  str = "";
+	} // end if is_init
+	return str;
+} // end get_portname
+
+port_t tsdb::get_portnumber(const char* pname, protocol_t prot, bool *res) {
+	register port_t pnum;
+	struct servent* entry = NULL;
+	if (is_init) {
+		bool tmpres = true;
+		string protoname = getprotobynumber(prot,&tmpres);
+		if (tmpres) {
+			pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
+			if (pname) entry = ::getservbyname(pname,protoname.c_str());
+			if (res) *res = (entry!=NULL);
+			if (entry) pnum = ntohs(entry->s_port);
+			else pnum = 0;
+			pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
+		} else {
+			if (res) *res = false;
+			pnum = 0;
+		} // end if tmpres
+	} else {
+	  Log(ERROR_LOG,LOG_NORMAL, "Threadsafe_DB", "Tried to access tsdb although not initialized.");
+	  if (res) *res = false;
+	  pnum = 0;
+	} // end if is_init
+	return pnum;
+} // end get_portnumber
+
+port_t tsdb::get_portnumber(const string& pname, protocol_t prot, bool *res) {
+	return get_portnumber(pname.c_str(),prot,res);
+} // end get_portnumber
+
+
+string 
+tsdb::get_hostname(const struct sockaddr* sa, bool *res) 
+{
+  string str;
+  static char tmpbuf[NI_MAXHOST];
+
+  if (is_init) 
+  {
+    pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
+    if (resolvenames)
+    {
+      int resultval= getnameinfo(sa,sizeof(struct sockaddr),
+				 tmpbuf,sizeof(tmpbuf),
+				 0,0, // services
+				 0);  // flags
+      
+      if (res) *res = (resultval==0);
+      if (resultval==0)
+      { // success
+	str= tmpbuf; // this should copy the buffer contents
+      }
+      else
+      {
+	str = "UNKNOWN";
+	if (resultval==EAI_AGAIN || errno==EAI_AGAIN)
+	{
+	  Log(INFO_LOG,LOG_NORMAL, "Threadsafe_DB", "Temporary failure in name lookup. Try again later.");
+	}
+	else
+	  Log(INFO_LOG,LOG_NORMAL, "Threadsafe_DB", "Name lookup failed -" << strerror(errno));
+
+	if (res) *res= false;
+      }
+    }
+    else
+    {
+      str= "disabled";
+      if (res) *res= false;
+    }
+    pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
+  }
+  else 
+  {
+    Log(ERROR_LOG,LOG_NORMAL, "Threadsafe_DB", "Tried to access tsdb although not initialized.");
+    if (res) *res = false;
+    str = "";
+  } // end if is_init
+  return str;
+} // ent get_hostname(in_addr)
+
+
+
+/** lookup of hostname for an ipv4 address
+ *  @param in ipv4 address structure
+ *  @param res returns true if name lookup was successful, otherwise false
+ *
+ *  @return in case that resolving is enabled it returns the host name corresponding to the given address or "UNKNOWN", 
+ *           otherwise it returns "disabled"
+ */
+string 
+tsdb::get_hostname(const in_addr& in, bool *res) 
+{
+  struct sockaddr_in sa={
+    AF_INET,
+    0,
+    in
+  };
+  return get_hostname(reinterpret_cast<const sockaddr*>(&sa),res);
+}
+
+/** lookup of hostname for ipv6 address
+ *  @param in ipv6 address structure
+ *  @param res returns true if name lookup was successful, otherwise false
+ *
+ *  @return in case that resolving is enabled it returns the host name corresponding to the given address or "UNKNOWN", 
+ *           otherwise it returns "disabled"
+ */
+string 
+tsdb::get_hostname(const in6_addr& in, bool *res) 
+{
+  struct sockaddr_in6 sa={
+    AF_INET6,
+    0, // transport layer port #
+    0, // IPv6 flow information
+    in,
+    0  // scope id (new in RFC2553)
+  };
+  return get_hostname(reinterpret_cast<const sockaddr*>(&sa),res);
+} // ent get_hostname(in6_addr)
+
+//@}
+
+} // end namespace protlib
Index: /source/ariba/utility/transport/tcpip/protlib/threadsafe_db.h
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/threadsafe_db.h	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/threadsafe_db.h	(revision 5284)
@@ -0,0 +1,122 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file threadsafe_db.h
+/// Thread-safe netdb access
+/// ----------------------------------------------------------
+/// $Id: threadsafe_db.h 2549 2007-04-02 22:17:37Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/threadsafe_db.h $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+/** @ingroup netdb
+ *
+ * Thread-safe netdb access for linux.
+ *
+ * As the reentrant functions for netdb access seem not portable, I decided to 
+ * write some wrappers for those functions I need. This is not 
+ * object-oriented because the NetDB would be another singleton object and
+ * I only want some wrapper functions.
+ */
+
+#ifndef THREADSAFE_DB_H
+#define THREADSAFE_DB_H
+
+#include <sys/types.h>
+#include <pthread.h>
+#include <netinet/in.h>
+#include <string>
+
+#include "protlib_types.h"
+
+namespace protlib { 
+
+/** @addtogroup netdb Thread-safe DB
+ * @{
+ */
+
+/// Thread-safe DB
+/** This class provides class methods for accessing the protocol database
+ * and maybe other services from netdb.h in a thread-safe way.
+ */
+class tsdb {
+private:
+	/// init state
+	static bool is_init;
+	/// enable/disable name resolving via DNS
+	static bool resolvenames;
+
+	/// netdb mutex
+	static pthread_mutex_t mutex;
+	// @{
+	/// last used IDs
+	static uint32 id32;
+	static uint64 id64;
+	// @}
+
+	// standard protocol ids
+	static protocol_t udp_id;
+	static protocol_t tcp_id;
+	static protocol_t sctp_id;
+
+public:
+	/// initialize netdb
+	static void init(bool noresolving= false);
+	/// cleanup netdb resources
+	static void end();
+	/// get new 32bit-ID
+	static uint32 get_new_id32();
+	/// get new 64bit-ID
+	static uint64 get_new_id64();
+	/// get protocol name by number
+	static string getprotobynumber(protocol_t proto, bool *res = NULL);
+	/// get protocol number by name
+	static protocol_t getprotobyname(const string &pname, bool *res = NULL);
+	/// get protocol number by name
+	static protocol_t getprotobyname(const char* pname, bool *res = NULL);
+	/// get frequently used protocol numbers
+	static protocol_t get_udp_id()  { return udp_id; }
+	static protocol_t get_tcp_id()  { return tcp_id; } 
+	static protocol_t get_sctp_id() { return sctp_id; } 
+	
+	/// get user name
+	static string get_username(uid_t uid, bool *res = NULL);
+	/// get user ID
+	static uid_t get_userid(const char* uname, bool *res = NULL);
+	/// get user ID
+	static uid_t get_userid(const string& uname, bool *res = NULL);
+	/// get port name
+	static string get_portname(port_t port, protocol_t prot, bool *res = NULL);
+	/// get port number
+	static port_t get_portnumber(const char* pname, protocol_t prot, bool *res = NULL);
+	/// get port number
+	static port_t get_portnumber(const string& pname, protocol_t prot, bool *res = NULL);
+	/// lookup host name
+	static string get_hostname(const struct sockaddr* sa, bool *res);
+	static string get_hostname(const in_addr& in, bool *res = NULL);
+	static string get_hostname(const in6_addr& in, bool *res = NULL);
+
+}; // end class tsdb
+
+//@}
+
+} // end namespace protlib
+
+#endif
Index: /source/ariba/utility/transport/tcpip/protlib/timer.cpp
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/timer.cpp	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/timer.cpp	(revision 5284)
@@ -0,0 +1,550 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file timer.cpp
+/// Software timer interface
+/// ----------------------------------------------------------
+/// $Id: timer.cpp 2549 2007-04-02 22:17:37Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/src/timer.cpp $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+/** @ingroup timer 
+ * You can create a software timer and attach a callback object to it.
+ * Timers are only accessed through their TimerManager and timer ID.
+ * timer managers are thread-safe.
+ *
+ * Timers are stored in an ordered list to ease checking for elapsed timers.
+ * Additionally, their IDs are kept in a hash_map, so a pointer to a
+ * timer object can be obtained very fast.
+ */
+
+//#define DEBUG_TIMER
+
+#include <errno.h>
+
+#include "cleanuphandler.h"
+#include "timer.h"
+#include "logfile.h"
+
+namespace protlib {
+
+/** @addtogroup timer Timer
+ * @{
+ */
+
+  using namespace log;
+
+static inline 
+void 
+normalize_timespec(struct timespec& ts) 
+{
+  while (ts.tv_nsec>=1000000000) {
+    ts.tv_sec++;
+    ts.tv_nsec -= 1000000000;
+  } // end while
+  if (ts.tv_sec<0) ts.tv_sec = 0;
+  if (ts.tv_nsec<0) ts.tv_nsec = 0;
+} // end normalize
+
+/**
+ *  fills in timespec with sec+msec, msec may be larger than 999!
+ */
+static inline 
+void 
+fill_timespec(struct timespec& ts, int32 sec, int32 msec) 
+{
+  if (sec<0) sec = 0;
+  if (msec<0) msec = 0;
+  ts.tv_sec = sec + (msec/1000);
+  ts.tv_nsec = (msec%1000)*1000000;
+  normalize_timespec(ts);
+} // end fill_timespec
+
+static inline 
+void 
+add_timespecs(struct timespec& ts1, struct timespec& ts2, struct timespec& res) {
+  res.tv_sec = ts1.tv_sec + ts2.tv_sec;
+  res.tv_nsec = ts1.tv_nsec + ts2.tv_nsec;
+  normalize_timespec(res);
+} // end add_timespecs
+
+static inline void gettimeofday_timespec(struct timespec& ts) {
+	struct timeval now = {0,0};
+	gettimeofday(&now,NULL);
+	ts.tv_sec = now.tv_sec;
+	ts.tv_nsec = now.tv_usec*1000;
+} // end gettimeofday_timespec
+
+/** Initialize a TimerManager object. */
+TimerManager::TimerManager() 
+{
+  pthread_mutexattr_init(&mutex_attr);
+#ifdef _DEBUG
+  pthread_mutexattr_settype(&mutex_attr,PTHREAD_MUTEX_ERRORCHECK);
+#else
+  pthread_mutexattr_settype(&mutex_attr,PTHREAD_MUTEX_NORMAL);
+#endif
+
+  pthread_mutex_init(&mutex,&mutex_attr);
+  pthread_cond_init(&cond,NULL);
+
+  Log(DEBUG_LOG,LOG_NORMAL, "Timer", "Creating TimerManager");
+} // end constructor TimerManager
+
+/** Destroy TimerManager. */
+TimerManager::~TimerManager() {
+#ifndef _NO_LOGGING
+	int num = cleanup();
+#else
+	cleanup();
+#endif
+	DLog("Timer", "Destroying TimerManager with " << num << " timers");
+	pthread_cond_destroy(&cond);
+	pthread_mutex_destroy(&mutex);
+	pthread_mutexattr_destroy(&mutex_attr);
+} // end destructor TimerManager
+
+/** Start a timer relative to current time.
+ * @return ID of the new timer.
+ */
+timer_id_t 
+TimerManager::start_relative(TimerCallback* tc, int32 sec, int32 msec, timer_callback_param_t tcp) 
+{
+  struct timespec timeofday = {0,0};
+  struct timespec reltime = {0,0};
+  struct timespec alarm = {0,0};
+  timer *t = NULL;
+  timer_id_t result = 0;
+  fill_timespec(reltime,sec,msec);
+  // calculate absolute alarm time
+  gettimeofday_timespec(timeofday);
+  add_timespecs(timeofday,reltime,alarm);	
+  // begin critical section
+  pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
+  // start timer
+  t = new(nothrow) timer(alarm,tc,tcp);
+  if (t) {
+    result = t->id;
+    // insert into list
+    insert_into_list(t);
+    // insert into hash
+    hashmap[result] = t;
+    // wake up threads
+    pthread_cond_signal(&cond);
+  } else {
+    Log(ERROR_LOG,LOG_CRIT, "Timer", "TimerManager::start_relative() is unable to create timer object");
+  } // end if t
+  // end critical section
+  pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
+  return result;
+} // end start_relative
+
+/** Start an absolute timer.
+ * @return ID of the new timer.
+ */
+timer_id_t 
+TimerManager::start_absolute(TimerCallback* tc, int32 sec, int32 msec, timer_callback_param_t tcp) {
+  struct timespec alarm = {0,0};
+  timer *t = NULL;
+  timer_id_t result = 0;
+  fill_timespec(alarm,sec,msec);
+  // begin critical section
+  pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
+  // start timer
+  t = new(nothrow) timer(alarm,tc,tcp);
+  if (t) {
+    result = t->id;
+    // insert into list
+    insert_into_list(t);
+    // insert into hash
+    hashmap[result] = t;
+    // wake up threads
+    pthread_cond_signal(&cond);
+  } else {
+    Log(ERROR_LOG,LOG_CRIT, "Timer", "TimerManager::start_absolute() is unable to create timer object");
+  } // end if t
+  // end critical section
+  pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
+  return result;
+} // end start_absolute
+
+/** Restart a timer and set the alarm relative to the current time.
+ * The timer must exist and go off in the future.
+ * @return true on success, false otherwise.
+ */
+bool 
+TimerManager::restart_relative(timer_id_t id, int32 sec, int32 msec) 
+{
+  struct timespec timeofday = {0,0};
+  struct timespec reltime = {0,0};
+  struct timespec alarm = {0,0};
+  timer *t = NULL;
+  bool result = false;
+  timer_hashmap_it_t hit;
+  fill_timespec(reltime,sec,msec);
+  // calculate absolute alarm time
+  gettimeofday_timespec(timeofday);
+  add_timespecs(timeofday,reltime,alarm);	
+  // begin critical section
+  pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
+  // try to get timer with given ID
+  if ((hit=hashmap.find(id))!=hashmap.end()) t = hit->second; else t = NULL;
+  if (t) {
+    // delete from list, set new alarm and insert
+    delete_from_list(t);
+    t->time = alarm;
+    insert_into_list(t);
+    // wake up threads
+    pthread_cond_signal(&cond);
+    result = true;
+  } else {
+    Log(DEBUG_LOG,LOG_NORMAL, "Timer", "TimerManager::restart_relative() is unable to restart timer " << id);
+  } // end if t
+  pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
+  return result;
+} // end restart_relative
+
+
+/** Restart a timer and set the alarm to an absolute time.
+ * The timer must exist and go off in the future.
+ * @return true on success, false otherwise.
+ */
+bool 
+TimerManager::restart_absolute(timer_id_t id, int32 sec, int32 msec) 
+{
+  struct timespec alarm = {0,0};
+  timer *t = NULL;
+  bool result = false;
+  timer_hashmap_it_t hit;
+  fill_timespec(alarm,sec,msec);
+  // begin critical section
+  pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
+  // try to get timer with given ID
+  if ((hit=hashmap.find(id))!=hashmap.end()) t = hit->second; else t = NULL;
+  if (t) {
+    // delete from list, set new alarm and insert
+    delete_from_list(t);
+    t->time = alarm;
+    insert_into_list(t);
+    // wake up threads
+    pthread_cond_signal(&cond);
+    result = true;
+  } else {
+    Log(DEBUG_LOG,LOG_NORMAL, "Timer", "TimerManager::restart_relative() is unable to restart timer " << id);
+  } // end if t
+  pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
+  return result;
+} // end restart_absolute
+
+/** Stop the given timer. */
+bool TimerManager::stop(timer_id_t id) 
+{
+  timer *t = NULL;
+  bool result = false;
+  timer_hashmap_it_t hit;
+  // begin critical section
+  pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
+  if ((hit=hashmap.find(id))!=hashmap.end()) {
+    t = hit->second;
+    // erase from hashmap
+    hashmap.erase(hit);
+  } else t = NULL;
+  // delete from list if t exists
+  if (t) {
+    delete_from_list(t);
+    // wake up threads
+    pthread_cond_signal(&cond);
+    result = true;
+  } else {
+    Log(DEBUG_LOG,LOG_NORMAL, "Timer", "TimerManager::stop() is unable to stop timer " << id);
+  } // end if t
+  pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
+  return result;
+} // end stop
+
+/** Check if timers have elapsed and call their callbacks.
+ * @return the number of elapsed timers. 
+ */
+uint32 
+TimerManager::check_timers() 
+{
+  timer *elapsed;
+  pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
+  elapsed = collect_elapsed();
+  pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
+	return process_elapsed();
+} // end check_timers
+
+/** Like check_timers() but waits msec milliseconds for a timer to elapse. */
+uint32 
+TimerManager::check_timers_wait(int32 msec) 
+{
+  struct timespec now = {0,0};
+  struct timespec reltime = {0,0};
+  struct timespec abstime = {0,0};
+  timer* elapsed;
+  int wait_res = 0;
+  fill_timespec(reltime,0,msec);
+  gettimeofday_timespec(now);
+  // calculate timespec for pthread_cond_timedwait()
+  add_timespecs(now,reltime,abstime);
+  timer maxwait(abstime,NULL,NULL,false);
+  // begin critical section
+  pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
+  // look for elapsed timers until timeout
+  elapsed = collect_elapsed();
+  while ((!elapsed) && (wait_res!=ETIMEDOUT)) {
+    // neither timeout nor elapsed timers
+    // if there is a timer in the list, wait until it elapses.
+    // otherwise wait abstime.
+    if (first() && ((*first())<=maxwait)) abstime = first()->time;
+    else abstime = maxwait.time;
+    // wait for condition or timeout
+    wait_res = pthread_cond_timedwait(&cond,&mutex,&abstime);
+#ifdef DEBUG_TIMER
+    Log(DEBUG_LOG,LOG_NORMAL, "Timer", "TimerManager::check_timers_wait() - timedwait returned " << wait_res << ":" << strerror(wait_res));
+#endif
+    elapsed = collect_elapsed();
+#ifdef DEBUG_TIMER
+    if (elapsed)
+      Log(DEBUG_LOG,LOG_NORMAL, "Timer", "TimerManager::check_timers_wait() - collect_elapsed() returned " <<  elapsed->id);
+#endif
+  } // end while !elapsed and !wait_res
+  // end critical section
+  pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
+  // now either timeout, cancellation or elapsed timers
+  return process_elapsed();
+} // end check_timers_wait
+
+/** Stop all timers. */
+uint32 
+TimerManager::stop_all() 
+{
+  uint32 result = 0;
+  pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
+  result = cleanup();
+  if (result) {
+    // wake up threads
+    pthread_cond_signal(&cond);
+  } // end if result
+  pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
+  return result;
+} // end stop_all_timers
+
+/** Stop all timers without locking the mutex.
+ * So this can be called safely inside the TimerManager constructor.
+ */
+uint32 
+TimerManager::cleanup() 
+{
+  uint32 num = 0;
+  // clear hashmap
+  hashmap.clear();
+  
+  // delete all timers
+  timer *curr= 0;
+  while (!active_timerlist.empty())
+  {
+    if ( (curr= active_timerlist.front()) != 0 )
+    {
+      delete curr;
+      active_timerlist.pop_front();
+      num++;
+    }
+  } // end while
+  return num;
+} // end cleanup
+
+/** Insert a timer object into the timer list.
+ * Timers are stored in an ordered list, so when checking for elapsed timers
+ * it's enough to check timers beginning at the front end until one is
+ * still running.
+ */
+inline 
+void 
+TimerManager::insert_into_list(timer *t) 
+{
+  timerlist_t::iterator listiter= active_timerlist.begin();
+  while(listiter != active_timerlist.end())
+  {
+    if ( *listiter ) 
+    {
+      // if current element is greater than *t, leave the loop
+      if (!( *(*listiter) <= *t ))
+	break;
+      
+    }
+    listiter++;
+  } // end for
+  active_timerlist.insert(listiter,t);
+
+
+#ifdef DEBUG_TIMER
+	Log(DEBUG_LOG,LOG_NORMAL, "Timer", "TimerManager::insert_into_list() - inserting timer " << t->id << " list now:");
+#endif
+
+#ifdef DEBUG_TIMER
+  for(timerlist_t::iterator listpiter= active_timerlist.begin();
+      listpiter != active_timerlist.end();
+      listpiter++)
+  {
+    Log(DEBUG_LOG,LOG_NORMAL, "Timer", "TimerManager::insert_into_list() - timer list, timer#: " << (*listpiter ? (*listpiter)->id : 0));
+  }
+#endif
+
+} // end insert_into_list
+
+/** Delete a timer from the ordered timer list. 
+ * The timer object is NOT freed because it may be needed for executing its
+ * callback or for restarting.
+ * The timer objects must be linked correctly, no checking is done.
+ */
+void 
+TimerManager::delete_from_list(timer *t) {
+
+  if (!t) return;
+
+#ifdef DEBUG_TIMER
+  Log(DEBUG_LOG,LOG_NORMAL, "Timer", "TimerManager::delete_from_list() - deleting timer " << t->id);
+#endif
+  timerlist_t::iterator listiter= find(active_timerlist.begin(),active_timerlist.end(),t);
+  if ( listiter != active_timerlist.end() )
+      active_timerlist.erase(listiter);
+#ifdef DEBUG_TIMER
+  if (first()) 
+    Log(DEBUG_LOG,LOG_NORMAL, "Timer", "TimerManager::delete_from_list() - first timer now " << (first() ? first()->id : 0) );
+#endif
+} // end delete_from_list
+
+/** Collect all elapsed timers in the elapsed_timerlist and delete them already
+ * from the hashmap. The timers are deleted in process_elapsed().
+ * You must lock the TimerManager mutex before collecting timers.
+ * When timers have elapsed, the condition is signaled.
+ */
+TimerManager::timer* 
+TimerManager::collect_elapsed() 
+{	
+  struct timespec tod;
+  gettimeofday_timespec(tod);
+  timer now(tod,NULL,NULL,false);
+
+  timerlist_t::iterator currentit = active_timerlist.begin();
+  timer* curr= first();
+#ifdef DEBUG_TIMER
+  if (curr)
+    Log(DEBUG_LOG,LOG_NORMAL, "Timer", "TimerManager::collect_elapsed() - first timer is " << curr->id);
+#endif
+
+  // search the last timer in list <= now
+  while (curr && ((*curr)<=now)) 
+  { // current timer is already elapsed
+    hashmap.erase(curr->id);
+#ifdef DEBUG_TIMER
+    Log(DEBUG_LOG,LOG_NORMAL, "Timer", "TimerManager::collect_elapsed() - deleted elapsed timer " << curr->id);
+#endif
+    // remember it in elapsed list
+    elapsed_timerlist.push_back(curr);
+    // delete it from the active timer list
+    currentit= active_timerlist.erase(currentit);
+
+    curr= (currentit != active_timerlist.end()) ? *currentit : 0;
+  } // end while
+  // List is ordered, so all timers before currentit are elapsed.
+
+  timer* elapsed = elapsed_timerlist.empty() ? 0 : elapsed_timerlist.front();
+
+  // wake up threads
+  if (elapsed) pthread_cond_signal(&cond);
+  
+  return elapsed;
+} // end collect_elapsed
+
+/** Process a list of timers by executing the callback routines and deleting
+ * the timer objects. They are NOT deleted from the TimerManager hashmap.
+ * The mutex should not be locked when callbacks are executed, because 
+ * it is unpossible to start a new timer inside a callback routine when
+ * the mutex is still locked.
+ * @see collect_elapsed()
+ */
+uint32 TimerManager::process_elapsed() 
+{
+  uint32 num = 0;
+  timer *tmp = NULL;
+
+  // for every elapsed timer (list should be prepared by collect_elapsed) do_callback()
+  for (timerlist_t::iterator elapsed_it= elapsed_timerlist.begin();
+       elapsed_it != elapsed_timerlist.end();
+       elapsed_it= elapsed_timerlist.erase(elapsed_it))
+  {
+    // invoke callback function on elapsed timer
+    if ( (tmp = *elapsed_it) != 0)
+    {
+      tmp->do_callback();
+      // when callback is finished, delete the stuff
+      delete tmp;
+      num++;
+    }
+    // get next elapsed timer
+  } // end for
+  return num;
+} // end process_elapsed
+
+/** Initialize a timer.
+ * If get_id is set (default) the timer gets a unique ID, otherwise the ID
+ * of the timer is 0.
+ */
+TimerManager::timer::timer(struct timespec& ts, TimerCallback* tc, timer_callback_param_t tcp, bool get_id) :
+  id (0),
+  time(ts),
+  callback(tc),
+  param(tcp)
+{
+  if (get_id) while (id==0) id = next_id++;
+} // end constructor timer
+
+/** This holds the timer ID of the next timer. */
+timer_id_t TimerManager::timer::next_id = 1;
+
+/** Check which timer goes off eralier. 
+ * The timespec structores of the timers are expected to have correct
+ * format.
+ */
+inline 
+bool 
+TimerManager::timer::operator<=(const timer& t) {
+  if (time.tv_sec == t.time.tv_sec) {
+    // Seconds are equal, it depends on nanoseconds.
+    return (time.tv_nsec <= t.time.tv_nsec);
+  } else {
+    // Seconds are not equal, nanoseconds do not matter.
+    return (time.tv_sec < t.time.tv_sec);
+  }
+} // end operator<=
+
+inline 
+void 
+TimerManager::timer::do_callback() {
+  callback->timer_expired(id,param);
+} // end do_callback
+
+//@}
+
+} // end namespace protlib
Index: /source/ariba/utility/transport/tcpip/protlib/timer.h
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/timer.h	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/timer.h	(revision 5284)
@@ -0,0 +1,162 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file timer.h
+/// Basic TimerManager class
+/// ----------------------------------------------------------
+/// $Id: timer.h 2549 2007-04-02 22:17:37Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/timer.h $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+// ----------------------------------------*- mode: C++; -*--
+// timer.h - Software Timer interface
+// ----------------------------------------------------------
+// $Id: timer.h 2549 2007-04-02 22:17:37Z bless $
+// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/timer.h $
+// ==========================================================
+//                      
+// Institute of Telematics, University of Karlsruhe (TH)
+// ==========================================================
+/** @ingroup timer 
+ * @file
+ * Software Timer interface
+ *
+ * You can create a software timer and attach a callback object to it.
+ * Timers are only accessed through their timer manager and thtimer ID.
+ * timer managers are thread-safe.
+ */
+
+#ifndef _PROTLIB__TIMER_H_
+#define _PROTLIB__TIMER_H_
+
+#include <pthread.h>
+#include <sys/time.h>
+#include <list>
+#include <ext/hash_map>
+
+#include "protlib_types.h"
+#include "llhashers.h"
+
+namespace protlib {
+
+/** @addtogroup timer Timer
+ * @{
+ */
+
+/// timer ID
+/** Each timer of a timer manager has a unique timer ID. */
+typedef uint64 timer_id_t;
+
+/// timer callback parameter
+typedef void* timer_callback_param_t;
+
+/// Timer Callback
+/** When a timer goes off, a callback is called. Each class that wants to
+ * receive timer events must inherit from TimerCallback. 
+ */
+class TimerCallback {
+public:
+	virtual ~TimerCallback() { }
+
+	/// callback member function
+   /** @param id timer ID
+    * @param param additional callback parameter.
+	 */
+	virtual void timer_expired(timer_id_t id, timer_callback_param_t param) = 0;
+};
+
+/// Timer Manager
+/** Creates, sets, resets, stops, checks and deletes timers. */
+class TimerManager {
+public:
+	/// constructor
+	TimerManager();
+	/// destructor
+        ~TimerManager();
+	/// start relative timer
+	timer_id_t start_relative(TimerCallback* tc, int32 sec, int32 msec = 0, timer_callback_param_t tcp = NULL);
+	/// start absolute timer
+	timer_id_t start_absolute(TimerCallback* tc, int32 sec, int32 msec = 0, timer_callback_param_t tcp = NULL);
+	/// restart relative timer
+	bool restart_relative(timer_id_t id, int32 sec, int32 msec = 0);
+	/// restart absolute timer
+	bool restart_absolute(timer_id_t id, int32 sec, int32 msec = 0);
+	/// stop timer
+	bool stop(timer_id_t id);
+	/// check for elapsed timers
+	uint32 check_timers();
+	/// check for elapsed timers or wait for next timer event.
+	uint32 check_timers_wait(int32 msec);
+	/// stop all timers
+	uint32 stop_all();
+private:
+	/// timer item
+	struct timer {
+		timer_id_t id;
+		struct timespec time;
+		TimerCallback* callback;
+		timer_callback_param_t param;
+		timer(struct timespec& ts, TimerCallback* tc, timer_callback_param_t tcp, bool get_id = true);
+		// compare two timers
+		bool operator<=(const timer& t);
+		/// execute callback
+		void do_callback();
+		/// timer ID counter
+		static timer_id_t next_id;
+	}; // end struct timer
+	/// timer manager hashmap
+	typedef hash_map<timer_id_t,timer*> timer_hashmap_t;
+	/// hashmap iterator
+	typedef timer_hashmap_t::iterator timer_hashmap_it_t;
+        /// timer list type
+        typedef list<timer*> timerlist_t;
+
+	/// cleanup hashmap and list
+	uint32 cleanup();
+	/// insert into list
+	void insert_into_list(timer* t);
+	/// delete timer from list
+	void delete_from_list(timer *t);
+	/// collect elapsed timers
+	timer* collect_elapsed();
+	/// process elapsed timers
+	uint32 process_elapsed();
+	/// timer manager mutex
+	pthread_mutex_t mutex;
+	/// timer manager mutex attributes
+        pthread_mutexattr_t mutex_attr;
+
+	/// timer manager condition
+	pthread_cond_t cond;	
+        /// sorted timer list (should be replaced by a heap for performance reasons...)
+        timerlist_t active_timerlist;
+        /// elapsed timer list
+        timerlist_t elapsed_timerlist;
+	/// return first element of active timer list 
+        timer* first() { return active_timerlist.empty() ? 0 : active_timerlist.front(); }
+	timer_hashmap_t hashmap;
+};
+
+//@}
+
+} // end namespace protlib
+
+#endif // _PROTLIB__TIMER_H_
Index: /source/ariba/utility/transport/tcpip/protlib/timer_module.cpp
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/timer_module.cpp	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/timer_module.cpp	(revision 5284)
@@ -0,0 +1,589 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file timer_module.cpp
+/// timer module that maintains timers and triggers messages
+/// ----------------------------------------------------------
+/// $Id: timer_module.cpp 2756 2007-08-06 12:51:39Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/src/timer_module.cpp $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+/** @ingroup timermodule
+ * The timer module provides a way for other modules to set timers via a
+ * message and receive a message back on their queue when the timer goes
+ * off.
+ */
+
+#include <sstream>
+
+#include "timer_module.h"
+#include "queuemanager.h"
+#include "logfile.h"
+#include "cleanuphandler.h"
+
+namespace protlib {
+
+/** @addtogroup timermodule Timer Module
+ * @{
+ */
+
+  using namespace log;
+
+/***** class TimerMsg *****/
+
+TimerMsg::TimerMsg(qaddr_t s, bool s_err)
+  : message(type_timer,s),
+    time_sec(0),
+    time_msec(0),
+    action(ac_ignore),
+    param1(NULL),
+    param2(NULL),
+    ok(true),
+    send_error(s_err),
+    relative(true)
+{
+  // Log(DEBUG_LOG,LOG_NORMAL,"TimerMsg","TimerMsg constructor. msgid:" << get_id());
+} // end TimerMsg
+
+/** Destructor, does nothing. */
+TimerMsg::~TimerMsg() {}
+
+
+/** Set result flag and get old value.
+ * You should not set this, this is done by the timer module.
+ */
+bool TimerMsg::set_ok(bool r) {
+	register bool old = ok;
+	ok = r;
+	return old;
+} // end set_ok
+
+/** Prepare message to start an absolute timer. */
+bool TimerMsg::start_absolute(int32 sec, int32 msec, param_t p1, param_t p2) {
+	return start(false,sec,msec,p1,p2);
+} // end start_absolute
+
+/** Prepare message to start a relative timer. */
+bool TimerMsg::start_relative(int32 sec, int32 msec, param_t p1, param_t p2) {
+	return start(true,sec,msec,p1,p2);
+} // end start_relative
+
+bool TimerMsg::start(bool rel, int32 sec, int32 msec, param_t p1, param_t p2) {
+	time_sec = (sec<=0)?0:sec;
+	time_msec = (msec<=0)?0:msec;
+	param1 = p1;
+	param2 = p2;
+	action = ac_start;
+	relative = rel;
+	ok = true;
+	return true;
+} // end start
+
+/** Restart an absolute timer. */
+bool TimerMsg::restart_absolute(id_t id, int32 sec, int32 msec) {
+	return restart(false,id,sec,msec);
+} // end restart_absolute
+
+/** Restart a relative timer. */
+bool TimerMsg::restart_relative(id_t id, int32 sec, int32 msec) {
+	return restart(true,id,sec,msec);
+} // end restart_relative
+
+/** restart timer 
+ * please note that this method actually overwrites the id of the message(!)
+ */
+bool TimerMsg::restart(bool rel, id_t id, int32 sec, int32 msec) {
+	relative = rel;
+	if (id && set_id(id)) {
+		time_sec = (sec<=0)?0:sec;
+		time_msec = (msec<=0)?0:msec;
+		action = ac_restart;
+		ok = true;
+	} else {
+		time_sec = 0;
+		time_msec = 0;
+		action = ac_ignore;
+		ok = false;
+	} // end if id
+	return ok;
+} // end restart
+
+/** Stop a timer. */
+bool TimerMsg::stop(id_t id) {
+	relative = false;
+	time_sec = 0;
+	time_msec = 0;
+	param1 = param2 = NULL;
+	if (id && set_id(id)) {
+		action = ac_stop;
+		ok = true;
+	} else {
+		action = ac_ignore;
+		ok = false;
+	} // end if id
+	return ok;
+} // end stop
+
+/** Stop all running timers. */
+bool TimerMsg::stop_all() {
+	relative = false,
+	time_sec = 0;
+	time_msec = 0;
+	param1 = param2 = NULL;
+	action = ac_stop_all;
+	ok = true;
+	return true;
+} // end stop_all
+
+/** Prepare message for sending it back as a reply message from the
+ * TimerModule when its timer expires.
+ */
+bool TimerMsg::set_elapsed() {
+	send_error = false;
+	action = ac_elapsed;
+	ok = true;
+	return ok;
+} // end set_elapsed
+
+bool TimerMsg::get_send_error() const {
+	return send_error;
+} // end get_send_error
+
+/** Set send_error flag and return old value. */
+bool TimerMsg::set_send_error(bool f) {
+	register bool o = send_error;
+	send_error = f;
+	return o;
+} // end set_send_error
+
+TimerMsg::param_t TimerMsg::get_param1() const { return param1; }
+
+TimerMsg::param_t TimerMsg::get_param2() const { return param2; }
+
+void TimerMsg::get_params(param_t& p1, param_t& p2) const {
+	p1 = param1;
+	p2 = param2;
+} // end get_params
+
+bool TimerMsg::is_absolute() const { return (!relative); }
+
+bool TimerMsg::is_relative() const { return relative; }
+
+/***** struct TimerModuleParam *****/
+
+/** @param sleep_time default sleep time
+ * @param sua send messages until aborted or just until stopped
+ * @param see send error messages as expedited data
+ * @param sre send reply messages as expedited data
+ */
+TimerModuleParam::TimerModuleParam(uint32 sleep_time, bool sua, bool see, bool sre)
+	: ThreadParam(sleep_time, "TimerModule", 2), send_until_abort(sua),
+	source(message::qaddr_timer), 
+	send_error_expedited(see), send_reply_expedited(sre) {
+	// nothing more to do
+} // end constructor TimerModuleParam
+
+/***** class TimerModule *****/
+
+/** Set parameters. */
+TimerModule::TimerModule(const TimerModuleParam& p) 
+	: Thread(p), timerparam(p) {
+	tmap.clear();
+	// register queue
+	QueueManager::instance()->register_queue(get_fqueue(),p.source);
+	DLog(timerparam.name, "Creating TimerModule object");
+} // end constructor TimerModule
+
+/** Stop all running timers. */
+TimerModule::~TimerModule() {
+	stop_all_timers();
+	DLog(timerparam.name, "Destroying TimerModule object");
+	QueueManager::instance()->unregister_queue(timerparam.source);
+
+} // end destructor TimerModule
+
+/** Devide Threads in thos which process the queue and those which process
+ * expired timers.
+ */
+void TimerModule::main_loop(uint32 nr) {
+  Log(INFO_LOG,LOG_NORMAL, timerparam.name, "Starting " << timerparam.name << " thread #" << nr << ", " << ((nr%2) ? "processing input queue" : "processing timer callbacks"));
+
+  if (nr%2) process_queue();
+  else process_elapsed_timers();
+
+  Log(INFO_LOG,LOG_NORMAL, timerparam.name,"Thread #" << nr << " stopped");
+} // end main_loop
+
+/** Wait for incomming mesages and evaluate message action.
+ * Messages are accepted until the module is asked to stop.
+ *
+ * The module mutex inherited from the Thread base class is locked here, so all
+ * called member functions are called inside a critical section if necessary.
+ */
+void TimerModule::process_queue() {
+  uint32 wait = timerparam.sleep_time*1000;
+  message* msg = NULL;
+  TimerMsg* tmsg = NULL;
+  FastQueue* fq = QueueManager::instance()->get_queue(message::qaddr_timer);
+  bool opresult = false;
+  if (!fq) {
+    Log(ERROR_LOG,LOG_ALERT, timerparam.name," cannot find input queue");
+    return;
+  } // end if not fq
+  // wait for messages
+  while (get_state()==STATE_RUN) {
+    msg = fq->dequeue_timedwait(wait);
+    if (msg) {
+      if (msg->get_type()==message::type_timer) {
+	tmsg = dynamic_cast<TimerMsg*>(msg);
+	if (tmsg) {
+	  // begin critical section
+	  lock(); // install_cleanup_thread_lock(TimerModule,this);
+	  if (tmsg->is_ok()) {
+	    // evaluate action
+	    switch (tmsg->get_action()) {
+	      case TimerMsg::ac_ignore:
+		      // do nothing
+		Log(DEBUG_LOG,LOG_UNIMP, timerparam.name,"received message with action set to ignore");
+		opresult = true;
+		break;
+	      case TimerMsg::ac_start:
+		opresult = start_timer(tmsg);
+		break;
+	      case TimerMsg::ac_restart:
+		opresult = restart_timer(tmsg);
+		break;
+	      case TimerMsg::ac_stop:
+		opresult = stop_timer(tmsg);
+		break;
+	      case TimerMsg::ac_stop_all:
+		opresult = stop_all_timers();
+		break;
+	      default:
+		ERRLog(timerparam.name, "Wrong action " << tmsg->get_action() << " in message from " << tmsg->get_qaddr_name() << " to " << message::get_qaddr_name(timerparam.source) );
+		
+		opresult = false;
+	    } // end switch get_action
+	  } else {
+	      Log(DEBUG_LOG,LOG_UNIMP, timerparam.name,"received message in invalid state, mid " << tmsg->get_id() );
+	    opresult = false;
+	  } // if tmsg->is_ok()
+	  // error handling, message disposing
+	  send_error_or_dispose(tmsg,opresult);
+	  // end critical section
+	  unlock(); // uninstall_cleanup(1);
+	} else {
+	  Log(ERROR_LOG,LOG_ALERT, timerparam.name, "Cannot cast message from " << msg->get_qaddr_name() << " of type " << msg->get_type_name() << " to TimerMsg");
+	  delete msg;
+	} // end if tmsg
+      } else {
+	ERRLog(timerparam.name,"received message that is not of type_timer from " << msg->get_qaddr_name() << ", type was " << msg->get_type_name());
+	delete msg;
+      } // end if type
+    } // end if msg
+  } // end while running
+} // end process_queue
+
+/** Check if timers expired and send reply messages.
+ * Reply messages are sent until the module is asked to abort if
+ * the flag send_until_abort is set true. Otherwise no messages are sent
+ * after a stop request.
+ */
+void TimerModule::process_elapsed_timers() {
+	state_t end_state;
+	uint32 num = 0;
+	uint32 sleeptime = timerparam.sleep_time*1000;
+	if (timerparam.send_until_abort) end_state = STATE_ABORT;
+	else end_state = STATE_STOP;
+	while(get_state()!=end_state) {
+		num = tm.check_timers_wait(sleeptime);
+		if (num) {
+		  Log(DEBUG_LOG,LOG_UNIMP, timerparam.name,"got " << num << " elapsed timer(s)");
+		} // end if num
+	} // end while state
+} // end process_elapsed_timers
+
+/** Starts a timer and stores its ID and the reply message in the hash maps. */
+bool TimerModule::start_timer(TimerMsg* m) {
+	timer_id_t tid = 0;
+	bool res = true;
+	message::id_t mid = m->get_id();
+	bool relative = m->is_relative();
+	int32 sec = 0;
+	int32 msec = 0;
+	if (mid) {
+	  // lookup timer ID in map
+	  if ((tid=tmap.lookup_tid(mid))) {
+	    ERRLog(timerparam.name, m->get_qaddr_name() << " tried to start a timer with mid " << mid << ", but there is already a timer " << tid);
+	    res = false;
+	  } else {
+	    // start timer
+	    m->get_time(sec,msec);
+	    if (relative) tid = tm.start_relative(this,sec,msec,NULL);
+	    else tid = tm.start_absolute(this,sec,msec,NULL);
+	    if (tid) {
+	      // insert in map
+	      tmap.insert(tid,m);
+	      // timer successfully started
+	      Log(EVENT_LOG,LOG_UNIMP, timerparam.name, "Timer " << tid << " (" << sec << "s " << msec << "ms) started for " 
+		                                         << m->get_qaddr_name() << " with mid " << mid);
+	      res = true;
+	    } else {
+	      // timer not started
+	      ERRLog(timerparam.name, "TimerManager in " << timerparam.name << " is unable to start a timer for " << m->get_qaddr_name());
+	      res = false;
+	    } // end if tid
+	  } // end if lookup repmsg
+	} else {
+	  ERRLog(timerparam.name, m->get_qaddr_name() << " tried to start a timer with message ID 0");
+	  res = false;
+	} // end if repmsg
+	return res;
+} // end start_timer
+
+/** Restarts a timer and stores its ID and the reply message in the hash maps. */
+bool TimerModule::restart_timer(TimerMsg* m) {
+	timer_id_t tid = 0;
+	bool res = true;
+	message::id_t mid = m->get_id();
+	bool relative = m->is_relative();
+	TimerMsg* repmsg = NULL;
+	int32 sec = 0;
+	int32 msec = 0;
+	if (mid) {
+	  // lookup timer_id and reply message for mid in map
+	  tid = tmap.lookup_tid(mid);
+	  repmsg = tmap.lookup_msg(tid);
+	  if (tid && repmsg) {
+	    // restart timer
+	    m->get_time(sec,msec);
+	    if (relative) res = tm.restart_relative(tid,sec,msec);
+	    else res = tm.restart_absolute(tid,sec,msec);
+	    if (res) {
+	      // modify reply message
+	      repmsg->restart(relative,mid,sec,msec);
+	      // timer successfully restarted
+	      DLog(timerparam.name, "Timer " << tid << ", mid " << mid << " restarted for " << m->get_qaddr_name());
+	    } else {
+	      // timer not restarted
+	      ERRLog(timerparam.name, "TimerManager in " << timerparam.name << " is unable to restart a timer for " << m->get_qaddr_name() << ", mid " << mid);
+	    } // end if res
+	  } else {
+	    if (tid) ERRLog(timerparam.name, m->get_qaddr_name() << " tried to restart a timer with mid " << mid << ": or no reply message for timer found");
+	    if (repmsg)  ERRLog(timerparam.name, m->get_qaddr_name() << " tried to restart timer with mid " << mid << ": timer not found");
+	    if ((!repmsg) & (!tid)) ERRLog(timerparam.name, m->get_qaddr_name() << " tried to restart timer with mid " << mid << ": neither timer nor reply message found");
+	    res = false;
+	  } // end if tid
+	} else {
+	  ERRLog(timerparam.name, m->get_qaddr_name() << " tried to restart a timer with an invalid message ID");
+	  res = false;
+	} // end if repmsg
+	return res;
+} // end restart_timer
+
+/** Stop a timer and remove its ID and reply message from the hash maps. */
+bool TimerModule::stop_timer(TimerMsg* m) {
+	timer_id_t tid = 0;
+	bool res = true;
+	message::id_t mid = m->get_id();
+	if (mid) {
+		// lookup timer_id for mid in map
+		tid = tmap.lookup_tid(mid);
+		if (tid) {
+			// stop timer
+			res = tm.stop(tid);
+			if (res) {
+				// delete from map
+				tmap.erase(tid,mid,true);
+				// timer stopped
+				DLog(timerparam.name, "Stopped timer " << tid << ", mid " << mid << " for " << m->get_qaddr_name());
+			} else {
+				// timer not stopped
+			  ERRLog(timerparam.name, "TimerManager in " << timerparam.name << " is unable to stop timer " << tid << ", mid " << mid << " for " << m->get_qaddr_name());
+			} // end if tid
+		} else {
+		  ERRLog(timerparam.name, m->get_qaddr_name() << " tried to stop a non-existing timer with mid " << mid);
+		  res = false;
+		} // end if tid
+	} else {
+	  ERRLog(timerparam.name, m->get_qaddr_name() << " tried to stop a timer with an invalid message ID");
+	  res = false;
+	} // end if repmsg
+	return res;
+} // end stop_timer
+
+/** Stop all timers and clear the hash maps. */
+bool TimerModule::stop_all_timers() {
+	uint32 num = 0;
+	// clear map
+	tmap.clear(true);
+	// clear TimerManager
+	num = tm.stop_all();
+	Log(DEBUG_LOG,LOG_UNIMP, timerparam.name,"stopped all timers, num " << num);
+	return true;
+} // end stop_all_timers
+
+/** Send back error message.
+ * If no error is necessary, the message is disposed.
+ * @param m message that is changed to an error message if 
+ *		its flags are set appropriately.
+ * @param ok success or error?
+ */
+void TimerModule::send_error_or_dispose(TimerMsg* m, bool ok) {
+	message::qaddr_t dest;
+	if (!m) return;
+
+#ifndef _NO_LOGGING
+	message::id_t mid = m->get_id();	// only used for logging
+#endif
+
+	// Do we send errors?
+	if ((!ok) && m->get_send_error()) ok = false;
+	else ok = true;
+	if (ok) {
+		// dispose if not a start message
+		if (m->get_action()!=TimerMsg::ac_start) {
+			dest = m->get_source();
+			delete m;
+			//Log(DEBUG_LOG,LOG_UNIMP, timerparam.name,"disposed message " << mid << " from " << message::get_qaddr_name(dest));
+		} // end if dispose message
+	} else {
+		// send error
+		dest = m->get_source();
+		m->set_ok(false);
+		if (m->send(timerparam.source,dest,timerparam.send_error_expedited)) {
+		  Log(DEBUG_LOG,LOG_UNIMP, timerparam.name,"sent error message w/ mid " << mid << " to " << message::get_qaddr_name(dest));
+		} else {
+		  ERRLog(timerparam.name,"cannot send error message w/ mid " << mid << " to " << message::get_qaddr_name(dest) << ", disposing it now");
+		  delete m;
+		} // end if sent error
+	} // end if ok
+} // end send_error_or_dispose
+
+/** This is the callback for the TimerManager used by the TimerModule object.
+ * @param timer timer ID
+ * @param callback_param additional callback parameter.
+ *
+ * The module mutex inherited from the Thread base class is locked here, so all
+ * called member functions are called inside a critical section if necessary.
+ */
+void TimerModule::timer_expired(timer_id_t timer, timer_callback_param_t callback_param) {
+	TimerMsg* msg = NULL;
+	message::qaddr_t dest;
+	message::id_t mid = 0;
+	// begin critical section
+	lock(); // install_cleanup_thread_lock(TimerModule,this);
+	// get reply message
+	msg = tmap.lookup_msg(timer);
+	if (msg) {
+		// store message ID for erasing this record from the map
+		mid = msg->get_id();
+		// send message
+		dest = msg->get_source();
+		if (msg->set_elapsed() && msg->send_back(timerparam.source,timerparam.send_reply_expedited)) {
+		  Log(DEBUG_LOG,LOG_UNIMP, timerparam.name,"sent reply mid " << mid << " for elapsed timer " << timer << " to " << message::get_qaddr_name(dest));
+		} else {
+		  ERRLog(timerparam.name,"cannot send reply mid " << mid << " for elapsed timer " << timer <<" to " << message::get_qaddr_name(dest));
+		  // dispose message
+		  delete msg;
+		} // end if send_back
+	} else {
+		// may be timer has been stopped
+	  DLog(timerparam.name, "TimerModule::timer_expired cannot find reply message for a timer " << timer << ". Maybe the timer has been stopped");
+	} // end if msg
+	// erase (timer,mid) without disposing the reply message
+	tmap.erase(timer,mid,false);
+	// end critical section
+	unlock(); // uninstall_cleanup(1);
+} // end timer_expired
+
+/***** class TimerModule::TimerMap *****/
+
+bool TimerModule::TimerMap::insert(timer_id_t tid, TimerMsg* m) {
+	if (tid && m) {
+		message::id_t mid = m->get_id();
+		tid2mid[tid] = mid;
+		mid2tid[mid] = tid;
+		tid2msg[tid] = m;
+		return true;
+	} else return false;
+} // end insert
+
+/** Returns the message ID of the timer bound to timer ID or 0 if not
+ * found, since every timer must have an ID <> 0.
+ */
+message::id_t TimerModule::TimerMap::lookup_mid(timer_id_t tid) const {
+	const_tid2mid_it_t hit;
+	hit = tid2mid.find(tid);
+	if (hit!=tid2mid.end()) return hit->second;
+	else return 0;
+} // end lookup
+
+/** Returns the timer-ID of the timer bound to the message ID or 0 if not
+ * found, since 0 is never used as a timer ID.
+ */
+timer_id_t TimerModule::TimerMap::lookup_tid(message::id_t mid) const {
+	const_mid2tid_it_t hit;
+	if ((hit=mid2tid.find(mid))!=mid2tid.end()) return hit->second;
+	else return 0;
+} // end lookup
+
+/** Returns the timer message of the timer bound to timer ID or NULL if not
+ * found.
+ */
+TimerMsg* TimerModule::TimerMap::lookup_msg(timer_id_t tid) const {
+	const_tid2msg_it_t hit;
+	hit = tid2msg.find(tid);
+	if (hit!=tid2msg.end()) return hit->second;
+	else return NULL;
+} // end lookup_msg
+
+/** Please be sure that timer ID and message ID are bound to the same timer. 
+ * No checking is done!
+ */
+void TimerModule::TimerMap::erase(timer_id_t tid, message::id_t mid, bool dispose) {
+	TimerMsg* m = NULL;
+	if (tid) {
+		if (dispose) {
+			m = lookup_msg(tid);
+			if (m) delete m;
+		} // end if dispose
+		tid2mid.erase(tid);
+		tid2msg.erase(tid);
+	} // end if tid
+	if (mid) mid2tid.erase(mid);
+} // end erase
+
+void TimerModule::TimerMap::clear(bool dispose) {
+	const_tid2msg_it_t hit;
+	if (dispose) {
+		for (hit=tid2msg.begin();hit!=tid2msg.end();hit++) {
+			if (hit->second) delete hit->second;
+		} // end for hit
+	} // end if dispose
+	tid2mid.clear();
+	tid2msg.clear();
+	mid2tid.clear();
+} // end clear
+
+//@}
+
+} // end namespace protlib
Index: /source/ariba/utility/transport/tcpip/protlib/timer_module.h
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/timer_module.h	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/timer_module.h	(revision 5284)
@@ -0,0 +1,266 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file timer_module.h
+/// Timer module (thread) that provides timer management functions
+/// ----------------------------------------------------------
+/// $Id: timer_module.h 2549 2007-04-02 22:17:37Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/timer_module.h $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+
+/** @ingroup timermodule
+ * The timer module provides a way for other modules to set timers via a
+ * message and receive a message back on their queue when the timer goes
+ * off.
+ */
+
+#ifndef _PROTLIB__TIMER_MODULE_H
+#define _PROTLIB__TIMER_MODULE_H
+
+#include <ext/hash_map>
+
+#include "messages.h"
+#include "threads.h"
+#include "llhashers.h"
+#include "timer.h"
+
+namespace protlib {
+
+/** @addtogroup timermodule Timer Module
+ * @{
+ */
+
+  static const char *const action_t_str[]=
+    {
+      "ignore",
+      "start",
+      "restart",
+      "stop",
+      "stop all",
+      "elapsed",
+      "unkown"
+    };
+
+/// timer message
+/** This message class is used to control timers managed by the timer
+ * module and for replies when a timer goes off.
+ * Timers are identified by the message ID.
+ */
+class TimerMsg : public message 
+{
+public:
+  /// timer module actions
+  /** Tell the timer module what to do or indicate that a timer elapsed. */
+  enum action_t 
+    {
+      ac_ignore   = 0,
+      ac_start    = 1,
+      ac_restart  = 2,
+      ac_stop     = 3,
+      ac_stop_all = 4,
+      ac_elapsed  = 5
+    }; // end action_t
+
+  /// timer parameter
+  /** This parameter corresponds to the timer parameters in timer.h and
+   * helps managing timers.
+   */
+  typedef timer_callback_param_t param_t;
+  /// constructor
+  TimerMsg(qaddr_t s = qaddr_unknown, bool s_err = false);
+  /// destructor
+  virtual ~TimerMsg();
+  /// get alarm
+  void get_time(int32& sec, int32& msec);
+  /// get action
+  action_t get_action() const;
+  /// get action str
+  const char* get_action_str() const;
+  /// set result
+  bool set_ok(bool r);
+  /// get result
+  bool is_ok();
+  /// start absolute timer
+  bool start_absolute(int32 sec, int32 msec = 0, param_t p1 = NULL, param_t p2 = NULL);
+  /// start relative timer
+  bool start_relative(int32 sec, int32 msec = 0, param_t p1 = NULL, param_t p2 = NULL);
+  /// start timer
+  bool start(bool rel, int32 sec, int32 msec = 0, param_t p1 = NULL, param_t p2 = NULL);
+  /// restart absolute timer
+  bool restart_absolute(id_t id, int32 sec, int32 msec = 0);
+  /// restart relative timer
+  bool restart_relative(id_t id, int32 sec, int32 msec = 0);
+  /// restart timer
+  bool restart(bool rel, id_t id, int32 sec, int32 msec = 0);
+  /// stop timer
+  bool stop(id_t id);
+  /// stop all timers
+  bool stop_all();
+  /// set to elapsed
+  bool set_elapsed();
+  /// get send_error flag
+  bool get_send_error() const;
+  /// set send_error flag
+  bool set_send_error(bool f);
+  /// get timer parameter #1
+  param_t get_param1() const;
+  /// get timer parameter #2
+  param_t get_param2() const;
+  /// get timer parameters
+  void get_params(param_t& p1, param_t& p2) const;
+  /// Is it an absolute or relative timer?
+  bool is_absolute() const;
+  /// Is it an absolute or relative timer?
+  bool is_relative() const;
+ private:
+  int32 time_sec;
+  int32 time_msec;
+  action_t action;
+  param_t param1;
+  param_t param2;
+  bool ok;
+  bool send_error;
+  bool relative;
+}; // end class TimerMsg
+ 
+/** Get alarm time. Please check message action to see if this is an
+ * absolute or relative time.
+ * If this is a expiration notification, the time is absolute.
+ */
+inline
+void 
+TimerMsg::get_time(int32& sec, int32& msec) 
+{
+  sec = time_sec;
+  msec = time_msec;
+} // end get_alarm
+
+/** Get timer message action. There is no way to set the action value, this
+ * is done by start_relative or start_absolute... 
+ */
+inline
+TimerMsg::action_t 
+TimerMsg::get_action() const 
+{
+	return action;
+} // end get_action
+
+inline
+const char*
+TimerMsg::get_action_str() const 
+{
+	return action_t_str[action];
+} // end get_action_str
+
+/** Get result flag. */
+bool 
+inline
+TimerMsg::is_ok() 
+{
+  return ok;
+} // end is_ok
+
+
+/// timer module parameters
+/** This holds the message queue and the default sleep time. */
+struct TimerModuleParam : public ThreadParam 
+{
+  TimerModuleParam(uint32 sleep_time = ThreadParam::default_sleep_time,
+		   bool sua = false, bool ser = true, bool sre = true);
+  /// send messages until abort
+  const bool send_until_abort;
+  const message::qaddr_t source;
+  const bool send_error_expedited;
+  const bool send_reply_expedited;
+}; // end TimerModuleParam
+
+/// timer module class
+/** This is the timer module. */
+class TimerModule : public Thread, public TimerCallback 
+{
+  /***** TimerCallback *****/
+ public:
+  /// callback member function
+  /** @param timer timer ID
+   * @param callback_param additional callback parameter.
+   */
+  virtual void timer_expired(timer_id_t timer, timer_callback_param_t callback_param);
+ public:
+  /// constructor
+  TimerModule(const TimerModuleParam& p);
+  /// destructor
+  virtual ~TimerModule();
+  /// timer module main loop
+  virtual void main_loop(uint32 nr);
+ private:
+  /// wait for incoming messages
+  void process_queue();
+  /// check timers and send messages
+  void process_elapsed_timers();
+  /// start a timer
+  bool start_timer(TimerMsg* m);
+  /// restart a timer
+  bool restart_timer(TimerMsg* m);
+  /// stop a timer
+  bool stop_timer(TimerMsg* m);
+  /// stop all timers
+  bool stop_all_timers();
+  /// send back error
+  void send_error_or_dispose(TimerMsg* m, bool ok);
+  /// timer module parameters
+  TimerManager tm;
+  /// module parameters
+  const TimerModuleParam timerparam;
+  /// timer map
+  /** This stores timer IDs and the corresponding message IDs. */
+  class TimerMap 
+  {
+  public:
+    bool insert(timer_id_t tid, TimerMsg* m);
+    /// lookup message ID
+    message::id_t lookup_mid(timer_id_t tid) const;
+    /// lookup timer ID
+    timer_id_t lookup_tid(message::id_t mid) const;
+    /// lookup message
+    TimerMsg* lookup_msg(timer_id_t tid) const;
+    /// erase record of timer ID and message ID
+    void erase(timer_id_t tid, message::id_t mid, bool dispose = true);
+    /// clear all
+    void clear(bool dispose = true);
+  private:
+    typedef hash_map<message::id_t,timer_id_t> mid2tid_t;
+    typedef mid2tid_t::const_iterator const_mid2tid_it_t;
+    typedef hash_map<timer_id_t,message::id_t> tid2mid_t;
+    typedef tid2mid_t::const_iterator const_tid2mid_it_t;
+    typedef hash_map<timer_id_t,TimerMsg*> tid2msg_t;
+    typedef tid2msg_t::const_iterator const_tid2msg_it_t;
+    mid2tid_t mid2tid;
+    tid2mid_t tid2mid;
+    tid2msg_t tid2msg;
+  } tmap; // end class TimerMap
+}; // end class TimerModule
+
+//@}
+
+} // end namespace protlib
+
+#endif
Index: /source/ariba/utility/transport/tcpip/protlib/tp.cpp
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/tp.cpp	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/tp.cpp	(revision 5284)
@@ -0,0 +1,104 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file tp.cpp
+/// generic interface for sending/receiving network messages via a transport protocol 
+/// ----------------------------------------------------------
+/// $Id: tp.cpp 2872 2008-02-18 10:58:03Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/src/tp.cpp $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+
+/** @ingroup transport
+ * This is the interface for sending network messages over a transport 
+ * protocol. You can receive messages through queues.
+ */
+
+#include "tp.h"
+#include "threadsafe_db.h"
+#include "logfile.h"
+
+namespace protlib {
+
+/** @addtogroup transport Transport Protocol
+ * @ingroup network
+ * @{
+ */
+
+  using namespace log;
+
+
+/***** class TP *****/
+
+/** Set ID of the underlying transport protocol, e.g. TCP, SCTP or UDP.
+ * Init is set false here, set to true in constructors of derived classes if
+ * initialization is done.
+ * If the maximum payload is greater than the maximum size of a network
+ * message, it is decreased.
+ */
+TP::TP(protocol_t p, const string& pname, const string& tpn, 
+       const unsigned short common_header_length, 
+       bool (*const getmsglength)(NetMsg& netmsg, uint32& msglen),
+       uint32 mp) 
+	: protocol(p), protoname(pname), tp_name(tpn), 
+	  common_header_length(common_header_length), 
+	  getmsglength(getmsglength),
+	  init(false), 
+	  max_payload((mp<NetMsg::max_size)?mp:(NetMsg::max_size))
+          {}
+
+/** TP destructor does nothing. */
+TP::~TP() { init = false; }
+
+/** Get the ID of the underlying transport protocol. */
+protocol_t TP::get_underlying_protocol() const { return protocol; }
+
+/** Get the name of the underlying transport protocol. */
+string TP::get_underlying_protocol_name() const { return protoname; }
+
+/** Get the name of this TP implementation. */
+string TP::get_tp_name() const { return tp_name; }
+
+uint32 TP::get_max_payload() const { return max_payload; }
+
+/* @param msg NetMsg to send
+ * @param addr destination address
+ * @return true if args are OK.
+ */
+
+void TP::check_send_args(const NetMsg& msg, const address& addr)
+		const {
+  if (!init) {
+    Log(ERROR_LOG,LOG_NORMAL, "TP", "TP::check_send_args: " << tp_name << " not initialized");
+    throw TPErrorArgsNotInit();
+  } // end if not init
+  
+  if ((msg.get_size()==0) || (msg.get_size()>max_payload)) {
+    Log(ERROR_LOG,LOG_NORMAL, "TP", "TP::check_send_args: NetMsg empty or too big. Size: " << msg.get_size() << ", " << tp_name << ", max_payload " << max_payload);
+    throw TPErrorPayload();
+  } // end if too big
+
+} // end check_send_args 
+
+
+//@}
+
+} // end namespace protlib
Index: /source/ariba/utility/transport/tcpip/protlib/tp.h
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/tp.h	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/tp.h	(revision 5284)
@@ -0,0 +1,257 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file tp.h
+/// generic interface for sending/receiving network messages via a transport protocol 
+/// ----------------------------------------------------------
+/// $Id: tp.h 2872 2008-02-18 10:58:03Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/tp.h $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+// ----------------------------------------*- mode: C++; -*--
+// tp.h - generic transport protocol interface module TP
+// ----------------------------------------------------------
+// $Id: tp.h 2872 2008-02-18 10:58:03Z bless $
+// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/tp.h $
+// ==========================================================
+//                      
+// (C)opyright, all rights reserved by
+// - Institute of Telematics, University of Karlsruhe (TH)
+// ==========================================================
+/** @ingroup transport
+ * This is the interface for sending network messages over a transport 
+ * protocol. You can receive messages through queues.
+ */
+
+#ifndef _PROTLIB__TP_H_
+#define _PROTLIB__TP_H_
+
+#include <string.h>
+
+#include "protlib_types.h"
+#include "messages.h"
+#include "network_message.h"
+#include "address.h"
+#include "tperror.h"
+
+namespace protlib {
+
+/** @ingroup transport Transport Protocol
+ * @ingroup network
+ * @{
+ */
+
+
+/// transport protocol base class
+/** This is the interface to all transport protocols.
+ * It is used by the signaling module to send network messages. 
+   // what kinds of messages?
+ * Received messages are delivered through FastQueues.
+ */
+class TP {
+public:
+	/// constructor
+	TP(protocol_t p, const string& pname, const string& tpn, 
+	   const unsigned short common_header_length, 
+	   bool (*const getmsglength)(NetMsg& netmsg, uint32& msglen),
+	   uint32 mp = (uint32)-1);
+
+	/// virtual destructor
+	virtual ~TP() = 0;
+
+	/// send a message, message is deleted after it has been sent
+        /// use_existing_connection indicates whether a new connection will be established
+        /// if required (true means that no connection will be set up if none exists yet)
+	virtual void send(NetMsg* msg, const address& addr, bool use_existing_connection= false) = 0;
+
+	/// terminates an existing signaling association/connection
+	virtual void terminate(const address& addr) = 0;
+
+	/// check send arguments
+	void check_send_args(const NetMsg& msg,
+		const address& addr) const;
+
+	/// get protocol ID
+	protocol_t get_underlying_protocol() const;
+
+	/// get protocol name
+	string get_underlying_protocol_name() const;
+
+	/// get TP name
+	string get_tp_name() const;
+
+	/// is it initialized?
+	bool is_init() const;
+
+	/// get maximum payload
+	uint32 get_max_payload() const;
+protected:
+
+	/// transport protocol ID
+	const protocol_t protocol;
+
+	/// transport protocol name
+	const string protoname;
+
+	/// TP subclass name
+	const string tp_name;
+
+        /// what is the length of the common header
+        const unsigned short common_header_length;
+
+        /// function pointer to a function that figures out the msg length in number of 4 byte words
+        /// it returns false if error occured (e.g., malformed header), result is returned in variable clen_words
+        bool (*const getmsglength) (NetMsg& m, uint32& clen_words);
+
+	/// init state
+	bool init;
+	const uint32 max_payload;
+}; // end class TP
+
+/// transport protcol message
+/** This message class is used to carry received network messages. */
+class TPMsg : public message {
+/***** inherited from message *****/
+public:
+	virtual void clear_pointers();
+/***** new *****/
+public:
+    /// constructor
+    TPMsg(NetMsg* m = NULL, address* peer = NULL, address* ownaddr = NULL, TPError* e = NULL, uint16 oif = 0);
+    /// destructor
+    virtual ~TPMsg();
+    /// get peer address
+    const address* get_peeraddress() const;
+    /// set own address
+    const address* get_ownaddress() const;
+    /// set peer address
+    address* set_peeraddress(address* a);
+    /// set own address
+    address* set_ownaddress(address* a);
+    /// get network message
+    NetMsg* get_message() const;
+    /// set network message
+    NetMsg* set_message(NetMsg* m);
+    /// get TP error
+    TPError* get_error() const;
+    /// set TP error
+    TPError* set_error(TPError* e);
+    /// set Outgoing Interface
+    void set_oif(uint16 iface) { oif=iface; }
+    /// get Outgoing Interface
+    uint16 get_oif() { return oif; }
+
+private:
+    /// peer address
+    address* peeraddr;
+    /// own address
+    address* ownaddr;
+    /// network message
+    NetMsg* msg;
+    TPError* err;
+    /// outgoing interface index
+    uint16 oif;
+}; // end class TPMsg
+
+inline
+bool TP::is_init() const { return init; }
+
+/***** class TPMsg *****/
+
+/***** inherited from message *****/
+
+/** Clear all pointer fields. */
+inline
+void TPMsg::clear_pointers() {
+	peeraddr = NULL;
+	ownaddr = NULL;
+	msg = NULL;
+	err = NULL;
+} // end clear
+
+/***** new in NetMsg *****/
+
+/** Initialize and set message type and source to 'transport'. */
+inline
+TPMsg::TPMsg(NetMsg* m, address* p, address* o, TPError* e, uint16 oif) 
+  : message(type_transport,qaddr_transport),
+    peeraddr(p),
+    ownaddr(o),
+    msg(m),
+    err(e),
+    oif(oif)
+{} // end constructor TPMsg
+
+/** Dispose NetMsg, address, err and then delete TPMsg. */
+inline
+TPMsg::~TPMsg() {
+	if (msg) delete msg;
+	if (peeraddr) delete peeraddr;
+	if (ownaddr) delete ownaddr;
+	if (err) delete err;
+} // end destructor TPMsg
+
+inline
+const address* TPMsg::get_peeraddress() const { return peeraddr; }
+
+inline
+const address* TPMsg::get_ownaddress() const { return ownaddr; }
+
+inline
+address* TPMsg::set_peeraddress(address* peer) {
+  register address* oa = peeraddr;
+  peeraddr = peer;
+  return oa;
+} // end set_address
+
+inline
+address* TPMsg::set_ownaddress(address* o) {
+  register address* oa = ownaddr;
+  ownaddr = o;
+  return oa;
+} // end set_address
+
+inline
+NetMsg* TPMsg::get_message() const { return msg; }
+
+inline
+NetMsg* TPMsg::set_message(NetMsg* m) {
+	register NetMsg* omsg = msg;
+	msg = m;
+	return omsg;
+} // end set_message
+
+inline
+TPError* TPMsg::get_error() const { return err; }
+
+inline
+TPError* TPMsg::set_error(TPError* e) {
+	register TPError* oe = err;
+	err = e;
+	return oe;
+} // end set_error
+
+
+//@}
+
+} // end namespace protlib
+
+#endif
Index: /source/ariba/utility/transport/tcpip/protlib/tp_over_tcp.cpp
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/tp_over_tcp.cpp	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/tp_over_tcp.cpp	(revision 5284)
@@ -0,0 +1,1754 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file tp_over_tcp.cpp
+/// TCP-based transport module (includes framing support)
+/// ----------------------------------------------------------
+/// $Id: tp_over_tcp.cpp 2872 2008-02-18 10:58:03Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/src/tp_over_tcp.cpp $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+ 
+extern "C"
+{
+  //#define _SOCKADDR_LEN    /* use BSD 4.4 sockets */
+#include <unistd.h>      /* gethostname */
+#include <sys/types.h>   /* network socket interface */
+#include <netinet/in.h>  /* network socket interface */
+#include <netinet/tcp.h> /* for TCP Socket Option */
+#include <sys/socket.h>
+#include <arpa/inet.h>   /* inet_addr */
+
+#include <fcntl.h>
+#include <sys/poll.h>
+}
+
+#include <iostream>
+#include <errno.h>
+#include <string>
+#include <sstream>
+
+#include "tp_over_tcp.h"
+#include "threadsafe_db.h"
+#include "cleanuphandler.h"
+#include "setuid.h"
+#include "queuemanager.h"
+#include "logfile.h"
+
+#include <set>
+
+#define TCP_SUCCESS 0
+#define TCP_SEND_FAILURE 1
+
+const unsigned int max_listen_queue_size= 10;
+
+namespace protlib {
+
+using namespace log;
+
+/** @defgroup tptcp TP over TCP
+ * @ingroup network
+ * @{
+ */
+
+char in6_addrstr[INET6_ADDRSTRLEN+1];
+
+
+/******* class TPoverTCP *******/
+
+
+/** get_connection_to() checks for already existing connections. 
+ *  If a connection exists, it returns "AssocData" 
+ *  and saves it in "connmap" for further use
+ *  If no connection exists, a new connection to "addr"
+ *  is created.
+ */
+AssocData* 
+TPoverTCP::get_connection_to(const appladdress& addr)
+{
+  // get timeout
+  struct timespec ts;
+  get_time_of_day(ts);
+  ts.tv_nsec+= tpparam.sleep_time * 1000000L;
+  if (ts.tv_nsec>=1000000000L)
+  {
+    ts.tv_sec += ts.tv_nsec / 1000000000L;
+    ts.tv_nsec= ts.tv_nsec % 1000000000L;
+  }
+
+  // create a new AssocData pointer, initialize it to NULL
+  AssocData* assoc= NULL;
+  int new_socket;
+  // loop until timeout is exceeded: TODO: check applicability of loop
+  do 
+  {
+    // check for existing connections to addr
+    // start critical section
+    lock(); // install_cleanup_thread_lock(TPoverTCP, this);
+    assoc= connmap.lookup(addr);
+    // end critical section
+    unlock(); // uninstall_cleanup(1);
+    if (assoc) 
+    {
+      // If not shut down then use it, else abort, wait and check again.
+      if (!assoc->shutdown) 
+      {
+	return assoc;
+      }
+      else
+      {
+	// TODO: connection is already in shutdown mode. What now?
+	ERRCLog(tpparam.name,"socket exists, but is already in mode shutdown");
+
+	return 0;
+      }  
+    } //end __if (assoc)__
+    else 
+    {
+      Log(DEBUG_LOG,LOG_UNIMP,tpparam.name,"No existing connection to " 
+	  << addr.get_ip_str() << " port #" << addr.get_port() << " found, creating a new one.");
+    }
+
+    // no connection found, create a new one
+    new_socket = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
+    if (new_socket == -1)
+    {
+      ERRCLog(tpparam.name,"Couldn't create a new socket: " << strerror(errno));
+
+      return 0;
+    }
+
+    // Disable Nagle Algorithm, set (TCP_NODELAY)
+    int nodelayflag= 1;
+    int status= setsockopt(new_socket,
+			   IPPROTO_TCP,
+			   TCP_NODELAY,
+			   &nodelayflag,
+			   sizeof(nodelayflag));
+    if (status)
+    {
+        ERRLog(tpparam.name, "Could not set socket option TCP_NODELAY:" << strerror(errno));
+    }
+    
+    // Reuse ports, even if they are busy
+    int socketreuseflag= 1;
+    status= setsockopt(new_socket,
+			   SOL_SOCKET,
+			   SO_REUSEADDR,
+			   (const char *) &socketreuseflag,
+			   sizeof(socketreuseflag));
+    if (status)
+    {
+        ERRLog(tpparam.name, "Could not set socket option SO_REUSEADDR:" << strerror(errno));
+    }
+
+    struct sockaddr_in6 dest_address;
+    dest_address.sin6_flowinfo= 0;
+    dest_address.sin6_scope_id= 0;
+    addr.get_sockaddr(dest_address);
+      
+    // connect the socket to the destination address
+    int connect_status = connect(new_socket,
+				 reinterpret_cast<const struct sockaddr*>(&dest_address),
+				 sizeof(dest_address));
+
+    // connects to the listening_port of the peer's masterthread    
+    if (connect_status != 0)
+    {
+      ERRLog(tpparam.name,"Connect to " << addr.get_ip_str() << " port #" << addr.get_port() 
+	  << " failed: [" << color[red] << strerror(errno) << color[off] << "]");
+      
+      return 0; // error: couldn't connect
+    }
+
+    
+    struct sockaddr_in6 own_address;
+    socklen_t own_address_len= sizeof(own_address);
+    getsockname(new_socket, reinterpret_cast<struct sockaddr*>(&own_address), &own_address_len);
+
+    
+
+    Log(DEBUG_LOG,LOG_UNIMP, tpparam.name,">>--Connect-->> to " << addr.get_ip_str() << " port #" << addr.get_port() 
+	<< " from " << inet_ntop(AF_INET6,&own_address.sin6_addr,in6_addrstr,INET6_ADDRSTRLEN) 
+	<< " port #" << ntohs(own_address.sin6_port));
+    
+   
+
+   
+    // create new AssocData record (will copy addr)
+    assoc = new(nothrow) AssocData(new_socket, addr, appladdress(own_address,IPPROTO_TCP));
+
+    // if assoc could be successfully created, insert it into ConnectionMap
+    if (assoc) 
+    {
+      bool insert_success= false;
+      // start critical section
+      lock(); // install_cleanup_thread_lock(TPoverTCP, this);
+      // insert AssocData into connection map
+      insert_success= connmap.insert(assoc);
+      // end critical section
+      unlock(); // uninstall_cleanup(1);
+
+      if (insert_success == true) 
+      {
+#ifdef _DEBUG
+	Log(DEBUG_LOG,LOG_UNIMP, tpparam.name, "Connected to " << addr.get_ip_str() << ", port #" << addr.get_port()
+	    << " via socket " << new_socket);
+
+		
+#endif
+
+	// notify master thread to start a receiver thread (i.e. send selfmessage)
+	TPoverTCPMsg* newmsg= new(nothrow)TPoverTCPMsg(assoc, tpparam.source, TPoverTCPMsg::start);
+	if (newmsg)
+	{
+	  newmsg->send_to(tpparam.source);
+	  return assoc;
+	}
+	else
+	  ERRCLog(tpparam.name,"get_connection_to: could not get memory for internal msg");
+      } 
+      else 
+      {
+	// delete data and abort
+	ERRCLog(tpparam.name, "Cannot insert AssocData for socket " << new_socket << ", "<< addr.get_ip_str()
+	    <<", port #" << addr.get_port() << " into connection map, aborting connection");
+		
+	// abort connection, delete its AssocData
+	close (new_socket);
+	if (assoc) 
+	{ 
+	  delete assoc; 
+	  assoc= 0;
+	}
+	return assoc;
+      } // end else connmap.insert			
+      
+    } // end "if (assoc)"
+  } 
+  while (wait_cond(ts)!=ETIMEDOUT);
+
+  return assoc;
+} //end get_connection_to
+
+
+/** terminates a signaling association/connection
+ *  - if no connection exists, generate a warning
+ *  - otherwise: generate internal msg to related receiver thread
+ */
+void
+TPoverTCP::terminate(const address& in_addr)
+{
+#ifndef _NO_LOGGING
+ const char *const thisproc="terminate()   - ";
+#endif
+
+ appladdress* addr = NULL;
+ addr = dynamic_cast<appladdress*>(in_addr.copy());
+
+ if (!addr) return;
+
+  // Create a new AssocData-pointer 
+  AssocData* assoc = NULL;
+
+  // check for existing connections to addr
+
+  // start critical section:
+  // please note if receiver_thread terminated already, the assoc data is not
+  // available anymore therefore we need a lock around cleanup_receiver_thread()
+
+  lock(); // install_cleanup_thread_lock(TPoverTCP, this);
+  assoc= connmap.lookup(*addr);
+  if (assoc) 
+  {
+    EVLog(tpparam.name,thisproc<<"got request to shutdown connection for peer " << addr);
+    // If not shut down then use it, else abort, wait and check again.
+    if (!assoc->shutdown) 
+    {
+      if (assoc->socketfd)
+      {
+	// disallow sending
+	if (shutdown(assoc->socketfd,SHUT_WR))
+	{
+	  ERRLog(tpparam.name,thisproc<<"shutdown (write) on socket for peer " << addr << " returned error:" << strerror(errno));
+	}
+	else
+        {
+	  EVLog(tpparam.name,thisproc<<"initiated closing of connection for peer " << addr << ". Shutdown (write) on socket "<< assoc->socketfd );	  
+	}
+      }
+      assoc->shutdown= true;
+    }
+    else
+      EVLog(tpparam.name,thisproc<<"connection for peer " << addr << " is already in mode shutdown");
+      
+  }
+  else
+    WLog(tpparam.name,thisproc<<"could not find a connection for peer " << *addr);
+
+  stop_receiver_thread(assoc);
+
+  // end critical section
+  unlock(); // uninstall_cleanup(1);
+
+  if (addr) delete addr;
+}
+
+
+/** generates and internal TPoverTCP message to send a NetMsg to the network
+ *  - it is necessary to let a thread do this, because the caller
+ *     may get blocked if the connect() or send() call hangs for a while
+ *  - the sending thread will call TPoverTCP::tcpsend()
+ *  - if no connection exists, creates a new one (unless use_existing_connection is true)
+ *  @note the netmsg is deleted by the send() method when it is not used anymore
+ */
+void
+TPoverTCP::send(NetMsg* netmsg, const address& in_addr, bool use_existing_connection)
+{
+  if (netmsg == NULL) {
+    ERRCLog(tpparam.name,"send() - called without valid NetMsg buffer (NULL)");
+    return;
+  }
+
+  appladdress* addr = NULL;
+  addr= dynamic_cast<appladdress*>(in_addr.copy());
+    
+  if (!addr)
+  {
+    ERRCLog(tpparam.name,"send() - given destination address is not of expected type (appladdress), has type " << (int) in_addr.get_type());
+    return;
+  } 
+
+  // lock due to sendermap access
+  lock();
+    
+  // check for existing sender thread
+  sender_thread_queuemap_t::const_iterator it= senderthread_queuemap.find(*addr);
+    
+  FastQueue* destqueue= 0;
+
+  if (it == senderthread_queuemap.end())
+  { // no sender thread found so far
+
+    // if we already have an existing connection it is save to create a sender thread
+    // since get_connection_to() will not be invoked, so an existing connection will
+    // be used
+    const AssocData* assoc = connmap.lookup(*addr);
+
+    //DLog(tpparam.name,"send() - use_existing_connection:" << (use_existing_connection ? "true" : "false") << " assoc:" << assoc);
+
+    if (use_existing_connection==false || (assoc && assoc->shutdown==false && assoc->socketfd>0))
+    { // it is allowed to create a new connection for this thread
+      // create a new queue for sender thread
+      FastQueue* sender_thread_queue= new FastQueue;
+      create_new_sender_thread(sender_thread_queue);
+      // remember queue for later use
+      
+      //pair<sender_thread_queuemap_t::iterator, bool> tmpinsiterator=
+      senderthread_queuemap.insert( pair<appladdress,FastQueue*> (*addr,sender_thread_queue) );
+      
+      destqueue= sender_thread_queue;
+    }
+  }
+  else
+  { // we have a sender thread, use stored queue from map
+    destqueue= it->second; 
+  }
+    
+  unlock();
+    
+  // send a send_data message to it (if we have a destination queue)
+  if (destqueue)
+  {
+    // both parameters will be freed after message was sent!
+    
+    TPoverTCPMsg* internalmsg= new TPoverTCPMsg(netmsg,new appladdress(*addr));
+    if (internalmsg)
+    {
+      // send the internal message to the sender thread queue
+      internalmsg->send(tpparam.source,destqueue);
+    }
+  }
+  else
+  {
+    if (!use_existing_connection)
+      WLog(tpparam.name,"send() - found entry for address, but no active sender thread available for peer addr:" << *addr << " - dropping data");
+    else
+    {
+      DLog(tpparam.name,"no active sender thread found for peer " << *addr << " - but policy forbids to set up a new connection, will drop data");
+
+    }
+    // cannot send data, so we must drop it
+    delete netmsg;
+  }
+  
+  if (addr) delete addr;
+}
+
+/** sends a NetMsg to the network.
+ *
+ * @param netmsg message to send
+ * @param addr   transport endpoint address
+ *
+ * @note   if no connection exists, creates a new one 
+ * @note   both parameters are deleted after the message was sent
+ */
+void
+TPoverTCP::tcpsend(NetMsg* netmsg, appladdress* addr)
+{                        
+#ifndef _NO_LOGGING
+  const char *const thisproc="sender   - ";
+#endif
+
+  // set result initially to success, set it to failure
+  // in places where these failures occur
+  int result = TCP_SUCCESS;
+  int saved_errno= 0;
+  int ret= 0;
+
+  // Create a new AssocData-pointer 
+  AssocData* assoc = NULL;
+  
+  // tp.cpp checks for initialisation of tp and correctness of
+  // msgsize, protocol and ip,
+  // throws an error if something is not right
+  if (addr) {
+    addr->convert_to_ipv6();
+    check_send_args(*netmsg,*addr);
+  } 
+  else 
+  {
+    ERRCLog(tpparam.name, thisproc << "address pointer is NULL");
+    result= TCP_SEND_FAILURE;
+
+    delete netmsg;
+    delete addr;
+
+    throw TPErrorInternal();
+  }
+
+
+  // check for existing connections, 
+  // if a connection exists, return its AssocData 
+  // and save it in assoc for further use
+  // if no connection exists, create a new one (in get_connection_to()).
+  // Connection is inserted into connection map that must be done
+  // with exclusive access
+  assoc= get_connection_to(*addr);
+
+  if (assoc==NULL || assoc->socketfd<=0)
+  {
+    ERRCLog(tpparam.name, color[red] << thisproc << "no valid assoc/socket data - dropping packet");
+
+    delete netmsg;
+    delete addr;
+    return;
+  }
+
+  if (assoc->shutdown)
+  {
+    Log(WARNING_LOG, LOG_ALERT, tpparam.name, thisproc << "should send message although connection already half closed");
+    delete netmsg;
+    delete addr;
+
+    throw TPErrorSendFailed();
+  }
+
+  uint32 msgsize= netmsg->get_size();
+#ifdef DEBUG_HARD
+  cerr << thisproc << "message size=" << netmsg->get_size() << endl;
+#endif
+
+  const uint32 retry_send_max = 3;
+  uint32 retry_count = 0;
+  // send all the data contained in netmsg to the socket
+  // which belongs to the address "addr"
+  for (uint32 bytes_sent= 0;
+       bytes_sent < msgsize;
+       bytes_sent+= ret)
+  {
+
+#ifdef _DEBUG_HARD
+    for (uint32 i=0;i<msgsize;i++)
+    {
+      cout << "send_buf: " << i << " : "; 
+      if ( isalnum(*(netmsg->get_buffer()+i)) )
+	cout << "'" << *(netmsg->get_buffer()+i) << "' (0x" << hex << (unsigned short) *(netmsg->get_buffer()+i) << dec << ")" ;
+      else
+	cout << "0x" << hex << (unsigned short) *(netmsg->get_buffer()+i) << dec;
+      cout << endl;
+    }
+
+    cout << endl;
+    cout << "bytes_sent: " << bytes_sent << endl;
+    cout << "Message size: " <<  msgsize << endl;
+    cout << "Send-Socket: " << assoc->socketfd << endl;
+    cout << "pointer-Offset. " << netmsg->get_pos() << endl;
+    cout << "vor send " << endl;
+#endif
+
+    retry_count= 0;
+    do 
+    {
+      // socket send
+      ret= ::send(assoc->socketfd, 
+		  netmsg->get_buffer() + bytes_sent,  
+		  msgsize - bytes_sent, 
+		  MSG_NOSIGNAL);
+      
+      // send_buf + bytes_sent
+
+      // Deal with temporary internal errors like EAGAIN, resource temporary unavailable etc.
+      // retry sending
+      if (ret < 0)
+      { // internal error during send occured
+	saved_errno= errno;
+	switch(saved_errno)
+	{
+	  case EAGAIN:  // same as EWOULDBLOCK
+          case EINTR:   // man page says: A signal occurred before any data was transmitted.
+	  case ENOBUFS: //  The output queue for a network interface was full.
+	    retry_count++;
+	    ERRLog(tpparam.name,"Temporary failure while calling send(): " << strerror(saved_errno) << ", errno: " << saved_errno 
+		   << " - retry sending, retry #" << retry_count);
+	    // pace down a little bit, sleep for a while
+	    sleep(1);
+	    break;
+
+	    // everything else should not lead to repetition 
+	  default:
+	    retry_count= retry_send_max;
+	    break;
+	} // end switch
+      } // endif
+      else // leave while
+	break;
+    } 
+    while(retry_count < retry_send_max);
+
+    if (ret < 0) 
+    { // unrecoverable error occured
+      
+      result= TCP_SEND_FAILURE;
+      break;
+    } // end if (ret < 0)
+    else
+    {
+      if (debug_pdu)
+      {
+	ostringstream hexdump;
+	netmsg->hexdump(hexdump,netmsg->get_buffer(),bytes_sent);
+	DLog(tpparam.name,"PDU debugging enabled - Sent:" << hexdump.str());
+      }
+    }
+
+    // continue with send next data block in next for() iteration
+  } // end for
+
+  // *** note: netmsg is deleted here ***
+  delete netmsg;
+  
+  // Throwing an exception within a critical section does not 
+  // unlock the mutex.
+
+  if (result != TCP_SUCCESS)
+  {
+    ERRLog(tpparam.name, thisproc << "TCP error, returns " << ret << ", error : " << strerror(errno));
+    delete addr;
+
+    throw TPErrorSendFailed(saved_errno);
+    
+  }
+  else
+    EVLog(tpparam.name, thisproc << ">>----Sent---->> message (" << msgsize << " bytes) using socket " << assoc->socketfd  << " to " << *addr);
+
+  if (!assoc) {
+    // no connection
+    
+    ERRLog(tpparam.name, thisproc << "cannot get connection to " << addr->get_ip_str() 
+	<< ", port #" << addr->get_port());
+
+    delete addr;
+
+    throw TPErrorUnreachable(); // should be no assoc found
+  } // end "if (!assoc)"
+  
+  // *** delete address ***
+  delete addr;
+}
+  
+/* this thread waits for an internal message that either:
+ * - requests transmission of a packet
+ * - requests to stop this thread
+ * @param argp points to the thread queue for internal messages
+ */
+void 
+TPoverTCP::sender_thread(void *argp)
+{
+#ifndef _NO_LOGGING
+  const char *const methodname="senderthread - ";
+#endif
+
+  message* internal_thread_msg = NULL;
+
+  EVLog(tpparam.name, methodname << "starting as thread <" << pthread_self() << ">");
+
+  FastQueue* fq= reinterpret_cast<FastQueue*>(argp);
+  if (!fq)
+  {
+    ERRLog(tpparam.name, methodname << "thread <" << pthread_self() << "> no valid pointer to msg queue. Stop.");
+    return;
+  }
+
+  bool terminate= false;
+  TPoverTCPMsg* internalmsg= 0;
+  while (terminate==false && (internal_thread_msg= fq->dequeue()) != 0 )
+  {
+    internalmsg= dynamic_cast<TPoverTCPMsg*>(internal_thread_msg);
+    
+    if (internalmsg == 0)
+    {
+      ERRLog(tpparam.name, methodname << "received not an TPoverTCPMsg but a" << internal_thread_msg->get_type_name());      
+    }
+    else
+    if (internalmsg->get_msgtype() == TPoverTCPMsg::send_data)
+    {
+      // create a connection if none exists and send the netmsg
+      if (internalmsg->get_netmsg() && internalmsg->get_appladdr())
+      {
+	try 
+	{
+	  tcpsend(internalmsg->get_netmsg(),internalmsg->get_appladdr());
+	} // end try
+	catch(TPErrorSendFailed& err)
+	{
+	  ERRLog(tpparam.name, methodname << "TCP send call failed - " << err.what() 
+		 << " cause: (" << err.get_reason() << ") " << strerror(err.get_reason()) );
+	} // end catch
+	catch(TPError& err)
+	{
+	  ERRLog(tpparam.name, methodname << "TCP send call failed - reason: " << err.what());
+	} // end catch
+	catch(...)
+	{
+	  ERRLog(tpparam.name, methodname << "TCP send call failed - unknown exception");
+	}
+      }
+      else
+      {
+	ERRLog(tpparam.name, methodname << "problem with passed arguments references, they point to 0");
+      } 
+    }
+    else
+    if (internalmsg->get_msgtype() == TPoverTCPMsg::stop)
+    {
+      terminate= true;
+    }  
+  } // end while
+  
+  EVLog(tpparam.name, methodname << "<" << pthread_self() << "> terminated connection.");
+}
+
+
+/** receiver thread listens at a TCP socket for incoming PDUs 
+ *  and passes complete PDUs to the coordinator. Incomplete
+ *  PDUs due to aborted connections or buffer overflows are discarded.
+ *  @param argp - assoc data and flags sig_terminate and terminated
+ *  
+ *  @note this is a static member function, so you cannot use class variables
+ */
+void 
+TPoverTCP::receiver_thread(void *argp)
+{
+#ifndef _NO_LOGGING
+  const char *const methodname="receiver - ";
+#endif
+
+  receiver_thread_arg_t *receiver_thread_argp= static_cast<receiver_thread_arg_t *>(argp);
+  const appladdress* peer_addr = NULL;
+  const appladdress* own_addr = NULL;
+  uint32 bytes_received = 0;
+  TPMsg* tpmsg= NULL;
+  
+  // argument parsing - start
+  if (receiver_thread_argp == 0)
+  {
+    ERRCLog(tpparam.name, methodname << "No arguments given at start of receiver thread <" << pthread_self() << ">, exiting.");
+
+    return;
+  }
+  else
+  {
+    // change status to running, i.e., not terminated
+    receiver_thread_argp->terminated= false;
+
+#ifdef _DEBUG
+    DLog(tpparam.name, methodname << "New receiver thread <" << pthread_self() << "> started. ");
+#endif
+  }
+
+  int conn_socket= 0;
+  if (receiver_thread_argp->peer_assoc)
+  {
+    // get socket descriptor from arg
+    conn_socket = receiver_thread_argp->peer_assoc->socketfd;
+    // get pointer to peer address of socket (source/sender address of peer) from arg
+    peer_addr= &receiver_thread_argp->peer_assoc->peer;
+    own_addr= &receiver_thread_argp->peer_assoc->ownaddr;
+  }
+  else
+  {
+    ERRCLog(tpparam.name, methodname << "No peer assoc available - pointer is NULL");
+    
+    return;
+  }
+
+  if (peer_addr == 0)
+  {
+    ERRCLog(tpparam.name, methodname << "No peer address available for socket " << conn_socket << ", exiting.");
+    
+    return;
+  }
+  // argument parsing - end
+#ifdef _DEBUG
+  Log(DEBUG_LOG,LOG_UNIMP, tpparam.name, methodname <<
+      "Preparing to wait for data at socket " 
+      << conn_socket << " from " << receiver_thread_argp->peer_assoc->peer);
+#endif
+
+  int ret= 0;
+  uint32 msgcontentlength= 0;
+  bool msgcontentlength_known= false;
+  bool pdu_complete= false; // when to terminate inner loop
+
+  /* maybe use this to create a new pdu, 
+    /// constructor
+    contextlistpdu(type_t t, subtype_t st, uint32 fc, uint32 numobj = 0);
+  */ 
+
+  // activate O_NON_BLOCK  for recv on socket conn_socket
+  // CAVEAT: this also implies non-blocking send()!
+  //fcntl(conn_socket,F_SETFL, O_NONBLOCK);
+    
+  // set options for polling
+  const unsigned int number_poll_sockets= 1; 
+  struct pollfd poll_fd;
+  // have to set structure before poll call
+  poll_fd.fd = conn_socket;
+  poll_fd.events = POLLIN | POLLPRI; 
+  poll_fd.revents = 0;
+
+  int poll_status;
+  bool recv_error= false;
+
+  NetMsg* netmsg= 0;
+  NetMsg* remainbuf= 0;
+  size_t buffer_bytes_left= 0;
+  size_t trailingbytes= 0;
+  bool skiprecv= false;
+  // loop until we receive a terminate signal (read-only var for this thread) 
+  // or get an error from socket read
+  while( receiver_thread_argp->sig_terminate == false )
+  {
+    // Read next PDU from socket or process trailing bytes in remainbuf
+    ret= 0;
+    msgcontentlength= 0;
+    msgcontentlength_known= false;
+    pdu_complete= false;
+    netmsg= 0;
+
+    // there are trailing bytes left from the last receive call
+    if (remainbuf != 0)
+    {
+      netmsg= remainbuf;
+      remainbuf= 0;
+      buffer_bytes_left= netmsg->get_size()-trailingbytes;
+      bytes_received= trailingbytes;
+      trailingbytes= 0;
+      skiprecv= true;
+    }
+    else // no trailing bytes, create a new buffer
+    if ( (netmsg= new NetMsg(NetMsg::max_size)) != 0 )
+    {
+      buffer_bytes_left= netmsg->get_size();
+      bytes_received= 0;
+      skiprecv= false;
+    }
+    else
+    { // buffer allocation failed
+      bytes_received= 0;
+      buffer_bytes_left= 0;
+      recv_error= true;
+    }
+    
+    // loops until PDU is complete
+    // >>>>>>>>>>>>>>>>>>>>>>>>>>> while >>>>>>>>>>>>>>>>>>>>>>>>
+    while (!pdu_complete && 
+	   !recv_error && 
+	   !receiver_thread_argp->sig_terminate)
+    {
+      if (!skiprecv)
+      {
+	// read from TCP socket or return after sleep_time
+	poll_status= poll(&poll_fd, number_poll_sockets, tpparam.sleep_time);
+	
+	if (receiver_thread_argp->sig_terminate)
+	{
+	  Log(EVENT_LOG,LOG_UNIMP,tpparam.name,methodname << "Thread <" << pthread_self() << "> found terminate signal after poll");
+	  // disallow sending
+	  AssocData* myassoc=const_cast<AssocData *>(receiver_thread_argp->peer_assoc);
+	  if (myassoc->shutdown == false)
+	  {
+	    myassoc->shutdown= true;
+	    if (shutdown(myassoc->socketfd,SHUT_WR))
+	    {
+	      if ( errno != ENOTCONN )
+		Log(ERROR_LOG,LOG_UNIMP,tpparam.name,methodname <<"shutdown (write) on socket " << conn_socket << " returned error:" << strerror(errno));
+	    }
+	  }
+	  // try to read do a last read from the TCP socket or return after sleep_time
+	  if (poll_status == 0)
+	  {
+	    poll_status= poll(&poll_fd, number_poll_sockets, tpparam.sleep_time);
+	  }
+	}
+
+	if (poll_fd.revents & POLLERR) // Error condition
+	{
+	  if (errno == 0 || errno == EINTR)
+	  {
+	    EVLog(tpparam.name, methodname << "poll(): " << strerror(errno));
+	  }
+	  else
+	  {
+	    ERRCLog(tpparam.name, methodname << "Poll indicates error: " << strerror(errno));
+	    recv_error= true;
+	  }
+	}
+	
+	if (poll_fd.revents & POLLHUP) // Hung up 
+	{
+	  Log(EVENT_LOG,LOG_CRIT, tpparam.name, methodname << "Poll hung up");
+	  recv_error= true;
+	}
+	
+	if (poll_fd.revents & POLLNVAL) // Invalid request: fd not open
+	{
+	  EVLog(tpparam.name, methodname << "Poll Invalid request: fd not open");
+	  recv_error= true;
+	}
+	
+	// check status (return value) of poll call
+	switch (poll_status)
+	{
+	  case -1:
+	    if (errno == 0 || errno == EINTR)
+	    {
+	      EVLog(tpparam.name, methodname << "Poll status: " << strerror(errno));
+	    }
+	    else
+	    {
+	      ERRCLog(tpparam.name, methodname << "Poll status indicates error: " << strerror(errno) << "- aborting");
+	      recv_error= true;
+	    }
+	    
+	    continue; // next while iteration
+	    break;
+	    
+	  case 0:
+#ifdef DEBUG_HARD
+	    Log(DEBUG_LOG,LOG_UNIMP, tpparam.name, methodname << "Poll timed out after " << tpparam.sleep_time << " ms.");
+#endif
+	    continue; // next while iteration
+	    break;
+	    
+	  default:
+#ifdef DEBUG_HARD
+	    Log(DEBUG_LOG,LOG_UNIMP, tpparam.name, methodname << "Poll: " << poll_status << " event(s) ocurred, of type " << poll_fd.revents);
+#endif
+	    break;
+	} // end switch
+
+
+	/// receive data from socket buffer (recv will not block)
+	ret = recv(conn_socket, 
+		   netmsg->get_buffer() + bytes_received, 
+		   buffer_bytes_left, 
+		   MSG_DONTWAIT);
+
+	if ( ret < 0 )
+	{
+	  if (errno!=EAGAIN && errno!=EWOULDBLOCK)
+	  {
+	    ERRCLog(tpparam.name, methodname << "Receive at socket " << conn_socket << " failed, error: " << strerror(errno));
+	    recv_error= true;
+	    continue;
+	  }
+	  else
+	  { // errno==EAGAIN || errno==EWOULDBLOCK
+	    // just nothing to read from socket, continue w/ next poll
+	    continue;
+	  }
+	}
+	else
+	{
+	  if (ret == 0)
+	  {
+	    // this means that EOF is reached, 
+	    // other side has closed connection
+	    Log(DEBUG_LOG,LOG_UNIMP, tpparam.name, methodname << "Other side (" << *peer_addr << ") closed connection for socket " << conn_socket);
+	    // disallow sending
+	    AssocData* myassoc=const_cast<AssocData *>(receiver_thread_argp->peer_assoc);
+	    if (myassoc->shutdown == false)
+	    {
+	      myassoc->shutdown= true;
+	      if (shutdown(myassoc->socketfd,SHUT_WR))
+	      {
+		if ( errno != ENOTCONN )
+		  Log(ERROR_LOG,LOG_UNIMP,tpparam.name, methodname << "shutdown (write) on socket " << conn_socket << " returned error:" << strerror(errno));
+	      }
+	    }
+	    // not a real error, but we must quit the receive loop
+	    recv_error= true;
+	  }
+	  else
+	  {
+
+	    Log(EVENT_LOG,LOG_UNIMP, tpparam.name, methodname << "<<--Received--<< packet (" << ret << " bytes) at socket " << conn_socket << " from " << *peer_addr);
+	    // track number of received bytes
+	    bytes_received+= ret;
+	    buffer_bytes_left-= ret;
+	  }
+	}
+      } // end if do not skip recv() statement      
+
+      if (buffer_bytes_left < 0) ///< buffer space exhausted now
+      {
+	recv_error= true;
+        Log(ERROR_LOG,LOG_CRIT, tpparam.name, methodname << "during receive buffer space exhausted");
+      }
+
+      if (!msgcontentlength_known) ///< common header not parsed
+      {
+	// enough bytes read to parse common header?
+	if (bytes_received >= common_header_length)
+	{
+	  // get message content length in number of bytes
+	  if (getmsglength(*netmsg, msgcontentlength))
+	    msgcontentlength_known= true;
+	  else
+	  {
+	    ERRCLog(tpparam.name, methodname << "Not a valid protocol header - discarding received packet. received size " << msgcontentlength);
+
+	    ostringstream hexdumpstr;
+	    netmsg->hexdump(hexdumpstr,netmsg->get_buffer(),bytes_received);
+	    DLog(tpparam.name,"dumping received bytes:" << hexdumpstr.str());
+
+	    // reset all counters
+	    msgcontentlength= 0;
+	    msgcontentlength_known= false;
+	    bytes_received= 0;
+	    pdu_complete= false;
+	    continue;
+	  }
+	}
+      } // endif common header not parsed
+
+      // check whether we have read the whole Protocol PDU
+      DLog(tpparam.name, "bytes_received-common_header_length=" << bytes_received-common_header_length << " msgcontentlength: " << msgcontentlength);
+      if (msgcontentlength_known)
+      {
+	if (bytes_received-common_header_length >= msgcontentlength )
+	{
+	  pdu_complete= true;
+	  // truncate buffer exactly at common_header_length+msgcontentlength==PDU size, trailing stuff is handled separately
+	  netmsg->truncate(common_header_length+msgcontentlength);
+
+	  // trailing bytes are copied into new buffer
+	  if (bytes_received-common_header_length > msgcontentlength)
+	  {
+	    WLog(tpparam.name,"trailing bytes - received more bytes ("<<bytes_received<<") than expected for PDU (" << common_header_length+msgcontentlength << ")");
+	    remainbuf= new NetMsg(NetMsg::max_size);
+	    trailingbytes= (bytes_received-common_header_length) - msgcontentlength;
+	    bytes_received= common_header_length+msgcontentlength;
+	    memcpy(remainbuf->get_buffer(),netmsg->get_buffer()+common_header_length+msgcontentlength, trailingbytes);
+	  }
+	}
+	else
+	{ // not enough bytes in the buffer must continue to read from network
+	  skiprecv= false;
+	}
+      } // endif msgcontentlength_known
+    } // end while (!pdu_complete && !recv_error && !signalled for termination)
+    // >>>>>>>>>>>>>>>>>>>>>>>>>>> while >>>>>>>>>>>>>>>>>>>>>>>>
+
+    // if other side closed the connection, we should still be able to deliver the remaining data
+    if (ret == 0)
+    {
+      recv_error= false;
+    }
+
+    // deliver only complete PDUs to signaling module
+    if (!recv_error && pdu_complete)
+    {
+      // create TPMsg and send it to the signaling thread
+      tpmsg = new(nothrow) TPMsg(netmsg, peer_addr->copy(), own_addr->copy());
+      if (tpmsg)
+      {
+	DLog(tpparam.name, methodname << "receipt of PDU now complete, sending msg#" << tpmsg->get_id()
+	     << " to module " <<  message::get_qaddr_name(tpparam.dest));
+      }
+
+      debug_pdu=false;
+
+      if (debug_pdu)
+      {
+	ostringstream hexdump;
+	netmsg->hexdump(hexdump,netmsg->get_buffer(),bytes_received);
+	Log(DEBUG_LOG,LOG_NORMAL, tpparam.name,"PDU debugging enabled - Received:" << hexdump.str());
+      }
+
+      // send the message if it was successfully created
+      // bool message::send_to(qaddr_t dest, bool exp = false);
+      if (!tpmsg
+	  || (!tpmsg->get_peeraddress())
+	  || (!tpmsg->send(message::qaddr_tp_over_tcp, tpparam.dest))) 
+      {
+	Log(ERROR_LOG,LOG_NORMAL, tpparam.name, methodname << "Cannot allocate/send TPMsg");
+	if (tpmsg) delete tpmsg;
+      } // end if tpmsg not allocated or not addr or not sent
+      
+
+    } // end if !recv_error
+    else
+    { // error during receive or PDU incomplete
+      if (bytes_received>0)
+      {
+	Log(WARNING_LOG,LOG_NORMAL, tpparam.name, methodname << "Attention! " << (recv_error? "Receive error, " : "") << (pdu_complete ?  "PDU complete" : "PDU incomplete") << "received bytes: " << bytes_received);
+      }
+
+      if (!pdu_complete && bytes_received>0 && bytes_received<common_header_length)
+      {
+	ostringstream hexdumpstr;
+	netmsg->hexdump(hexdumpstr,netmsg->get_buffer(),bytes_received);
+	Log(DEBUG_LOG,LOG_NORMAL,tpparam.name,"Message too short to be a valid protocol header - dumping received bytes:" << hexdumpstr.str());	
+      }
+      // leave the outer loop
+      /**********************/
+      break;
+      /**********************/
+    } // end else
+
+  } // end while (thread not signalled for termination)
+
+  Log(DEBUG_LOG,LOG_NORMAL, tpparam.name, methodname << "Thread <" << pthread_self() 
+      << "> shutting down and closing socket " << receiver_thread_argp->peer_assoc->peer);
+
+  // shutdown socket
+  if (shutdown(conn_socket, SHUT_RD))
+  {
+    if ( errno != ENOTCONN )
+      Log(ERROR_LOG,LOG_NORMAL, tpparam.name, methodname << "Thread <" << pthread_self() << "> shutdown (read) on socket failed, reason: " << strerror(errno));
+  }
+
+  // close socket
+  close(conn_socket);
+
+  receiver_thread_argp->terminated= true;
+
+  Log(DEBUG_LOG,LOG_NORMAL, tpparam.name, methodname << "Thread <" << pthread_self() << "> terminated");
+
+#ifdef _DEBUG
+  Log(DEBUG_LOG,LOG_NORMAL, tpparam.name, methodname << "Signaling main loop for cleanup");
+#endif
+  // notify master thread for invocation of cleanup procedure
+  TPoverTCPMsg* newmsg= new(nothrow)TPoverTCPMsg(receiver_thread_argp->peer_assoc);
+  // send message to main loop thread
+  newmsg->send_to(tpparam.source);
+
+}  
+
+
+/** this signals a terminate to a thread and wait for the thread to stop
+ *  @note it is not safe to access any thread related data after this method returned,
+ *        because the receiver thread will initiate a cleanup_receiver_thread() method 
+ *        which may erase all relevant thread data.
+ */
+void 
+TPoverTCP::stop_receiver_thread(AssocData* peer_assoc)
+{
+  // All operations on  recv_thread_argmap and connmap require an already acquired lock
+  // after this procedure peer_assoc may be invalid because it was erased
+
+  // start critical section
+
+  if (peer_assoc == 0)
+    return;
+
+  pthread_t thread_id=  peer_assoc->thread_ID;
+  
+  // try to clean up receiver_thread_arg
+  recv_thread_argmap_t::iterator recv_thread_arg_iter= recv_thread_argmap.find(thread_id);
+  receiver_thread_arg_t* recv_thread_argp=  
+    (recv_thread_arg_iter != recv_thread_argmap.end()) ? recv_thread_arg_iter->second : 0;
+  if (recv_thread_argp)
+  {
+    if (!recv_thread_argp->terminated)
+    {
+      // thread signaled termination, but is not?
+      Log(EVENT_LOG,LOG_NORMAL, tpparam.name,"stop_receiver_thread() - Receiver thread <" << thread_id << "> signaled for termination");
+
+      // signal thread for its termination
+      recv_thread_argp->sig_terminate= true;
+      // wait for thread to join after termination
+      pthread_join(thread_id, 0);
+      // the dying thread will signal main loop to call this method, but this time we should enter the else branch
+      return;
+    }
+  }
+  else
+    Log(ERROR_LOG,LOG_NORMAL, tpparam.name,"stop_receiver_thread() - Receiver thread <" << thread_id << "> not found");
+
+}
+
+
+/** cleans up left over structures (assoc,receiver_thread_arg) from already terminated receiver_thread
+ *  usually called by the master_thread after the receiver_thread terminated
+ * @note clean_up_receiver_thread() should be only called when an outer lock ensures that peer_assoc
+ *       is still valid
+ */
+void 
+TPoverTCP::cleanup_receiver_thread(AssocData* peer_assoc)
+{
+  // All operations on  recv_thread_argmap and connmap require an already acquired lock
+  // after this procedure peer_assoc may be invalid because it was erased
+
+  // start critical section
+
+  if (peer_assoc == 0)
+    return;
+
+  pthread_t thread_id=  peer_assoc->thread_ID;
+  
+  // try to clean up receiver_thread_arg
+  recv_thread_argmap_t::iterator recv_thread_arg_iter= recv_thread_argmap.find(thread_id);
+  receiver_thread_arg_t* recv_thread_argp=  
+    (recv_thread_arg_iter != recv_thread_argmap.end()) ? recv_thread_arg_iter->second : 0;
+  if (recv_thread_argp)
+  {
+    if (!recv_thread_argp->terminated)
+    {
+      // thread signaled termination, but is not?
+      Log(ERROR_LOG,LOG_NORMAL, tpparam.name,"cleanup_receiver_thread() - Receiver thread <" << thread_id << "> not terminated yet?!");
+      return;
+    }
+    else
+    { // if thread is already terminated
+      Log(EVENT_LOG,LOG_NORMAL, tpparam.name,"cleanup_receiver_thread() - Receiver thread <" << thread_id << "> is terminated");
+
+      // delete it from receiver map
+      recv_thread_argmap.erase(recv_thread_arg_iter);
+
+      // then delete receiver arg structure
+      delete recv_thread_argp;
+    }
+  }
+
+  // delete entry from connection map
+
+  // cleanup sender thread
+  // no need to lock explicitly, because caller of cleanup_receiver_thread() must already locked
+  terminate_sender_thread(peer_assoc);
+
+  // delete the AssocData structure from the connection map
+  // also frees allocated AssocData structure
+  connmap.erase(peer_assoc);
+
+  // end critical section
+
+  Log(DEBUG_LOG,LOG_NORMAL, tpparam.name,"cleanup_receiver_thread() - Cleanup receiver thread <" << thread_id << ">. Done.");
+}
+
+
+/* sends a stop message to the sender thread that belongs to the peer address given in assoc
+ * @note terminate_receiver_thread() should be only called when an outer lock ensures that assoc
+ *       is still valid, a lock is also required, because senderthread_queuemap is changed
+ */
+void 
+TPoverTCP::terminate_sender_thread(const AssocData* assoc)
+{
+  if (assoc == 0)
+  {
+    Log(ERROR_LOG,LOG_NORMAL,tpparam.name,"terminate_sender_thread() - assoc data == NULL");
+    return;
+  }
+
+  sender_thread_queuemap_t::iterator it= senderthread_queuemap.find(assoc->peer);
+
+  if (it != senderthread_queuemap.end())
+  { // we have a sender thread: send a stop message to it
+    FastQueue* destqueue= it->second; 
+    if (destqueue)
+    {
+      TPoverTCPMsg* internalmsg= new TPoverTCPMsg(assoc,tpparam.source,TPoverTCPMsg::stop);
+      if (internalmsg)
+      {
+	// send the internal message to the sender thread queue
+	internalmsg->send(tpparam.source,destqueue);
+      }
+    }
+    else
+    {
+      Log(WARNING_LOG,LOG_NORMAL,tpparam.name,"terminate_sender_thread() - found entry for address, but no sender thread. addr:" << assoc->peer);
+    }
+    // erase entry from map
+    senderthread_queuemap.erase(it);
+  }
+}
+
+/* terminate all active threads
+ * note: locking should not be necessary here because this message is called as last method from
+ * main_loop()
+ */
+void 
+TPoverTCP::terminate_all_threads()
+{
+  AssocData* assoc= 0;
+  receiver_thread_arg_t* terminate_argp;
+
+  for (recv_thread_argmap_t::iterator terminate_iterator=  recv_thread_argmap.begin();
+       terminate_iterator !=  recv_thread_argmap.end();
+       terminate_iterator++)
+  {
+    if ( (terminate_argp= terminate_iterator->second) != 0)
+    {
+      // we need a non const pointer to erase it later on
+      assoc= const_cast<AssocData*>(terminate_argp->peer_assoc);
+      // check whether thread is still alive
+      if (terminate_argp->terminated == false)
+      {
+	terminate_argp->sig_terminate= true;
+	// then wait for its termination
+	Log(DEBUG_LOG,LOG_NORMAL, tpparam.name, 
+	    "Signaled receiver thread <" << terminate_iterator->first << "> for termination");
+	
+	pthread_join(terminate_iterator->first, 0);
+	
+	Log(DEBUG_LOG,LOG_NORMAL, tpparam.name, "Thread <" << terminate_iterator->first  << "> is terminated");
+      }
+      else
+	Log(DEBUG_LOG,LOG_NORMAL, tpparam.name, 
+	    "Receiver thread <" << terminate_iterator->first << "> already terminated");
+	
+      // cleanup all remaining argument structures of terminated threads
+      delete terminate_argp;
+
+      // terminate any related sender thread that is still running
+      terminate_sender_thread(assoc);
+      
+      connmap.erase(assoc);
+      // delete assoc is not necessary, because connmap.erase() will do the job
+    }
+  } // end for
+}
+
+
+/**
+ * sender thread starter: 
+ * just a static starter method to allow starting the 
+ * actual sender_thread() method.
+ *
+ * @param argp - pointer to the current TPoverTCP object instance and receiver_thread_arg_t struct
+ */
+void*
+TPoverTCP::sender_thread_starter(void *argp)
+{
+  sender_thread_start_arg_t *sargp= static_cast<sender_thread_start_arg_t *>(argp);
+  
+  //cout << "invoked sender_thread_Starter" << endl;
+
+  // invoke sender thread method
+  if (sargp != 0 && sargp->instance != 0)
+  {
+    // call receiver_thread member function on object instance
+    sargp->instance->sender_thread(sargp->sender_thread_queue);
+
+    //cout << "Before deletion of sarg" << endl;
+
+    // no longer needed
+    delete sargp;
+  }
+  else
+  {
+    Log(ERROR_LOG,LOG_CRIT,"sender_thread_starter","while starting sender_thread: 0 pointer to arg or object");
+  }
+  return 0;
+}
+
+
+
+
+/**
+ * receiver thread starter: 
+ * just a static starter method to allow starting the 
+ * actual receiver_thread() method.
+ *
+ * @param argp - pointer to the current TPoverTCP object instance and receiver_thread_arg_t struct
+ */
+void*
+TPoverTCP::receiver_thread_starter(void *argp)
+{
+  receiver_thread_start_arg_t *rargp= static_cast<receiver_thread_start_arg_t *>(argp);
+  // invoke receiver thread method
+  if (rargp != 0 && rargp->instance != 0)
+  {
+    // call receiver_thread member function on object instance
+    rargp->instance->receiver_thread(rargp->rtargp);
+
+    // no longer needed
+    delete rargp;
+  }
+  else
+  {
+    Log(ERROR_LOG,LOG_CRIT,"receiver_thread_starter","while starting receiver_thread: 0 pointer to arg or object");
+  }
+  return 0;
+}
+
+
+void
+TPoverTCP::create_new_sender_thread(FastQueue* senderfqueue)
+{
+  Log(EVENT_LOG,LOG_NORMAL, tpparam.name, "Starting new sender thread...");
+
+  pthread_t senderthreadid;
+  // create new thread; (arg == 0) is handled by thread, too
+  int pthread_status= pthread_create(&senderthreadid, 
+				     NULL, // NULL: default attributes: thread is joinable and has a 
+				     //       default, non-realtime scheduling policy
+				     TPoverTCP::sender_thread_starter,
+				     new sender_thread_start_arg_t(this,senderfqueue));
+  if (pthread_status)
+  {
+    Log(ERROR_LOG,LOG_CRIT, tpparam.name, "A new thread could not be created: " <<  strerror(pthread_status));
+    
+    delete senderfqueue;
+  }
+}
+
+
+void
+TPoverTCP::create_new_receiver_thread(AssocData* peer_assoc)
+{
+  receiver_thread_arg_t* argp= 
+    new(nothrow) receiver_thread_arg(peer_assoc);
+  
+  Log(EVENT_LOG,LOG_NORMAL, tpparam.name, "Starting new receiver thread...");
+
+  // create new thread; (arg == 0) is handled by thread, too
+  int pthread_status= pthread_create(&peer_assoc->thread_ID, 
+				     NULL, // NULL: default attributes: thread is joinable and has a 
+				     //       default, non-realtime scheduling policy
+				     receiver_thread_starter,
+				     new(nothrow) receiver_thread_start_arg_t(this,argp));
+  if (pthread_status)
+  {
+    Log(ERROR_LOG,LOG_CRIT, tpparam.name, "A new thread could not be created: " <<  strerror(pthread_status));
+    
+    delete argp;
+  }
+  else
+  {
+    lock(); // install_cleanup_thread_lock(TPoverTCP, this);
+
+    // remember pointer to thread arg structure
+    // thread arg structure should be destroyed after thread termination only
+    pair<recv_thread_argmap_t::iterator, bool> tmpinsiterator=
+      recv_thread_argmap.insert( pair<pthread_t,receiver_thread_arg_t*> (peer_assoc->thread_ID,argp) );
+    if (tmpinsiterator.second == false)
+    {
+      Log(ERROR_LOG,LOG_CRIT, tpparam.name, "Thread argument could not be inserted into hashmap");
+    }
+    unlock(); // uninstall_cleanup(1);
+  }  
+}
+
+
+/**
+ * master listener thread starter: 
+ * just a static starter method to allow starting the 
+ * actual master_listener_thread() method.
+ *
+ * @param argp - pointer to the current TPoverTCP object instance
+ */
+void*
+TPoverTCP::master_listener_thread_starter(void *argp)
+{
+  // invoke listener thread method
+  if (argp != 0)
+  {
+    (static_cast<TPoverTCP*>(argp))->master_listener_thread();
+  }
+  return 0;
+}
+
+
+
+/**
+ * master listener thread: waits for incoming connections at the well-known tcp port
+ * when a connection request is received this thread spawns a receiver_thread for
+ * receiving packets from the peer at the new socket. 
+ */
+void
+TPoverTCP::master_listener_thread()
+{
+  // create a new address-structure for the listening masterthread
+  struct sockaddr_in6 own_address;
+  own_address.sin6_family = AF_INET6;
+  own_address.sin6_flowinfo= 0;
+  own_address.sin6_port = htons(tpparam.port); // use port number in param structure
+  // accept incoming connections on all interfaces 
+  own_address.sin6_addr = in6addr_any;
+  own_address.sin6_scope_id= 0;
+  
+  // create a listening socket
+  int master_listener_socket= socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
+  if (master_listener_socket == -1)
+  {
+    Log(ERROR_LOG,LOG_CRIT, tpparam.name, "Could not create a new socket, error: " << strerror(errno));
+    return;
+  }
+  
+  // Disable Nagle Algorithm, set (TCP_NODELAY)
+  int nodelayflag= 1;
+  int status= setsockopt(master_listener_socket,
+			 IPPROTO_TCP,
+			 TCP_NODELAY,
+			 &nodelayflag,
+			 sizeof(nodelayflag));
+  if (status)
+  {
+    Log(ERROR_LOG,LOG_NORMAL,tpparam.name, "Could not set socket option TCP_NODELAY:" << strerror(errno));
+  }
+  
+  // Reuse ports, even if they are busy
+  int socketreuseflag= 1;
+  status= setsockopt(master_listener_socket,
+			   SOL_SOCKET,
+			   SO_REUSEADDR,
+			   (const char *) &socketreuseflag,
+			   sizeof(socketreuseflag));
+  if (status)
+  {
+       Log(ERROR_LOG,LOG_NORMAL,tpparam.name, "Could not set socket option SO_REUSEADDR:" << strerror(errno));
+  }
+  
+  
+  // bind the newly created socket to a specific address
+  int bind_status = bind(master_listener_socket,
+			 reinterpret_cast<struct sockaddr *>(&own_address),
+			 sizeof(own_address));
+  if (bind_status)
+    { 
+      Log(ERROR_LOG,LOG_CRIT, tpparam.name, "Binding to " 
+	  << inet_ntop(AF_INET6, &own_address.sin6_addr, in6_addrstr, INET6_ADDRSTRLEN)
+	  << " port " << tpparam.port << " failed, error: " << strerror(errno));
+      return;
+    }
+
+    // listen at the socket, 
+    // queuesize for pending connections= max_listen_queue_size
+    int listen_status = listen(master_listener_socket, max_listen_queue_size);
+    if (listen_status)
+    {
+      Log(ERROR_LOG,LOG_CRIT, tpparam.name, "Listen at socket " << master_listener_socket 
+	  << " failed, error: " << strerror(errno));
+      return;
+    }
+    else
+    {
+      Log(INFO_LOG,LOG_NORMAL, tpparam.name, color[green] << "Listening at port #" << tpparam.port << color[off]);
+    }
+
+    // activate O_NON_BLOCK for accept (accept does not block)
+    fcntl(master_listener_socket,F_SETFL, O_NONBLOCK);
+
+    // create a pollfd struct for use in the mainloop
+    struct pollfd poll_fd;
+    poll_fd.fd = master_listener_socket;
+    poll_fd.events = POLLIN | POLLPRI; 
+    poll_fd.revents = 0;
+    /*
+      #define POLLIN	0x001	// There is data to read. 
+      #define POLLPRI	0x002	// There is urgent data to read.  
+      #define POLLOUT	0x004	// Writing now will not block.  
+    */
+    
+    bool terminate = false;
+    // check for thread terminate condition using get_state()
+    state_t currstate= get_state();
+    int poll_status= 0;
+    const unsigned int number_poll_sockets= 1; 
+    struct sockaddr_in6 peer_address;
+    socklen_t peer_address_len;
+    int conn_socket;
+
+    // check whether this thread is signaled for termination
+    while(! (terminate= (currstate==STATE_ABORT || currstate==STATE_STOP) ) )
+    {
+      // wait on number_poll_sockets (main drm socket) 
+      // for the events specified above for sleep_time (in ms)
+      poll_status= poll(&poll_fd, number_poll_sockets, tpparam.sleep_time);
+      if (poll_fd.revents & POLLERR) // Error condition
+      {
+	if (errno != EINTR) 
+	{
+	  Log(ERROR_LOG,LOG_CRIT, tpparam.name, 
+	      "Poll caused error " << strerror(errno) << " - indicated by revents");
+	}
+	else
+	{
+	  Log(EVENT_LOG,LOG_NORMAL, tpparam.name, "poll(): " << strerror(errno));
+	}
+
+      }
+      if (poll_fd.revents & POLLHUP) // Hung up 
+      {
+	Log(ERROR_LOG,LOG_CRIT, tpparam.name, "Poll hung up");
+	return;
+      }
+      if (poll_fd.revents & POLLNVAL) // Invalid request: fd not open
+      {
+	Log(ERROR_LOG,LOG_CRIT, tpparam.name, "Poll Invalid request: fd not open");
+	return;
+      }
+      
+      switch (poll_status)
+      {
+	case -1:
+	  if (errno != EINTR)
+	  {
+	    Log(ERROR_LOG,LOG_CRIT, tpparam.name, "Poll status indicates error: " << strerror(errno));
+	  }
+	  else
+	  {
+	    Log(EVENT_LOG,LOG_NORMAL, tpparam.name, "Poll status: " << strerror(errno));
+	  }
+	    
+	  break;
+
+	case 0:
+#ifdef DEBUG_HARD
+	  Log(DEBUG_LOG,LOG_UNIMP, tpparam.name, 
+	      "Listen Thread - Poll timed out after " << tpparam.sleep_time << " ms.");
+#endif
+	  currstate= get_state();
+	  continue;
+	  break;
+
+	default:
+#ifdef DEBUG_HARD
+	  Log(DEBUG_LOG,LOG_UNIMP, tpparam.name, "Poll: " << poll_status << " event(s) ocurred, of type " << poll_fd.revents);
+#endif
+	  break;
+      } // end switch
+
+      // after a successful accept call, 
+      // accept stores the address information of the connecting party
+      // in peer_address and the size of its address in addrlen
+      peer_address_len= sizeof(peer_address);
+      conn_socket = accept (master_listener_socket,
+			    reinterpret_cast<struct sockaddr *>(&peer_address),
+			    &peer_address_len);
+      if (conn_socket == -1)
+      {
+	if (errno != EWOULDBLOCK && errno != EAGAIN)
+	{
+	  Log(ERROR_LOG,LOG_EMERG, tpparam.name, "Accept at socket " << master_listener_socket
+	      << " failed, error: " << strerror(errno));
+	  return;
+	}
+      }
+      else
+      {
+	// create a new assocdata-object for the new thread
+	AssocData* peer_assoc = NULL;
+	appladdress addr(peer_address, IPPROTO_TCP);
+
+	Log(DEBUG_LOG,LOG_NORMAL, tpparam.name, "<<--Received connect--<< request from " << addr.get_ip_str() 
+	    << " port #" << addr.get_port());
+
+	struct sockaddr_in6 own_address;
+	socklen_t own_address_len= sizeof(own_address);
+	getsockname(conn_socket, reinterpret_cast<struct sockaddr*>(&own_address), &own_address_len);
+
+	// AssocData will copy addr content into its own structure
+	// allocated peer_assoc will be stored in connmap
+	peer_assoc = new(nothrow) AssocData(conn_socket, addr, appladdress(own_address,IPPROTO_TCP));
+
+	bool insert_success= false;
+	if (peer_assoc)
+	{
+	  // start critical section
+	  lock(); // install_cleanup_thread_lock(TPoverTCP, this);
+	  insert_success= connmap.insert(peer_assoc);
+	  // end critical section
+	  unlock(); // uninstall_cleanup(1);
+	}
+	
+	
+	if (insert_success == false) // not inserted into connmap
+	{
+	  Log(ERROR_LOG,LOG_CRIT, tpparam.name, "Cannot insert AssocData for socket " << conn_socket
+	      << ", " << addr.get_ip_str() << ", port #" 
+	      << addr.get_port() << " into connection map, aborting connection...");
+
+	  // abort connection, delete its AssocData
+	  close (conn_socket);
+	  if (peer_assoc) 
+	  { 
+	    delete peer_assoc;
+	    peer_assoc= 0;
+	  }
+	  return;
+		
+	} //end __else(connmap.insert());__
+	
+	// create a new thread for each new connection
+	create_new_receiver_thread(peer_assoc);
+      } // end __else (connsocket)__
+      
+      // get new thread state
+      currstate= get_state();
+
+    } // end while(!terminate)
+    return;
+} // end listen_for_connections()    
+
+
+TPoverTCP::~TPoverTCP()
+{
+  init= false;
+
+  Log(DEBUG_LOG,LOG_NORMAL, tpparam.name,  "Destructor called");
+
+  QueueManager::instance()->unregister_queue(tpparam.source);
+}
+
+/** TPoverTCP Thread main loop.
+ * This loop checks for internal messages of either
+ * a send() call to start a new receiver thread, or,
+ * of a receiver_thread() that signals its own termination
+ * for proper cleanup of control structures.
+ * It also handles the following internal TPoverTCPMsg types:
+ * - TPoverTCPMsg::stop - a particular receiver thread is terminated
+ * - TPoverTCPMsg::start - a particular receiver thread is started
+ * @param nr number of current thread instance
+ */
+void 
+TPoverTCP::main_loop(uint32 nr)
+{
+
+  // get internal queue for messages from receiver_thread
+  FastQueue* fq = get_fqueue();
+  if (!fq) 
+  {
+    Log(ERROR_LOG,LOG_CRIT, tpparam.name, "Cannot find message queue");
+    return;
+  } // end if not fq
+  // register queue for receiving internal messages from other modules
+  QueueManager::instance()->register_queue(fq,tpparam.source);
+
+  // start master listener thread
+  pthread_t master_listener_thread_ID;
+  int pthread_status= pthread_create(&master_listener_thread_ID, 
+				     NULL, // NULL: default attributes: thread is joinable and has a 
+				     //       default, non-realtime scheduling policy
+				     master_listener_thread_starter,
+				     this);
+  if (pthread_status)
+  {
+    Log(ERROR_LOG,LOG_CRIT, tpparam.name, 
+	"New master listener thread could not be created: " <<  strerror(pthread_status));
+  }
+  else
+    Log(DEBUG_LOG,LOG_NORMAL, tpparam.name, "Master listener thread started");
+
+
+  // define max latency for thread reaction on termination/stop signal
+  timespec wait_interval= { 0, 250000000L }; // 250ms
+  message* internal_thread_msg = NULL;
+  state_t currstate= get_state();
+
+  // check whether this thread is signaled for termination
+  while( currstate!=STATE_ABORT && currstate!=STATE_STOP )  
+  {
+    // poll internal message queue (blocking)
+    if ( (internal_thread_msg= fq->dequeue_timedwait(wait_interval)) != 0 )
+    {
+      TPoverTCPMsg* internalmsg= dynamic_cast<TPoverTCPMsg*>(internal_thread_msg);
+      if (internalmsg)
+      {
+	if (internalmsg->get_msgtype() == TPoverTCPMsg::stop)
+	{
+	  // a receiver thread terminated and signaled for cleanup by master thread
+	  AssocData* assocd= const_cast<AssocData*>(internalmsg->get_peer_assoc());
+	  Log(DEBUG_LOG,LOG_NORMAL, tpparam.name, "Got cleanup request for thread <" << assocd->thread_ID <<'>');
+	  lock();
+	  cleanup_receiver_thread( assocd );
+	  unlock();
+	}
+	else
+	if (internalmsg->get_msgtype() == TPoverTCPMsg::start)
+	{
+	  // start a new receiver thread
+	  create_new_receiver_thread( const_cast<AssocData*>(internalmsg->get_peer_assoc()) );
+	}
+	else
+	  Log(ERROR_LOG,LOG_CRIT, tpparam.name, "unexpected internal message:" << internalmsg->get_msgtype());
+	  
+	delete internalmsg;
+      }
+      else
+      {
+	Log(ERROR_LOG,LOG_CRIT, tpparam.name, "Dynamic_cast failed - received unexpected and unknown internal message source "
+	    << internal_thread_msg->get_source());
+      }
+    } // endif
+
+    // get thread state
+    currstate= get_state();
+  } // end while
+
+  if (currstate==STATE_STOP)
+  {
+    // start abort actions
+    Log(INFO_LOG,LOG_NORMAL, tpparam.name, "Asked to abort, stopping all receiver threads");
+  } // end if stopped
+
+  // do not accept any more messages
+  fq->shutdown();
+  // terminate all receiver and sender threads that are still active 
+  terminate_all_threads();
+}
+
+} // end namespace protlib
+///@}
Index: /source/ariba/utility/transport/tcpip/protlib/tp_over_tcp.h
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/tp_over_tcp.h	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/tp_over_tcp.h	(revision 5284)
@@ -0,0 +1,256 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file tp_over_tcp.h
+/// Transport over TCP
+/// ----------------------------------------------------------
+/// $Id: tp_over_tcp.h 2718 2007-07-24 03:23:14Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/tp_over_tcp.h $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+/** @ingroup tptcp
+ * @ file
+ * TP over TCP
+ */
+
+#ifndef TP_OVER_TCP_H
+#define TP_OVER_TCP_H
+
+#include <ext/hash_map>
+
+#include "tp.h"
+#include "threads.h"
+#include "threadsafe_db.h"
+#include "connectionmap.h"
+#include "assocdata.h"
+
+namespace protlib 
+{
+/** this struct conatains parameters that determine 
+  * the behavior of listener and receiver threads in TPoverTCP
+  * @param port - port number for master listener thread (server port)
+  * @param sleep - time (in ms) that listener and receiver wait at a poll() call
+  * @param d - destination module, where internal message are sent
+  */
+struct TPoverTCPParam : public ThreadParam 
+{
+  /// constructor
+    TPoverTCPParam(unsigned short common_header_length,
+		 bool (*const getmsglength) (NetMsg& m, uint32& clen_bytes),
+		 port_t p,
+		 const char* threadname= "TPoverTCP",
+		 uint32 sleep = ThreadParam::default_sleep_time,
+		 bool debug_pdu = false,
+		 message::qaddr_t source = message::qaddr_transport,
+		 message::qaddr_t dest = message::qaddr_signaling,
+		 bool sendaborts = false,
+		 uint8 tos = 0x10) :
+    ThreadParam(sleep,threadname,1,1),
+       port(p),
+       debug_pdu(debug_pdu),
+       source(source),
+       dest(dest),
+       common_header_length(common_header_length),
+       getmsglength(getmsglength),
+       terminate(false),
+       ip_tos(tos)
+        {};
+
+
+  /// port to bind master listener thread to
+  const port_t port;
+  bool debug_pdu;
+  /// message source
+  const message::qaddr_t source;
+  const message::qaddr_t dest;
+  /// what is the length of the common header
+  const unsigned short common_header_length;
+
+  /// function pointer to a function that figures out the msg length in number of 4 byte words
+  /// it returns false if error occured (e.g., malformed header), result is returned in variable clen_words
+  bool (*const getmsglength) (NetMsg& m, uint32& clen_words);
+
+  /// should master thread terminate?
+  const bool terminate;
+  const uint8 ip_tos;
+}; // end TPoverUDPParam
+
+
+/// TP over TCP
+/** This class implements the TP interface using TCP. */
+class TPoverTCP : public TP, public Thread 
+{
+/***** inherited from TP *****/
+public:
+  /// sends a network message, spawns receiver thread if necessary
+  virtual void send(NetMsg* msg,const address& addr, bool use_existing_connection);
+  virtual void terminate(const address& addr);
+  
+  /***** inherited from Thread *****/
+public:
+  /// main loop
+  virtual void main_loop(uint32 nr);
+  
+/***** other members *****/
+public:
+  /// constructor
+  TPoverTCP(const TPoverTCPParam& p) :
+    TP(tsdb::get_tcp_id(),"tcp",p.name,p.common_header_length,p.getmsglength),
+    Thread(p), tpparam(p), already_aborted(false), msgqueue(NULL), debug_pdu(p.debug_pdu)
+  { 
+    // perform some initializing actions
+    // currently not required (SCTP had to init its library)
+    init= true; ///< init done;
+  }
+  /// virtual destructor
+  virtual ~TPoverTCP();
+  
+  typedef
+  struct receiver_thread_arg
+  {
+    const AssocData* peer_assoc;
+    bool sig_terminate;
+    bool terminated;
+  public:
+    receiver_thread_arg(const AssocData* peer_assoc) : 
+      peer_assoc(peer_assoc), sig_terminate(false), terminated(true) {};
+  } receiver_thread_arg_t;
+  
+  class receiver_thread_start_arg_t
+  {
+  public:
+    TPoverTCP* instance;
+    receiver_thread_arg_t* rtargp;
+    
+    receiver_thread_start_arg_t(TPoverTCP* instance, receiver_thread_arg_t* rtargp) :
+      instance(instance), rtargp(rtargp) {};
+  };
+
+  class sender_thread_start_arg_t
+  {
+  public:
+    TPoverTCP* instance;
+    FastQueue* sender_thread_queue;
+    
+    sender_thread_start_arg_t(TPoverTCP* instance, FastQueue* sq) :
+      instance(instance), sender_thread_queue(sq) {};
+  };
+  
+private:
+  /// returns already existing connection or establishes a new one
+  AssocData* get_connection_to(const appladdress& addr);
+
+  /// receiver thread for a specific socket
+  void sender_thread(void *argp);
+  
+  /// receiver thread for a specific socket
+  void receiver_thread(void *argp);
+
+  /// send a message to the network via TCP
+  void tcpsend(NetMsg* msg, appladdress* addr);
+  
+  /// sender thread starter for a specific socket
+  static void* sender_thread_starter(void *argp);
+
+  /// receiver thread starter for a specific socket
+  static void* receiver_thread_starter(void *argp);
+  
+  /// a static starter method to invoke the actual main listener
+  static void* master_listener_thread_starter(void *argp);
+  
+  /// main listener thread procedure
+  void master_listener_thread();
+  
+  // create and start new sender thread
+  void create_new_sender_thread(FastQueue* senderqueue);
+
+  // create and start new receiver thread
+  void create_new_receiver_thread(AssocData* peer_assoc);
+  
+  /// terminates particular thread
+  void stop_receiver_thread(AssocData* peer_assoc);
+
+  /// cleans up thread management structures
+  void cleanup_receiver_thread(AssocData* peer_assoc);
+
+  /// terminates a sender thread
+  void terminate_sender_thread(const AssocData* assoc);
+  
+  /// terminates all active receiver or sender threads
+  void terminate_all_threads();
+  
+  /// ConnectionMap instance for keeping track of all existing connections
+  ConnectionMap connmap;
+  
+  /// store per receiver thread arguments, e.g. for signaling termination
+  typedef hash_map<pthread_t, receiver_thread_arg_t*> recv_thread_argmap_t;
+  recv_thread_argmap_t  recv_thread_argmap;
+
+  /// store sender thread related information
+  typedef hash_map<appladdress, FastQueue*> sender_thread_queuemap_t;
+  sender_thread_queuemap_t  senderthread_queuemap;
+  
+  /// parameters for main TPoverTCP thread
+  const TPoverTCPParam tpparam;
+  
+  /// did we already abort at thread shutdown
+  bool already_aborted;
+  /// message queue
+  FastQueue* msgqueue;
+  
+  bool debug_pdu;
+}; // end class TPoverTCP
+
+/** A simple internal message for selfmessages
+ * please note that carried items may get deleted after use of this message 
+ * the message destructor does not delete any item automatically
+ */
+class TPoverTCPMsg : public message 
+{
+ public:
+  // message type start/stop thread, send data
+  enum msg_t { start, 
+	       stop,
+	       send_data
+  };
+
+ private:
+  const AssocData* peer_assoc;
+  const TPoverTCPMsg::msg_t type;
+  NetMsg* netmsg;
+  appladdress* addr;
+
+public:
+  TPoverTCPMsg(const AssocData* peer_assoc, message::qaddr_t source= qaddr_unknown, TPoverTCPMsg::msg_t type= stop) : 
+    message(type_transport, source), peer_assoc(peer_assoc), type(type), netmsg(0), addr(0)  {}
+
+  TPoverTCPMsg(NetMsg* netmsg, appladdress* addr, message::qaddr_t source= qaddr_unknown) : 
+    message(type_transport, source), peer_assoc(0), type(send_data), netmsg(netmsg), addr(addr) {}
+
+  const AssocData* get_peer_assoc() const { return peer_assoc; }
+  TPoverTCPMsg::msg_t get_msgtype() const { return type; }
+  NetMsg* get_netmsg() const { return netmsg; }
+  appladdress* get_appladdr() const { return addr; } 
+};
+
+} // end namespace protlib
+
+#endif
Index: /source/ariba/utility/transport/tcpip/protlib/tp_over_udp.cpp
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/tp_over_udp.cpp	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/tp_over_udp.cpp	(revision 5284)
@@ -0,0 +1,627 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file tp_over_udp.cpp
+/// UDP-based transport module
+/// ----------------------------------------------------------
+/// $Id: tp_over_udp.cpp 2872 2008-02-18 10:58:03Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/src/tp_over_udp.cpp $
+// ===========================================================
+//
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+
+extern "C"
+{
+  //#define _SOCKADDR_LEN    /* use BSD 4.4 sockets */
+#include <unistd.h>		/* gethostname */
+#include <sys/types.h>		/* network socket interface */
+#include <netinet/ip.h>         /* iphdr */
+#include <netinet/ip6.h>        /* ip6_hdr */
+#include <netinet/in.h>		/* network socket interface */
+#include <netinet/tcp.h>	/* for TCP Socket Option */
+#include <netinet/udp.h>	/* for UDP header */
+#include <sys/socket.h>
+#include <arpa/inet.h>		/* inet_addr */
+
+#include <fcntl.h>
+#include <sys/poll.h>
+}
+
+#include <iostream>
+#include <errno.h>
+#include <string>
+#include <sstream>
+
+#include "tp_over_udp.h"
+#include "threadsafe_db.h"
+#include "cleanuphandler.h"
+#include "setuid.h"
+#include "logfile.h"
+#include "linux/netfilter.h"
+
+#include <set>
+
+#define UDP_SUCCESS 0
+#define UDP_SEND_FAILURE 1
+
+#define BUFSIZE 2048000
+
+
+const unsigned int max_listen_queue_size = 10;
+
+namespace protlib
+{
+
+  using namespace log;
+
+/** @defgroup tpudp TP over UDP
+ * @ingroup network
+ * @{
+ */
+
+char in6_addrstr_loc[INET6_ADDRSTRLEN+1];
+
+/******* class TPoverUDP *******/
+
+
+/** generates an internal TPoverUDP message to send a NetMsg to the network
+ *
+ *  - the sending thread will call TPoverUDP::udpsend()
+ *  - since UDP is connectionless we can safely ignore the use_existing_connection attribute
+ *  @note the netmsg is deleted by the send() method when it is not used anymore
+ */
+void TPoverUDP::send (NetMsg * netmsg, const address & in_addr, bool use_existing_connection)
+{
+
+  appladdress* addr = NULL;
+  addr= dynamic_cast<appladdress*>(in_addr.copy());
+
+  if (!addr) return;
+
+  // Do it independently from master thread
+  udpsend(netmsg, addr);
+
+}
+
+/** sends a NetMsg to the network.
+ *
+ * @param netmsg   message to send
+ * @param addr     transport endpoint address
+ *
+ * @note           both parameters are deleted after the message was sent
+ */
+void
+TPoverUDP::udpsend (NetMsg * netmsg, appladdress * addr)
+{
+#ifndef _NO_LOGGING
+  const char *const thisproc = "sender   - ";
+#endif
+
+  // set result initially to success, set it to failure
+  // in places where these failures occur
+  int result = UDP_SUCCESS;
+  int ret = 0;
+
+
+  if (addr)
+    check_send_args (*netmsg, *addr);
+  else
+    {
+      ERRCLog (tpparam.name, thisproc << "address pointer is NULL");
+      result = UDP_SEND_FAILURE;
+      throw TPErrorInternal();
+    }
+
+
+  addr->convert_to_ipv6();
+  in6_addr ip6addr;
+
+  //convert to v4-mapped address if necessary! (we use dual-stack IPv4/IPv6 socket)
+  addr->get_ip(ip6addr);
+
+
+  // *********************************** revised socket code *********************************
+
+
+  // msghdr for sendmsg
+  struct msghdr header;
+
+  // pointer for ancillary data
+  struct cmsghdr *ancillary = NULL;
+
+  // iovec for sendmsg
+  struct iovec iov;
+  iov.iov_base = netmsg->get_buffer();
+  iov.iov_len = netmsg->get_size();
+
+  // destination address
+  struct sockaddr_in6 dest_address;
+  dest_address.sin6_family= AF_INET6;
+  dest_address.sin6_port  = htons(addr->get_port());
+  dest_address.sin6_addr  = ip6addr;
+  dest_address.sin6_flowinfo = 0;
+  dest_address.sin6_scope_id = 0;
+
+  // fill msghdr
+  header.msg_iov = &iov;
+  header.msg_iovlen = 1;
+  header.msg_name = &dest_address;
+  header.msg_namelen=sizeof(dest_address);
+  header.msg_control=NULL;
+  header.msg_controllen=0;
+
+
+  // pktinfo
+  in6_pktinfo pktinfo;
+
+  //addr->set_if_index(1);
+
+
+  // we have to add up to 2 ancillary data objects (for interface and hop limit)
+
+  uint32 buflength = 0;
+  if (addr->get_if_index()) {
+    buflength = CMSG_SPACE(sizeof(pktinfo));
+    //cout << "PKTINFO data object, total buffer size: " << buflength << "byte" << endl;
+  }
+
+  int hlim = addr->get_ip_ttl();
+
+  if (hlim) {
+    buflength = buflength + CMSG_SPACE(sizeof(int));
+    //cout << "HOPLIMIT data object, total buffer size: " << buflength << "byte" << endl;
+  }
+  // create the buffer
+  if ((addr->get_if_index()) || hlim) {
+    header.msg_control = malloc(buflength);
+    if (header.msg_control == 0)
+      ERRCLog(tpparam.name, thisproc << " malloc failed for ancillary data of size " << buflength);
+  }
+
+  // are we to set the outgoing interface?
+  if (addr->get_if_index()) {
+
+    DLog(tpparam.name, thisproc << " UDP send via Interface " << addr->get_if_index() << " requested.");
+
+    // first cmsghdr at beginning of buffer
+    ancillary = (cmsghdr*) header.msg_control;
+
+    ancillary->cmsg_level=IPPROTO_IPV6;
+    ancillary->cmsg_type=IPV6_PKTINFO;
+    ancillary->cmsg_len=CMSG_LEN(sizeof(pktinfo));
+
+    //cout << "Set up properties of ancillary data object 1" << endl;
+
+    pktinfo.ipi6_addr = in6addr_any;
+    pktinfo.ipi6_ifindex = addr->get_if_index();
+
+    memcpy (CMSG_DATA(ancillary), &pktinfo, sizeof(pktinfo));
+
+    //cout << "Set up data of ancillary data object 1" << endl;
+
+    // update msghdr controllen
+    header.msg_controllen = CMSG_SPACE(sizeof(pktinfo));
+
+  }
+
+  // should we set an explicit Hop Limit?
+  if (hlim) {
+    DLog(tpparam.name, thisproc << " UDP send with IP TTL of " << hlim << " requested.");
+
+    // second cmsghdr after first one
+    cmsghdr* ancillary2 = NULL;
+
+    if (ancillary) {
+      ancillary2 = (cmsghdr*) (ancillary + CMSG_SPACE(sizeof(pktinfo)));
+    } else {
+      ancillary2 = (cmsghdr*) header.msg_control;
+    }
+
+    ancillary2->cmsg_level=IPPROTO_IPV6;
+    ancillary2->cmsg_type=IPV6_HOPLIMIT;
+    ancillary2->cmsg_len = CMSG_LEN(sizeof(int));
+
+    memcpy(CMSG_DATA(ancillary2), &hlim, sizeof(int));
+
+    // update msghdr controllen
+    header.msg_controllen = header.msg_controllen + ancillary2->cmsg_len;
+
+  }
+
+#ifndef _NO_LOGGING
+  uint32 msgsize = netmsg->get_size();	// only used for logging below
+#endif
+
+  // check whether socket is already up and initialized by listener thread
+  // otherwise we may have a race condition, i.e., trying to send before socket is created
+  // FIXME: it may be the case that the socket is already created, but not bound
+  //        I'm not sure what happens, when we try to send...
+  while (master_listener_socket == -1)
+  {
+    const unsigned int sleeptime= 1;
+    DLog(tpparam.name, "socket not yet ready for sending - sending deferred (" << sleeptime << " s)");
+    sleep(sleeptime);
+    DLog(tpparam.name, "retrying to send");
+  }
+  // reset IP RAO option
+  ret = setsockopt(master_listener_socket, SOL_IP, IP_OPTIONS, 0, 0);
+  if ( ret != 0 )
+    ERRLog(tpparam.name, "unsetting IP options for IPv4 failed");
+
+  // send UDP packet
+  DLog(tpparam.name, "SEND to " << *addr);
+  ret= sendmsg(master_listener_socket,&header,MSG_DONTWAIT);
+
+  if (ret<0)
+    ERRCLog(tpparam.name, "Socket Send failed! - error (" << errno << "):" << strerror(errno));
+  if (debug_pdu)
+    {
+      ostringstream hexdump;
+      netmsg->hexdump (hexdump);
+      Log (DEBUG_LOG, LOG_NORMAL, tpparam.name,
+	   "PDU debugging enabled - Sent:" << hexdump.str ());
+    }
+
+  if (ret < 0)
+    {
+      result = UDP_SEND_FAILURE;
+      //    break;
+    } // end if (ret < 0)
+
+
+      // *** note: netmsg is deleted here ***
+  delete netmsg;
+
+
+  // Throwing an exception within a critical section does not
+  // unlock the mutex.
+
+  if (result != UDP_SUCCESS)
+    {
+      ERRLog(tpparam.name, thisproc << "UDP error, returns " << ret << ", error : " << strerror (errno));
+      delete addr;
+
+      throw TPErrorSendFailed();
+
+    }
+  else
+    Log (EVENT_LOG, LOG_NORMAL, tpparam.name,
+	 thisproc << ">>----Sent---->> message (" << msgsize <<
+	 " bytes) using socket " << master_listener_socket << " to " << *addr);
+
+  // *** delete address ***
+  delete addr;
+} // end TPoverUDP::udpsend
+
+
+
+/**
+ * IPv4 catcher thread starter:
+ * just a static starter method to allow starting the
+ * actual master_listener_thread() method.
+ *
+ * @param argp - pointer to the current TPoverUDP object instance
+ */
+void *
+TPoverUDP::listener_thread_starter (void *argp)
+{
+  // invoke listener thread method
+  if (argp != 0)
+    {
+	(static_cast < TPoverUDP * >(argp))->listener_thread ();
+    }
+  return 0;
+}
+
+
+
+
+
+/**
+ * UDP master receiver thread: waits for incoming connections at the well-known udp port
+ *
+ */
+void TPoverUDP::listener_thread ()
+{
+  // create a new address-structure for the listening masterthread
+  struct sockaddr_in6 own_address;
+  own_address.sin6_family = AF_INET6;
+  own_address.sin6_flowinfo= 0;
+  own_address.sin6_port = htons(tpparam.port); // use port number in param structure
+  // accept incoming connections on all interfaces
+  own_address.sin6_addr = in6addr_any;
+  own_address.sin6_scope_id= 0;
+
+  // create a listening socket
+  master_listener_socket= socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+  if (master_listener_socket == -1)
+    {
+      ERRCLog(tpparam.name, "Could not create a new socket, error: " << strerror(errno));
+      return;
+    }
+
+  int socketreuseflag= 1;
+  int status= setsockopt(master_listener_socket,
+			 SOL_SOCKET,
+			 SO_REUSEADDR,
+			 (const char *) &socketreuseflag,
+			 sizeof(socketreuseflag));
+  if (status)
+  {
+    ERRCLog(tpparam.name, "Could not set socket option SO_REUSEADDR:" << strerror(errno));
+  }
+
+  // TODO: insert multicast socket options/calls here
+
+  // bind the newly created socket to a specific address
+  int bind_status = bind(master_listener_socket,
+			 reinterpret_cast<struct sockaddr *>(&own_address),
+			 sizeof(own_address));
+  if (bind_status)
+    {
+      ERRCLog(tpparam.name, "Binding to "
+	  << inet_ntop(AF_INET6, &own_address.sin6_addr, in6_addrstr_loc, INET6_ADDRSTRLEN)
+	  << " port " << tpparam.port << " failed, error: " << strerror(errno));
+      return;
+    }
+
+
+  // create a pollfd struct for use in the mainloop
+  struct pollfd poll_fd;
+  poll_fd.fd = master_listener_socket;
+  poll_fd.events = POLLIN | POLLPRI;
+  poll_fd.revents = 0;
+  /*
+    #define POLLIN	0x001	// There is data to read.
+    #define POLLPRI	0x002	// There is urgent data to read.
+    #define POLLOUT	0x004	// Writing now will not block.
+  */
+
+  bool terminate = false;
+  // check for thread terminate condition using get_state()
+  state_t currstate= get_state();
+  int poll_status= 0;
+  const unsigned int number_poll_sockets= 1;
+  struct sockaddr_in6 peer_address;
+  socklen_t peer_address_len;
+  // int conn_socket;
+
+  // check whether this thread is signaled for termination
+  while(! (terminate= (currstate==STATE_ABORT || currstate==STATE_STOP) ) )
+    {
+
+
+      // wait on number_poll_sockets (main drm socket)
+      // for the events specified above for sleep_time (in ms) tpparam.sleep_time
+      poll_status= poll(&poll_fd, number_poll_sockets, 250);
+      if (poll_fd.revents & POLLERR) // Error condition
+	{
+	  if (errno != EINTR)
+	    {
+	      ERRCLog(tpparam.name, "Poll caused error " << strerror(errno) << " - indicated by revents");
+	    }
+	  else
+	    {
+	      EVLog(tpparam.name, "poll(): " << strerror(errno));
+	    }
+
+	}
+      if (poll_fd.revents & POLLHUP) // Hung up
+	{
+	  ERRCLog(tpparam.name, "Poll hung up");
+	  return;
+	}
+      if (poll_fd.revents & POLLNVAL) // Invalid request: fd not open
+	{
+	  ERRCLog(tpparam.name, "Poll Invalid request: fd not open");
+	  return;
+	}
+
+      switch (poll_status)
+	{
+	case -1:
+	  if (errno != EINTR)
+	    {
+	      ERRCLog(tpparam.name, "Poll status indicates error: " << strerror(errno));
+	    }
+	  else
+	    {
+	      EVLog(tpparam.name, "Poll status: " << strerror(errno));
+	    }
+
+	  break;
+
+	case 0:
+#ifdef DEBUG_HARD
+	  Log(DEBUG_LOG,LOG_UNIMP, tpparam.name,
+	      "Listen Thread - Poll timed out after " << tpparam.sleep_time << " ms.");
+#endif
+	  currstate= get_state();
+	  continue;
+	  break;
+
+	default:
+#ifdef DEBUG_HARD
+	  Log(DEBUG_LOG,LOG_UNIMP, tpparam.name, "Poll: " << poll_status << " event(s) ocurred, of type " << poll_fd.revents);
+#endif
+	  break;
+	} // end switch
+
+
+
+      //if there is data to read, do it
+
+      if ((poll_fd.revents & POLLIN) || (poll_fd.revents & POLLPRI)) {
+
+
+	// in peer_address and the size of its address in addrlen
+	peer_address_len= sizeof(peer_address);
+
+	//Build us a NetMsg
+	NetMsg *netmsg=0;
+	netmsg = new NetMsg (NetMsg::max_size);
+
+
+
+	/// receive data from socket buffer (recv will not block)
+	int ret = recvfrom (master_listener_socket,
+			    netmsg->get_buffer (), NetMsg::max_size, 0, reinterpret_cast<struct sockaddr *>(&peer_address),
+			    &peer_address_len);
+
+	if (ret)
+	{
+	  DLog(tpparam.name, "Yankeedoo, we received " << ret << " bytes of DATA!!");
+
+	  // truncate netmsg buffer
+	  netmsg->truncate(ret);
+	}
+
+	/**************************************************************
+	 *  The following restrictions should apply:                  *
+	 *                                                            *
+	 *  This is UDP, messages are contained in ONE datagram       *
+	 *  datagrams CANNOT fragment, as otherwise TCP is used       *
+	 *  so we now build a TPMsg, send it to signaling and         *
+	 *  all should be well. At least until now.                   *
+	 **************************************************************/
+
+	// Build peer_adr and own_addr
+	appladdress* peer_addr = new appladdress;
+	peer_addr->set_ip(peer_address.sin6_addr);
+	peer_addr->set_port(peer_address.sin6_port);
+	appladdress* own_addr = new appladdress();
+
+	// Log the sender peer and write to peer_addr
+	char source_addr[INET6_ADDRSTRLEN+1];
+	inet_ntop(AF_INET6, &peer_address.sin6_addr, source_addr, INET6_ADDRSTRLEN);
+
+
+	peer_addr->set_port(htons(peer_address.sin6_port));
+	peer_addr->set_ip(peer_address.sin6_addr);
+	peer_addr->set_protocol(get_underlying_protocol());
+
+	DLog(tpparam.name, "Peer: [" << *peer_addr << "]");
+
+	// create TPMsg and send it to the signaling thread
+	//fprintf (stderr, "Before TPMsg creation\n");
+	TPMsg *tpmsg=
+	  new (nothrow) TPMsg (netmsg, peer_addr, own_addr);
+
+	Log (DEBUG_LOG, LOG_NORMAL, tpparam.name,
+	     "recvthread - receipt of GIST PDU now complete, sending msg#" << tpmsg->get_id() << " to signaling module");
+
+
+	if (tpmsg == NULL || !tpmsg->send(tpparam.source, tpparam.dest))
+	  {
+	    ERRLog(tpparam.name, "rcvthread" << "Cannot allocate/send TPMsg");
+	    if (tpmsg)
+	      delete tpmsg;
+	    if (netmsg)
+	      delete netmsg;
+
+	  }
+
+      }
+
+      // get new thread state
+      currstate= get_state();
+
+    } // end while(!terminate)
+
+  return;
+
+}
+
+
+TPoverUDP::~TPoverUDP ()
+{
+  init = false;
+
+  Log (DEBUG_LOG, LOG_NORMAL, tpparam.name, "Destructor called");
+
+}
+
+/** TPoverUDP Thread main loop.
+ * This loop checks for internal messages of either
+ * a send() call to start a new receiver thread, or,
+ * of a receiver_thread() that signals its own termination
+ * for proper cleanup of control structures.
+ *
+ * @param nr number of current thread instance
+ */
+void
+TPoverUDP::main_loop (uint32 nr)
+{
+
+  int pthread_status = 0;
+
+
+  // start UDP listener thread
+  pthread_t listener_thread_ID;
+  pthread_status = pthread_create (&listener_thread_ID, NULL,	//NULL: default attributes
+				   listener_thread_starter, this);
+  if (pthread_status)
+    {
+      ERRCLog(tpparam.name,
+	   "UDP listening thread could not be created: " <<
+	   strerror (pthread_status));
+    }
+  else
+
+    Log(INFO_LOG,LOG_NORMAL, tpparam.name, color[green] << "Listening at port #" << tpparam.port << color[off]);
+
+
+
+  // define max latency for thread reaction on termination/stop signal
+  state_t currstate = get_state ();
+
+  // check whether this thread is signaled for termination
+  while (currstate != STATE_ABORT && currstate != STATE_STOP)
+    {
+
+      // get thread state
+      currstate = get_state ();
+
+      sleep(4);
+
+    }				// end while
+
+  if (currstate == STATE_STOP)
+    {
+      // start abort actions
+      Log (INFO_LOG, LOG_NORMAL, tpparam.name,
+	   "Asked to abort, stopping all receiver threads");
+    }				// end if stopped
+
+  // do not accept any more messages
+  // terminate all receiver and sender threads that are still active
+  //terminate_all_threads ();
+}
+
+
+void
+TPoverUDP::terminate(const address& addr)
+{
+	// no connection oriented protocol, nothing to terminate
+}
+
+}				// end namespace protlib
+
+///@}
Index: /source/ariba/utility/transport/tcpip/protlib/tp_over_udp.h
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/tp_over_udp.h	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/tp_over_udp.h	(revision 5284)
@@ -0,0 +1,205 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file tp_over_udp.h
+/// Transport over UDP
+/// ----------------------------------------------------------
+/// $Id: tp_over_udp.h 2718 2007-07-24 03:23:14Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/tp_over_udp.h $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+/** @ingroup tpudp
+ * @ file
+ * TP over UDP
+ */
+
+#ifndef TP_OVER_UDP_H
+#define TP_OVER_UDP_H
+
+#include <ext/hash_map>
+
+#include "tp.h"
+#include "threads.h"
+#include "threadsafe_db.h"
+#include "connectionmap.h"
+#include "assocdata.h"
+
+namespace protlib 
+{
+/** this struct conatains parameters that determine 
+  * the behavior of listener and receiver threads in TPoverUDP
+  * @param port - port number for master listener thread (server port)
+  * @param sleep - time (in ms) that listener and receiver wait at a poll() call
+  * @param d - destination module, where internal message are sent
+  */
+struct TPoverUDPParam : public ThreadParam 
+{
+  /// constructor
+    TPoverUDPParam(
+		 unsigned short common_header_length,
+		 bool (*const getmsglength) (NetMsg& m, uint32& clen_words),
+		 port_t listen_port,
+		 uint32 sleep = ThreadParam::default_sleep_time,
+		 bool debug_pdu = false,
+		 message::qaddr_t source = message::qaddr_tp_over_udp,
+		 message::qaddr_t dest = message::qaddr_signaling,
+		 bool sendaborts = false,
+		 uint8 tos = 0x10) :
+    ThreadParam(sleep,"TPoverUDP",1,1),
+    port(listen_port),
+    debug_pdu(debug_pdu),
+    source(source),
+    dest(dest),
+    common_header_length(common_header_length),
+    getmsglength(getmsglength),
+    terminate(false),
+    ip_tos(tos)
+	{};
+
+    /// port to bind master listener thread to
+    const port_t port;
+    bool debug_pdu;
+    /// message source
+    const message::qaddr_t source;
+    const message::qaddr_t dest;
+    /// what is the length of the common header
+    const unsigned short common_header_length;
+    
+    /// function pointer to a function that figures out the msg length in number of 4 byte words
+    /// it returns false if error occured (e.g., malformed header), result is returned in variable clen_words
+    bool (*const getmsglength) (NetMsg& m, uint32& clen_words);
+    
+    /// should master thread terminate?
+    const bool terminate;
+    const uint8 ip_tos;
+    
+    bool (*rao_lookup) (uint32);
+    
+    
+}; // end TPoverUDPParam
+    
+
+/// TP over UDP
+/** This class implements the TP interface using UDP. */
+class TPoverUDP : public TP, public Thread 
+{
+/***** inherited from TP *****/
+public:
+  /// sends a network message, spawns receiver thread if necessary
+  virtual void send(NetMsg* msg, const address& addr, bool use_existing_connection);
+  virtual void terminate(const address& addr);
+  
+  /***** inherited from Thread *****/
+public:
+  /// main loop
+  virtual void main_loop(uint32 nr);
+  
+/***** other members *****/
+public:
+  /// constructor
+  TPoverUDP(const TPoverUDPParam& p) :
+    TP(tsdb::getprotobyname("udp"),"udp",p.name,p.common_header_length,p.getmsglength),
+    Thread(p), tpparam(p), already_aborted(false), msgqueue(NULL), debug_pdu(p.debug_pdu),
+    master_listener_socket(-1)
+  { 
+    // perform some initializing actions
+    // currently not required (SCTP had to init its library)
+    init= true; ///< init done;
+  }
+  /// virtual destructor
+  virtual ~TPoverUDP();
+
+  class sender_thread_start_arg_t
+  {
+  public:
+    TPoverUDP* instance;
+    FastQueue* sender_thread_queue;
+    
+    sender_thread_start_arg_t(TPoverUDP* instance, FastQueue* sq) :
+      instance(instance), sender_thread_queue(sq) {};
+  };
+
+  int get_listener_socket() const { return master_listener_socket; }
+  
+private:
+
+
+  /// send a message to the network via UDP
+  void udpsend(NetMsg* msg, appladdress* addr);
+  
+  /// a static starter method to invoke the listener thread
+  static void* listener_thread_starter(void *argp);
+
+  /// listener thread procedure
+  void listener_thread();
+
+  /// terminates all active receiver or sender threads
+  void terminate_all_threads();
+  
+  /// parameters for main TPoverUDP thread
+  const TPoverUDPParam tpparam;
+  
+  /// did we already abort at thread shutdown
+  bool already_aborted;
+  /// message queue
+  FastQueue* msgqueue;
+  
+  bool debug_pdu;
+
+  int master_listener_socket;
+
+}; // end class TPoverUDP
+
+/** A simple internal message for selfmessages
+ * please note that carried items may get deleted after use of this message 
+ * the message destructor does not delete any item automatically
+ */
+class TPoverUDPMsg : public message 
+{
+ public:
+  // message type start/stop thread, send data
+  enum msg_t { start, 
+	       stop,
+	       send_data
+  };
+
+ private:
+  const AssocData* peer_assoc;
+  const TPoverUDPMsg::msg_t type;
+  NetMsg* netmsg;
+  appladdress* addr;
+
+public:
+  TPoverUDPMsg(const AssocData* peer_assoc, message::qaddr_t source= qaddr_unknown, TPoverUDPMsg::msg_t type= stop) : 
+    message(type_transport, source), peer_assoc(peer_assoc), type(type), netmsg(0), addr(0)  {}
+
+  TPoverUDPMsg(NetMsg* netmsg, appladdress* addr, message::qaddr_t source= qaddr_unknown) : 
+    message(type_transport, source), peer_assoc(0), type(send_data), netmsg(netmsg), addr(addr) {}
+
+  const AssocData* get_peer_assoc() const { return peer_assoc; }
+  TPoverUDPMsg::msg_t get_msgtype() const { return type; }
+  NetMsg* get_netmsg() const { return netmsg; }
+  appladdress* get_appladdr() const { return addr; } 
+};
+
+} // end namespace protlib
+
+#endif
Index: /source/ariba/utility/transport/tcpip/protlib/tperror.h
===================================================================
--- /source/ariba/utility/transport/tcpip/protlib/tperror.h	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/protlib/tperror.h	(revision 5284)
@@ -0,0 +1,157 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file tperror.h
+/// Errors from TP module
+/// ----------------------------------------------------------
+/// $Id: tperror.h 2794 2007-09-05 12:01:22Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/tperror.h $
+// ===========================================================
+//                      
+// Copyright (C) 2005-2007, all rights reserved by
+// - Institute of Telematics, Universitaet Karlsruhe (TH)
+//
+// More information and contact:
+// https://projekte.tm.uka.de/trac/NSIS
+//                      
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// ===========================================================
+/** @ingroup transport
+ * This is the interface for sending network messages over a transport 
+ * protocol. You can receive messages through queues.
+ */
+
+#ifndef _PROTLIB__TP_ERROR_H_
+#define _PROTLIB__TP_ERROR_H_
+
+#include <string.h>
+
+#include "protlib_types.h"
+
+namespace protlib {
+
+/** @addtogroup transport Transport Protocol
+ * @ingroup network
+ * @{
+ */
+
+/// Transport Protocol Error
+/** Reports a TP error while connection setup, sending a network message or initialization. */
+class TPError : public ProtLibException {
+public:
+	/// TP error codes
+	enum tp_error_t {
+	  TPERR_OK,           // everything ok
+	  TPERR_BAD_ADDRESS,  // Bad destination address
+	  TPERR_BAD_NETMSG,   // not used
+	  TPERR_ARGS_NOT_INIT,// arguments not initialized
+	  TPERR_UNREACHABLE,  // destination unreachable
+	  TPERR_INTERNAL,     // any other internal error
+	  TPERR_PAYLOAD,      // maximum payload
+	  TPERR_INITFAILED,   // Initialization failed, e.g. during socket setup 
+	  TPERR_SENDFAILED,   // send failure
+	  TPERR_CONNSETUPFAIL, // connection setup failed
+	  TPERR_CLOSEIND,       // close indication (other side closed connection)
+	  TPERR_ABORTIND      // abort indication (transport protocol)
+	}; // end tp_error_t
+
+	/// constructor
+        TPError(tp_error_t e) : errtype(e) {};
+
+	/// get error string
+	virtual const char* getstr() const= 0;
+	virtual const char *what() const throw() { return getstr(); }
+	/// error code
+	const tp_error_t errtype;
+}; // end class TPError
+
+
+/***** class TPError *****/
+
+class TPErrorBadDestAddress : public TPError
+{
+public:
+  TPErrorBadDestAddress() : TPError(TPError::TPERR_BAD_ADDRESS) {}
+  virtual const char* getstr() const {  return "Bad Destination Address"; }
+};
+
+
+class TPErrorArgsNotInit : public TPError 
+{
+public:
+  TPErrorArgsNotInit() : TPError(TPError::TPERR_ARGS_NOT_INIT) {}
+  virtual const char* getstr() const {  return "arguments of TPMsg not initialized"; }
+};
+
+class TPErrorUnreachable : public TPError 
+{
+public:
+  TPErrorUnreachable() : TPError(TPError::TPERR_UNREACHABLE) {}
+  virtual const char* getstr() const {  return "Destination unreachable"; }
+};
+
+class TPErrorInternal : public TPError 
+{
+public:
+  TPErrorInternal() : TPError(TPError::TPERR_INTERNAL) {}
+  virtual const char* getstr() const {  return "Internal Transport Protocol Error"; }
+};
+
+
+class TPErrorPayload : public TPError 
+{
+public:
+  TPErrorPayload() : TPError(TPError::TPERR_PAYLOAD) {}
+  virtual const char* getstr() const {  return "Payload exceeds maximum transmission unit or empty payload given"; }
+};
+
+class TPErrorInitFailed : public TPError 
+{
+public:
+  TPErrorInitFailed() : TPError(TPError::TPERR_INITFAILED) {}
+  virtual const char* getstr() const {  return "Initialization of protocol failed"; }
+};
+
+class TPErrorSendFailed : public TPError 
+{
+  int saved_errno; ///< value of errno from send call
+public:
+  TPErrorSendFailed(int current_errno= 0) : TPError(TPError::TPERR_SENDFAILED), saved_errno(current_errno) {}
+  virtual const char* getstr() const {  return "Failure while trying to send a protocol data unit"; }
+  int get_reason() const { return saved_errno; } ///< returns saved value of errno from send call
+};
+
+class TPErrorConnectSetupFail : public TPError 
+{
+public:
+  TPErrorConnectSetupFail() : TPError(TPError::TPERR_CONNSETUPFAIL) {}
+  virtual const char* getstr() const {  return "Connection Setup Failure"; }
+};
+
+class TPErrorCloseInd : public TPError 
+{
+public:
+  TPErrorCloseInd() : TPError(TPError::TPERR_CLOSEIND) {}
+  virtual const char* getstr() const {  return "Other side closed connection"; }
+};
+
+class TPErrorAbortInd : public TPError 
+{
+public:
+  TPErrorAbortInd() : TPError(TPError::TPERR_ABORTIND) {}
+  virtual const char* getstr() const {  return "Abort indication, transport protocol indicated failure/abort"; }
+};
+
+} // end namespace protlib
+
+#endif // _PROTLIB__TP_ERROR_H_
Index: /source/ariba/utility/transport/tcpip/tcpip.cpp
===================================================================
--- /source/ariba/utility/transport/tcpip/tcpip.cpp	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/tcpip.cpp	(revision 5284)
@@ -0,0 +1,205 @@
+#include "tcpip.hpp"
+
+#define _NO_LOGGING
+
+// std includes
+#include <unistd.h>
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <boost/foreach.hpp>
+
+// protlib includes
+#include "protlib/network_message.h"
+#include "protlib/tp_over_tcp.h"
+#include "protlib/tperror.h"
+#include "protlib/logfile.h"
+#include "protlib/queuemanager.h"
+#include "protlib/threadsafe_db.h"
+#include "protlib/setuid.h"
+
+// protlib namespaces
+using namespace protlib;
+using namespace protlib::log;
+
+logfile commonlog;
+protlib::log::logfile& protlib::log::DefaultLog(commonlog);
+
+namespace ariba {
+namespace transport {
+
+using namespace ariba::addressing;
+
+
+tcpip_endpoint convert( const appladdress* addr ) {
+	const char* ip_str = addr->get_ip_str();
+	tcpip_endpoint endpoint( std::string(ip_str), addr->get_port() );
+	return endpoint;
+}
+
+appladdress convert( const tcpip_endpoint& endpoint ) {
+	tcpip_endpoint* e = const_cast<tcpip_endpoint*>(&endpoint);
+	appladdress
+		peer(e->address().to_string().c_str(), "tcp", e->port().asio() );
+//	cout << endpoint.to_string() << " to " << peer.get_ip_str() << ":" << peer.get_port() << endl;
+	return peer;
+}
+
+tcpip::tcpip( uint16_t port ) {
+	this->done = false;
+	this->running = false;
+	this->port = port;
+	this->listener = NULL;
+}
+
+tcpip::~tcpip() {
+
+}
+
+bool get_message_length( NetMsg& m, uint32& clen_bytes ) {
+	clen_bytes = m.decode32();
+	m.set_pos_r(-4);
+	return true;
+}
+
+void tcpip::start() {
+	done = false;
+	running = false;
+
+	// initalize netdb and setuid
+	protlib::tsdb::init();
+	protlib::setuid::init();
+
+	// set tcp parameters
+	port_t port = this->port; // port
+	TPoverTCPParam tppar(4, get_message_length, port);
+
+	// create receiver thread
+	FastQueue* tpchecker_fq = new FastQueue("TCPTransport", true);
+	QueueManager::instance()->register_queue(tpchecker_fq,
+			message::qaddr_signaling);
+
+	// start thread
+	pthread_create( &tpreceivethread, NULL, tcpip::receiverThread, this );
+	tpthread = new ThreadStarter<TPoverTCP, TPoverTCPParam> ( 1, tppar );
+	tpthread->start_processing();
+}
+
+void tcpip::stop() {
+	// stop receiver thread
+	done = true;
+
+	// stop TPoverTCP
+	tpthread->stop_processing();
+	tpthread->abort_processing(true);
+	tpthread->wait_until_stopped();
+
+	// unregister TPoverTCP
+	QueueManager::instance()->unregister_queue( message::qaddr_signaling );
+
+	// destroy QueueManager
+	QueueManager::clear();
+
+	// de-initalize netdb and setuid
+	protlib::setuid::end();
+	protlib::tsdb::end();
+}
+
+void tcpip::send( const address_v* remote, const uint8_t* data, size_t size ) {
+
+	// prepare netmsg with length and and port
+	NetMsg* datamsg = new NetMsg(size + 6);
+	datamsg->encode32( size + 2,  true );
+	datamsg->encode16( this->port,true );
+
+	for (size_t i=0; i<size; i++)
+		datamsg->encode8( data[i],true );
+
+	// send message
+	tcpip_endpoint endpoint = *remote;
+	appladdress peer = convert(endpoint);
+
+	// add to output queue
+	tpthread->get_thread_object()->send( datamsg, peer, false );
+}
+
+void tcpip::send( const endpoint_set& endpoints, const uint8_t* data, size_t size ) {
+	// send a message to each combination of ip-address and port
+	BOOST_FOREACH( const ip_address ip, endpoints.ip ) {
+		BOOST_FOREACH( const tcp_port_address port, endpoints.tcp ) {
+			tcpip_endpoint endpoint(ip,port);
+			address_vf vf = endpoint;
+			send(vf,data,size);
+		}
+	}
+}
+
+void tcpip::terminate(const address_v* local, const address_v* remote) {
+	tcpip_endpoint endpoint = *remote;
+	appladdress peer = convert(endpoint);
+	peer.convert_to_ipv6();
+	tpthread->get_thread_object()->terminate( peer );
+}
+
+void tcpip::register_listener( transport_listener* listener ) {
+	this->listener = listener;
+}
+
+void* tcpip::receiverThread( void* ptp ) {
+	// get reference to transport object
+	tcpip& tp = *((tcpip*)ptp);
+
+	// get queue
+	FastQueue* fq =
+		QueueManager::instance()->get_queue(message::qaddr_signaling);
+
+	// main processing loop
+	tp.running = true;
+	while (!tp.done) {
+
+		// wait for new message to approach
+		message* msg = fq->dequeue_timedwait(300);
+
+		// message has arrived? no-> continue
+		if (!msg) continue;
+
+		// handle transport message
+		TPMsg* tpmsg = dynamic_cast<TPMsg*> (msg);
+		if (!tpmsg) continue;
+
+		// get address & message
+		const appladdress* remote_peer = static_cast<const appladdress*>( tpmsg->get_peeraddress() );
+		const appladdress* local_peer  = static_cast<const appladdress*>( tpmsg->get_ownaddress() );
+		NetMsg* datamsg = tpmsg->get_message();
+
+		// not a data message? -> continue!
+		if (!datamsg) continue;
+
+		// get length and remote endpoint port
+		datamsg->set_pos(0);
+		uint32_t message_size = datamsg->decode32(true)-2;
+		uint16_t remote_port = datamsg->decode16(true);
+
+
+		// inform listener
+		if (tp.listener != NULL) {
+			tcpip_endpoint remote = convert(remote_peer);
+			tcpip_endpoint local  = convert(local_peer);
+
+// DO NOT SET REMOTE PORT!
+//			remote.port() = remote_port;
+//			cout << "received: remote="
+//				 << remote.to_string()
+//               << " local="
+// 				 << local.to_string() << " size=" << message_size << endl;
+			tp.listener->receive_message(
+					&tp, local, remote, datamsg->get_buffer()+6, message_size );
+		}
+	}
+	// clean queue & stop
+	fq->cleanup();
+	tp.running = false;
+	return NULL;
+}
+
+}} // namespace ariba::transport
Index: /source/ariba/utility/transport/tcpip/tcpip.hpp
===================================================================
--- /source/ariba/utility/transport/tcpip/tcpip.hpp	(revision 5284)
+++ /source/ariba/utility/transport/tcpip/tcpip.hpp	(revision 5284)
@@ -0,0 +1,47 @@
+#ifndef TCPIP_HPP_
+#define TCPIP_HPP_
+
+#include "../transport.hpp"
+#include <pthread.h>
+
+// forward declaration
+namespace protlib {
+template<class X, class Y>
+class ThreadStarter;
+class TPoverTCP;
+class TPoverTCPParam;
+}
+
+namespace ariba {
+namespace transport {
+
+using namespace protlib;
+
+/**
+ * TODO: Doc
+ *
+ * @author Sebastian Mies <mies@tm.uka.de>
+ */
+class tcpip : public transport_protocol {
+public:
+	tcpip( uint16_t port );
+	virtual ~tcpip();
+	virtual void start();
+	virtual void stop();
+	virtual void send( const address_v* remote, const uint8_t* data, size_t size );
+	virtual void send( const endpoint_set& endpoints, const uint8_t* data, size_t size );
+	virtual void terminate( const address_v* local, const address_v* remote );
+	virtual void register_listener( transport_listener* listener );
+
+private:
+	volatile bool done, running;
+	uint16_t port;
+	pthread_t tpreceivethread;
+	ThreadStarter<TPoverTCP, TPoverTCPParam>* tpthread;
+	static void* receiverThread( void* ptp );
+	transport_listener* listener;
+};
+
+}} // namespace ariba::transport
+
+#endif /* TCPIP_HPP_ */
Index: /source/ariba/utility/transport/test_transport.hpp
===================================================================
--- /source/ariba/utility/transport/test_transport.hpp	(revision 5284)
+++ /source/ariba/utility/transport/test_transport.hpp	(revision 5284)
@@ -0,0 +1,82 @@
+// test_transport.hpp, created on 01.07.2009 by Sebastian Mies
+
+#ifndef TEST_TRANSPORT_HPP_
+#define TEST_TRANSPORT_HPP_
+
+#include "transport_peer.hpp"
+#include "transport_listener.hpp"
+
+#include "rfcomm/rfcomm.hpp"
+
+#include <iostream>
+#include <string>
+#include <sys/types.h>
+#include <unistd.h>
+
+namespace ariba {
+namespace transport {
+namespace detail {
+
+using namespace std;
+using namespace ariba::transport;
+using namespace ariba::addressing;
+
+class listener : public transport_listener {
+public:
+	virtual void receive_message(
+		transport_protocol* transport,
+		const address_vf local, const address_vf remote,
+		const uint8_t* data, size_t size
+	) {
+		cout << "transport_listener: " << endl;
+		cout << "received message data='" << data << "' local=" << local->to_string() << " remote=" << remote->to_string() << endl;
+	}
+};
+
+void test_transport_process( endpoint_set& local, endpoint_set& remote ) {
+	cout << "started " << local.to_string() << endl;
+	transport_peer* peer = new transport_peer( local );
+	peer->register_listener( new listener() );
+	peer->start();
+	peer->send( remote, (uint8_t*)"Hello!", 7 );
+	getchar();
+}
+
+/**
+ * TODO: Doc
+ *
+ * @author Sebastian Mies <mies@tm.uka.de>
+ */
+void tcp_test() {
+
+	endpoint_set local  = string("tcp{5001};ip{127.0.0.1 | 2001:638:204:6:216:d3ff:fece:1070}");
+	endpoint_set remote = string("tcp{5002};ip{127.0.0.1 | 2001:638:204:6:216:d3ff:fece:1070}");
+
+	pid_t pID = fork();
+	if (pID < 0) {
+		cerr << "Failed to fork" << endl;
+	} else
+	if (pID == 0) {
+		test_transport_process(local,remote);
+	} else {
+		getchar();
+		test_transport_process(remote,local);
+	}
+	getchar();
+}
+
+void bluetooth_test( string& endp_str ) {
+	cout << endp_str << endl;
+	rfcomm* rfc = new rfcomm( 3 );
+	rfc->register_listener( new listener() );
+	rfc->start();
+	if (endp_str.size()!=0) {
+		rfcomm_endpoint endp = endp_str;
+		rfc->send( endp, (uint8_t*)"Hello!", 7 );
+	}
+	getchar();
+}
+
+}}} // namespace ariba::transport::detail
+
+#endif /* TEST_TRANSPORT_HPP_ */
Index: /source/ariba/utility/transport/transport.hpp
===================================================================
--- /source/ariba/utility/transport/transport.hpp	(revision 5284)
+++ /source/ariba/utility/transport/transport.hpp	(revision 5284)
@@ -0,0 +1,15 @@
+#ifndef TRANSPORT_HPP_
+#define TRANSPORT_HPP_
+
+// abstract classes
+#include "transport_protocol.hpp"
+#include "transport_listener.hpp"
+
+// transport protocol implementations
+#include "tcpip/tcpip.hpp"
+#include "rfcomm/rfcomm.hpp"
+
+// common transport peer using all known protocols
+#include "transport_peer.hpp"
+
+#endif /* TRANSPORT_HPP_ */
Index: /source/ariba/utility/transport/transport_listener.hpp
===================================================================
--- /source/ariba/utility/transport/transport_listener.hpp	(revision 5284)
+++ /source/ariba/utility/transport/transport_listener.hpp	(revision 5284)
@@ -0,0 +1,36 @@
+// transport_listener.hpp, created on 01.07.2009 by Sebastian Mies
+
+#ifndef TRANSPORT_LISTENER_HPP_
+#define TRANSPORT_LISTENER_HPP_
+
+#include "../addressing/addressing.hpp"
+
+// namespace ariba::transport
+namespace ariba {
+namespace transport {
+
+using namespace ariba::addressing;
+
+class transport_protocol;
+
+/**
+ * TODO: Doc
+ *
+ * @author Sebastian Mies <mies@tm.uka.de>
+ */
+class transport_listener {
+public:
+	/// called when a message is received
+	virtual void receive_message(
+		transport_protocol* transport,
+		const address_vf local, const address_vf remote,
+		const uint8_t* data, size_t size
+	) {
+		std::cout << "transport_listener: not implemented" << std::endl;
+	}
+};
+
+}} // namespace ariba::transport
+
+
+#endif /* TRANSPORT_LISTENER_HPP_ */
Index: /source/ariba/utility/transport/transport_peer.cpp
===================================================================
--- /source/ariba/utility/transport/transport_peer.cpp	(revision 5284)
+++ /source/ariba/utility/transport/transport_peer.cpp	(revision 5284)
@@ -0,0 +1,70 @@
+
+#include "transport_peer.hpp"
+#include "transport.hpp"
+
+// namespace ariba::transport
+namespace ariba {
+namespace transport {
+
+using namespace ariba::addressing;
+
+transport_peer::transport_peer( endpoint_set& local_set ) : local(local_set) {
+	// setup tcp transports
+	tcp = NULL;
+	cout << "#tcpip_transports = " << local.tcp.size() << endl;
+	if (local.tcp.size()==1) {
+		tcp = new tcpip(local.tcp.begin()->value());
+		cout << "Started tcpip_transport on port "  << local.tcp.begin()->value() << endl;
+	}
+	// setup rfcomm transports
+	rfc = NULL;
+	cout << "#rfcomm_transports = " << local.rfcomm.size() << endl;
+	if ( local.rfcomm.size() == 1 ) {
+		rfc = new rfcomm( local.rfcomm.begin()->value() );
+		cout << "Started rfcomm_transport on port "  << local.rfcomm.begin()->value() << endl;
+	}
+}
+
+transport_peer::~transport_peer() {
+	if (tcp !=NULL ) delete tcp;
+	if (rfc !=NULL ) delete rfc;
+}
+
+void transport_peer::start() {
+	if (tcp!=NULL) tcp->start();
+	if (rfc!=NULL) rfc->start();
+}
+
+void transport_peer::stop() {
+	if (tcp!=NULL) tcp->stop();
+	if (rfc!=NULL) rfc->stop();
+}
+
+void transport_peer::send( const address_v* remote, const uint8_t* data, size_t size ) {
+	if (remote->instanceof<tcpip_endpoint>() && tcp!=NULL) {
+		tcp->send(remote,data,size);
+	} else
+	if (remote->instanceof<rfcomm_endpoint>() && rfc!=NULL) {
+		rfc->send(remote,data,size);
+	} else
+		cerr << "Could not send message to " << remote->to_string() << endl;
+}
+
+void transport_peer::send( const endpoint_set& endpoints, const uint8_t* data, size_t size ) {
+	if (tcp!=NULL) tcp->send(endpoints,data,size);
+	if (rfc!=NULL) rfc->send(endpoints,data,size);
+}
+
+void transport_peer::terminate( const address_v* local, const address_v* remote ) {
+	if (remote->instanceof<tcpip_endpoint>() && tcp!=NULL)
+		tcp->terminate(local,remote);
+	if (remote->instanceof<rfcomm_endpoint>() && rfc!=NULL)
+		rfc->terminate(local,remote);
+}
+
+void transport_peer::register_listener( transport_listener* listener ) {
+	if (tcp!=NULL) tcp->register_listener(listener);
+	if (rfc!=NULL) rfc->register_listener(listener);
+}
+
+}} // namespace ariba::transport
Index: /source/ariba/utility/transport/transport_peer.hpp
===================================================================
--- /source/ariba/utility/transport/transport_peer.hpp	(revision 5284)
+++ /source/ariba/utility/transport/transport_peer.hpp	(revision 5284)
@@ -0,0 +1,42 @@
+#ifndef TRANSPORT_PEER_HPP_
+#define TRANSPORT_PEER_HPP_
+
+#include "transport_protocol.hpp"
+#include "../addressing/endpoint_set.hpp"
+
+// namespace ariba::transport
+namespace ariba {
+namespace transport {
+
+using namespace ariba::addressing;
+
+class tcpip;
+class rfcomm;
+
+/**
+ * TODO: Doc
+ *
+ * @author Sebastian Mies <mies@tm.uka.de>
+ */
+/// this transport peer allocates implemenations of various transport
+/// protocols and can sent message to an entire set of endpoints
+class transport_peer : public transport_protocol {
+public:
+	transport_peer( endpoint_set& local_set );
+	virtual ~transport_peer();
+	virtual void start();
+	virtual void stop();
+	virtual void send( const address_v* remote, const uint8_t* data, size_t size );
+	virtual void send( const endpoint_set& endpoints, const uint8_t* data, size_t size );
+	virtual void terminate( const address_v* local, const address_v* remote );
+	virtual void register_listener( transport_listener* listener );
+
+private:
+	endpoint_set&  local;
+	tcpip* tcp;
+	rfcomm* rfc;
+};
+
+}} // namespace ariba::transport
+
+#endif /* TRANSPORT_PEER_HPP_ */
Index: /source/ariba/utility/transport/transport_protocol.hpp
===================================================================
--- /source/ariba/utility/transport/transport_protocol.hpp	(revision 5284)
+++ /source/ariba/utility/transport/transport_protocol.hpp	(revision 5284)
@@ -0,0 +1,30 @@
+#ifndef TRANSPORT_PROTOCOL_HPP_
+#define TRANSPORT_PROTOCOL_HPP_
+
+#include "../addressing/addressing.hpp"
+#include "transport_listener.hpp"
+
+// namespace ariba::transport
+namespace ariba {
+namespace transport {
+
+using namespace ariba::addressing;
+
+/**
+ * TODO: Doc
+ *
+ * @author Sebastian Mies <mies@tm.uka.de>
+ */
+class transport_protocol {
+public:
+	virtual void start() = 0;
+	virtual void stop() = 0;
+	virtual void send( const address_v* remote, const uint8_t* data, size_t size ) = 0;
+	virtual void send( const endpoint_set& endpoints, const uint8_t* data, size_t size ) = 0;
+	virtual void terminate( const address_v* local, const address_v* remote ) = 0;
+	virtual void register_listener( transport_listener* listener ) = 0;
+};
+
+}} // namespace ariba::transport
+
+#endif /* TRANSPORT_PROTOCOL_HPP_ */
