Index: /trash/old-modules/_namespace.h
===================================================================
--- /trash/old-modules/_namespace.h	(revision 5641)
+++ /trash/old-modules/_namespace.h	(revision 5641)
@@ -0,0 +1,47 @@
+// [License]
+// The Ariba-Underlay Copyright
+//
+// Copyright (c) 2008-2009, Institute of Telematics, UniversitÃ€t Karlsruhe (TH)
+//
+// Institute of Telematics
+// UniversitÃ€t Karlsruhe (TH)
+// Zirkel 2, 76128 Karlsruhe
+// Germany
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The views and conclusions contained in the software and documentation
+// are those of the authors and should not be interpreted as representing
+// official policies, either expressed or implied, of the Institute of
+// Telematics.
+// [License]
+
+#undef NAMESPACE_BEGIN
+#undef NAMESPACE_END
+
+#define NAMESPACE_BEGIN \
+	namespace ariba { \
+	namespace communication {
+
+#define NAMESPACE_END \
+	}}
Index: /trash/old-modules/modules.h
===================================================================
--- /trash/old-modules/modules.h	(revision 5641)
+++ /trash/old-modules/modules.h	(revision 5641)
@@ -0,0 +1,60 @@
+// [License]
+// The Ariba-Underlay Copyright
+//
+// Copyright (c) 2008-2009, Institute of Telematics, UniversitÃ€t Karlsruhe (TH)
+//
+// Institute of Telematics
+// UniversitÃ€t Karlsruhe (TH)
+// Zirkel 2, 76128 Karlsruhe
+// Germany
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The views and conclusions contained in the software and documentation
+// are those of the authors and should not be interpreted as representing
+// official policies, either expressed or implied, of the Institute of
+// Telematics.
+// [License]
+
+#ifndef MODULES_H_
+#define MODULES_H_
+
+// network
+#include "network/NetworkProtocol.h"
+#include "network/NetworkLocator.h"
+#include "network/ip/IPv4Locator.h"
+#include "network/ip/IPv4NetworkProtocol.h"
+
+// transport
+#include "transport/TransportLocator.h"
+#include "transport/TransportProtocol.h"
+
+#ifdef UNDERLAY_OMNET
+  #include "ariba/communication/modules/transport/omnet/SpoVNetOmnetModule.h"
+  #include "ariba/communication/modules/network/omnet/OmnetNetworkProtocol.h"
+#else
+  #include "ariba/communication/modules/transport/tcp/TCPTransport.h"
+  #include "ariba/communication/modules/transport/tcp/TCPTransportLocator.h"
+#endif
+
+#endif /* MODULES_H_ */
Index: /trash/old-modules/network/NetworkLocator.cpp
===================================================================
--- /trash/old-modules/network/NetworkLocator.cpp	(revision 5641)
+++ /trash/old-modules/network/NetworkLocator.cpp	(revision 5641)
@@ -0,0 +1,49 @@
+// [License]
+// The Ariba-Underlay Copyright
+//
+// Copyright (c) 2008-2009, Institute of Telematics, UniversitÃ€t Karlsruhe (TH)
+//
+// Institute of Telematics
+// UniversitÃ€t Karlsruhe (TH)
+// Zirkel 2, 76128 Karlsruhe
+// Germany
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The views and conclusions contained in the software and documentation
+// are those of the authors and should not be interpreted as representing
+// official policies, either expressed or implied, of the Institute of
+// Telematics.
+// [License]
+
+#include "NetworkLocator.h"
+
+NAMESPACE_BEGIN;
+
+NetworkLocator::NetworkLocator() {
+}
+
+NetworkLocator::~NetworkLocator() {
+}
+
+NAMESPACE_END;
Index: /trash/old-modules/network/NetworkLocator.h
===================================================================
--- /trash/old-modules/network/NetworkLocator.h	(revision 5641)
+++ /trash/old-modules/network/NetworkLocator.h	(revision 5641)
@@ -0,0 +1,63 @@
+// [License]
+// The Ariba-Underlay Copyright
+//
+// Copyright (c) 2008-2009, Institute of Telematics, UniversitÃ€t Karlsruhe (TH)
+//
+// Institute of Telematics
+// UniversitÃ€t Karlsruhe (TH)
+// Zirkel 2, 76128 Karlsruhe
+// Germany
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The views and conclusions contained in the software and documentation
+// are those of the authors and should not be interpreted as representing
+// official policies, either expressed or implied, of the Institute of
+// Telematics.
+// [License]
+
+#ifndef NETWORKLOCATOR_H_
+#define NETWORKLOCATOR_H_
+
+#include <string>
+#include "ariba/utility/types/Locator.h"
+
+#include "../_namespace.h"
+NAMESPACE_BEGIN;
+
+using std::string;
+using ariba::utility::Locator;
+
+class NetworkLocator : public Locator {
+public:
+	NetworkLocator();
+	virtual ~NetworkLocator();
+
+	virtual bool operator==(const NetworkLocator& rh) const = 0;
+	virtual bool operator!=(const NetworkLocator& rh) const = 0;
+	virtual string toString() const = 0;
+};
+
+NAMESPACE_END;
+
+#endif /* NETWORKLOCATOR_H_ */
Index: /trash/old-modules/network/NetworkProtocol.cpp
===================================================================
--- /trash/old-modules/network/NetworkProtocol.cpp	(revision 5641)
+++ /trash/old-modules/network/NetworkProtocol.cpp	(revision 5641)
@@ -0,0 +1,49 @@
+// [License]
+// The Ariba-Underlay Copyright
+//
+// Copyright (c) 2008-2009, Institute of Telematics, UniversitÃ€t Karlsruhe (TH)
+//
+// Institute of Telematics
+// UniversitÃ€t Karlsruhe (TH)
+// Zirkel 2, 76128 Karlsruhe
+// Germany
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The views and conclusions contained in the software and documentation
+// are those of the authors and should not be interpreted as representing
+// official policies, either expressed or implied, of the Institute of
+// Telematics.
+// [License]
+
+#include "NetworkProtocol.h"
+
+NAMESPACE_BEGIN;
+
+NetworkProtocol::NetworkProtocol() {
+}
+
+NetworkProtocol::~NetworkProtocol() {
+}
+
+NAMESPACE_END;
Index: /trash/old-modules/network/NetworkProtocol.h
===================================================================
--- /trash/old-modules/network/NetworkProtocol.h	(revision 5641)
+++ /trash/old-modules/network/NetworkProtocol.h	(revision 5641)
@@ -0,0 +1,61 @@
+// [License]
+// The Ariba-Underlay Copyright
+//
+// Copyright (c) 2008-2009, Institute of Telematics, UniversitÃ€t Karlsruhe (TH)
+//
+// Institute of Telematics
+// UniversitÃ€t Karlsruhe (TH)
+// Zirkel 2, 76128 Karlsruhe
+// Germany
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The views and conclusions contained in the software and documentation
+// are those of the authors and should not be interpreted as representing
+// official policies, either expressed or implied, of the Institute of
+// Telematics.
+// [License]
+
+#ifndef NETWORKPROTOCOL_H_
+#define NETWORKPROTOCOL_H_
+
+#include "../_namespace.h"
+#include "ariba/communication/modules/network/NetworkLocator.h"
+#include <vector>
+
+using std::vector;
+
+NAMESPACE_BEGIN;
+
+class NetworkProtocol {
+public:
+	NetworkProtocol();
+	virtual ~NetworkProtocol();
+
+	typedef vector<NetworkLocator*> NetworkLocatorSet;
+	virtual const NetworkLocatorSet getAddresses() const = 0;
+};
+
+NAMESPACE_END;
+
+#endif /* NETWORKPROTOCOL_H_ */
Index: /trash/old-modules/network/ip/IPv4Locator.cpp
===================================================================
--- /trash/old-modules/network/ip/IPv4Locator.cpp	(revision 5641)
+++ /trash/old-modules/network/ip/IPv4Locator.cpp	(revision 5641)
@@ -0,0 +1,96 @@
+// [License]
+// The Ariba-Underlay Copyright
+//
+// Copyright (c) 2008-2009, Institute of Telematics, UniversitÃ€t Karlsruhe (TH)
+//
+// Institute of Telematics
+// UniversitÃ€t Karlsruhe (TH)
+// Zirkel 2, 76128 Karlsruhe
+// Germany
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The views and conclusions contained in the software and documentation
+// are those of the authors and should not be interpreted as representing
+// official policies, either expressed or implied, of the Institute of
+// Telematics.
+// [License]
+
+#include "IPv4Locator.h"
+
+namespace ariba {
+namespace communication {
+
+vsznDefault(IPv4Locator);
+
+IPv4Locator IPv4Locator::ANY        = IPv4Locator::fromString("0.0.0.0");
+IPv4Locator IPv4Locator::LOCALHOST  = IPv4Locator::fromString("127.0.0.1");
+IPv4Locator IPv4Locator::BROADCAST  = IPv4Locator::fromString("255.255.255.255");
+
+IPv4Locator::IPv4Locator() {
+	this->port = 0;
+}
+
+IPv4Locator::~IPv4Locator() {
+}
+
+bool IPv4Locator::operator==(const NetworkLocator& rh) const {
+
+	IPv4Locator* ipv4Rh = dynamic_cast<IPv4Locator*>(const_cast<NetworkLocator*>(&rh));
+	if( ipv4Rh == NULL ) return false;
+
+	return (this->ipv4Address == ipv4Rh->ipv4Address) /*&& (this->port == ipv4Rh->port)*/;
+}
+
+bool IPv4Locator::operator!=(const NetworkLocator& rh) const {
+	return (!operator==(rh));
+}
+
+IPv4Locator IPv4Locator::fromString(string addr){
+
+	IPv4Locator locator;
+	string::size_type p = addr.find(':');
+
+	string port = "";
+	if (p != string::npos) {
+		port = addr.substr(p+1);
+		addr = addr.substr(0,p);
+		std::istringstream i(port);
+		i >> locator.port;
+	}
+	locator.ipv4Address = boost::asio::ip::address_v4::from_string( addr );
+
+	return locator;
+}
+
+string IPv4Locator::toString() const {
+	std::ostringstream o;
+	o << ipv4Address.to_string();
+	if (port!=0) o << ":" << port;
+	return o.str();
+}
+
+IPv4Locator::IPv4Locator(const IPv4Locator& rh) : ipv4Address(rh.ipv4Address), port(rh.port){
+}
+
+}} // namespace ariba, communication
Index: /trash/old-modules/network/ip/IPv4Locator.h
===================================================================
--- /trash/old-modules/network/ip/IPv4Locator.h	(revision 5641)
+++ /trash/old-modules/network/ip/IPv4Locator.h	(revision 5641)
@@ -0,0 +1,108 @@
+// [License]
+// The Ariba-Underlay Copyright
+//
+// Copyright (c) 2008-2009, Institute of Telematics, UniversitÃ€t Karlsruhe (TH)
+//
+// Institute of Telematics
+// UniversitÃ€t Karlsruhe (TH)
+// Zirkel 2, 76128 Karlsruhe
+// Germany
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The views and conclusions contained in the software and documentation
+// are those of the authors and should not be interpreted as representing
+// official policies, either expressed or implied, of the Institute of
+// Telematics.
+// [License]
+
+#ifndef IPV4LOCATOR_H_
+#define IPV4LOCATOR_H_
+
+#include <string>
+
+#include "ariba/communication/modules/network/NetworkLocator.h"
+#include <boost/asio/ip/address_v4.hpp>
+
+using std::string;
+using ariba::communication::NetworkLocator;
+
+namespace ariba {
+namespace communication {
+
+/**
+ * An address class for IPv4 locators (= addresses).
+ *
+ * This class handles IPv4 locators only.
+ *
+ */
+class IPv4Locator: public NetworkLocator {
+	VSERIALIZEABLE;
+public:
+	/** Constructor initializing the address to the one given in string representation. */
+	IPv4Locator();
+	IPv4Locator(const IPv4Locator& rh);
+
+	static IPv4Locator LOCALHOST;
+	static IPv4Locator ANY;
+	static IPv4Locator BROADCAST;
+
+	virtual bool operator==(const NetworkLocator& rh) const;
+	virtual bool operator!=(const NetworkLocator& rh) const;
+
+	/** Default destructor. */
+	virtual ~IPv4Locator();
+
+	static IPv4Locator fromString(string addr);
+	virtual string toString() const;
+
+	void setIP( string ip ) {
+		ipv4Address = boost::asio::ip::address_v4::from_string( ip );
+	}
+
+	string getIP() const {
+		return ipv4Address.to_string();
+	}
+
+	void setPort( uint16_t port ) {
+		this->port = port;
+	}
+
+	uint16_t getPort() const {
+		return this->port;
+	}
+private:
+	boost::asio::ip::address_v4 ipv4Address;
+	uint16_t port;
+};
+
+}} // namespace ariba, communication
+
+sznBeginDefault( ariba::communication::IPv4Locator, X ) {
+	boost::asio::ip::address_v4::bytes_type buffer = ipv4Address.to_bytes();
+	for (int i=0; i<4; i++) X && buffer[i];
+	if (X.isDeserializer()) ipv4Address = boost::asio::ip::address_v4(buffer);
+	X && port;
+} sznEnd();
+
+#endif /* IPV4LOCATOR_H_ */
Index: /trash/old-modules/network/ip/IPv4NetworkProtocol.cpp
===================================================================
--- /trash/old-modules/network/ip/IPv4NetworkProtocol.cpp	(revision 5641)
+++ /trash/old-modules/network/ip/IPv4NetworkProtocol.cpp	(revision 5641)
@@ -0,0 +1,80 @@
+// [License]
+// The Ariba-Underlay Copyright
+//
+// Copyright (c) 2008-2009, Institute of Telematics, UniversitÃ€t Karlsruhe (TH)
+//
+// Institute of Telematics
+// UniversitÃ€t Karlsruhe (TH)
+// Zirkel 2, 76128 Karlsruhe
+// Germany
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The views and conclusions contained in the software and documentation
+// are those of the authors and should not be interpreted as representing
+// official policies, either expressed or implied, of the Institute of
+// Telematics.
+// [License]
+
+#include "IPv4NetworkProtocol.h"
+
+namespace ariba {
+namespace communication {
+
+IPv4NetworkProtocol::IPv4NetworkProtocol(){
+}
+
+IPv4NetworkProtocol::~IPv4NetworkProtocol(){
+}
+
+const NetworkProtocol::NetworkLocatorSet IPv4NetworkProtocol::getAddresses() const{
+
+	NetworkProtocol::NetworkLocatorSet interfaces;
+
+	struct ifaddrs* ifaceBuffer = NULL;
+	struct ifaddrs* tmpAddr     = NULL;
+	void*           tmpAddrPtr  = NULL;
+	char            straddr     [INET_ADDRSTRLEN];
+
+	int ret = getifaddrs( &ifaceBuffer );
+	if( ret != 0 ) return interfaces;
+
+	for( struct ifaddrs* i=ifaceBuffer; i != NULL; i=i->ifa_next ){
+
+		// ignore devices that are disabled or have no ip
+		if(i == NULL || i->ifa_addr == NULL) continue;
+
+		// only look at IPv4, not IPv6 addresses
+		if(i->ifa_addr->sa_family != AF_INET) continue;
+
+		tmpAddrPtr= &((struct sockaddr_in*)i->ifa_addr)->sin_addr;
+		inet_ntop( i->ifa_addr->sa_family, tmpAddrPtr, straddr, sizeof(straddr) );
+
+		IPv4Locator* iplocator = new IPv4Locator(IPv4Locator::fromString(straddr));
+		interfaces.push_back( iplocator );
+	}
+
+	return interfaces;
+}
+
+}} // namespace ariba, communication
Index: /trash/old-modules/network/ip/IPv4NetworkProtocol.h
===================================================================
--- /trash/old-modules/network/ip/IPv4NetworkProtocol.h	(revision 5641)
+++ /trash/old-modules/network/ip/IPv4NetworkProtocol.h	(revision 5641)
@@ -0,0 +1,71 @@
+// [License]
+// The Ariba-Underlay Copyright
+//
+// Copyright (c) 2008-2009, Institute of Telematics, UniversitÃ€t Karlsruhe (TH)
+//
+// Institute of Telematics
+// UniversitÃ€t Karlsruhe (TH)
+// Zirkel 2, 76128 Karlsruhe
+// Germany
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The views and conclusions contained in the software and documentation
+// are those of the authors and should not be interpreted as representing
+// official policies, either expressed or implied, of the Institute of
+// Telematics.
+// [License]
+
+#ifndef IPV4_NETWORK_PROTOCOL_H__
+#define IPV4_NETWORK_PROTOCOL_H__
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <ifaddrs.h>
+
+#include "ariba/communication/modules/network/ip/IPv4Locator.h"
+#include "ariba/communication/modules/network/NetworkProtocol.h"
+#include "ariba/communication/modules/network/NetworkLocator.h"
+
+using ariba::communication::IPv4Locator;
+using ariba::communication::NetworkProtocol;
+using ariba::communication::NetworkLocator;
+
+namespace ariba {
+namespace communication {
+
+class IPv4NetworkProtocol : public NetworkProtocol{
+public:
+	IPv4NetworkProtocol();
+	virtual ~IPv4NetworkProtocol();
+
+	virtual const NetworkProtocol::NetworkLocatorSet getAddresses() const;
+
+};
+
+}} // namespace ariba, communication
+
+#endif // IPV4_NETWORK_PROTOCOL_H__
Index: /trash/old-modules/network/omnet/OmnetNetworkProtocol.cpp
===================================================================
--- /trash/old-modules/network/omnet/OmnetNetworkProtocol.cpp	(revision 5641)
+++ /trash/old-modules/network/omnet/OmnetNetworkProtocol.cpp	(revision 5641)
@@ -0,0 +1,81 @@
+// [License]
+// The Ariba-Underlay Copyright
+//
+// Copyright (c) 2008-2009, Institute of Telematics, UniversitÃ€t Karlsruhe (TH)
+//
+// Institute of Telematics
+// UniversitÃ€t Karlsruhe (TH)
+// Zirkel 2, 76128 Karlsruhe
+// Germany
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The views and conclusions contained in the software and documentation
+// are those of the authors and should not be interpreted as representing
+// official policies, either expressed or implied, of the Institute of
+// Telematics.
+// [License]
+
+#include "OmnetNetworkProtocol.h"
+
+namespace ariba {
+namespace communication {
+
+OmnetNetworkProtocol::OmnetNetworkProtocol(cSimpleModule* _module) : module(_module) {
+}
+
+OmnetNetworkProtocol::~OmnetNetworkProtocol(){
+}
+
+const NetworkProtocol::NetworkLocatorSet OmnetNetworkProtocol::getAddresses() const{
+
+	NetworkProtocol::NetworkLocatorSet interfaces;
+	InterfaceTable* table = NULL;
+
+	for( cModule* mod = module; mod->parentModule() != NULL; mod = mod->parentModule() ){
+		cModule* rtmod = mod->submodule("interfaceTable");
+		if( rtmod == NULL) continue;
+
+ 		InterfaceTable* rt = dynamic_cast<InterfaceTable*>(rtmod);
+		if( rt == NULL ) continue;
+
+		table = rt;
+		break;
+	}
+
+	if( table == NULL ) return interfaces;
+
+	for( int i=0; i<table->numInterfaces(); i++ ){
+		InterfaceEntry* entry = table->interfaceAt( i );
+		IPv4InterfaceData* v4 = entry->ipv4();
+		IPAddress address = v4->inetAddress();
+		if( address.isUnspecified() ) continue;
+
+		IPv4Locator* iplocator = new IPv4Locator( IPv4Locator::fromString(address.str()) );
+		interfaces.push_back( iplocator );
+	}
+
+	return interfaces;
+}
+
+}} // namespace ariba, communication, internal
Index: /trash/old-modules/network/omnet/OmnetNetworkProtocol.h
===================================================================
--- /trash/old-modules/network/omnet/OmnetNetworkProtocol.h	(revision 5641)
+++ /trash/old-modules/network/omnet/OmnetNetworkProtocol.h	(revision 5641)
@@ -0,0 +1,72 @@
+// [License]
+// The Ariba-Underlay Copyright
+//
+// Copyright (c) 2008-2009, Institute of Telematics, UniversitÃ€t Karlsruhe (TH)
+//
+// Institute of Telematics
+// UniversitÃ€t Karlsruhe (TH)
+// Zirkel 2, 76128 Karlsruhe
+// Germany
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The views and conclusions contained in the software and documentation
+// are those of the authors and should not be interpreted as representing
+// official policies, either expressed or implied, of the Institute of
+// Telematics.
+// [License]
+
+#ifndef __OMNET_NETWORK_PROTOCOL_H
+#define __OMNET_NETWORK_PROTOCOL_H
+
+#include "ariba/communication/modules/network/ip/IPv4Locator.h"
+#include "ariba/communication/modules/network/NetworkProtocol.h"
+#include "ariba/communication/modules/network/NetworkLocator.h"
+#include <iostream>
+#include <omnetpp.h>
+#include <InterfaceTable.h>
+#include <IPv4InterfaceData.h>
+#include <IPAddress.h>
+
+using std::cout;
+using ariba::communication::IPv4Locator;
+using ariba::communication::NetworkProtocol;
+using ariba::communication::NetworkLocator;
+
+namespace ariba {
+namespace communication {
+
+class OmnetNetworkProtocol : public NetworkProtocol{
+public:
+	OmnetNetworkProtocol( cSimpleModule* _module );
+	virtual ~OmnetNetworkProtocol();
+
+	virtual const NetworkProtocol::NetworkLocatorSet getAddresses() const;
+
+protected:
+	cSimpleModule* module;
+};
+
+}} // namespace ariba, communication, internal
+
+#endif // __OMNET_NETWORK_PROTOCOL_H
Index: /trash/old-modules/transport/TransportLocator.cpp
===================================================================
--- /trash/old-modules/transport/TransportLocator.cpp	(revision 5641)
+++ /trash/old-modules/transport/TransportLocator.cpp	(revision 5641)
@@ -0,0 +1,49 @@
+// [License]
+// The Ariba-Underlay Copyright
+//
+// Copyright (c) 2008-2009, Institute of Telematics, UniversitÃ€t Karlsruhe (TH)
+//
+// Institute of Telematics
+// UniversitÃ€t Karlsruhe (TH)
+// Zirkel 2, 76128 Karlsruhe
+// Germany
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The views and conclusions contained in the software and documentation
+// are those of the authors and should not be interpreted as representing
+// official policies, either expressed or implied, of the Institute of
+// Telematics.
+// [License]
+
+#include "TransportLocator.h"
+
+NAMESPACE_BEGIN;
+
+TransportLocator::TransportLocator() {
+}
+
+TransportLocator::~TransportLocator() {
+}
+
+NAMESPACE_END;
Index: /trash/old-modules/transport/TransportLocator.h
===================================================================
--- /trash/old-modules/transport/TransportLocator.h	(revision 5641)
+++ /trash/old-modules/transport/TransportLocator.h	(revision 5641)
@@ -0,0 +1,82 @@
+// [License]
+// The Ariba-Underlay Copyright
+//
+// Copyright (c) 2008-2009, Institute of Telematics, UniversitÃ€t Karlsruhe (TH)
+//
+// Institute of Telematics
+// UniversitÃ€t Karlsruhe (TH)
+// Zirkel 2, 76128 Karlsruhe
+// Germany
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The views and conclusions contained in the software and documentation
+// are those of the authors and should not be interpreted as representing
+// official policies, either expressed or implied, of the Institute of
+// Telematics.
+// [License]
+
+#ifndef TRANSPORTLOCATOR_H_
+#define TRANSPORTLOCATOR_H_
+
+#include <vector>
+#include "boost/cstdint.hpp"
+#include "ariba/utility/types/Locator.h"
+#include "../network/NetworkLocator.h"
+
+using ariba::utility::Locator;
+using std::vector;
+
+#include "ariba/communication/modules/_namespace.h"
+NAMESPACE_BEGIN;
+
+class TransportLocator : public Locator {
+public:
+	typedef uint16_t prot_t;
+
+private:
+	prot_t type;
+	vector<NetworkLocator*> netLocators;
+
+public:
+	TransportLocator();
+	virtual ~TransportLocator();
+
+	inline prot_t getType() const {
+		return type;
+	}
+
+	inline void setType( prot_t type ) {
+		this->type = type;
+	}
+
+	inline const vector<NetworkLocator*> getNetworkLocators() const {
+		return netLocators;
+	}
+
+	virtual bool operator==( TransportLocator* locator ) const = 0;
+};
+
+NAMESPACE_END;
+
+#endif /* TRANSPORTLOCATOR_H_ */
Index: /trash/old-modules/transport/TransportProtocol.cpp
===================================================================
--- /trash/old-modules/transport/TransportProtocol.cpp	(revision 5641)
+++ /trash/old-modules/transport/TransportProtocol.cpp	(revision 5641)
@@ -0,0 +1,50 @@
+// [License]
+// The Ariba-Underlay Copyright
+//
+// Copyright (c) 2008-2009, Institute of Telematics, UniversitÃ€t Karlsruhe (TH)
+//
+// Institute of Telematics
+// UniversitÃ€t Karlsruhe (TH)
+// Zirkel 2, 76128 Karlsruhe
+// Germany
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The views and conclusions contained in the software and documentation
+// are those of the authors and should not be interpreted as representing
+// official policies, either expressed or implied, of the Institute of
+// Telematics.
+// [License]
+
+#include "TransportProtocol.h"
+
+#include "../_namespace.h"
+NAMESPACE_BEGIN;
+
+TransportProtocol::TransportProtocol() {
+}
+
+TransportProtocol::~TransportProtocol() {
+}
+
+NAMESPACE_END;
Index: /trash/old-modules/transport/TransportProtocol.h
===================================================================
--- /trash/old-modules/transport/TransportProtocol.h	(revision 5641)
+++ /trash/old-modules/transport/TransportProtocol.h	(revision 5641)
@@ -0,0 +1,67 @@
+// [License]
+// The Ariba-Underlay Copyright
+//
+// Copyright (c) 2008-2009, Institute of Telematics, UniversitÃ€t Karlsruhe (TH)
+//
+// Institute of Telematics
+// UniversitÃ€t Karlsruhe (TH)
+// Zirkel 2, 76128 Karlsruhe
+// Germany
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The views and conclusions contained in the software and documentation
+// are those of the authors and should not be interpreted as representing
+// official policies, either expressed or implied, of the Institute of
+// Telematics.
+// [License]
+
+#ifndef TRANSPORTPROTOCOL_H_
+#define TRANSPORTPROTOCOL_H_
+
+#include <vector>
+#include "TransportLocator.h"
+#include "ariba/utility/messages.h"
+
+#include "ariba/communication/modules/_namespace.h"
+NAMESPACE_BEGIN;
+
+using std::vector;
+using ariba::utility::MessageSender;
+using ariba::utility::MessageProvider;
+
+class TransportProtocol : public MessageSender, public MessageProvider {
+public:
+	TransportProtocol();
+	virtual ~TransportProtocol();
+
+	virtual void start() = 0;
+	virtual void stop() = 0;
+	virtual void terminate(const NetworkLocator* local, const NetworkLocator* remote) = 0;
+	virtual TransportLocator::prot_t getId() = 0;
+	virtual const vector<TransportLocator*> getLocators() = 0;
+};
+
+NAMESPACE_END;
+
+#endif /* TRANSPORTPROTOCOL_H_ */
Index: /trash/old-modules/transport/omnet/AribaOmnetMessage.msg
===================================================================
--- /trash/old-modules/transport/omnet/AribaOmnetMessage.msg	(revision 5641)
+++ /trash/old-modules/transport/omnet/AribaOmnetMessage.msg	(revision 5641)
@@ -0,0 +1,44 @@
+// [License]
+// The Ariba-Underlay Copyright
+//
+// Copyright (c) 2008-2009, Institute of Telematics, UniversitÃ€t Karlsruhe (TH)
+//
+// Institute of Telematics
+// UniversitÃ€t Karlsruhe (TH)
+// Zirkel 2, 76128 Karlsruhe
+// Germany
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The views and conclusions contained in the software and documentation
+// are those of the authors and should not be interpreted as representing
+// official policies, either expressed or implied, of the Institute of
+// Telematics.
+// [License]
+
+message AribaOmnetMessage
+{
+	fields:
+		unsigned int port;
+		unsigned char data[];
+}
Index: /trash/old-modules/transport/omnet/AribaOmnetMessage_m.cc
===================================================================
--- /trash/old-modules/transport/omnet/AribaOmnetMessage_m.cc	(revision 5641)
+++ /trash/old-modules/transport/omnet/AribaOmnetMessage_m.cc	(revision 5641)
@@ -0,0 +1,351 @@
+//
+// Generated file, do not edit! Created by opp_msgc 3.4 from ./AribaOmnetMessage.msg.
+//
+
+// Disable warnings about unused variables, empty switch stmts, etc:
+#ifdef _MSC_VER
+#  pragma warning(disable:4101)
+#  pragma warning(disable:4065)
+#endif
+
+#include <iostream>
+#include <sstream>
+#include "./AribaOmnetMessage_m.h"
+
+// Template rule which fires if a struct or class doesn't have operator<<
+template<typename T>
+std::ostream& operator<<(std::ostream& out,const T&) {return out;}
+
+// Another default rule (prevents compiler from choosing base class' doPacking())
+template<typename T>
+void doPacking(cCommBuffer *, T& t) {
+    throw new cRuntimeError("Parsim error: no doPacking() function for type %s or its base class (check .msg and _m.cc/h files!)",opp_typename(typeid(t)));
+}
+template<typename T>
+void doUnpacking(cCommBuffer *, T& t) {
+    throw new cRuntimeError("Parsim error: no doUnpacking() function for type %s or its base class (check .msg and _m.cc/h files!)",opp_typename(typeid(t)));
+}
+
+// Automatically supply array (un)packing functions
+template<typename T>
+void doPacking(cCommBuffer *b, T *t, int n) {
+    for (int i=0; i<n; i++)
+        doPacking(b,t[i]);
+}
+template<typename T>
+void doUnpacking(cCommBuffer *b, T *t, int n) {
+    for (int i=0; i<n; i++)
+        doUnpacking(b,t[i]);
+}
+inline void doPacking(cCommBuffer *, cPolymorphic&) {}
+inline void doUnpacking(cCommBuffer *, cPolymorphic&) {}
+
+#define DOPACKING(T,R) \
+    inline void doPacking(cCommBuffer *b, T R a) {b->pack(a);}  \
+    inline void doPacking(cCommBuffer *b, T *a, int n) {b->pack(a,n);}  \
+    inline void doUnpacking(cCommBuffer *b, T& a) {b->unpack(a);}  \
+    inline void doUnpacking(cCommBuffer *b, T *a, int n) {b->unpack(a,n);}
+#define _
+DOPACKING(char,_)
+DOPACKING(unsigned char,_)
+DOPACKING(bool,_)
+DOPACKING(short,_)
+DOPACKING(unsigned short,_)
+DOPACKING(int,_)
+DOPACKING(unsigned int,_)
+DOPACKING(long,_)
+DOPACKING(unsigned long,_)
+DOPACKING(float,_)
+DOPACKING(double,_)
+DOPACKING(long double,_)
+DOPACKING(char *,_)
+DOPACKING(const char *,_)
+DOPACKING(opp_string,&)
+//DOPACKING(std::string,&)
+#undef _
+#undef DOPACKING
+
+
+Register_Class(AribaOmnetMessage);
+
+AribaOmnetMessage::AribaOmnetMessage(const char *name, int kind) : cMessage(name,kind)
+{
+    unsigned int i;
+    this->port_var = 0;
+    data_arraysize = 0;
+    this->data_var = 0;
+}
+
+AribaOmnetMessage::AribaOmnetMessage(const AribaOmnetMessage& other) : cMessage()
+{
+    unsigned int i;
+    setName(other.name());
+    data_arraysize = 0;
+    this->data_var = 0;
+    operator=(other);
+}
+
+AribaOmnetMessage::~AribaOmnetMessage()
+{
+    unsigned int i;
+    delete [] data_var;
+}
+
+AribaOmnetMessage& AribaOmnetMessage::operator=(const AribaOmnetMessage& other)
+{
+    if (this==&other) return *this;
+    unsigned int i;
+    cMessage::operator=(other);
+    this->port_var = other.port_var;
+    delete [] this->data_var;
+    this->data_var = (other.data_arraysize==0) ? NULL : new unsigned char[other.data_arraysize];
+    data_arraysize = other.data_arraysize;
+    for (i=0; i<data_arraysize; i++)
+        this->data_var[i] = other.data_var[i];
+    return *this;
+}
+
+void AribaOmnetMessage::netPack(cCommBuffer *b)
+{
+    cMessage::netPack(b);
+    doPacking(b,this->port_var);
+    b->pack(data_arraysize);
+    doPacking(b,this->data_var,data_arraysize);
+}
+
+void AribaOmnetMessage::netUnpack(cCommBuffer *b)
+{
+    cMessage::netUnpack(b);
+    doUnpacking(b,this->port_var);
+    delete [] this->data_var;
+    b->unpack(data_arraysize);
+    if (data_arraysize==0) {
+        this->data_var = 0;
+    } else {
+        this->data_var = new unsigned char[data_arraysize];
+        doUnpacking(b,this->data_var,data_arraysize);
+    }
+}
+
+unsigned int AribaOmnetMessage::getPort() const
+{
+    return port_var;
+}
+
+void AribaOmnetMessage::setPort(unsigned int port_var)
+{
+    this->port_var = port_var;
+}
+
+void AribaOmnetMessage::setDataArraySize(unsigned int size)
+{
+    unsigned char *data_var2 = (size==0) ? NULL : new unsigned char[size];
+    unsigned int sz = data_arraysize < size ? data_arraysize : size;
+    unsigned int i;
+    for (i=0; i<sz; i++)
+        data_var2[i] = this->data_var[i];
+    for (i=sz; i<size; i++)
+        data_var2[i] = 0;
+    data_arraysize = size;
+    delete [] this->data_var;
+    this->data_var = data_var2;
+}
+
+unsigned int AribaOmnetMessage::getDataArraySize() const
+{
+    return data_arraysize;
+}
+
+unsigned char AribaOmnetMessage::getData(unsigned int k) const
+{
+    if (k>=data_arraysize) throw new cRuntimeError("Array of size %d indexed by %d", data_arraysize, k);
+    return data_var[k];
+}
+
+void AribaOmnetMessage::setData(unsigned int k, unsigned char data_var)
+{
+    if (k>=data_arraysize) throw new cRuntimeError("Array of size %d indexed by %d", data_arraysize, k);
+    this->data_var[k]=data_var;
+}
+
+class AribaOmnetMessageDescriptor : public cClassDescriptor
+{
+  public:
+    AribaOmnetMessageDescriptor();
+    virtual ~AribaOmnetMessageDescriptor();
+
+    virtual bool doesSupport(cPolymorphic *obj);
+    virtual const char *getProperty(const char *propertyname);
+    virtual int getFieldCount(void *object);
+    virtual const char *getFieldName(void *object, int field);
+    virtual unsigned int getFieldTypeFlags(void *object, int field);
+    virtual const char *getFieldTypeString(void *object, int field);
+    virtual const char *getFieldProperty(void *object, int field, const char *propertyname);
+    virtual int getArraySize(void *object, int field);
+
+    virtual bool getFieldAsString(void *object, int field, int i, char *resultbuf, int bufsize);
+    virtual bool setFieldAsString(void *object, int field, int i, const char *value);
+
+    virtual const char *getFieldStructName(void *object, int field);
+    virtual void *getFieldStructPointer(void *object, int field, int i);
+};
+
+Register_ClassDescriptor(AribaOmnetMessageDescriptor);
+
+AribaOmnetMessageDescriptor::AribaOmnetMessageDescriptor() : cClassDescriptor("AribaOmnetMessage", "cMessage")
+{
+}
+
+AribaOmnetMessageDescriptor::~AribaOmnetMessageDescriptor()
+{
+}
+
+bool AribaOmnetMessageDescriptor::doesSupport(cPolymorphic *obj)
+{
+    return dynamic_cast<AribaOmnetMessage *>(obj)!=NULL;
+}
+
+const char *AribaOmnetMessageDescriptor::getProperty(const char *propertyname)
+{
+    cClassDescriptor *basedesc = getBaseClassDescriptor();
+    return basedesc ? basedesc->getProperty(propertyname) : NULL;
+}
+
+int AribaOmnetMessageDescriptor::getFieldCount(void *object)
+{
+    cClassDescriptor *basedesc = getBaseClassDescriptor();
+    return basedesc ? 2+basedesc->getFieldCount(object) : 2;
+}
+
+unsigned int AribaOmnetMessageDescriptor::getFieldTypeFlags(void *object, int field)
+{
+    cClassDescriptor *basedesc = getBaseClassDescriptor();
+    if (basedesc) {
+        if (field < basedesc->getFieldCount(object))
+            return basedesc->getFieldTypeFlags(object, field);
+        field -= basedesc->getFieldCount(object);
+    }
+    switch (field) {
+        case 0: return FD_ISEDITABLE;
+        case 1: return FD_ISARRAY | FD_ISEDITABLE;
+        default: return 0;
+    }
+}
+
+const char *AribaOmnetMessageDescriptor::getFieldName(void *object, int field)
+{
+    cClassDescriptor *basedesc = getBaseClassDescriptor();
+    if (basedesc) {
+        if (field < basedesc->getFieldCount(object))
+            return basedesc->getFieldName(object, field);
+        field -= basedesc->getFieldCount(object);
+    }
+    switch (field) {
+        case 0: return "port";
+        case 1: return "data";
+        default: return NULL;
+    }
+}
+
+const char *AribaOmnetMessageDescriptor::getFieldTypeString(void *object, int field)
+{
+    cClassDescriptor *basedesc = getBaseClassDescriptor();
+    if (basedesc) {
+        if (field < basedesc->getFieldCount(object))
+            return basedesc->getFieldTypeString(object, field);
+        field -= basedesc->getFieldCount(object);
+    }
+    switch (field) {
+        case 0: return "unsigned int";
+        case 1: return "unsigned char";
+        default: return NULL;
+    }
+}
+
+const char *AribaOmnetMessageDescriptor::getFieldProperty(void *object, int field, const char *propertyname)
+{
+    cClassDescriptor *basedesc = getBaseClassDescriptor();
+    if (basedesc) {
+        if (field < basedesc->getFieldCount(object))
+            return basedesc->getFieldProperty(object, field, propertyname);
+        field -= basedesc->getFieldCount(object);
+    }
+    switch (field) {
+        default: return NULL;
+    }
+}
+
+int AribaOmnetMessageDescriptor::getArraySize(void *object, int field)
+{
+    cClassDescriptor *basedesc = getBaseClassDescriptor();
+    if (basedesc) {
+        if (field < basedesc->getFieldCount(object))
+            return basedesc->getArraySize(object, field);
+        field -= basedesc->getFieldCount(object);
+    }
+    AribaOmnetMessage *pp _MAYBEUNUSED = (AribaOmnetMessage *)object;
+    switch (field) {
+        case 1: return pp->getDataArraySize();
+        default: return 0;
+    }
+}
+
+bool AribaOmnetMessageDescriptor::getFieldAsString(void *object, int field, int i, char *resultbuf, int bufsize)
+{
+    cClassDescriptor *basedesc = getBaseClassDescriptor();
+    if (basedesc) {
+        if (field < basedesc->getFieldCount(object))
+            return basedesc->getFieldAsString(object,field,i,resultbuf,bufsize);
+        field -= basedesc->getFieldCount(object);
+    }
+    AribaOmnetMessage *pp _MAYBEUNUSED = (AribaOmnetMessage *)object;
+    switch (field) {
+        case 0: long2string(pp->getPort(),resultbuf,bufsize); return true;
+        case 1: long2string(pp->getData(i),resultbuf,bufsize); return true;
+        default: return false;
+    }
+}
+
+bool AribaOmnetMessageDescriptor::setFieldAsString(void *object, int field, int i, const char *value)
+{
+    cClassDescriptor *basedesc = getBaseClassDescriptor();
+    if (basedesc) {
+        if (field < basedesc->getFieldCount(object))
+            return basedesc->setFieldAsString(object,field,i,value);
+        field -= basedesc->getFieldCount(object);
+    }
+    AribaOmnetMessage *pp _MAYBEUNUSED = (AribaOmnetMessage *)object;
+    switch (field) {
+        case 0: pp->setPort(string2long(value)); return true;
+        case 1: pp->setData(i,string2long(value)); return true;
+        default: return false;
+    }
+}
+
+const char *AribaOmnetMessageDescriptor::getFieldStructName(void *object, int field)
+{
+    cClassDescriptor *basedesc = getBaseClassDescriptor();
+    if (basedesc) {
+        if (field < basedesc->getFieldCount(object))
+            return basedesc->getFieldStructName(object, field);
+        field -= basedesc->getFieldCount(object);
+    }
+    switch (field) {
+        default: return NULL;
+    }
+}
+
+void *AribaOmnetMessageDescriptor::getFieldStructPointer(void *object, int field, int i)
+{
+    cClassDescriptor *basedesc = getBaseClassDescriptor();
+    if (basedesc) {
+        if (field < basedesc->getFieldCount(object))
+            return basedesc->getFieldStructPointer(object, field, i);
+        field -= basedesc->getFieldCount(object);
+    }
+    AribaOmnetMessage *pp _MAYBEUNUSED = (AribaOmnetMessage *)object;
+    switch (field) {
+        default: return NULL;
+    }
+}
+
Index: /trash/old-modules/transport/omnet/AribaOmnetMessage_m.h
===================================================================
--- /trash/old-modules/transport/omnet/AribaOmnetMessage_m.h	(revision 5641)
+++ /trash/old-modules/transport/omnet/AribaOmnetMessage_m.h	(revision 5641)
@@ -0,0 +1,59 @@
+//
+// Generated file, do not edit! Created by opp_msgc 3.4 from ./SpoVNetOmnetMessage.msg.
+//
+
+#ifndef _ARIBAOMNETMESSAGE_M_H_
+#define _ARIBAOMNETMESSAGE_M_H_
+
+#include <omnetpp.h>
+
+// opp_msgc version check
+#define MSGC_VERSION 0x0304
+#if (MSGC_VERSION!=OMNETPP_VERSION)
+#    error Version mismatch! Probably this file was generated by an earlier version of opp_msgc: 'make clean' should help.
+#endif
+
+
+/**
+ * Class generated from <tt>./AribaOmnetMessage.msg</tt> by opp_msgc.
+ * <pre>
+ * message AribaOmnetMessage
+ * {
+ * 	fields:
+ * 		unsigned int port;
+ * 		unsigned char data[];
+ * }
+ * </pre>
+ */
+class AribaOmnetMessage : public cMessage
+{
+  protected:
+    unsigned int port_var;
+    unsigned char *data_var; // array ptr
+    unsigned int data_arraysize;
+
+    // protected and unimplemented operator==(), to prevent accidental usage
+    bool operator==(const AribaOmnetMessage&);
+
+  public:
+    AribaOmnetMessage(const char *name=NULL, int kind=0);
+    AribaOmnetMessage(const AribaOmnetMessage& other);
+    virtual ~AribaOmnetMessage();
+    AribaOmnetMessage& operator=(const AribaOmnetMessage& other);
+    virtual cPolymorphic *dup() const {return new AribaOmnetMessage(*this);}
+    virtual void netPack(cCommBuffer *b);
+    virtual void netUnpack(cCommBuffer *b);
+
+    // field getter/setter methods
+    virtual unsigned int getPort() const;
+    virtual void setPort(unsigned int port_var);
+    virtual void setDataArraySize(unsigned int size);
+    virtual unsigned int getDataArraySize() const;
+    virtual unsigned char getData(unsigned int k) const;
+    virtual void setData(unsigned int k, unsigned char data_var);
+};
+
+inline void doPacking(cCommBuffer *b, AribaOmnetMessage& obj) {obj.netPack(b);}
+inline void doUnpacking(cCommBuffer *b, AribaOmnetMessage& obj) {obj.netUnpack(b);}
+
+#endif // _ARIBAOMNETMESSAGE_M_H_
Index: /trash/old-modules/transport/omnet/AribaOmnetModule.cpp
===================================================================
--- /trash/old-modules/transport/omnet/AribaOmnetModule.cpp	(revision 5641)
+++ /trash/old-modules/transport/omnet/AribaOmnetModule.cpp	(revision 5641)
@@ -0,0 +1,320 @@
+// [License]
+// The Ariba-Underlay Copyright
+//
+// Copyright (c) 2008-2009, Institute of Telematics, UniversitÃ€t Karlsruhe (TH)
+//
+// Institute of Telematics
+// UniversitÃ€t Karlsruhe (TH)
+// Zirkel 2, 76128 Karlsruhe
+// Germany
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The views and conclusions contained in the software and documentation
+// are those of the authors and should not be interpreted as representing
+// official policies, either expressed or implied, of the Institute of
+// Telematics.
+// [License]
+
+#include "AribaOmnetModule.h"
+
+#include "ariba/utility/system/StartupWrapper.h" // circular inclusion
+using ariba::utility::StartupWrapper;
+
+namespace ariba {
+namespace communication {
+
+use_logging_cpp( AribaOmnetModule );
+
+AribaOmnetModule::AribaOmnetModule(){
+}
+
+AribaOmnetModule::~AribaOmnetModule(){
+}
+
+void AribaOmnetModule::setServerPort(uint16_t _port){
+	serverPort = _port;
+}
+
+void AribaOmnetModule::start(){
+
+	//ostringstream o;
+	//o << (void*)this;
+	//cout << "AribaOmnetModule " + o.str() + " start" << std::endl;
+
+	Enter_Method_Silent();
+
+ 	serverSocket.setCallbackObject(this);
+    	serverSocket.setOutputGate(gate("tcpOut"));
+	serverSocket.bind( IPvXAddress(), serverPort );
+	serverSocket.listen();
+
+	logging_debug( cModule::fullPath() << "listening on server socket" );
+}
+
+void AribaOmnetModule::stop(){
+
+	Enter_Method_Silent();
+
+	logging_debug( "stopping module " << cModule::fullPath() );
+
+	SocketMap::iterator i = sockets.begin();
+	SocketMap::iterator iend = sockets.end();
+
+	for( ; i != iend; i++ )
+		i->second->close();
+
+	serverSocket.close();
+}
+
+TransportLocator::prot_t AribaOmnetModule::getId(){
+	return 6; // TCP
+}
+
+const vector<TransportLocator*> AribaOmnetModule::getLocators(){
+	return vector<TransportLocator*>();
+}
+
+int AribaOmnetModule::numInitStages() const {
+	// the FlatNetworkConfiguration distributes the IP address in stage 3
+	// so to get the assigned IP address we init in stage 4 :)
+	return 4;
+}
+
+void AribaOmnetModule::initialize(int stage){
+	if( stage != 3 ) return;
+
+	StartupWrapper::initSystem();
+	StartupWrapper::initConfig( par("configfile").stringValue() );
+
+	StartupWrapper::insertCurrentModule( this );
+
+	logging_debug( "initializing " << cModule::fullPath() );
+	logging_debug( "AribaOmnetModule " << (void*)this << " initialize" );
+
+	StartupInterface* service = NULL;
+	cModuleType* type = findModuleType( ARIBA_SIMULATION_MODULE );
+
+	if( type != NULL ) {
+		logging_debug( "found module type ... creating ..." );
+		service = (StartupInterface*)type->create( ARIBA_SIMULATION_MODULE, this );
+	} else {
+		logging_fatal( "module type not found " << ARIBA_SIMULATION_MODULE );
+	}
+
+	if( service == NULL ){
+		logging_fatal( "no service defined for simulation. " <<
+				"service not loaded using load-libs in omnetpp.ini, " <<
+				" or ARIBA_SIMULATION_SERVICE() not used" );
+	} else {
+		StartupWrapper::startup( service );
+	}
+}
+
+void AribaOmnetModule::handleMessage(cMessage* msg){
+
+	logging_debug( cModule::fullPath() << " handling message" );
+	bool socketfound = false;
+
+	SocketMap::iterator i = sockets.begin();
+	SocketMap::iterator iend = sockets.end();
+
+	for( ; i != iend; i++ ){
+		if( i->second->belongsToSocket( msg )){
+			i->second->processMessage( msg );
+			socketfound = true;
+
+			logging_debug( cModule::fullPath() << " found socket for message" );
+			break;
+		}
+	}
+
+	if( ! socketfound ) {
+
+		logging_debug( cModule::fullPath() << " creating new socket for message" );
+
+		TCPSocket* dispatch = new TCPSocket( msg );
+		dispatch->setCallbackObject( this, dispatch );
+		dispatch->setOutputGate(gate("tcpOut"));
+
+		ostringstream o;
+		o << dispatch->remoteAddress().str() << ":" << dispatch->remotePort();
+
+		sockets.insert( make_pair(o.str(), dispatch) );
+		dispatch->processMessage( msg );
+	}
+}
+
+void AribaOmnetModule::finish(){
+	StartupWrapper::shutdown();
+}
+
+seqnum_t AribaOmnetModule::sendMessage(const Message* message){
+
+	Enter_Method_Silent();
+	logging_debug( cModule::fullPath() << " sending message" );
+
+	//
+	// serialize the data, get the destination address
+	//
+
+	Data data = data_serialize( message );
+	const_cast<Message*>(message)->dropPayload();
+
+	const IPv4Locator* address = dynamic_cast<const IPv4Locator*>(message->getDestinationAddress());
+	if( address == NULL ) return 0;
+
+	size_t len = data.getLength()/8;
+	uint8_t* buffer = data.getBuffer();
+
+	AribaOmnetMessage* outmsg = new AribaOmnetMessage( "AribaOmnetMessage");
+	outmsg->setPort( serverPort );
+	outmsg->setDataArraySize( len );
+	outmsg->setByteLength( len );
+
+	for( size_t i=0; i<len; i++, buffer++)
+		outmsg->setData(i, *buffer);
+
+	//
+	// find the socket for this endpoint
+	//
+
+	SocketMap::iterator i = sockets.find( address->toString() );
+	TCPSocket* connectionSocket = NULL;
+
+	if( i == sockets.end() ){
+
+		logging_debug( cModule::fullPath() <<
+			" creating new socket, connecting and queueing message" );
+
+		// don't have no connection yet for this endpoint
+		// initiate a connection and remember the message for later sending ...
+
+		SocketMap::iterator ret = sockets.insert(
+					make_pair(address->toString(), new TCPSocket()) );
+		connectionSocket = ret->second;
+
+		connectionSocket->setCallbackObject( this, connectionSocket );
+		connectionSocket->setOutputGate(gate("tcpOut"));
+
+		pendingSends.insert( make_pair(connectionSocket, outmsg) );
+		connectionSocket->connect( address->getIP().c_str(), address->getPort() );
+
+	} else {
+
+		logging_debug( cModule::fullPath() << " found socket, just sending out message" );
+		connectionSocket = i->second;
+		connectionSocket->send( outmsg );
+	}
+
+	//
+	// release the data and we are out!
+	//
+
+	data.release();
+	return 0;
+}
+
+void AribaOmnetModule::socketDataArrived(int connId, void* socket, cMessage* msg, bool urgent){
+
+	TCPSocket* tcpsocket = (TCPSocket*)socket;
+
+	AribaOmnetMessage* encap = dynamic_cast<AribaOmnetMessage*>(msg);
+	if( encap == NULL ) return;
+
+	logging_debug( cModule::fullPath() << " socket data arrived " << msg->info() );
+
+	size_t len = encap->getDataArraySize();
+	Data data( len*8 );
+ 	uint8_t* pnt = data.getBuffer();
+
+	for( size_t i=0; i<len; i++, pnt++)
+		*pnt = encap->getData( i );
+
+	Message* spovnetmsg = new Message(data);
+
+	ostringstream o;
+	o << tcpsocket->remoteAddress().str() << ":" << encap->getPort();
+	spovnetmsg->setSourceAddress( new IPv4Locator(IPv4Locator::fromString(o.str())) );
+
+	logging_debug( cModule::fullPath() << " forwarding to base communication" );
+	MessageProvider::sendMessageToReceivers( spovnetmsg );
+
+	delete encap;
+}
+
+void AribaOmnetModule::socketFailure(int connId, void* socket, int code){
+	logging_warn( cModule::fullPath() << " socket failure " << code );
+}
+
+void AribaOmnetModule::socketClosed(int connId, void* socket){
+	logging_debug( cModule::fullPath() << " socket closed" );
+}
+
+void AribaOmnetModule::socketPeerClosed(int connId, void* socket){
+
+	logging_debug( cModule::fullPath() << " socket peer closed" );
+	TCPSocket* tcpsocket = (TCPSocket*)socket;
+
+	SocketMap::iterator i = sockets.begin();
+	SocketMap::iterator iend = sockets.end();
+
+	for( ; i != iend; i++ ){
+
+		if( i->second == tcpsocket ){
+			sockets.erase( i );
+			delete tcpsocket;
+			break;
+		}
+	}
+}
+
+void AribaOmnetModule::socketEstablished(int connId, void* socket){
+
+	logging_debug( cModule::fullPath() << " socket established" );
+
+	TCPSocket* tcpsocket = (TCPSocket*)socket;
+	assert( tcpsocket != NULL );
+
+	// if we have pending data for this socket
+	// we are on the client side and initiated the connection
+	// else, this is a dispatched socket on the server side
+
+	PendingSendQueue::iterator i = pendingSends.find( tcpsocket );
+	if( i != pendingSends.end() ){
+
+		logging_debug( cModule::fullPath() << " socket established ... scheduling send msg" );
+
+		tcpsocket->send( i->second );
+		pendingSends.erase( i );
+
+	} else {
+		logging_debug( cModule::fullPath() << " dispatch socket established ... server side" );
+	}
+}
+
+void AribaOmnetModule::socketStatusArrived(int connId, void* socket, TCPStatusInfo *status){
+	logging_debug( cModule::fullPath() << " socket status arrivede" );
+}
+
+}} // namespace ariba, communication, internal
Index: /trash/old-modules/transport/omnet/AribaOmnetModule.h
===================================================================
--- /trash/old-modules/transport/omnet/AribaOmnetModule.h	(revision 5641)
+++ /trash/old-modules/transport/omnet/AribaOmnetModule.h	(revision 5641)
@@ -0,0 +1,150 @@
+// [License]
+// The Ariba-Underlay Copyright
+//
+// Copyright (c) 2008-2009, Institute of Telematics, UniversitÃ€t Karlsruhe (TH)
+//
+// Institute of Telematics
+// UniversitÃ€t Karlsruhe (TH)
+// Zirkel 2, 76128 Karlsruhe
+// Germany
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The views and conclusions contained in the software and documentation
+// are those of the authors and should not be interpreted as representing
+// official policies, either expressed or implied, of the Institute of
+// Telematics.
+// [License]
+
+#ifndef ARIBA_OMNET_MODULE_H__
+#define ARIBA_OMNET_MODULE_H__
+
+#include "ariba/utility/types.h"
+#include "ariba/utility/messages.h"
+#include "ariba/utility/types/Address.h"
+#include "ariba/utility/misc/Helper.h"
+#include "ariba/utility/logging/Logging.h"
+#include "ariba/utility/serialization/DataStream.hpp"
+#include "ariba/communication/modules/transport/TransportProtocol.h"
+#include "ariba/communication/modules/transport/TransportLocator.h"
+#include "ariba/communication/modules/network/ip/IPv4Locator.h"
+#include "AribaOmnetMessage_m.h"
+#include <omnetpp.h>
+#include <INETDefs.h>
+#include <TCPSocket.h>
+#include <map>
+#include <iostream>
+#include <sstream>
+#include <vector>
+
+using std::vector;
+using std::ostringstream;
+using std::cout;
+using std::pair;
+using std::make_pair;
+using std::map;
+using std::multimap;
+using ariba::utility::seqnum_t;
+using ariba::utility::Message;
+using ariba::utility::Address;
+using ariba::utility::serialization::data_serialize;
+using ariba::communication::IPv4Locator;
+
+namespace ariba {
+namespace communication {
+
+class INET_API AribaOmnetModule : public cSimpleModule, public TransportProtocol, TCPSocket::CallbackInterface {
+
+	use_logging_h( AribaOmnetModule );
+
+public:
+	AribaOmnetModule();
+	virtual ~AribaOmnetModule();
+
+	void setServerPort(uint16_t _port);
+
+	/**
+	 * see TransportProtocol
+	 */
+	virtual void start();
+	virtual void stop();
+	virtual TransportLocator::prot_t getId();
+	virtual const vector<TransportLocator*> getLocators();
+	virtual seqnum_t sendMessage( const Message* message );
+
+	/**
+	 * see TCPSocket::CallbackInterface
+	 */
+	virtual void socketDataArrived( int connId, void* socket, cMessage* msg, bool urgent );
+	virtual void socketFailure( int connId, void* socket, int code );
+	virtual void socketClosed( int connId, void* socket );
+	virtual void socketPeerClosed( int connId, void* socket );
+	virtual void socketEstablished( int connId, void* socket );
+	virtual void socketStatusArrived( int connId, void* socket, TCPStatusInfo *status);
+
+protected:
+	/**
+	 * Called from Omnet++ on initialization of the simulation
+	 */
+	virtual void initialize(int stage);
+ 	virtual int numInitStages () const ;
+
+	/**
+	 * Called from Omnet++ during simulation:
+	 * called when the module receives a message
+	 */
+	virtual void handleMessage( cMessage* msg );
+
+	/** Called from Omnet++ during simulation:
+	 * called when the simulation terminates.
+	 * Can be used for writing statistics and the likes.
+	 */
+	virtual void finish();
+
+private:
+	/**
+	 * All our sockets to other nodes and the server socket
+	 */
+	TCPSocket serverSocket;
+	typedef multimap<string, TCPSocket*> SocketMap;
+	SocketMap sockets;
+	uint16_t serverPort;
+
+	/**
+	 * Pending data that we have to send when the socket
+	 * has been opened asynchronously
+	 */
+	typedef map<TCPSocket*, AribaOmnetMessage*> PendingSendQueue;
+	PendingSendQueue pendingSends;
+
+};
+
+//
+// The module class needs to be registered with OMNeT++
+//
+
+Define_Module( AribaOmnetModule );
+
+}} // namespace ariba, communication
+
+#endif // ARIBA_OMNET_MODULE_H__
Index: /trash/old-modules/transport/protlib/address.cpp
===================================================================
--- /trash/old-modules/transport/protlib/address.cpp	(revision 5641)
+++ /trash/old-modules/transport/protlib/address.cpp	(revision 5641)
@@ -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;
+	const 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: /trash/old-modules/transport/protlib/address.h
===================================================================
--- /trash/old-modules/transport/protlib/address.h	(revision 5641)
+++ /trash/old-modules/transport/protlib/address.h	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/assocdata.h
===================================================================
--- /trash/old-modules/transport/protlib/assocdata.h	(revision 5641)
+++ /trash/old-modules/transport/protlib/assocdata.h	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/assocdata_uds.h
===================================================================
--- /trash/old-modules/transport/protlib/assocdata_uds.h	(revision 5641)
+++ /trash/old-modules/transport/protlib/assocdata_uds.h	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/cleanuphandler.h
===================================================================
--- /trash/old-modules/transport/protlib/cleanuphandler.h	(revision 5641)
+++ /trash/old-modules/transport/protlib/cleanuphandler.h	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/configuration.cpp
===================================================================
--- /trash/old-modules/transport/protlib/configuration.cpp	(revision 5641)
+++ /trash/old-modules/transport/protlib/configuration.cpp	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/configuration.h
===================================================================
--- /trash/old-modules/transport/protlib/configuration.h	(revision 5641)
+++ /trash/old-modules/transport/protlib/configuration.h	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/connectionmap.cpp
===================================================================
--- /trash/old-modules/transport/protlib/connectionmap.cpp	(revision 5641)
+++ /trash/old-modules/transport/protlib/connectionmap.cpp	(revision 5641)
@@ -0,0 +1,162 @@
+/// ----------------------------------------*- 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 
+{
+	// hack: only search for ip addresses!
+	const char* addr_ip = addr.get_ip_str();
+	for (const_addr2data_it_t::const_iterator i=addr2data.begin(); i!=addr2data.end(); i++) {
+		const appladdress& map_addr = i->first;
+		const char* map_ip =  map_addr.get_ip_str();
+		if (strcmp(map_ip, addr_ip)==0) return i->second;
+	}
+	return NULL;
+
+//	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: /trash/old-modules/transport/protlib/connectionmap.h
===================================================================
--- /trash/old-modules/transport/protlib/connectionmap.h	(revision 5641)
+++ /trash/old-modules/transport/protlib/connectionmap.h	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/connectionmap_uds.cpp
===================================================================
--- /trash/old-modules/transport/protlib/connectionmap_uds.cpp	(revision 5641)
+++ /trash/old-modules/transport/protlib/connectionmap_uds.cpp	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/connectionmap_uds.h
===================================================================
--- /trash/old-modules/transport/protlib/connectionmap_uds.h	(revision 5641)
+++ /trash/old-modules/transport/protlib/connectionmap_uds.h	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/eclock_gettime.c
===================================================================
--- /trash/old-modules/transport/protlib/eclock_gettime.c	(revision 5641)
+++ /trash/old-modules/transport/protlib/eclock_gettime.c	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/fastqueue.c
===================================================================
--- /trash/old-modules/transport/protlib/fastqueue.c	(revision 5641)
+++ /trash/old-modules/transport/protlib/fastqueue.c	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/fastqueue.h
===================================================================
--- /trash/old-modules/transport/protlib/fastqueue.h	(revision 5641)
+++ /trash/old-modules/transport/protlib/fastqueue.h	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/fqueue.cpp
===================================================================
--- /trash/old-modules/transport/protlib/fqueue.cpp	(revision 5641)
+++ /trash/old-modules/transport/protlib/fqueue.cpp	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/fqueue.h
===================================================================
--- /trash/old-modules/transport/protlib/fqueue.h	(revision 5641)
+++ /trash/old-modules/transport/protlib/fqueue.h	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/ie.cpp
===================================================================
--- /trash/old-modules/transport/protlib/ie.cpp	(revision 5641)
+++ /trash/old-modules/transport/protlib/ie.cpp	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/ie.h
===================================================================
--- /trash/old-modules/transport/protlib/ie.h	(revision 5641)
+++ /trash/old-modules/transport/protlib/ie.h	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/llhashers.h
===================================================================
--- /trash/old-modules/transport/protlib/llhashers.h	(revision 5641)
+++ /trash/old-modules/transport/protlib/llhashers.h	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/logfile.cpp
===================================================================
--- /trash/old-modules/transport/protlib/logfile.cpp	(revision 5641)
+++ /trash/old-modules/transport/protlib/logfile.cpp	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/logfile.h
===================================================================
--- /trash/old-modules/transport/protlib/logfile.h	(revision 5641)
+++ /trash/old-modules/transport/protlib/logfile.h	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/messages.cpp
===================================================================
--- /trash/old-modules/transport/protlib/messages.cpp	(revision 5641)
+++ /trash/old-modules/transport/protlib/messages.cpp	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/messages.h
===================================================================
--- /trash/old-modules/transport/protlib/messages.h	(revision 5641)
+++ /trash/old-modules/transport/protlib/messages.h	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/network_message.cpp
===================================================================
--- /trash/old-modules/transport/protlib/network_message.cpp	(revision 5641)
+++ /trash/old-modules/transport/protlib/network_message.cpp	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/network_message.h
===================================================================
--- /trash/old-modules/transport/protlib/network_message.h	(revision 5641)
+++ /trash/old-modules/transport/protlib/network_message.h	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/protlib_types.h
===================================================================
--- /trash/old-modules/transport/protlib/protlib_types.h	(revision 5641)
+++ /trash/old-modules/transport/protlib/protlib_types.h	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/queuemanager.cpp
===================================================================
--- /trash/old-modules/transport/protlib/queuemanager.cpp	(revision 5641)
+++ /trash/old-modules/transport/protlib/queuemanager.cpp	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/queuemanager.h
===================================================================
--- /trash/old-modules/transport/protlib/queuemanager.h	(revision 5641)
+++ /trash/old-modules/transport/protlib/queuemanager.h	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/setuid.cpp
===================================================================
--- /trash/old-modules/transport/protlib/setuid.cpp	(revision 5641)
+++ /trash/old-modules/transport/protlib/setuid.cpp	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/setuid.h
===================================================================
--- /trash/old-modules/transport/protlib/setuid.h	(revision 5641)
+++ /trash/old-modules/transport/protlib/setuid.h	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/testqueue.c
===================================================================
--- /trash/old-modules/transport/protlib/testqueue.c	(revision 5641)
+++ /trash/old-modules/transport/protlib/testqueue.c	(revision 5641)
@@ -0,0 +1,121 @@
+/// ----------------------------------------*- 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;
+}
+
+int
+main(int argc, char **argv)
+{
+  void *exit_value;        /* for pthread_join */
+
+  fprintf(stderr,"<program start>\n");
+  /** create a queue **/
+  if ((consumer_cmdq= create_queue("testqueue"))==NULL) exit(1);
+
+  /** Start Threads **/
+  status= pthread_create(&consumer_thread,
+                         NULL,
+                         consumertask,
+                         NULL);
+  error_check(status,"fatal: cannot create consumertask");
+
+  status= pthread_create(&producer_thread,
+                         NULL,
+                         producertask,
+                         NULL);
+  error_check(status,"fatal: cannot create producertask");
+
+  /** wait for threads to end **/
+  status= pthread_join(producer_thread, &exit_value);
+  error_check(status,"pthread_join");
+
+  status= pthread_join(consumer_thread, &exit_value);
+  error_check(status,"pthread_join");
+
+  /** destroy all queues **/
+  status= destroy_queue(consumer_cmdq);
+  error_check(status,"destroying consumer queue");
+
+  fprintf(stderr,"<program exited normally>\n");
+   return 0;
+}
+/**** end of source ****/
+
+//@}
Index: /trash/old-modules/transport/protlib/threads.cpp
===================================================================
--- /trash/old-modules/transport/protlib/threads.cpp	(revision 5641)
+++ /trash/old-modules/transport/protlib/threads.cpp	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/threads.h
===================================================================
--- /trash/old-modules/transport/protlib/threads.h	(revision 5641)
+++ /trash/old-modules/transport/protlib/threads.h	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/threadsafe_db.cpp
===================================================================
--- /trash/old-modules/transport/protlib/threadsafe_db.cpp	(revision 5641)
+++ /trash/old-modules/transport/protlib/threadsafe_db.cpp	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/threadsafe_db.h
===================================================================
--- /trash/old-modules/transport/protlib/threadsafe_db.h	(revision 5641)
+++ /trash/old-modules/transport/protlib/threadsafe_db.h	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/timer.cpp
===================================================================
--- /trash/old-modules/transport/protlib/timer.cpp	(revision 5641)
+++ /trash/old-modules/transport/protlib/timer.cpp	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/timer.h
===================================================================
--- /trash/old-modules/transport/protlib/timer.h	(revision 5641)
+++ /trash/old-modules/transport/protlib/timer.h	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/timer_module.cpp
===================================================================
--- /trash/old-modules/transport/protlib/timer_module.cpp	(revision 5641)
+++ /trash/old-modules/transport/protlib/timer_module.cpp	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/timer_module.h
===================================================================
--- /trash/old-modules/transport/protlib/timer_module.h	(revision 5641)
+++ /trash/old-modules/transport/protlib/timer_module.h	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/tp.cpp
===================================================================
--- /trash/old-modules/transport/protlib/tp.cpp	(revision 5641)
+++ /trash/old-modules/transport/protlib/tp.cpp	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/tp.h
===================================================================
--- /trash/old-modules/transport/protlib/tp.h	(revision 5641)
+++ /trash/old-modules/transport/protlib/tp.h	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/tp_over_tcp.cpp
===================================================================
--- /trash/old-modules/transport/protlib/tp_over_tcp.cpp	(revision 5641)
+++ /trash/old-modules/transport/protlib/tp_over_tcp.cpp	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/tp_over_tcp.h
===================================================================
--- /trash/old-modules/transport/protlib/tp_over_tcp.h	(revision 5641)
+++ /trash/old-modules/transport/protlib/tp_over_tcp.h	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/tp_over_tls_tcp.cpp
===================================================================
--- /trash/old-modules/transport/protlib/tp_over_tls_tcp.cpp	(revision 5641)
+++ /trash/old-modules/transport/protlib/tp_over_tls_tcp.cpp	(revision 5641)
@@ -0,0 +1,1873 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file tp_over_tls_tcp.cpp
+/// TCP/TLS-based transport module
+/// ----------------------------------------------------------
+/// $Id: tp_over_tls_tcp.cpp 2872 2008-02-18 10:58:03Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/src/tp_over_tls_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_tls_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_tls[INET6_ADDRSTRLEN+1];
+
+
+/******* class TPoverTLS_TCP *******/
+
+/*
+ * Obtain reason string for last SSL error
+ *
+ * Some caution is needed here since ERR_reason_error_string will
+ * return NULL if it doesn't recognize the error code.  We don't
+ * want to return NULL ever.
+ */
+const char *
+TPoverTLS_TCP::SSLerrmessage(void)
+{
+	unsigned long	errcode;
+	const char	   *errreason;
+	static char		errbuf[32];
+
+	errcode = ERR_get_error();
+	if (errcode == 0)
+		return "No SSL error reported";
+	errreason = ERR_reason_error_string(errcode);
+	if (errreason != NULL)
+		return errreason;
+	snprintf(errbuf, sizeof(errbuf), "SSL error code %lu", errcode);
+	return errbuf;
+}
+
+
+
+/** 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* 
+TPoverTLS_TCP::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(TPoverTLS_TCP, 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?
+	Log(ERROR_LOG,LOG_CRIT,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)
+    {
+      Log(ERROR_LOG,LOG_CRIT,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)
+    {
+        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(new_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));
+    }
+
+    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)
+    {
+      Log(ERROR_LOG,LOG_NORMAL, tpparam.name,"Connect to " << addr.get_ip_str() << " port #" << addr.get_port() 
+	  << " failed: [" << color[red] << strerror(errno) << color[off] << "]");
+      // FIXME: that doesn't work gracefully
+      //throw TPError(TPError::ERROR_UNREACHABLE);
+      return 0;
+    }
+    
+    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_tls,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));
+
+    DLog(tpparam.name, "Before creation of a new SSL object");
+
+    SSL *ssl = NULL;
+
+    if (!ssl_ctx) ERRCLog(tpparam.name, "Could not create SSL context");
+
+    ssl = SSL_new(ssl_ctx);
+    
+    if (!ssl)
+    {
+      ERRCLog(tpparam.name,"could not create SSL context: " << SSLerrmessage());
+    }
+
+    if (!ssl) 
+      ERRCLog(tpparam.name, "Could not create SSL object");
+ 
+    DLog(tpparam.name, "Before binding it to the socket");
+
+    SSL_set_fd(ssl, new_socket);
+    
+    DLog(tpparam.name, "Bound SSL object to the socket");
+
+
+    // Connect to the server
+    if ((SSL_connect(ssl)) < 1) {
+	ERRCLog(tpparam.name, "SSL connect failed in get_connection_to(): " << SSLerrmessage());
+    }
+
+    sslmap[new_socket]=ssl;
+
+    DLog(tpparam.name, "Inserted SSL object into sslmap");
+
+    // if assoc could be successfully created, insert it into ConnectionMap
+    if (assoc) 
+    {
+      bool insert_success= false;
+      // start critical section
+      lock(); // install_cleanup_thread_lock(TPoverTLS_TCP, 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)
+	TPoverTLS_TCPMsg* newmsg= new(nothrow)TPoverTLS_TCPMsg(assoc, tpparam.source, TPoverTLS_TCPMsg::start);
+	if (newmsg)
+	{
+	  newmsg->send_to(tpparam.source);
+	  return assoc;
+	}
+	else
+	  Log(ERROR_LOG,LOG_CRIT,tpparam.name,"get_connection_to: could not get memory for internal msg");
+      } 
+      else 
+      {
+	// delete data and abort
+	Log(ERROR_LOG,LOG_CRIT, 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
+TPoverTLS_TCP::terminate(const address& in_addr)
+{
+
+    appladdress* addr = NULL;
+    addr= dynamic_cast<appladdress*>(in_addr.copy());
+    
+    if (!addr) return;
+
+#ifndef _NO_LOGGING
+  const char *const thisproc="terminate()   - ";
+#endif
+
+  // 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(TPoverTLS_TCP, this);
+  assoc= connmap.lookup(*addr);
+  if (assoc) 
+  {
+    Log(EVENT_LOG,LOG_NORMAL,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))
+	{
+	  Log(ERROR_LOG,LOG_UNIMP,tpparam.name,thisproc<<"shutdown (write) on socket for peer " << *addr << " returned error:" << strerror(errno));
+	}
+	else
+        {
+	  Log(EVENT_LOG,LOG_NORMAL,tpparam.name,thisproc<<"initiated closing of connection for peer " << *addr << ". Shutdown (write) on socket "<< assoc->socketfd );	  
+	}
+      }
+      assoc->shutdown= true;
+    }
+    else
+      Log(EVENT_LOG,LOG_NORMAL,tpparam.name,thisproc<<"connection for peer " << *addr << " is already in mode shutdown");
+      
+  }
+  else
+    Log(WARNING_LOG,LOG_NORMAL,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 TPoverTLS_TCP 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 TPoverTLS_TCP::tcpsend()
+ *  - if no connection exists, creates a new one
+ *  @note the netmsg is deleted by the send() method when it is not used anymore
+ */
+void
+TPoverTLS_TCP::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 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!
+    
+    TPoverTLS_TCPMsg* internalmsg= new TPoverTLS_TCPMsg(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
+TPoverTLS_TCP::tcptlssend(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 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 {
+      Log(ERROR_LOG,LOG_CRIT, tpparam.name, thisproc << "address pointer is NULL");
+      result= TCP_SEND_FAILURE;    
+      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)
+  {
+    Log(ERROR_LOG,LOG_CRIT, tpparam.name, thisproc << "no valid assoc/socket data");
+
+    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
+
+
+  // get SSL connection data
+  SSL* ssl= sslmap[assoc->socketfd];
+
+
+  // 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
+
+
+    // socket send
+    //ret= ::send(assoc->socketfd, 
+//		netmsg->get_buffer() + bytes_sent,  
+//		msgsize - bytes_sent, 
+//		MSG_NOSIGNAL);
+
+
+    ret = SSL_write(ssl, netmsg->get_buffer() + bytes_sent, msgsize - bytes_sent);
+
+    //int SSL_write(SSL *ssl, const void *buf, int num);
+
+    //send_buf + bytes_sent
+
+    if (debug_pdu)
+    {
+      ostringstream hexdump;
+      netmsg->hexdump(hexdump,netmsg->get_buffer(),bytes_sent);
+      Log(DEBUG_LOG,LOG_NORMAL,tpparam.name,"PDU debugging enabled - Sent:" << hexdump.str());
+    }
+
+    if (ret < 0) 
+    {
+      result= TCP_SEND_FAILURE;
+      break;
+    } // end if (ret < 0)
+  } // 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)
+  {
+    Log(ERROR_LOG,LOG_NORMAL, tpparam.name, thisproc << "TLS/TCP 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 " << assoc->socketfd  << " to " << *addr);
+
+  if (!assoc) {
+    // no connection
+    
+    Log(ERROR_LOG,LOG_NORMAL, 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 
+TPoverTLS_TCP::sender_thread(void *argp)
+{
+#ifndef _NO_LOGGING
+  const char *const methodname="senderthread - ";
+#endif
+
+  message* internal_thread_msg = NULL;
+
+  Log(EVENT_LOG,LOG_NORMAL, tpparam.name, methodname << "starting as thread <" << pthread_self() << ">");
+
+  FastQueue* fq= reinterpret_cast<FastQueue*>(argp);
+  if (!fq)
+  {
+    Log(ERROR_LOG,LOG_NORMAL, tpparam.name, methodname << "thread <" << pthread_self() << "> no valid pointer to msg queue. Stop.");
+    return;
+  }
+
+  bool terminate= false;
+  TPoverTLS_TCPMsg* internalmsg= 0;
+  while (terminate==false && (internal_thread_msg= fq->dequeue()) != 0 )
+  {
+    internalmsg= dynamic_cast<TPoverTLS_TCPMsg*>(internal_thread_msg);
+    
+    if (internalmsg == 0)
+    {
+      Log(ERROR_LOG,LOG_NORMAL, tpparam.name, methodname << "received not an TPoverTLS_TCPMsg but a" << internal_thread_msg->get_type_name());      
+    }
+    else
+    if (internalmsg->get_msgtype() == TPoverTLS_TCPMsg::send_data)
+    {
+      // create a connection if none exists and send the netmsg
+      if (internalmsg->get_netmsg() && internalmsg->get_appladdr())
+      {
+	tcptlssend(internalmsg->get_netmsg(),internalmsg->get_appladdr());
+      }
+      else
+      {
+	Log(ERROR_LOG,LOG_NORMAL, tpparam.name, methodname << "problem with passed arguments references, they point to 0");
+      } 
+    }
+    else
+    if (internalmsg->get_msgtype() == TPoverTLS_TCPMsg::stop)
+    {
+      terminate= true;
+    }  
+  } // end while
+  
+  Log(EVENT_LOG,LOG_NORMAL, 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 
+TPoverTLS_TCP::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;
+
+  //uchar* sslbuffer = NULL;
+ 
+  
+  // argument parsing - start
+  if (receiver_thread_argp == 0)
+  {
+    Log(ERROR_LOG,LOG_CRIT, 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
+    Log(DEBUG_LOG,LOG_UNIMP, 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
+  {
+    Log(ERROR_LOG,LOG_CRIT, tpparam.name, methodname << "No peer assoc available - pointer is NULL");
+    
+    return;
+  }
+
+  if (peer_addr == 0)
+  {
+    Log(ERROR_LOG,LOG_CRIT, 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
+  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; 
+
+  int poll_status;
+  bool recv_error= false;
+
+  //get SSL handle
+  SSL *ssl=sslmap[conn_socket];
+
+  NetMsg* netmsg= 0;
+  NetMsg* remainbuf= 0;
+  uint32 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)
+	  {
+	    Log(EVENT_LOG,LOG_NORMAL, tpparam.name, methodname << "poll(): " << strerror(errno));
+	  }
+	  else
+	  {
+	    Log(ERROR_LOG,LOG_CRIT, 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
+	{
+	  Log(ERROR_LOG,LOG_CRIT, 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)
+	    {
+	      Log(EVENT_LOG,LOG_NORMAL, tpparam.name, methodname << "Poll status: " << strerror(errno));
+	    }
+	    else
+	    {
+	      Log(ERROR_LOG,LOG_CRIT, 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
+
+	/// spawn a new buffer for SSL decoding
+	//sslbuffer = new(nothrow) uchar[NetMsg::max_size];
+
+	/// receive data from socket buffer (recv will not block)
+	//ret = recv(conn_socket, 
+	//	   netmsg->get_buffer() + bytes_received, 
+	//	   buffer_bytes_left, 
+	//	   0);
+	
+	/// try to read from SSL
+	ret = SSL_read(ssl, netmsg->get_buffer() + bytes_received, buffer_bytes_left);
+
+
+	/// memcpy decoded contents back into netmsg
+	//memcpy(netmsg->get_buffer() + bytes_received, sslbuffer, buffer_bytes_left);
+
+	/// delete sslbuffer
+	//delete sslbuffer;
+
+	if ( ret < 0 )
+	{
+	  if (errno!=EAGAIN && errno!=EWOULDBLOCK)
+	  {
+	    Log(ERROR_LOG,LOG_CRIT, 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
+	  {
+	      Log(ERROR_LOG,LOG_CRIT, tpparam.name, methodname << "Not a valid protocol header - discarding received packet. received size " << msgcontentlength);
+
+	    ostringstream hexdumpstr;
+	    netmsg->hexdump(hexdumpstr,netmsg->get_buffer(),bytes_received);
+	    Log(DEBUG_LOG,LOG_NORMAL,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 && 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)
+	{
+	  Log(WARNING_LOG,LOG_NORMAL,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);
+	}
+      }
+    } // 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());
+
+      Log(DEBUG_LOG,LOG_NORMAL, tpparam.name, methodname << "receipt of PDU now complete, sending 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_to(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
+  TPoverTLS_TCPMsg* newmsg= new(nothrow)TPoverTLS_TCPMsg(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 
+TPoverTLS_TCP::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 
+TPoverTLS_TCP::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 
+TPoverTLS_TCP::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)
+    {
+      TPoverTLS_TCPMsg* internalmsg= new TPoverTLS_TCPMsg(assoc,tpparam.source,TPoverTLS_TCPMsg::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 
+TPoverTLS_TCP::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 TPoverTLS_TCP object instance and receiver_thread_arg_t struct
+ */
+void*
+TPoverTLS_TCP::sender_thread_starter(void *argp)
+{
+  sender_thread_start_arg_t *sargp= static_cast<sender_thread_start_arg_t *>(argp);
+  
+  // 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);
+
+    // 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 TPoverTLS_TCP object instance and receiver_thread_arg_t struct
+ */
+void*
+TPoverTLS_TCP::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
+TPoverTLS_TCP::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
+				     TPoverTLS_TCP::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
+TPoverTLS_TCP::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(TPoverTLS_TCP, 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 TPoverTLS_TCP object instance
+ */
+void*
+TPoverTLS_TCP::master_listener_thread_starter(void *argp)
+{
+  // invoke listener thread method
+  if (argp != 0)
+  {
+    (static_cast<TPoverTLS_TCP*>(argp))->master_listener_thread();
+  }
+  return 0;
+}
+
+
+int 
+verify_callback(int ok, X509_STORE_CTX * store)
+{
+  if (!ok) {
+    ERRLog("TPoverTLS", color[red] << "Client cert check failed" << color[off]);
+  } else {
+    DLog("TPoverTLS", color[green] << "Client cert check OK" << color[off]);
+  };
+  return ok;
+}
+
+
+/**
+ * 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
+TPoverTLS_TCP::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_tls, 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; 
+    /*
+      #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) {
+
+	  // initialise SSL handshake, save ssl pointer in sslmap
+	  
+	  SSL_CTX *ssl_ctx_server = SSL_CTX_new(TLSv1_server_method());
+	  
+	  // Load client certificate
+	  if (SSL_CTX_use_certificate_chain_file(ssl_ctx_server, "client_cert.pem") != 1) {
+	      ERRCLog(tpparam.name, "Unable to load client certificate");
+	      this->abort_processing();
+	      
+	  }
+	  
+	  // Load private key
+	  if (SSL_CTX_use_PrivateKey_file(ssl_ctx_server, "client_privkey.pem", SSL_FILETYPE_PEM) != 1) {
+	    ERRCLog(tpparam.name, "Unable to load private Key, reason:" << SSLerrmessage());
+	      this->abort_processing();
+	  }
+	  
+	  // Verify private key
+	  if (SSL_CTX_load_verify_locations(ssl_ctx_server, "root_cert.pem", ".") != 1) {
+	      ERRCLog(tpparam.name, "Private Key failed verification against CA");
+	      this->abort_processing();
+	  }
+	  
+	  
+	  
+	  
+	  // We trust clients from this CA
+	  SSL_CTX_set_client_CA_list(ssl_ctx_server, SSL_load_client_CA_file("root_cert.pem"));
+	  
+	  // Enable (optional) client authentication
+	  SSL_CTX_set_verify(ssl_ctx_server, SSL_VERIFY_PEER, verify_callback);
+	  SSL_CTX_set_verify_depth(ssl_ctx_server, 4);
+	  
+	  SSL *ssl = SSL_new(ssl_ctx_server);
+	  
+	  SSL_set_fd(ssl, conn_socket);
+	  
+	  int result = SSL_accept(ssl);
+	  
+	  if (result==-1) ERRCLog(tpparam.name, "SSL connect failed");
+	  
+	  sslmap[conn_socket]=ssl;
+	  
+	  DLog(tpparam.name, "SSL handle saved for future use with that socket");
+	  
+      }
+
+      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);
+
+	addr.set_protocol(prot_tls_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(TPoverTLS_TCP, 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()    
+
+
+TPoverTLS_TCP::~TPoverTLS_TCP()
+{
+  init= false;
+
+  Log(DEBUG_LOG,LOG_NORMAL, tpparam.name,  "Destructor called");
+
+  QueueManager::instance()->unregister_queue(tpparam.source);
+}
+
+/** TPoverTLS_TCP 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 TPoverTLS_TCPMsg types:
+ * - TPoverTLS_TCPMsg::stop - a particular receiver thread is terminated
+ * - TPoverTLS_TCPMsg::start - a particular receiver thread is started
+ * @param nr number of current thread instance
+ */
+void 
+TPoverTLS_TCP::main_loop(uint32 nr)
+{
+    SSL_library_init();
+    OpenSSL_add_ssl_algorithms();
+    SSL_load_error_strings();
+
+    ssl_ctx=SSL_CTX_new(TLSv1_client_method());
+
+    if (!ssl_ctx)
+    {
+      ERRCLog(tpparam.name, "could not create SSL context: "<< SSLerrmessage());
+    }
+
+    // Load client certificate
+    if (SSL_CTX_use_certificate_chain_file(ssl_ctx, tpparam.client_cert_filename) != 1) {
+	ERRCLog(tpparam.name, "Unable to load client certificate: " << SSLerrmessage());
+    }
+    else
+    {
+      DLog(tpparam.name, color[green] << "Client certificate successfully loaded from " <<  tpparam.client_cert_filename << color[off]); 
+    }
+    
+    // Load private key
+    if (SSL_CTX_use_PrivateKey_file(ssl_ctx, tpparam.client_privkey_filename, SSL_FILETYPE_PEM) != 1) {
+	ERRCLog(tpparam.name, "Unable to load private Key: " << SSLerrmessage());
+    }
+    else
+    {
+      DLog(tpparam.name, color[green] << "Private key successfully loaded from " <<  tpparam.client_privkey_filename << color[off]); 
+    }
+    
+    // Verify private key
+    if (SSL_CTX_load_verify_locations(ssl_ctx, tpparam.root_cert_filename, ".") != 1) {
+	ERRCLog(tpparam.name, "Private Key failed verification against CA");
+    }
+    else
+    {
+      DLog(tpparam.name, color[green] << "Private key successfully verified as being certified by our CA " <<  tpparam.root_cert_filename << color[off]); 
+    }
+
+
+  // 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
+    DLog(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 )
+    {
+      TPoverTLS_TCPMsg* internalmsg= dynamic_cast<TPoverTLS_TCPMsg*>(internal_thread_msg);
+      if (internalmsg)
+      {
+	if (internalmsg->get_msgtype() == TPoverTLS_TCPMsg::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() == TPoverTLS_TCPMsg::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: /trash/old-modules/transport/protlib/tp_over_tls_tcp.h
===================================================================
--- /trash/old-modules/transport/protlib/tp_over_tls_tcp.h	(revision 5641)
+++ /trash/old-modules/transport/protlib/tp_over_tls_tcp.h	(revision 5641)
@@ -0,0 +1,300 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file tp_over_tls_tcp.h
+/// Transport over TLS/TCP
+/// ----------------------------------------------------------
+/// $Id: tp_over_tls_tcp.h 2872 2008-02-18 10:58:03Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/tp_over_tls_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 transport
+ * @file tp_over_tls_tcp.h
+ * TP over TLS/TCP
+ */
+
+#ifndef TP_OVER_TLS_H
+#define TP_OVER_TLS_H
+
+#include <ext/hash_map>
+
+#include "tp.h"
+#include "threads.h"
+#include "threadsafe_db.h"
+#include "connectionmap.h"
+#include "assocdata.h"
+
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+
+
+namespace protlib 
+{
+
+/** this struct contains parameters that determine 
+  * the behavior of listener and receiver threads in TPoverTLS_TCP
+  * @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 TPoverTLS_TCPParam : public ThreadParam 
+{
+  /// constructor
+  TPoverTLS_TCPParam(
+	const char* client_cert_filename,
+	const char* client_privkey_filename,
+	const char* root_cert_filename,
+        unsigned short common_header_length,
+	bool (*const getmsglength) (NetMsg& m, uint32& clen_bytes),
+	port_t p,
+	const char* threadname= "TPoverTLS_TCP",
+	uint32 sleep = ThreadParam::default_sleep_time,
+	bool debug_pdu = false,
+	message::qaddr_t source = message::qaddr_tp_over_tls_tcp,
+	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),
+	client_cert_filename(client_cert_filename),
+	client_privkey_filename(client_privkey_filename),
+	root_cert_filename(root_cert_filename),
+	getmsglength(getmsglength),
+	terminate(false),
+	ip_tos(tos)
+  {
+    
+    //set up SSL
+    ssl_ctx_client = SSL_CTX_new(TLSv1_client_method());
+    ssl_ctx_server = SSL_CTX_new(TLSv1_server_method());
+    
+  };
+
+  /// 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;
+    
+  /// holds SSL context
+  SSL_CTX *ssl_ctx_client;
+  SSL_CTX *ssl_ctx_server;
+
+  const char* client_cert_filename;
+  const char* client_privkey_filename;
+  const char* root_cert_filename;
+  
+  /// 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 TPoverTLS_TCPParam
+
+
+typedef hash_map<uint32, SSL*> sslmap_t;
+
+/// TP over TCP
+/** This class implements the TP interface using TCP. */
+class TPoverTLS_TCP : 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
+  TPoverTLS_TCP(const TPoverTLS_TCPParam& p) :
+    TP(prot_tls_tcp,"TLS",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;
+    
+    
+    sslmap.resize(128);
+
+  }
+  /// virtual destructor
+  virtual ~TPoverTLS_TCP();
+  
+  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:
+    TPoverTLS_TCP* instance;
+    receiver_thread_arg_t* rtargp;
+    
+    receiver_thread_start_arg_t(TPoverTLS_TCP* instance, receiver_thread_arg_t* rtargp) :
+      instance(instance), rtargp(rtargp) {};
+  };
+
+  class sender_thread_start_arg_t
+  {
+  public:
+    TPoverTLS_TCP* instance;
+    FastQueue* sender_thread_queue;
+    
+    sender_thread_start_arg_t(TPoverTLS_TCP* 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);
+    
+  static const char *SSLerrmessage(void);
+
+  /// 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+TLS
+  void tcptlssend(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;
+    
+    
+  /// SSL Context
+  SSL_CTX *ssl_ctx;
+   
+  /// 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 TPoverTLS_TCP thread
+  const TPoverTLS_TCPParam tpparam;
+    
+  /// did we already abort at thread shutdown
+  bool already_aborted;
+  /// message queue
+  FastQueue* msgqueue;
+    
+  bool debug_pdu;
+
+  /// holds socket<->SSL pointer assignment
+  sslmap_t sslmap;
+    
+}; // end class TPoverTLS_TCP
+
+/** 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 TPoverTLS_TCPMsg : public message 
+{
+ public:
+  // message type start/stop thread, send data
+  enum msg_t { start, 
+	       stop,
+	       send_data
+  };
+
+ private:
+  const AssocData* peer_assoc;
+  const TPoverTLS_TCPMsg::msg_t type;
+  NetMsg* netmsg;
+  appladdress* addr;
+
+public:
+  TPoverTLS_TCPMsg(const AssocData* peer_assoc, message::qaddr_t source= qaddr_unknown, TPoverTLS_TCPMsg::msg_t type= stop) : 
+    message(type_transport, source), peer_assoc(peer_assoc), type(type), netmsg(0), addr(0)  {}
+
+  TPoverTLS_TCPMsg(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; }
+  TPoverTLS_TCPMsg::msg_t get_msgtype() const { return type; }
+  NetMsg* get_netmsg() const { return netmsg; }
+  appladdress* get_appladdr() const { return addr; } 
+};
+
+} // end namespace protlib
+
+#endif
Index: /trash/old-modules/transport/protlib/tp_over_udp.cpp
===================================================================
--- /trash/old-modules/transport/protlib/tp_over_udp.cpp	(revision 5641)
+++ /trash/old-modules/transport/protlib/tp_over_udp.cpp	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/tp_over_udp.h
===================================================================
--- /trash/old-modules/transport/protlib/tp_over_udp.h	(revision 5641)
+++ /trash/old-modules/transport/protlib/tp_over_udp.h	(revision 5641)
@@ -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: /trash/old-modules/transport/protlib/tp_over_uds.cpp
===================================================================
--- /trash/old-modules/transport/protlib/tp_over_uds.cpp	(revision 5641)
+++ /trash/old-modules/transport/protlib/tp_over_uds.cpp	(revision 5641)
@@ -0,0 +1,1651 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file tp_over_uds.cpp
+/// transport module for unix domain socket communication
+/// ----------------------------------------------------------
+/// $Id: tp_over_uds.cpp 2872 2008-02-18 10:58:03Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/src/tp_over_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.
+//
+// ===========================================================
+ 
+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 <sys/un.h>
+}
+
+#include <iostream>
+#include <errno.h>
+#include <string>
+#include <sstream>
+
+#include "tp_over_uds.h"
+#include "threadsafe_db.h"
+#include "cleanuphandler.h"
+#include "setuid.h"
+#include "queuemanager.h"
+#include "logfile.h"
+
+#include <set>
+
+#define UDS_SUCCESS 0
+#define UDS_SEND_FAILURE 1
+
+const unsigned int max_listen_queue_size= 10;
+
+namespace protlib {
+
+using namespace log;
+
+/** @defgroup tpuds TP over UDS
+ * @ingroup network
+ * @{
+ */
+
+
+/******* class TPoverUDS *******/
+
+
+/** 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.
+ */
+AssocDataUDS* 
+TPoverUDS::get_connection_to(udsaddress& 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
+  AssocDataUDS* 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(TPoverUDS, 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?
+	Log(ERROR_LOG,LOG_CRIT,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 << " found, creating a new one.");
+    }
+
+    // no connection found, create a new one
+    new_socket = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (new_socket == -1)
+    {
+      Log(ERROR_LOG,LOG_CRIT,tpparam.name,"Couldn't create a new socket: " << strerror(errno));
+
+      return 0;
+    }
+    
+    // Reuse ports, even if they are busy
+    int socketreuseflag= 1;
+    int status= setsockopt(new_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));
+    }
+
+    struct sockaddr_un dest_address;
+    dest_address.sun_family= AF_UNIX;
+    strcpy(dest_address.sun_path, addr.get_udssocket().c_str());
+      
+    // 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)
+    {
+	Log(ERROR_LOG,LOG_NORMAL, tpparam.name,"Connect to " << addr.get_udssocket() << "failed: [" << color[red] << strerror(errno) << color[off] << "]");
+      
+      throw TPErrorConnectSetupFail();
+    }
+
+    
+    //struct sockaddr_un 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 << " from " << udsaddress(new_socket));
+    
+    // create new AssocData record (will copy addr)
+    assoc = new(nothrow) AssocDataUDS(new_socket, addr, udsaddress(new_socket));
+
+    // if assoc could be successfully created, insert it into ConnectionMap
+    if (assoc) 
+    {
+      bool insert_success= false;
+      // start critical section
+      lock(); // install_cleanup_thread_lock(TPoverUDS, 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 << " via socket " << new_socket);
+
+		
+#endif
+
+	// notify master thread to start a receiver thread (i.e. send selfmessage)
+	TPoverUDSMsg* newmsg= new(nothrow)TPoverUDSMsg(assoc, tpparam.source, TPoverUDSMsg::start);
+	if (newmsg)
+	{
+	  newmsg->send_to(tpparam.source);
+	  return assoc;
+	}
+	else
+	  Log(ERROR_LOG,LOG_CRIT,tpparam.name,"get_connection_to: could not get memory for internal msg");
+      } 
+      else 
+      {
+	// delete data and abort
+	Log(ERROR_LOG,LOG_CRIT, tpparam.name, "Cannot insert AssocData for socket " << new_socket << ", "<< addr << " 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
+TPoverUDS::terminate(const address& in_addr)
+{
+
+    udsaddress* addr = NULL;
+    addr = dynamic_cast<udsaddress*>(in_addr.copy());
+
+#ifndef _NO_LOGGING
+  const char *const thisproc="terminate()   - ";
+#endif
+
+  // Create a new AssocData-pointer 
+  AssocDataUDS* 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(TPoverUDS, this);
+  assoc= connmap.lookup(*addr);
+  if (assoc) 
+  {
+    Log(EVENT_LOG,LOG_NORMAL,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))
+	{
+	  Log(ERROR_LOG,LOG_UNIMP,tpparam.name,thisproc<<"shutdown (write) on socket for peer " << addr << " returned error:" << strerror(errno));
+	}
+	else
+        {
+	  Log(EVENT_LOG,LOG_NORMAL,tpparam.name,thisproc<<"initiated closing of connection for peer " << addr << ". Shutdown (write) on socket "<< assoc->socketfd );	  
+	}
+      }
+      assoc->shutdown= true;
+    }
+    else
+      Log(EVENT_LOG,LOG_NORMAL,tpparam.name,thisproc<<"connection for peer " << addr << " is already in mode shutdown");
+      
+  }
+  else
+    Log(WARNING_LOG,LOG_NORMAL,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 TPoverUDS 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 TPoverUDS::udssend()
+ *  - if no connection exists, creates a new one
+ *
+ *  @note the netmsg is deleted by the send() method when it is not used anymore
+ */
+void
+TPoverUDS::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;
+    }
+
+    udsaddress* addr = NULL;
+    addr = dynamic_cast<udsaddress*>(in_addr.copy());
+
+    if (!addr)
+    {
+      ERRCLog(tpparam.name,"send() - given destination address is not of expected type (udsaddress), 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 so far
+
+    if (!use_existing_connection)
+    { // 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<udsaddress,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!
+    
+      //DLog(tpparam.name, "Sending self-message for socket " << addr->get_udssocket().c_str());
+
+      TPoverUDSMsg* internalmsg= new TPoverUDSMsg(netmsg,addr->copy());
+      if (internalmsg)
+      {
+	  //DLog(tpparam.name, "Address in internal message: " << internalmsg->get_appladdr()->get_udssocket());
+          // 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 " << *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
+TPoverUDS::udssend(NetMsg* netmsg, udsaddress* 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 = UDS_SUCCESS;
+  int ret= 0;
+
+  // Create a new AssocData-pointer 
+  AssocDataUDS* 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) {
+      if (!(addr->get_udssocket().size() || addr->get_socknum())) {
+	  ERRCLog(tpparam.name, "No UNIX Domain Socket Path / Socket Number in address, will not process it: " << addr->get_udssocket());
+	  return;
+      }
+  } else {
+      Log(ERROR_LOG,LOG_CRIT, tpparam.name, thisproc << "address pointer is NULL");
+      result= UDS_SEND_FAILURE;    
+      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)
+  {
+    Log(ERROR_LOG,LOG_CRIT, tpparam.name, thisproc << "no valid assoc/socket data");
+
+    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
+
+  // 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
+
+    // socket send
+    ret= ::send(assoc->socketfd, 
+		netmsg->get_buffer() + bytes_sent,  
+		msgsize - bytes_sent, 
+		MSG_NOSIGNAL);
+
+    //send_buf + bytes_sent
+
+    if (debug_pdu)
+    {
+      ostringstream hexdump;
+      netmsg->hexdump(hexdump,netmsg->get_buffer(),bytes_sent);
+      Log(DEBUG_LOG,LOG_NORMAL,tpparam.name,"PDU debugging enabled - Sent:" << hexdump.str());
+    }
+
+    if (ret < 0) 
+    {
+      result= UDS_SEND_FAILURE;
+      break;
+    } // end if (ret < 0)
+  } // end for
+
+
+  // *** note: netmsg is deleted here ***
+  delete netmsg;
+  
+  // Throwing an exception within a critical section does not 
+  // unlock the mutex.
+
+  if (result != UDS_SUCCESS)
+  {
+    Log(ERROR_LOG,LOG_NORMAL, tpparam.name, thisproc << "Unix Domain Socket error, returns " << ret << ", error : " << strerror(errno));
+    delete addr;
+
+    throw TPErrorSendFailed();
+    
+    // There is no special errorcode for sending failed
+    // in tp.h, there are only these:
+    /*
+      ERROR_BAD_ADDRESS,
+      ERROR_BAD_NETMSG,
+      ERROR_NOT_INIT,
+      ERROR_UNREACHABLE,
+      ERROR_INTERNAL,
+      ERROR_PAYLOAD
+    */
+  }
+  else
+    Log(EVENT_LOG,LOG_NORMAL,tpparam.name, thisproc << ">>----Sent---->> message (" << msgsize << " bytes) using socket " << assoc->socketfd  << " to " << *addr);
+
+  if (!assoc) {
+    // no connection
+    
+    Log(ERROR_LOG,LOG_NORMAL, tpparam.name, thisproc << "cannot get connection to " << *addr);
+
+    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 
+TPoverUDS::sender_thread(void *argp)
+{
+#ifndef _NO_LOGGING
+  const char *const methodname="senderthread - ";
+#endif
+
+  message* internal_thread_msg = NULL;
+
+  Log(EVENT_LOG,LOG_NORMAL, tpparam.name, methodname << "starting as thread <" << pthread_self() << ">");
+
+  FastQueue* fq= reinterpret_cast<FastQueue*>(argp);
+  if (!fq)
+  {
+    Log(ERROR_LOG,LOG_NORMAL, tpparam.name, methodname << "thread <" << pthread_self() << "> no valid pointer to msg queue. Stop.");
+    return;
+  }
+
+  bool terminate= false;
+  TPoverUDSMsg* internalmsg= 0;
+  while (terminate==false && (internal_thread_msg= fq->dequeue()) != 0 )
+  {
+    internalmsg= dynamic_cast<TPoverUDSMsg*>(internal_thread_msg);
+    
+    if (internalmsg == 0)
+    {
+      Log(ERROR_LOG,LOG_NORMAL, tpparam.name, methodname << "received not an TPoverUDSMsg but a" << internal_thread_msg->get_type_name());      
+    }
+    else
+    if (internalmsg->get_msgtype() == TPoverUDSMsg::send_data)
+    {
+      
+	//DLog(tpparam.name, "Got a send request for socket " << *(internalmsg->get_appladdr()));
+
+      // create a connection if none exists and send the netmsg
+      if (internalmsg->get_netmsg() && internalmsg->get_udsaddr())
+      {
+	udssend(internalmsg->get_netmsg(),internalmsg->get_udsaddr());
+      }
+      else
+      {
+	Log(ERROR_LOG,LOG_NORMAL, tpparam.name, methodname << "problem with passed arguments references, they point to 0");
+      } 
+    }
+    else
+    if (internalmsg->get_msgtype() == TPoverUDSMsg::stop)
+    {
+      terminate= true;
+    }  
+  } // end while
+  
+  Log(EVENT_LOG,LOG_NORMAL, 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 
+TPoverUDS::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 udsaddress* peer_addr = NULL;
+  const udsaddress* own_addr = NULL;
+  uint32 bytes_received = 0;
+  TPMsg* tpmsg= NULL;
+  
+  // argument parsing - start
+  if (receiver_thread_argp == 0)
+  {
+    Log(ERROR_LOG,LOG_CRIT, 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
+    Log(DEBUG_LOG,LOG_UNIMP, 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
+  {
+    Log(ERROR_LOG,LOG_CRIT, tpparam.name, methodname << "No peer assoc available - pointer is NULL");
+    
+    return;
+  }
+
+  if (peer_addr == 0)
+  {
+    Log(ERROR_LOG,LOG_CRIT, 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
+  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; 
+
+  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
+	  AssocDataUDS* myassoc=const_cast<AssocDataUDS *>(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)
+	  {
+	    Log(EVENT_LOG,LOG_NORMAL, tpparam.name, methodname << "poll(): " << strerror(errno));
+	  }
+	  else
+	  {
+	    Log(ERROR_LOG,LOG_CRIT, 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
+	{
+	  Log(ERROR_LOG,LOG_CRIT, 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)
+	    {
+	      Log(EVENT_LOG,LOG_NORMAL, tpparam.name, methodname << "Poll status: " << strerror(errno));
+	    }
+	    else
+	    {
+	      Log(ERROR_LOG,LOG_CRIT, 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, 
+		   0);
+
+	if ( ret < 0 )
+	{
+	  if (errno!=EAGAIN && errno!=EWOULDBLOCK)
+	  {
+	    Log(ERROR_LOG,LOG_CRIT, 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
+	    AssocDataUDS* myassoc=const_cast<AssocDataUDS *>(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
+	  {
+	      Log(ERROR_LOG,LOG_CRIT, tpparam.name, methodname << "Not a valid protocol header - discarding received packet. received size " << msgcontentlength);
+
+	    ostringstream hexdumpstr;
+	    netmsg->hexdump(hexdumpstr,netmsg->get_buffer(),bytes_received);
+	    Log(DEBUG_LOG,LOG_NORMAL,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 && bytes_received-common_header_length >= msgcontentlength )
+      {
+	
+	pdu_complete= true;
+	if (bytes_received-common_header_length > msgcontentlength)
+	{
+	  Log(WARNING_LOG,LOG_NORMAL,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);
+	}
+      }
+    } // 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());
+
+      Log(DEBUG_LOG,LOG_NORMAL, tpparam.name, methodname << "receipt of PDU now complete, sending 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_to(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
+  TPoverUDSMsg* newmsg= new(nothrow)TPoverUDSMsg(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 
+TPoverUDS::stop_receiver_thread(AssocDataUDS* 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 
+TPoverUDS::cleanup_receiver_thread(AssocDataUDS* 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 
+TPoverUDS::terminate_sender_thread(const AssocDataUDS* 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)
+    {
+      TPoverUDSMsg* internalmsg= new TPoverUDSMsg(assoc,tpparam.source,TPoverUDSMsg::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 
+TPoverUDS::terminate_all_threads()
+{
+  AssocDataUDS* 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<AssocDataUDS*>(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 TPoverUDS object instance and receiver_thread_arg_t struct
+ */
+void*
+TPoverUDS::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 TPoverUDS object instance and receiver_thread_arg_t struct
+ */
+void*
+TPoverUDS::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
+TPoverUDS::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
+				     TPoverUDS::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
+TPoverUDS::create_new_receiver_thread(AssocDataUDS* 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(TPoverUDS, 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 TPoverUDS object instance
+ */
+void*
+TPoverUDS::master_listener_thread_starter(void *argp)
+{
+  // invoke listener thread method
+  if (argp != 0)
+  {
+    (static_cast<TPoverUDS*>(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
+TPoverUDS::master_listener_thread()
+{
+    //remove any existing socket files
+    unlink(tpparam.udssocket.c_str());
+
+
+  // create a new address-structure for the listening masterthread
+    struct sockaddr_un  own_address;
+    own_address.sun_family = AF_UNIX;
+    strcpy(own_address.sun_path, tpparam.udssocket.c_str());
+    unlink(tpparam.udssocket.c_str());
+    uint32 len = strlen(tpparam.udssocket.c_str()) + sizeof(own_address.sun_family);
+    
+    
+  // create a listening socket
+  int master_listener_socket= socket(AF_UNIX, SOCK_STREAM, 0);
+  if (master_listener_socket == -1)
+  {
+    Log(ERROR_LOG,LOG_CRIT, tpparam.name, "Could not create a new socket, error: " << strerror(errno));
+    return;
+  }
+  
+
+  // Reuse ports, even if they are busy
+  int socketreuseflag= 1;
+  int 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),
+			 len);
+  if (bind_status)
+    { 
+      Log(ERROR_LOG,LOG_CRIT, tpparam.name, "Binding to " << tpparam.udssocket);
+      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 " << tpparam.udssocket << 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_un 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
+	AssocDataUDS* peer_assoc = NULL;
+	udsaddress addr(conn_socket);
+
+	Log(DEBUG_LOG,LOG_NORMAL, tpparam.name, "<<--Received connect--<< request from " << addr);
+
+	//struct sockaddr_un 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) AssocDataUDS(conn_socket, addr, udsaddress(conn_socket));
+
+	bool insert_success= false;
+	if (peer_assoc)
+	{
+	  // start critical section
+	  lock(); // install_cleanup_thread_lock(TPoverUDS, 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 << " 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()    
+
+
+TPoverUDS::~TPoverUDS()
+{
+  init= false;
+
+  Log(DEBUG_LOG,LOG_NORMAL, tpparam.name,  "Destructor called");
+
+  QueueManager::instance()->unregister_queue(tpparam.source);
+}
+
+/** TPoverUDS 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 TPoverUDSMsg types:
+ * - TPoverUDSMsg::stop - a particular receiver thread is terminated
+ * - TPoverUDSMsg::start - a particular receiver thread is started
+ * @param nr number of current thread instance
+ */
+void 
+TPoverUDS::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 )
+    {
+      TPoverUDSMsg* internalmsg= dynamic_cast<TPoverUDSMsg*>(internal_thread_msg);
+      if (internalmsg)
+      {
+	if (internalmsg->get_msgtype() == TPoverUDSMsg::stop)
+	{
+	  // a receiver thread terminated and signaled for cleanup by master thread
+	  AssocDataUDS* assocd= const_cast<AssocDataUDS*>(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() == TPoverUDSMsg::start)
+	{
+	  // start a new receiver thread
+	  create_new_receiver_thread( const_cast<AssocDataUDS*>(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: /trash/old-modules/transport/protlib/tp_over_uds.h
===================================================================
--- /trash/old-modules/transport/protlib/tp_over_uds.h	(revision 5641)
+++ /trash/old-modules/transport/protlib/tp_over_uds.h	(revision 5641)
@@ -0,0 +1,265 @@
+/// ----------------------------------------*- mode: C++; -*--
+/// @file tp_over_uds.h
+/// Transport over Unix Domain Sockets
+/// ----------------------------------------------------------
+/// $Id: tp_over_uds.h 2872 2008-02-18 10:58:03Z bless $
+/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/tp_over_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.
+//
+// ===========================================================
+// ----------------------------------------*- mode: C++; -*--
+// tp_over_uds.h
+// Implementation of a transport module for Unix domain sockets
+// ----------------------------------------------------------
+// $Id: tp_over_uds.h 2872 2008-02-18 10:58:03Z bless $
+// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/include/tp_over_uds.h $
+// ==========================================================
+/** @ingroup transport
+ * @file tp_over_uds.h
+ * TP over UDS
+ */
+
+#ifndef TP_OVER_UDS_H
+#define TP_OVER_UDS_H
+
+#include <ext/hash_map>
+
+#include "tp.h"
+#include "threads.h"
+#include "threadsafe_db.h"
+#include "connectionmap_uds.h"
+#include "assocdata_uds.h"
+
+namespace protlib 
+{
+/** this struct conatains parameters that determine 
+  * the behavior of listener and receiver threads in TPoverUDS
+  * @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 TPoverUDSParam : public ThreadParam 
+{
+  /// constructor
+  TPoverUDSParam(
+         unsigned short common_header_length,
+	 bool (*const getmsglength) (NetMsg& m, uint32& clen_bytes),
+	 string udssocket,
+	 bool server,
+	 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,"TPoverUDS", 1,1),
+      udssocket(udssocket),
+      debug_pdu(debug_pdu),
+      source(source),
+      dest(dest),
+      common_header_length(common_header_length),
+      getmsglength(getmsglength),
+      terminate(false),
+      ip_tos(tos),
+      server(server)
+        {};
+
+    /// port to bind master listener thread to
+    const string udssocket;
+    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 server;
+}; // end TPoverUDPParam
+
+
+/// TP over TCP
+/** This class implements the TP interface using TCP. */
+class TPoverUDS : 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
+  TPoverUDS(const TPoverUDSParam& p) :
+    TP(253,"uds",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 ~TPoverUDS();
+  
+  typedef
+  struct receiver_thread_arg
+  {
+    const AssocDataUDS* peer_assoc;
+    bool sig_terminate;
+    bool terminated;
+  public:
+    receiver_thread_arg(const AssocDataUDS* peer_assoc) : 
+      peer_assoc(peer_assoc), sig_terminate(false), terminated(true) {};
+  } receiver_thread_arg_t;
+  
+  class receiver_thread_start_arg_t
+  {
+  public:
+    TPoverUDS* instance;
+    receiver_thread_arg_t* rtargp;
+    
+    receiver_thread_start_arg_t(TPoverUDS* instance, receiver_thread_arg_t* rtargp) :
+      instance(instance), rtargp(rtargp) {};
+  };
+
+  class sender_thread_start_arg_t
+  {
+  public:
+    TPoverUDS* instance;
+    FastQueue* sender_thread_queue;
+    
+    sender_thread_start_arg_t(TPoverUDS* instance, FastQueue* sq) :
+      instance(instance), sender_thread_queue(sq) {};
+  };
+  
+private:
+  /// returns already existing connection or establishes a new one
+  AssocDataUDS* get_connection_to(udsaddress& 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 local process via UNIX domain sockets
+  void udssend(NetMsg* msg, udsaddress* 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(AssocDataUDS* peer_assoc);
+  
+  /// terminates particular thread
+  void stop_receiver_thread(AssocDataUDS* peer_assoc);
+
+  /// cleans up thread management structures
+  void cleanup_receiver_thread(AssocDataUDS* peer_assoc);
+
+  /// terminates a sender thread
+  void terminate_sender_thread(const AssocDataUDS* assoc);
+  
+  /// terminates all active receiver or sender threads
+  void terminate_all_threads();
+  
+  /// ConnectionMap instance for keeping track of all existing connections
+  ConnectionMapUDS 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<udsaddress, FastQueue*> sender_thread_queuemap_t;
+  sender_thread_queuemap_t  senderthread_queuemap;
+  
+  /// parameters for main TPoverUDS thread
+  const TPoverUDSParam tpparam;
+  
+  /// did we already abort at thread shutdown
+  bool already_aborted;
+  /// message queue
+  FastQueue* msgqueue;
+  
+  bool debug_pdu;
+}; // end class TPoverUDS
+
+/** 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 TPoverUDSMsg : public message 
+{
+ public:
+  // message type start/stop thread, send data
+  enum msg_t { start, 
+	       stop,
+	       send_data
+  };
+
+ private:
+  const AssocDataUDS* peer_assoc;
+  const TPoverUDSMsg::msg_t type;
+  NetMsg* netmsg;
+  udsaddress* addr;
+
+public:
+  TPoverUDSMsg(const AssocDataUDS* peer_assoc, message::qaddr_t source= qaddr_unknown, TPoverUDSMsg::msg_t type= stop) : 
+    message(type_transport, source), peer_assoc(peer_assoc), type(type), netmsg(0), addr(0)  {}
+
+  TPoverUDSMsg(NetMsg* netmsg, udsaddress* addr, message::qaddr_t source= qaddr_unknown) : 
+    message(type_transport, source), peer_assoc(0), type(send_data), netmsg(netmsg), addr(addr) {}
+
+  const AssocDataUDS* get_peer_assoc() const { return peer_assoc; }
+  TPoverUDSMsg::msg_t get_msgtype() const { return type; }
+  NetMsg* get_netmsg() const { return netmsg; }
+  udsaddress* get_udsaddr() const { return addr; } 
+};
+
+} // end namespace protlib
+
+#endif
Index: /trash/old-modules/transport/protlib/tperror.h
===================================================================
--- /trash/old-modules/transport/protlib/tperror.h	(revision 5641)
+++ /trash/old-modules/transport/protlib/tperror.h	(revision 5641)
@@ -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: /trash/old-modules/transport/tcp/TCPTransport.cpp
===================================================================
--- /trash/old-modules/transport/tcp/TCPTransport.cpp	(revision 5641)
+++ /trash/old-modules/transport/tcp/TCPTransport.cpp	(revision 5641)
@@ -0,0 +1,326 @@
+// [License]
+// The Ariba-Underlay Copyright
+//
+// Copyright (c) 2008-2009, Institute of Telematics, UniversitÃ€t Karlsruhe (TH)
+//
+// Institute of Telematics
+// UniversitÃ€t Karlsruhe (TH)
+// Zirkel 2, 76128 Karlsruhe
+// Germany
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The views and conclusions contained in the software and documentation
+// are those of the authors and should not be interpreted as representing
+// official policies, either expressed or implied, of the Institute of
+// Telematics.
+// [License]
+
+#include "TCPTransport.h"
+
+#define _NO_LOGGING
+
+// std includes
+#include <unistd.h>
+#include <iostream>
+#include <string>
+#include <sstream>
+
+// protlib includes
+#include "../protlib/network_message.h"
+#include "../protlib/tp_over_tcp.h"
+#include "../protlib/logfile.h"
+#include "../protlib/queuemanager.h"
+#include "../protlib/threadsafe_db.h"
+#include "../protlib/setuid.h"
+
+// spovnet includes
+#include "ariba/utility/serialization.h"
+#include "ariba/utility/system/SystemQueue.h"
+#include "ariba/utility/system/SystemEvent.h"
+#include "ariba/utility/system/SystemEventType.h"
+#include "ariba/communication/modules/network/ip/IPv4Locator.h"
+
+// protlib namespaces
+using namespace protlib;
+using namespace protlib::log;
+
+// spovnet namespaces
+using ariba::utility::SystemQueue;
+using ariba::utility::SystemEvent;
+using ariba::utility::SystemEventType;
+using ariba::utility::MessageProvider;
+using ariba::utility::TextMessage;
+using ariba::utility::MessageReceiver;
+using ariba::communication::IPv4Locator;
+
+using_serialization;
+
+logfile commonlog;
+protlib::log::logfile& protlib::log::DefaultLog(commonlog);
+
+#include "ariba/communication/modules/_namespace.h"
+NAMESPACE_BEGIN;
+
+SystemEventType TCPTransportEvent("TCPTransport");
+SystemEventType TCPMessageDispatchEvent("MessageDispatchEvent", TCPTransportEvent );
+SystemEventType TCPTransportTestEvent("Test", TCPTransportEvent );
+
+use_logging_cpp(TCPTransport);
+
+TCPTransport::TCPTransport( port_t port ) {
+	this->running = false;
+	this->done = false;
+	this->port = port;
+
+	logging_debug( "creating tcp transport module" );
+}
+
+TCPTransport::~TCPTransport() {
+	logging_debug( "deleting tcp transport module" );
+}
+
+void TCPTransport::start() {
+
+	logging_info( "starting tcp transport module ..." );
+
+	// initalize netdb and setuid
+	protlib::tsdb::init();
+	protlib::setuid::init();
+
+	/* set tcp parameters */
+	port_t port = this->port; // port
+	TPoverTCPParam tppar(4, TCPTransport::getMessageLength, 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, TCPTransport::receiverThread, this );
+	tpthread = new ThreadStarter<TPoverTCP, TPoverTCPParam> ( 1, tppar );
+	tpthread->start_processing();
+
+	logging_info( "tcp transport module started" );
+}
+
+void TCPTransport::stop() {
+
+	logging_info( "stopping tcp transport module ..." );
+
+	// 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();
+
+	logging_info( "tcp transport module stopped" );
+}
+
+bool TCPTransport::getMessageLength( NetMsg& m, uint32& clen_bytes ) {
+	clen_bytes = m.decode32();
+	m.set_pos_r(-4);
+	return true;
+}
+
+void* TCPTransport::receiverThread( void* ptp ) {
+
+	logging_info( "running tcp transport receiver thread" );
+
+	// get reference to transport object
+	TCPTransport& tp = *((TCPTransport*)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);
+
+		// handle message
+		if (msg) {
+
+			logging_debug( "Received incoming message" );
+
+			// handle transport message
+			TPMsg* tpmsg = dynamic_cast<TPMsg*> (msg);
+			if (tpmsg) {
+				// evaluate TP message
+				const appladdress* peer = static_cast<const appladdress*>( tpmsg->get_peeraddress() );
+				NetMsg* datamsg = tpmsg->get_message();
+				TPError* err = tpmsg->get_error();
+
+				// get data
+				if (datamsg) {
+
+					datamsg->set_pos(0);
+					uint32_t msgLength = datamsg->decode32(true);
+					uint16_t remotePort = datamsg->decode16(true);
+
+					// convert data
+					Data data(
+						(uint8_t*)(datamsg->get_buffer()+6),
+						(datamsg->get_size()-6)*8
+					);
+
+					// converting message
+					logging_debug( "converting message" );
+					Message* msg = new Message(data);
+
+					std::ostringstream o;
+					o << (peer->get_ip_str() + 7) << ":" << remotePort;
+					msg->setSourceAddress( new IPv4Locator(IPv4Locator::fromString(o.str())) );
+					logging_debug( "> source address = " << o.str() );
+					logging_debug( "> message = " << msg->toString() );
+
+					// dispatching message
+					logging_debug( "Dispatching message" );
+					SystemQueue::instance().scheduleEvent(
+						SystemEvent( &tp, TCPMessageDispatchEvent, msg )
+					);
+				}
+
+				// check error
+				if (err)
+					logging_error( "TCP transport error " + string(err->getstr()) );
+
+				logging_debug( "Message processed." );
+
+				tpmsg = NULL;
+			}
+			delete msg;
+		}
+	}
+
+	// clean queue & stop
+	fq->cleanup();
+	tp.running = false;
+	return NULL;
+}
+
+seqnum_t TCPTransport::sendMessage(const Message* message ) {
+
+	Data data = data_serialize( message );
+	//std::cout << "XXXXXXXXXXXXXsending out data using tcp transport: " << data << std::endl;
+
+
+	// prepare netmsg and send it
+	NetMsg* datamsg = new NetMsg(data.getLength()/8+6);
+	datamsg->encode32(data.getLength()/8+2, true);
+	datamsg->encode16(this->port,true);
+	for (int i=0; i<data.getLength()/8; i++)
+		datamsg->encode8(data.getBuffer()[i],true);
+
+	// send message
+	const IPv4Locator* address = dynamic_cast<const IPv4Locator*>(message->getDestinationAddress());
+	if( address == NULL) return 0;
+
+	logging_debug( "sending message of size " << data.getLength() <<
+			" to address " + address->toString() <<
+			": " + message->toString() );
+	const_cast<Message*>(message)->dropPayload();
+
+	string s = address->toString();
+	string::size_type i = s.find(':');
+	string ip = address->toString().substr(0,i).c_str();
+	logging_debug( "ip= " << ip << " port=" << address->getPort() );
+
+	appladdress peer(ip.c_str(), "tcp", address->getPort() );
+	tpthread->get_thread_object()->send(datamsg, peer, false);
+
+	// release data
+	data.release();
+	logging_debug( "message sent!" );
+
+	return 0;
+}
+
+void TCPTransport::terminate(const NetworkLocator* local, const NetworkLocator* remote){
+
+	const IPv4Locator* address = dynamic_cast<const IPv4Locator*>(remote);
+	if( address == NULL) return;
+
+	string s = address->toString();
+	string::size_type i = s.find(':');
+	string ip = address->toString().substr(0,i).c_str();
+
+	appladdress peer( ip.c_str(), "tcp", address->getPort() );
+	peer.convert_to_ipv6();
+
+	tpthread->get_thread_object()->terminate( peer );
+}
+
+TransportLocator::prot_t TCPTransport::getId() {
+	return 6; // TCP
+}
+
+
+
+const vector<TransportLocator*> TCPTransport::getLocators() {
+	return vector<TransportLocator*>();
+}
+
+/* system event handler */
+void TCPTransport::handleSystemEvent( const SystemEvent& event ) {
+
+	// dispatch received messages
+	if ( event.getType() == TCPMessageDispatchEvent ){
+		logging_debug( "forwarding message to local receivers" );
+		Message* msg = event.getData<Message>();
+		MessageProvider::sendMessageToReceivers( msg );
+		msg->dropPayload();
+//		delete msg->getSourceAddress();
+		delete msg;
+	}
+
+	if ( event.getType() == TCPTransportTestEvent ) {
+
+		// add listener
+		addMessageReceiver( new MessageReceiver() );
+
+		// send message
+		//cout << "Sending message ..." << endl;
+		sendMessage( new TextMessage( "Hello World!" ) );
+		//cout << "Message sent ..." << endl;
+
+	}
+}
+
+NAMESPACE_END;
Index: /trash/old-modules/transport/tcp/TCPTransport.h
===================================================================
--- /trash/old-modules/transport/tcp/TCPTransport.h	(revision 5641)
+++ /trash/old-modules/transport/tcp/TCPTransport.h	(revision 5641)
@@ -0,0 +1,115 @@
+// [License]
+// The Ariba-Underlay Copyright
+//
+// Copyright (c) 2008-2009, Institute of Telematics, UniversitÃ€t Karlsruhe (TH)
+//
+// Institute of Telematics
+// UniversitÃ€t Karlsruhe (TH)
+// Zirkel 2, 76128 Karlsruhe
+// Germany
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The views and conclusions contained in the software and documentation
+// are those of the authors and should not be interpreted as representing
+// official policies, either expressed or implied, of the Institute of
+// Telematics.
+// [License]
+
+#ifndef TCPTRANSPORT_H_
+#define TCPTRANSPORT_H_
+
+// kill protlib logging
+#define _NO_LOGGING
+
+#include <iostream>
+#include "ariba/utility/logging/Logging.h"
+#include "ariba/utility/messages.h"
+#include "ariba/utility/types/Address.h"
+#include "ariba/utility/misc/Helper.h"
+#include "ariba/utility/system/SystemEventListener.h"
+#include "ariba/utility/system/SystemEvent.h"
+#include "ariba/utility/system/SystemEventType.h"
+#include "ariba/communication/modules/network/ip/IPv4Locator.h"
+#include "ariba/communication/modules/transport/TransportProtocol.h"
+#include "ariba/communication/modules/transport/protlib/network_message.h"
+#include "ariba/communication/modules/transport/protlib/protlib_types.h"
+#include "ariba/communication/modules/transport/protlib/threads.h"
+#include "ariba/communication/modules/transport/protlib/tp_over_tcp.h"
+
+#include "ariba/communication/modules/_namespace.h"
+NAMESPACE_BEGIN;
+
+using namespace protlib;
+using ariba::utility::Address;
+using ariba::utility::seqnum_t;
+using ariba::utility::Message;
+using ariba::utility::SystemEventListener;
+using ariba::utility::SystemEvent;
+using ariba::utility::SystemEventType;
+using ariba::communication::IPv4Locator;
+
+class TCPTransport : public TransportProtocol, public SystemEventListener {
+
+	use_logging_h(TCPTransport);
+
+private:
+	port_t port;
+	volatile bool done;
+	volatile bool running;
+	pthread_t tpreceivethread;
+	ThreadStarter<TPoverTCP, TPoverTCPParam>* tpthread;
+
+	static void* receiverThread( void* ptp );
+	static bool  getMessageLength( NetMsg& m, uint32& clen_bytes );
+
+public:
+	TCPTransport( port_t port );
+	virtual ~TCPTransport();
+
+	/** @see TransportProtocol.h */
+	virtual void start();
+
+	/** @see TransportProtocol.h */
+	virtual void stop();
+
+	/** @see TransportProtocol.h */
+	virtual TransportLocator::prot_t getId();
+
+	/** @see TransportProtocol.h */
+	virtual const vector<TransportLocator*> getLocators();
+
+	/* @see MessageSender */
+	virtual seqnum_t sendMessage( const Message* message );
+
+	/** @see TransportProtocol.h */
+	virtual void terminate(const NetworkLocator* local, const NetworkLocator* remote);
+
+protected:
+	virtual void handleSystemEvent( const SystemEvent& event );
+
+};
+
+NAMESPACE_END;
+
+#endif /* TCPTRANSPORT_H_ */
Index: /trash/old-modules/transport/tcp/TCPTransportLocator.cpp
===================================================================
--- /trash/old-modules/transport/tcp/TCPTransportLocator.cpp	(revision 5641)
+++ /trash/old-modules/transport/tcp/TCPTransportLocator.cpp	(revision 5641)
@@ -0,0 +1,56 @@
+// [License]
+// The Ariba-Underlay Copyright
+//
+// Copyright (c) 2008-2009, Institute of Telematics, UniversitÃ€t Karlsruhe (TH)
+//
+// Institute of Telematics
+// UniversitÃ€t Karlsruhe (TH)
+// Zirkel 2, 76128 Karlsruhe
+// Germany
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The views and conclusions contained in the software and documentation
+// are those of the authors and should not be interpreted as representing
+// official policies, either expressed or implied, of the Institute of
+// Telematics.
+// [License]
+
+#include "TCPTransportLocator.h"
+
+#include "ariba/communication/modules/_namespace.h"
+NAMESPACE_BEGIN;
+
+vsznDefault( TCPTransportLocator );
+
+TCPTransportLocator::TCPTransportLocator( port_t port ) {
+	this->port = port;
+}
+
+TCPTransportLocator::TCPTransportLocator() {
+}
+
+TCPTransportLocator::~TCPTransportLocator() {
+}
+
+NAMESPACE_END;
Index: /trash/old-modules/transport/tcp/TCPTransportLocator.h
===================================================================
--- /trash/old-modules/transport/tcp/TCPTransportLocator.h	(revision 5641)
+++ /trash/old-modules/transport/tcp/TCPTransportLocator.h	(revision 5641)
@@ -0,0 +1,87 @@
+// [License]
+// The Ariba-Underlay Copyright
+//
+// Copyright (c) 2008-2009, Institute of Telematics, UniversitÃ€t Karlsruhe (TH)
+//
+// Institute of Telematics
+// UniversitÃ€t Karlsruhe (TH)
+// Zirkel 2, 76128 Karlsruhe
+// Germany
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The views and conclusions contained in the software and documentation
+// are those of the authors and should not be interpreted as representing
+// official policies, either expressed or implied, of the Institute of
+// Telematics.
+// [License]
+
+#ifndef TCPTRANSPORTLOCATOR_H_
+#define TCPTRANSPORTLOCATOR_H_
+
+// forward decl
+class TCPTransportLocator;
+
+// spovnet includes
+#include "../../modules.h"
+#include "ariba/utility/serialization.h"
+
+// boost includes
+#include <boost/cstdint.hpp>
+
+// lib includes
+#include <vector>
+
+// namespace begin
+#include "ariba/communication/modules/_namespace.h"
+NAMESPACE_BEGIN;
+
+using std::vector;
+
+class TCPTransportLocator : public TransportLocator {
+	VSERIALIZEABLE;
+	friend class TCPTransport;
+public:
+	typedef uint16_t port_t;
+
+protected:
+	port_t port;
+
+public:
+	TCPTransportLocator();
+	TCPTransportLocator( port_t port );
+	virtual ~TCPTransportLocator();
+
+	inline uint16_t getPort() const {
+		return port;
+	}
+};
+
+// namespace end
+NAMESPACE_END
+
+sznBeginDefault( ariba::communication::TCPTransportLocator, X ) {
+	X && port;
+} sznEnd();
+
+#endif /* TCPTRANSPORTLOCATOR_H_ */
