Index: source/ariba/utility/transport/StreamTransport/StreamTransport.cpp
===================================================================
--- source/ariba/utility/transport/tcpip/tcpip.cpp	(revision 10653)
+++ source/ariba/utility/transport/StreamTransport/StreamTransport.cpp	(revision 12060)
@@ -1,19 +1,40 @@
-#include "tcpip.hpp"
-
+#include "StreamTransport.hpp"
+
+// ariba
+#include "ariba/utility/addressing2/tcpip_endpoint.hpp"
+
+// boost-adaption
+#include "ariba/utility/transport/rfcomm/bluetooth_rfcomm.hpp"
+
+// boost
+#include <boost/foreach.hpp>
 #include <boost/array.hpp>
-
-// interface discovery for link-local destinations
+#include <boost/asio/ip/address.hpp>
+
+// interface discovery for link-local destinations (tcp-only)
 #include <ifaddrs.h>
+
 
 namespace ariba {
 namespace transport {
 
-use_logging_cpp(tcpip)
-
-using namespace ariba::addressing;
+//use_logging_cpp(StreamTransport<T>)
+
+#ifdef HAVE_LIBBLUETOOTH
+    using boost::asio::bluetooth::rfcomm;
+#endif /* HAVE_LIBBLUETOOTH */
+
+using namespace ariba::addressing2;
+using ariba::utility::LinkID;
+
+using boost::asio::ip::tcp;
+using boost::asio::ip::address_v6;
+using boost::shared_ptr;
 
 typedef boost::mutex::scoped_lock unique_lock;
 
-tcpip::tcpip( const tcp::endpoint& endp )  :
+
+template <class T>
+StreamTransport<T>::StreamTransport( const typename T::endpoint& endp )  :
         listener(NULL),
         acceptor(u_io_service.get_asio_io_service(), endp)
@@ -21,7 +42,9 @@
 }
 
-tcpip::~tcpip(){}
-
-void tcpip::start()
+template <class T>
+StreamTransport<T>::~StreamTransport(){}
+
+template <class T>
+void StreamTransport<T>::start()
 {
     // open server socket
@@ -32,5 +55,6 @@
 
 
-void tcpip::stop()
+template <class T>
+void StreamTransport<T>::stop()
 {
     acceptor.close();
@@ -41,6 +65,7 @@
 
 /* see header file for comments */
-void tcpip::send(
-        const tcp::endpoint& dest_addr,
+template <class T>
+void StreamTransport<T>::send(
+        const typename T::endpoint& dest_addr,
         reboost::message_t message,
         uint8_t priority)
@@ -52,26 +77,32 @@
         unique_lock lock(connections_lock);
         
-        ConnectionMap::iterator it = connections.find(dest_addr);
+        // try to find existing connection to this endpoint 
+        typename ConnectionMap::iterator it = connections.find(dest_addr);
+        
+        // BRANCH: create new connection
         if (it == connections.end())
         {
             ConnPtr tmp_ptr(
-                    new tcpip_connection(
+                    new StreamConnection(
                             u_io_service.get_asio_io_service(),
-                            shared_from_this() )
+                            this->shared_from_this() )
                     );
             conn = tmp_ptr;
-            
-            conn->partner = dest_addr;
-            conn->remote = convert_address(dest_addr);
+
+            // save partner endpoint
+            conn->partner_endpoint = dest_addr;
             
             // Note: starting the send is the obligation of the connect_handler
             // (avoids trying to send while not connected yet)
-            conn->sending =  true;
+            conn->sending = true;
             need_to_connect = true;
             
-            ConnectionMap::value_type item(dest_addr, conn);
+            typename ConnectionMap::value_type item(dest_addr, conn);
             connections.insert(item);
             
-        } else {
+        }
+        // BRANCH: use existing connection
+        else
+        {
             conn = it->second;
         }
@@ -88,5 +119,5 @@
                 dest_addr,
                 boost::bind(
-                        &tcpip_connection::async_connect_handler,
+                        &StreamConnection::async_connect_handler,
                         conn,
                         boost::asio::placeholders::error));
@@ -95,62 +126,27 @@
 
 
+// TODO is this a private function? ... and still needed?
 /* see header file for comments */
-void tcpip::send(
-        const address_v* remote,
+template <class T>
+void StreamTransport<T>::send(
+        const EndpointPtr remote,
         reboost::message_t message,
         uint8_t priority)
 {
-    send(convert_address(remote), message, priority);
-}
-
-
-/* see header file for comments */
-void tcpip::send(
-        const endpoint_set& endpoints,
-        reboost::message_t message,
-        uint8_t priority )
-{
-    // network interfaces scope_ids, for link-local connections (lazy initialization)
-    vector<uint64_t> scope_ids;
-    
-    // send a message to each combination of address-address and port
-    BOOST_FOREACH( const ip_address address, endpoints.ip ) {
-        BOOST_FOREACH( const tcp_port_address port, endpoints.tcp ) {
-            tcp::endpoint endp(address.asio(), port.asio());
-            
-            // special treatment for link local addresses
-            //   ---> send over all (suitable) interfaces
-            if ( endp.address().is_v6() )
-            {
-                boost::asio::ip::address_v6 v6_addr = endp.address().to_v6();
-                
-                if ( v6_addr.is_link_local() )
-                {
-                    // initialize scope_ids
-                    if ( scope_ids.size() == 0 )
-                        scope_ids = get_interface_scope_ids();
-                    
-                    BOOST_FOREACH ( uint64_t id, scope_ids )
-                    {                        
-                        v6_addr.scope_id(id);
-                        endp.address(v6_addr);
-    
-                        logging_debug("------> SEND TO (link-local): " << endp);
-                        // * send *
-                        send(endp, message, priority);
-                    }
-                }
-                
-                continue;
-            }
-            
-            // * send *
-            send(endp, message, priority);
-        }
-    }
-}
-
-
-void tcpip::register_listener( transport_listener* listener )
+    if ( remote->get_category() == endpoint_category::TCPIP )
+    {
+        const addressing2::tcpip_endpoint* endp =
+                static_cast<const addressing2::tcpip_endpoint*>(remote.get());
+        
+        send(endp->to_asio(), message, priority);
+    }
+    
+    // else
+    // TODO what now?
+}
+
+
+template <class T>
+void StreamTransport<T>::register_listener( transport_listener* listener )
 {
     this->listener = listener;
@@ -158,10 +154,20 @@
 
 
-void tcpip::terminate( const address_v* remote )
-{
-    terminate(convert_address(remote));
-}
-
-void tcpip::terminate( const tcp::endpoint& remote )
+// XXX DEPRECATED
+template <class T>
+void StreamTransport<T>::terminate( const EndpointPtr remote )
+{
+    if ( remote->get_category() == endpoint_category::TCPIP )
+    {
+        const addressing2::tcpip_endpoint* endp =
+                static_cast<const addressing2::tcpip_endpoint*>(remote.get());
+
+        
+        this->terminate(endp->to_asio());
+    }
+}
+
+template <class T>
+void StreamTransport<T>::terminate( const typename T::endpoint& remote )
 {
     ConnPtr conn;
@@ -171,5 +177,5 @@
         unique_lock lock(connections_lock);
         
-        ConnectionMap::iterator it = connections.find(remote);
+        typename ConnectionMap::iterator it = connections.find(remote);
         if (it == connections.end())
         {
@@ -178,11 +184,47 @@
         
         conn = it->second;
-        
+
+        // prevent upper layers from using this link
+        conn->valid = false;
+
         connections.erase(it);
     }
+    
+    // XXX aktuell
+//     cout << "/// MARIO: TCP/IP TERMINATE: " << conn->partner_endpoint << endl;
+    
+    // notify higher layers
+    if ( listener )
+    {
+        listener->connection_terminated(conn);
+    }
+
+    
+    // XXX debug aktuell
+//    cout << "/// MARIO Open connections:" << endl;
+//    for ( typename ConnectionMap::iterator it = connections.begin(); it != connections.end(); ++it )
+//    {
+//        cout << "  CONNECTION: " << it->second->local_endpoint << " <---> " << it->second->partner_endpoint << endl;
+//        cout << "    used by: " << endl;
+//        
+//        int usecount = 0;
+//        ConnPtr xx;
+//        std::vector<LinkID*> links = it->second->get_communication_links();
+//        for ( std::vector<LinkID*>::iterator it2 = links.begin(); it2 != links.end(); ++it2 )
+//        {
+//            cout << "      - " << *it2 << endl;
+//            usecount++;
+//        }
+//        if ( usecount == 0 )
+//        {
+//            cout << "      ---> NOBODY !!" << endl;
+//        }
+//    }
+//    cout << "/// -------" << endl;
+
 
     // close connection
     boost::system::error_code ec;
-    conn->sock.shutdown(tcp::socket::shutdown_both, ec);
+    conn->sock.shutdown(T::socket::shutdown_both, ec);
     conn->sock.close(ec);
 }
@@ -190,11 +232,12 @@
 
 /* private */
-void tcpip::accept()
+template <class T>
+void StreamTransport<T>::accept()
 {
     // create new connection object
     ConnPtr conn(
-            new tcpip_connection(
+            new StreamConnection(
                     u_io_service.get_asio_io_service(),
-                    shared_from_this()
+                    this->shared_from_this()
             )
     );
@@ -210,16 +253,16 @@
 }
 
-void tcpip::async_accept_handler(ConnPtr conn, const error_code& error)
+template <class T>
+void StreamTransport<T>::async_accept_handler(ConnPtr conn, const error_code& error)
 {
     if ( ! error )
     {
-        conn->partner = conn->sock.remote_endpoint();
-        conn->remote = convert_address(conn->partner);
-        conn->local = convert_address(conn->sock.local_endpoint());
+        // save partner endpoint
+        conn->partner_endpoint = conn->sock.remote_endpoint();
         
         {
             unique_lock lock(connections_lock);
             
-            ConnectionMap::value_type item(conn->sock.remote_endpoint(), conn);
+            typename ConnectionMap::value_type item(conn->sock.remote_endpoint(), conn);
             connections.insert(item);
         }
@@ -233,73 +276,82 @@
 }
 
-inline tcp::endpoint tcpip::convert_address( const address_v* address )
-{
-    tcpip_endpoint endpoint = *address;
-    
-    return tcp::endpoint(
-        endpoint.address().asio(), endpoint.port().value()
-    );
-}
-
-
-inline tcpip_endpoint tcpip::convert_address(const tcp::endpoint& endpoint)
-{
-    ip_address address;
-    address.asio(endpoint.address());
-    tcp_port_address port;
-    port.value(endpoint.port());
-    return tcpip_endpoint(address, port);
-}
-
-
-vector<uint64_t> tcpip::get_interface_scope_ids()
-{
-    vector<uint64_t> ret;
-    
-    struct ifaddrs* ifaceBuffer = NULL;
-    void*           tmpAddrPtr  = NULL;
-    
-    int ok = getifaddrs( &ifaceBuffer );
-    if( ok != 0 ) return ret;
-
-    for( struct ifaddrs* i=ifaceBuffer; i != NULL; i=i->ifa_next ) {
-
-        // ignore devices that are disabled or have no ip
-        if(i == NULL) continue;
-        struct sockaddr* addr = i->ifa_addr;
-        if (addr==NULL) continue;
-
-        // only use ethX and wlanX devices
-        string device = string(i->ifa_name);
-        if ( (device.find("eth") == string::npos) &&
-              (device.find("wlan")  == string::npos) /* &&
-              (device.find("lo")  == string::npos) XXX */ )
-        {
+
+
+/*------------------
+ | specializations |
+ ------------------*/
+/* TCP */
+template <>
+void StreamTransport<tcp>::send(
+        const addressing2::const_EndpointSetPtr endpoints,
+        reboost::message_t message,
+        uint8_t priority )
+{
+    // network interfaces scope_ids, for link-local connections (lazy initialization)
+    vector<uint64_t> scope_ids;
+    
+    // send a message to each combination of address-address and port
+    BOOST_FOREACH( const TcpIP_EndpointPtr address, endpoints->get_tcpip_endpoints() )
+//    vector<TcpIP_EndpointPtr> endpoint_vec = endpoints->get_tcpip_endpoints();
+//    for ( vector<TcpIP_EndpointPtr>::iterator it = endpoint_vec.begin(); it != endpoint_vec.end(); ++it )
+    {
+        tcp::endpoint endp = address->to_asio();
+        
+        // special treatment for link local addresses
+        //   ---> send over all (suitable) interfaces
+        if ( endp.address().is_v6() )
+        {
+            boost::asio::ip::address_v6 v6_addr = endp.address().to_v6();
+            
+            if ( v6_addr.is_link_local() )
+            {
+                // initialize scope_ids
+                if ( scope_ids.size() == 0 )
+                    scope_ids = get_interface_scope_ids();
+                
+                BOOST_FOREACH ( uint64_t id, scope_ids )
+                {                        
+                    v6_addr.scope_id(id);
+                    endp.address(v6_addr);
+
+//                    logging_debug("------> SEND TO (link-local): " << endp);
+                    // * send *
+                    send(endp, message, priority);
+                }
+            }
+            
             continue;
         }
-
-        // only use interfaces with ipv6 link-local addresses 
-        if (addr->sa_family == AF_INET6)
-        {
-            // convert address
-            // TODO should be possible without detour over strings
-            char straddr[INET6_ADDRSTRLEN];
-            tmpAddrPtr= &((struct sockaddr_in6*)addr)->sin6_addr;
-            inet_ntop( i->ifa_addr->sa_family, tmpAddrPtr, straddr, sizeof(straddr) );
-
-            address_v6 v6addr = address_v6::from_string(straddr);
-            if ( v6addr.is_link_local() )
-            {
-                // * append the scope_id to the return vector *
-                ret.push_back(if_nametoindex(i->ifa_name));
-            }
-
-        }
-    }
-
-    freeifaddrs(ifaceBuffer);
-    
-    return ret;
-}
+        
+        // * send *
+        send(endp, message, priority);
+    }
+}
+
+
+/* RFCOMM */
+#ifdef HAVE_LIBBLUETOOTH
+
+// TODO
+
+//    template <>
+//    void StreamTransport<rfcomm>::send(
+//            const endpoint_set& endpoints,
+//            reboost::message_t message,
+//            uint8_t priority )
+//    {
+//        // send a message to each combination of address-address and port
+//        BOOST_FOREACH( const mac_address mac, endpoints.bluetooth ) {
+//            BOOST_FOREACH( const rfcomm_channel_address channel, endpoints.rfcomm ) {
+//                rfcomm::endpoint endp(mac.bluetooth(), channel.value());
+//                
+//                // * send *
+//                send(endp, message, priority);
+//            }
+//        }
+//    }
+
+#endif /* HAVE_LIBBLUETOOTH */
+
 
 
@@ -308,5 +360,6 @@
  *****************/
 
-tcpip::tcpip_connection::tcpip_connection(boost::asio::io_service & io_service, TcpIpPtr parent)  :
+template <class T>
+StreamTransport<T>::StreamConnection::StreamConnection(boost::asio::io_service & io_service, StreamTransportPtr parent)  :
         sock(io_service),
         valid(true),
@@ -316,5 +369,4 @@
 {
         header.length = 0;
-        header.prot = 0;
 }
 
@@ -322,27 +374,108 @@
  | implement transport_connection interface |
  -------------------------------------------*/
-void tcpip::tcpip_connection::send(
+template <class T>
+bool StreamTransport<T>::StreamConnection::send(
         reboost::message_t message,
         uint8_t priority)
 {
+    if ( ! valid )
+    {
+        // XXX aktuell
+//         cout << "/// MARIO: USED INVALID LINK: " << this->partner_endpoint << endl;
+
+        return false;
+    }
+    
+    // * enqueue data *
     enqueue_for_sending(message, priority);
-}
-
-
-address_vf tcpip::tcpip_connection::getLocalEndpoint()
-{
-    return local;
-}
-
-
-address_vf tcpip::tcpip_connection::getRemoteEndpoint()
-{
-    return remote;
-}
-
-
-void tcpip::tcpip_connection::terminate()
-{
-    parent->terminate(partner);
+    
+    return true;
+}
+
+
+template <class T>
+EndpointPtr StreamTransport<T>::StreamConnection::getLocalEndpoint()
+{
+    EndpointPtr ret(new addressing2::tcpip_endpoint(local_endpoint));
+    
+    return ret;
+}
+
+
+template <class T>
+EndpointPtr StreamTransport<T>::StreamConnection::getRemoteEndpoint()
+{
+    EndpointPtr ret(new addressing2::tcpip_endpoint(partner_endpoint));
+    
+    return ret;
+}
+
+template <class T>
+void StreamTransport<T>::StreamConnection::register_communication_link(LinkID* link)
+{
+    if ( ! link )
+        return;
+    
+    // add link
+    communication_links.push_back(link);
+}
+
+template <class T>
+void StreamTransport<T>::StreamConnection::unregister_communication_link(LinkID* link)
+{
+    if ( ! link )
+        return;
+
+    
+    // remove link
+    {
+        std::vector<LinkID*>::iterator it = communication_links.begin();
+        
+        while ( it != communication_links.end() )
+        {
+            if ( (*it) == link )
+            {
+                it = communication_links.erase(it);
+            }
+            else
+            {
+                ++it;
+            }
+        }
+    }
+    
+    // this connection is no longer used by any link
+    if ( communication_links.empty() )
+    {
+        //XXX
+//         cout << "communication_links.empty() " << getLocalEndpoint()->to_string() << " - " << getRemoteEndpoint()->to_string() << endl;
+        
+        // terminate connection
+        this->terminate();  // TODO aktuell
+        
+        /*
+         *  TODO racecondition:
+         *  When receiving a link request, the connection could closed
+         *  before the request is handled.
+         *  
+         *  ---> Maybe wait a timeout before actually terminate the connection.
+         *  (e.g. record last-used time:
+         *      if last used > timeout and communication_links.empty()
+         *      then terminate the connection)  
+         */
+    }
+}
+
+template <class T>
+std::vector<LinkID*> StreamTransport<T>::StreamConnection::get_communication_links()
+{
+    return communication_links;
+}
+
+
+template <class T>
+void StreamTransport<T>::StreamConnection::terminate()
+{
+    parent->terminate(partner_endpoint);
 }
 
@@ -351,15 +484,16 @@
  | things we defined ourselves |
  ------------------------------*/
-void tcpip::tcpip_connection::async_connect_handler(const error_code& error)
+template <class T>
+void StreamTransport<T>::StreamConnection::async_connect_handler(const error_code& error)
 {
     if (error)
     {
-        parent->terminate(partner);
+        parent->terminate(partner_endpoint);
 
         return;
     }
     
-    // save address in ariba format
-    local = parent->convert_address(sock.local_endpoint());
+    // save local endpoint
+    local_endpoint = sock.local_endpoint();
     
     // Note: sending has to be true at this point
@@ -370,5 +504,6 @@
 
 
-void tcpip::tcpip_connection::listen()
+template <class T>
+void StreamTransport<T>::StreamConnection::listen()
 {
     boost::asio::async_read(
@@ -376,5 +511,5 @@
             boost::asio::mutable_buffers_1(&this->header, sizeof(header_t)),
             boost::bind(
-                    &tcpip::tcpip_connection::async_read_header_handler,
+                    &StreamTransport<T>::StreamConnection::async_read_header_handler,
                     this->shared_from_this(),
                     boost::asio::placeholders::error,
@@ -385,18 +520,21 @@
 
 
-void tcpip::tcpip_connection::async_read_header_handler(const error_code& error, size_t bytes_transferred)
+template <class T>
+void StreamTransport<T>::StreamConnection::async_read_header_handler(const error_code& error, size_t bytes_transferred)
 {
     if (error)
     {
-        parent->terminate(partner);
+        parent->terminate(partner_endpoint);
 
         return;
     }
-
-    // convert byte order
-    header.length = ntohl(header.length);
-    header.length -= 2;  // XXX protlib
-    
-    assert(header.length > 0);
+    
+    // sanity checks
+    //   NOTE: max size 8k (may be changed later..)
+    if ( header.length == 0 || header.length > 8192 )
+    {
+        parent->terminate(partner_endpoint);
+    }
+
     
     // new buffer for the new packet
@@ -408,5 +546,5 @@
             boost::asio::buffer(buffy.mutable_data(), buffy.size()),
             boost::bind(
-                    &tcpip::tcpip_connection::async_read_data_handler,
+                    &StreamTransport<T>::StreamConnection::async_read_data_handler,
                     this->shared_from_this(),
                     boost::asio::placeholders::error,
@@ -416,31 +554,30 @@
 }
 
-void tcpip::tcpip_connection::async_read_data_handler(
+template <class T>
+void StreamTransport<T>::StreamConnection::async_read_data_handler(
         const error_code& error, size_t bytes_transferred)
 {
     if (error)
     {
-        parent->terminate(partner);
+        parent->terminate(partner_endpoint);
 
         return;
     }
     
-    message_t msg;
-    msg.push_back(buffy);
+    if ( parent->listener )
+        parent->listener->receive_message(this->shared_from_this(), buffy);
+
     buffy = shared_buffer_t();
-
-    if ( parent->listener )
-        parent->listener->receive_message(shared_from_this(), msg);
-    
     listen();
 }
 
 /* see header file for comments */
-void tcpip::tcpip_connection::async_write_handler(reboost::shared_buffer_t packet, const error_code& error, size_t bytes_transferred)
+template <class T>
+void StreamTransport<T>::StreamConnection::async_write_handler(reboost::shared_buffer_t packet, const error_code& error, size_t bytes_transferred)
 {
     if ( error )
     {        
         // remove this connection
-        parent->terminate(partner); 
+        parent->terminate(partner_endpoint); 
 
         return;
@@ -452,5 +589,6 @@
 
 
-void tcpip::tcpip_connection::enqueue_for_sending(Packet packet, uint8_t priority)
+template <class T>
+void StreamTransport<T>::StreamConnection::enqueue_for_sending(Packet packet, uint8_t priority)
 {
     bool restart_sending = false;
@@ -478,5 +616,6 @@
 
 /* see header file for comments */
-void tcpip::tcpip_connection::send_next_package()
+template <class T>
+void StreamTransport<T>::StreamConnection::send_next_package()
 {
     Packet packet;
@@ -512,5 +651,5 @@
         reboost::shared_buffer_t header_buf(sizeof(header_t));
         header_t* header = (header_t*)(header_buf.mutable_data());
-        header->length = htonl(packet.size()+2);  // XXX protlib
+        header->length = packet.size();
         
         packet.push_front(header_buf);
@@ -529,5 +668,5 @@
                 send_sequence,
                 boost::bind(
-                        &tcpip::tcpip_connection::async_write_handler,
+                        &StreamTransport<T>::StreamConnection::async_write_handler,
                         this->shared_from_this(),
                         packet,  // makes sure our shared pointer lives long enough ;-)
@@ -537,4 +676,139 @@
     }
 }
+/*********************
+ ** [ inner class ] **
+ *********************/
+
+
+
+// explicitly tell the compiler to create a Â»tcpÂ« (and Â»rfcommÂ«) specialization
+//   --> (needed since hpp and cpp are separated) 
+template class StreamTransport<boost::asio::ip::tcp>;
+
+#ifdef HAVE_LIBBLUETOOTH
+    template class StreamTransport<rfcomm>;
+#endif /* HAVE_LIBBLUETOOTH */
+
+
+
+/////////////////////////////////////////////////////////////////////////////////////
+    
+
+// XXX testing
+///** 
+// * Conversion between ASIO Adresses and ARIBA adresses
+// */
+///* TCP */
+//template <>
+//inline typename tcp::endpoint convert_address<tcp>( const address_v* address )
+//{
+//    tcpip_endpoint endpoint = *address;
+//    
+//    return typename tcp::endpoint(
+//        endpoint.address().asio(), endpoint.port().value()
+//    );
+//}
+//
+//template <>
+//inline EndpointPtr convert_address<tcp>(const typename tcp::endpoint& endpoint)
+//{
+//    ip_address address;
+//    address.asio(endpoint.address());
+//    tcp_port_address port;
+//    port.value(endpoint.port());
+//    
+////    new tcpip_endpoint(address, port);
+//    tcpip_endpoint xx;
+//    address_vf yy;
+//    address_v* zz = yy->clone();
+//    address_v::shared_ptr endp(zz); // XXX
+//    
+//    return endp; 
+//}
+//
+///* RFCOMM */
+//#ifdef HAVE_LIBBLUETOOTH
+//    template <>
+//    inline typename rfcomm::endpoint convert_address<rfcomm>( const address_v* address )
+//    {
+//        rfcomm_endpoint endpoint = *address;
+//        
+//        return rfcomm::endpoint(
+//            endpoint.mac().bluetooth(), endpoint.channel().value()
+//        );
+//    }
+//    
+//    template <>
+//    inline address_v::shared_ptr convert_address<rfcomm>(const typename rfcomm::endpoint& endpoint)
+//    {
+//        mac_address mac;
+//        mac.bluetooth(endpoint.address());
+//        rfcomm_channel_address channel;
+//        channel.value(endpoint.channel());
+//        
+//        address_v::shared_ptr endp((ariba::addressing::address_v*) new rfcomm_endpoint(mac, channel));
+//        
+//        return endp; 
+//    }
+//#endif /* HAVE_LIBBLUETOOTH */
+
+
+    
+/////////////////////////////////////////////////////////////////////////////////////
+    
+
+/*
+ *  Get Ethernet scope ids (for link-local)
+ */
+vector<uint64_t> get_interface_scope_ids()
+{
+    vector<uint64_t> ret;
+    
+    struct ifaddrs* ifaceBuffer = NULL;
+    void*           tmpAddrPtr  = NULL;
+    
+    int ok = getifaddrs( &ifaceBuffer );
+    if( ok != 0 ) return ret;
+
+    for( struct ifaddrs* i=ifaceBuffer; i != NULL; i=i->ifa_next ) {
+
+        // ignore devices that are disabled or have no ip
+        if(i == NULL) continue;
+        struct sockaddr* addr = i->ifa_addr;
+        if (addr==NULL) continue;
+
+        // only use ethX and wlanX devices
+        string device = string(i->ifa_name);
+        if ( (device.find("eth") == string::npos) &&
+              (device.find("wlan")  == string::npos) /* &&
+              (device.find("lo")  == string::npos) XXX */ )
+        {
+            continue;
+        }
+
+        // only use interfaces with ipv6 link-local addresses 
+        if (addr->sa_family == AF_INET6)
+        {
+            // convert address
+            // TODO should be possible without detour over strings
+            char straddr[INET6_ADDRSTRLEN];
+            tmpAddrPtr= &((struct sockaddr_in6*)addr)->sin6_addr;
+            inet_ntop( i->ifa_addr->sa_family, tmpAddrPtr, straddr, sizeof(straddr) );
+
+            address_v6 v6addr = address_v6::from_string(straddr);
+            if ( v6addr.is_link_local() )
+            {
+                // * append the scope_id to the return vector *
+                ret.push_back(if_nametoindex(i->ifa_name));
+            }
+
+        }
+    }
+
+    freeifaddrs(ifaceBuffer);
+    
+    return ret;
+}
+
 
 }} // namespace ariba::transport
