--- /dev/null
+/**
+ * @file
+ *
+ * @author Reinhard Pfau \<reinhard.pfau@intra2net.com\>
+ *
+ * @copyright © Copyright 2008 by Intra2net AG
+ * @license commercial
+ * @contact info@intra2net.com
+ */
+
+#include "glue_t2n.hpp"
+
+#include <iostream>
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/signal.hpp>
+#include <climits>
+#include <logfunc.hpp>
+#include <tracefunc.hpp>
+#include <log_macros.hpp>
+
+
+
+namespace I2n
+{
+
+using namespace SimpleIo;
+
+
+namespace
+{
+
+
+Logger::PartLogger& module_logger()
+{
+    static Logger::PartLogger _module_logger(HERE);
+    return _module_logger;
+} // eo module_logger();
+
+
+
+/**
+ * @brief a class with some methods we like to have on our io classes.
+ *
+ * This class is to be used as second base in a wrapper class and needs it's methods to
+ * be redefined for "the real thing".
+ */
+class IOExportWrapperBase
+{
+    public:
+
+        IOExportWrapperBase()
+        {
+        }
+
+        virtual ~IOExportWrapperBase()
+        {
+        }
+
+        virtual void sendData(const std::string& data)
+        {
+        }
+
+
+        virtual std::string receiveData()
+        {
+            return std::string();
+        }
+
+        virtual boost::signals::connection connectEof( const boost::function< void() >& func )
+        {
+            return boost::signals::connection();
+        }
+
+        virtual boost::signals::connection connectRead( const boost::function< void() >& func )
+        {
+            return boost::signals::connection();
+        }
+
+}; // eo class IOExportWrapperBase
+
+
+typedef boost::shared_ptr< IOExportWrapperBase > IOExportWrapperBasePtr;
+
+
+/**
+ * @brief IO wrapper template.
+ * @tparam IOClass a type based on SimpleIo::IOImplementation
+ *
+ * The type is used as a public base for the resulting class; the second public base is our
+ * helper with the additional methods we need internally and which we (finally) define here.
+ */
+template<
+    class IOClass
+>
+class IOExportWrapper
+: public IOClass
+, public IOExportWrapperBase
+{
+        BOOST_STATIC_ASSERT(( boost::is_base_of< IOImplementation,IOClass >::value ));
+
+    public:
+        IOExportWrapper()
+        {
+        }
+
+        template<
+            typename Arg1
+        >
+        IOExportWrapper(Arg1 arg1)
+        : IOClass(arg1)
+        {}
+
+
+        template<
+            typename Arg1, typename Arg2
+        >
+        IOExportWrapper(Arg1 arg1, Arg2 arg2)
+        : IOClass(arg1,arg2)
+        {}
+
+
+        template<
+            typename Arg1, typename Arg2, typename Arg3
+        >
+        IOExportWrapper(Arg1 arg1, Arg2 arg2, Arg3 arg3)
+        : IOClass(arg1,arg2,arg3)
+        {}
+
+
+        template<
+            typename Arg1, typename Arg2, typename Arg3, typename Arg4
+        >
+        IOExportWrapper(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
+        : IOClass(arg1,arg2,arg3,arg4)
+        {}
+
+
+        template<
+            typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5
+        >
+        IOExportWrapper(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5)
+        : IOClass(arg1,arg2,arg3,arg4,arg5)
+        {}
+
+
+        /**
+         * @brief exposed funtion for sending data.
+         * @param data the chunk to be send.
+         */
+        virtual void sendData(const std::string& data)
+        {
+            IOClass::lowSend(data);
+        }
+
+        /**
+         * @brief returns the new received data.
+         * @return the receievd data.
+         *
+         * Clears the receive buffer.
+         */
+        virtual std::string receiveData()
+        {
+            std::string result;
+            result.swap(IOClass::m_input_buffer);
+            return result;
+        }
+
+        /**
+         * @brief exposed connect to EOF signal.
+         * @param func the function which should be connected to the eof signal.
+         * @return signal connection handle.
+         */
+        virtual boost::signals::connection connectEof( const boost::function< void() >& func )
+        {
+            return IOClass::m_signal_eof.connect(func);
+        }
+
+        /**
+         * @brief exposed connect to "read" signal.
+         * @param func the function which should be connected to the "read" signal.
+         * @return signal connection handle.
+         */
+        virtual boost::signals::connection connectRead( const boost::function< void() >& func )
+        {
+            return IOClass::m_signal_read.connect(func);
+        }
+
+    protected:
+
+}; // eo class IOExportWrapper
+
+
+/*
+** specialized versions of io classes:
+*/
+
+/**
+ * @brief enhanced unix domain socket class with reconnect feature.
+ *
+ * Used for t2n client connections.
+ */
+class T2nUnixIOSocket
+: public SimpleIo::UnixIOSocket
+{
+        typedef SimpleIo::UnixIOSocket inherited;
+    public:
+        T2nUnixIOSocket( const std::string& path );
+
+        virtual void close(SimpleIo::Direction direction = SimpleIo::Direction::both);
+
+        bool reopen(bool force= false);
+
+    protected:
+
+        virtual void doRead();
+
+
+    protected:
+
+        bool m_in_do_read;
+        bool m_may_reconnect;
+
+}; // T2nUnixIOSocket
+
+
+T2nUnixIOSocket::T2nUnixIOSocket(const std::string& path)
+: inherited(path)
+, m_in_do_read(false)
+, m_may_reconnect(false)
+{
+} // eo T2nUnixIOSocket::T2nUnixIOSocket(const std::string&)
+
+
+void T2nUnixIOSocket::close(SimpleIo::Direction direction)
+{
+    bool was_open= opened();
+    inherited::close(direction);
+    if (m_in_do_read and not opened())
+    {
+        m_may_reconnect= was_open;
+    }
+} // eo T2nUnixIOSocket::close(SimpleIo::Direction)
+
+
+bool T2nUnixIOSocket::reopen(bool force)
+{
+    if (m_path.empty())
+    {
+        return false;
+    }
+    if (m_may_reconnect || force)
+    {
+        return inherited::open( m_path );
+    }
+    return false;
+} // eo T2nUnixIOSocket::reopen()
+
+
+void T2nUnixIOSocket::doRead()
+{
+    m_in_do_read= true;
+    try
+    {
+        inherited::doRead();
+    }
+    catch (...)
+    {
+        m_in_do_read= false;
+        throw;
+    }
+    m_in_do_read= false;
+} // eo T2nUnixIOSocket::doRead()
+
+
+/**
+ * @brief server class for libt2n using unix domain sockets.
+ *
+ * well, it's enough to provide an appropriate constructor.
+ * (did i mention that templates are really cool stuff? :-) )
+ */
+class T2NUnixServer
+: public T2NServerBase
+{
+    public:
+
+        T2NUnixServer(const std::string& path, int mode=0600)
+        : T2NServerBase( ServerSocketBaseImplementationPtr(
+            new UnixServerSocket<
+                IOExportWrapper< UnixIOSocket >
+            >(path, mode)
+        ) )
+        {
+        } // eo T2NServerBase
+
+}; // eo T2NUnixServer
+
+
+
+class RealT2NClientConnection
+: public T2NClientConnection
+{
+    public:
+        RealT2NClientConnection( SimpleIo::IOImplementationPtr connection )
+        : T2NClientConnection(connection)
+        {
+        }
+}; // eo class T2NClient
+
+} // eo namespace <anonymous>
+
+
+
+/*
+** implementation of T2NClientConnection
+*/
+
+
+T2NClientConnection::T2NClientConnection(
+    IOImplementationPtr connection
+)
+: libt2n::client_connection()
+, m_real_connection(connection)
+, m_got_new_data(false)
+{
+    SCOPETRACKER();
+    IOExportWrapperBasePtr ptr = boost::dynamic_pointer_cast< IOExportWrapperBase >(connection);
+    if (!ptr)
+    {
+        module_logger().error(HERE) << "illegal pointer passed";
+        close();
+        return;
+    }
+    if (!connection->opened())
+    {
+        module_logger().warning(HERE) << "connection not open, either failed or already closed";
+        close();
+        return;
+    }
+
+    ptr->connectRead( boost::bind(&T2NClientConnection::newDataSlot, this) );
+    ptr->connectEof( boost::bind(&T2NClientConnection::eofSlot, this) );
+
+} // eo T2NClientConnection::T2NClientConnection(IOImplementationPtr)
+
+
+T2NClientConnection::~T2NClientConnection()
+{
+    SCOPETRACKER();
+} // eo T2NClientConnection::~T2NClientConnection
+
+
+/**
+ * @brief returns if the connection is open.
+ * @return @a true if the connection is open.
+ */
+bool T2NClientConnection::isOpen()
+{
+    return m_real_connection and m_real_connection->opened();
+} // eo T2NClientConnection::isOpen()
+
+
+/**
+ * @brief try to reopen a connection.
+ * @return @a true if the connection was reopened.
+ */
+bool T2NClientConnection::reopen(bool force)
+{
+    if (not m_real_connection)
+    {
+        return false;
+    }
+    boost::shared_ptr< T2nUnixIOSocket > t2n_socket=
+        boost::shared_dynamic_cast< T2nUnixIOSocket >(m_real_connection);
+    if (t2n_socket)
+    {
+        return t2n_socket->reopen(force);
+    }
+    return false;
+} // eo T2NClientConnection::reopen()
+
+
+/**
+ * @brief closes the connection.
+ *
+ * This closes the underlying IO connection and calls libt2n::server_connection::close() to
+ * mark the connection as closed for libt2n.
+ */
+void T2NClientConnection::close()
+{
+    SCOPETRACKER();
+    if (m_real_connection)
+    {
+        m_real_connection->close();
+        m_real_connection.reset();
+    }
+    libt2n::client_connection::close();
+} // eo T2NClientConnection::close()
+
+
+/**
+ * @brief sends a raw data chunk on the connection.
+ *
+ * @param data the /raw) data chunk which should be sended.
+ */
+void T2NClientConnection::real_write(const std::string& data)
+{
+    SCOPETRACKER();
+    if (is_closed())
+    {
+        module_logger().warning(HERE) << "attempt to write data on closed connection";
+        return;
+    }
+    IOExportWrapperBasePtr ptr = boost::dynamic_pointer_cast< IOExportWrapperBase >(m_real_connection);
+    if (!ptr)
+    {
+        // should never happen...
+        module_logger().error(HERE)<< "illegal io pointer";
+        close();
+        //TODO: throw an error?!
+        NOT_REACHED();
+        return;
+    }
+    ptr->sendData(data);
+} // eo T2NClientConnection::real_write(const std::string)
+
+
+/**
+ * @brief called to fill the connection buffer.
+ *
+ * Since this class uses the asnychronous SimpleIo framework, new data may already be read when
+ * this method is called.
+ *
+ * @param usec_timeout 
+ * @param usec_timeout_remaining 
+ * @return @a true if new data is available.
+ */
+bool T2NClientConnection::fill_buffer(long long usec_timeout,long long* usec_timeout_remaining)
+{
+    SCOPETRACKER();
+    if (is_closed())
+    {
+        module_logger().debug(HERE) << "fill_buffer() called on closed connection";
+        return false;
+    }
+    SimpleIo::MilliTime t0,t1;
+    SimpleIo::get_current_monotonic_time(t0);
+    if (!m_got_new_data)
+    {
+        IOExportWrapperBasePtr ptr = boost::dynamic_pointer_cast< IOExportWrapperBase >(m_real_connection);
+        if (!ptr)
+        {
+            module_logger().error(HERE) << "illegal io pointer";
+            close();
+            return false;
+        }
+        // try to fetch data (call the backend)
+        int timeout= 0;
+
+        if (usec_timeout<0)
+        {
+            timeout= -1;
+        }
+        else if (usec_timeout > 0)
+        {
+            long long msec_timeout= (usec_timeout + 500)/1000;
+
+            if (msec_timeout >= INT_MAX)
+            {
+                timeout= INT_MAX;
+            }
+            else
+            {
+                timeout= (int)msec_timeout;
+            }
+        }
+        Backend::getBackend()->doOneStep( timeout );
+    }
+    SimpleIo::get_current_monotonic_time(t1);
+    if (usec_timeout_remaining)
+    {
+        long long delta= ((long long)(t1 - t0).get_milliseconds())* 1000L;
+        *usec_timeout_remaining= (usec_timeout > delta ) ? (usec_timeout - delta) : 0L;
+        module_logger().debug() << "timeout: " << usec_timeout << " -> " << *usec_timeout_remaining;
+    }
+    if (m_got_new_data)
+    {
+        m_got_new_data= false;
+        return true;
+    }
+    return false;
+} // eo T2NClientConnection::fill_buffer(long long,long long*)
+
+
+/**
+ * @brief called when new data arrived on this connection.
+ *
+ * reads the new data from the underlying IO object and stores it in the connection buffer.
+ * Also remembers (in the bool member var @a m_got_new_data) that new data was received.
+ */
+void T2NClientConnection::newDataSlot()
+{
+    SCOPETRACKER();
+    IOExportWrapperBasePtr ptr = boost::dynamic_pointer_cast< IOExportWrapperBase >(m_real_connection);
+    if (!ptr)
+    {
+        //TODO: throw an error?!
+        NOT_REACHED();
+        return;
+    }
+    std::string new_data= ptr->receiveData();
+    module_logger().debug() << "got " << new_data.size() << " bytes of new data";
+    buffer+= new_data;
+    m_got_new_data= true;
+} // eo T2NClientConnection::newDataSlot()
+
+
+/**
+ * @brief called when an EOF was detected by the underlying IO object (i.e. the connection
+ * was closed by the peer side).
+ *
+ * Calls close().
+ */
+void T2NClientConnection::eofSlot()
+{
+    SCOPETRACKER();
+    close();
+} // eo T2NClientConnection::eofSlot()
+
+
+/*
+** implementation of T2NServerConnection
+*/
+
+
+T2NServerConnection::T2NServerConnection(
+    T2NServerBasePtr server,
+    IOImplementationPtr connection,
+    int timeout
+)
+: libt2n::server_connection(timeout)
+, m_real_connection(connection)
+, m_server_weak_ptr(server)
+, m_got_new_data(false)
+{
+    SCOPETRACKER();
+    IOExportWrapperBasePtr ptr = boost::dynamic_pointer_cast< IOExportWrapperBase >(connection);
+    if (!ptr)
+    {
+        module_logger().error(HERE) << "illegal pointer passed";
+        close();
+        return;
+    }
+    if (!connection->opened())
+    {
+        module_logger().warning(HERE) << "connection not open, either failed or already closed";
+        close();
+        return;
+    }
+
+    ptr->connectRead( boost::bind(&T2NServerConnection::newDataSlot, this) );
+    ptr->connectEof( boost::bind(&T2NServerConnection::eofSlot, this) );
+
+} // eo T2NServerConnection::T2NServerConnection(IOImplementationPtr)
+
+
+T2NServerConnection::~T2NServerConnection()
+{
+    SCOPETRACKER();
+} // eo T2NServerConnection::~T2NServerConnection
+
+
+/**
+ * @brief closes the connection.
+ *
+ * This closes the underlying IO connection and calls libt2n::server_connection::close() to
+ * mark the connection as closed for libt2n.
+ */
+void T2NServerConnection::close()
+{
+    SCOPETRACKER();
+    if (m_real_connection)
+    {
+        m_real_connection->close();
+        m_real_connection.reset();
+    }
+    libt2n::server_connection::close();
+} // eo T2NServerConnection::close()
+
+
+/**
+ * @brief sends a raw data chunk on the connection.
+ *
+ * @param data the (raw) data chunk which should be sended.
+ */
+void T2NServerConnection::real_write(const std::string& data)
+{
+    SCOPETRACKER();
+    if (is_closed())
+    {
+        module_logger().warning(HERE) << "attempt to write data on closed connection";
+        return;
+    }
+    IOExportWrapperBasePtr ptr = boost::dynamic_pointer_cast< IOExportWrapperBase >(m_real_connection);
+    if (!ptr)
+    {
+        // should never happen...
+        module_logger().error(HERE)<< "illegal io pointer";
+        close();
+        //TODO: throw an error?!
+        NOT_REACHED();
+        return;
+    }
+    ptr->sendData(data);
+} // eo T2NServerConnection::real_write(const std::string)
+
+
+/**
+ * @brief called to fill the connection buffer.
+ *
+ * Since this class uses the asnychronous SimpleIo framework, new data may already be read when
+ * this method is called.
+ *
+ * @param usec_timeout 
+ * @param usec_timeout_remaining 
+ * @return @a true if new data is available.
+ */
+bool T2NServerConnection::fill_buffer(long long usec_timeout,long long* usec_timeout_remaining)
+{
+    SCOPETRACKER();
+    if (is_closed())
+    {
+        module_logger().debug(HERE) << "fill_buffer() called on closed connection";
+        return false;
+    }
+    SimpleIo::MilliTime t0,t1;
+    SimpleIo::get_current_monotonic_time(t0);
+    if (!m_got_new_data)
+    {
+        IOExportWrapperBasePtr ptr = boost::dynamic_pointer_cast< IOExportWrapperBase >(m_real_connection);
+        if (!ptr)
+        {
+            module_logger().error(HERE) << "illegal io pointer";
+            close();
+            return false;
+        }
+        // try to fetch data (call the backend)
+        int timeout= 0;
+
+        if (usec_timeout<0)
+        {
+            timeout= -1;
+        }
+        else if (usec_timeout > 0)
+        {
+            long long msec_timeout= (usec_timeout + 500)/1000;
+
+            if (msec_timeout >= INT_MAX)
+            {
+                timeout= INT_MAX;
+            }
+            else
+            {
+                timeout= (int)msec_timeout;
+            }
+        }
+        Backend::getBackend()->doOneStep( timeout );
+    }
+    SimpleIo::get_current_monotonic_time(t1);
+    if (usec_timeout_remaining)
+    {
+        long long delta= ((long long)(t1 - t0).get_milliseconds())* 1000L;
+        *usec_timeout_remaining= (usec_timeout > delta ) ? (usec_timeout - delta) : 0L;
+    }
+    if (m_got_new_data)
+    {
+        m_got_new_data= false;
+        return true;
+    }
+    return false;
+} // eo T2NServerConnection::fill_buffer(long long,long long*)
+
+
+/**
+ * @brief called when new data arrived on this connection.
+ *
+ * reads the new data from the underlying IO object and stores it in the connection buffer.
+ * Also remembers (in the bool member var @a m_got_new_data that new data was received.
+ */
+void T2NServerConnection::newDataSlot()
+{
+    SCOPETRACKER();
+    IOExportWrapperBasePtr ptr = boost::dynamic_pointer_cast< IOExportWrapperBase >(m_real_connection);
+    if (!ptr)
+    {
+        //TODO:throw an error?!
+        NOT_REACHED();
+        return;
+    }
+    buffer+= ptr->receiveData();
+    m_got_new_data= true;
+    reset_timeout();
+
+    T2NServerBasePtr server =m_server_weak_ptr.lock();
+    if (server)
+    {
+        server->m_signal_client_got_new_data();
+    }
+} // eo T2NServerConnection::newDataSlot()
+
+
+/**
+ * @brief called when an EOF was detected by the underlying IO object (i.e. the connection
+ * was closed by the peer side).
+ *
+ * Calls close().
+ */
+void T2NServerConnection::eofSlot()
+{
+    SCOPETRACKER();
+    close();
+} // eo T2NServerConnection::eofSlot()
+
+
+
+/*
+** implementation of T2NServerBase
+*/
+
+
+/**
+ * @brief constructs a libt2n server object.
+ *
+ * @param server_port shared pointer to a (SimpleIo) port server object which
+ * is used as underlying port handler.
+ */
+T2NServerBase::T2NServerBase( ServerSocketBaseImplementationPtr server_port)
+: m_server_port(server_port)
+{
+    SCOPETRACKER();
+    // register our callback for new incoming conncetions.
+    server_port->setNewConnectionBaseCallback(
+        boost::bind(&T2NServerBase::newConnectionSlot, this, _1)
+    );
+} // eo T2NServerBase::T2NServerBase(ServerSocketBaseImplementationPtr)
+
+
+/**
+ * @brief destructor.
+ *
+ */
+T2NServerBase::~T2NServerBase()
+{
+    SCOPETRACKER();
+} // eo T2NServerBase::~T2NServerBase()
+
+
+/**
+ * @brief returns wether the server port is opened.
+ *
+ * @return @a true iff the server port is open.
+ */
+bool T2NServerBase::isOpen()
+{
+    return (m_server_port && m_server_port->opened());
+} // eo T2NServerBase
+
+
+
+/**
+ * @brief callback for the port server object when a new connection is established.
+ *
+ * @param io_ptr the (shared) pointer to the new connection.
+ */
+void T2NServerBase::newConnectionSlot(IOImplementationPtr io_ptr)
+{
+    SCOPETRACKER();
+    add_connection( new T2NServerConnection( get_ptr_as< T2NServerBase >(), io_ptr, get_default_timeout() ) );
+} // eo T2NServerBase::newConnectionSlot(IOImplementationPtr)
+
+
+/**
+ * @brief try to fill the buffers of the managed connections.
+ *
+ * will be called by T2NServerBase::fill_buffer().
+ *
+ * @return @a true if at least one connection buffer has new data.
+ */
+bool T2NServerBase::fill_connection_buffers()
+{
+    SCOPETRACKER();
+    Backend::getBackend()->doOneStep(0);
+    bool result= false;
+    for(std::map<unsigned int, libt2n::server_connection*>::iterator it=connections.begin();
+        it != connections.end();
+        ++it)
+    {
+        T2NServerConnection *conn = dynamic_cast<T2NServerConnection*>(it->second);
+        if (!conn)
+        {
+            if (it->second)
+            {
+                // react somehow if (it->second) is not NULL...
+                module_logger().error(HERE) << "illegal connection pointer";
+                it->second->close();
+            }
+            continue;
+        }
+        result= result or conn->fill_buffer(0);
+    }
+    return result;
+} // eo T2NServerBase::fill_connection_buffers()
+
+
+/**
+ * @brief fills the connection buffers.
+ *
+ * Uses the SimpleIo Backend to wait for new data.
+ *
+ * @param usec_timeout the maximum time period to wait for new data (in microseconds). 
+ *  0 returns immediately, -1 waits until some event occurred.
+ * @param timeout_remaining ignored!
+ * @return @a true if new data for at least one connection arrived.
+ *
+ * @note since this method uses the SimpleIo backend, the timeout will have only milli second
+ * resolution.
+ */
+bool T2NServerBase::fill_buffer(long long usec_timeout, long long* timeout_remaining)
+{
+    SCOPETRACKER();
+    int timeout= 0;
+
+    if (usec_timeout<0)
+    {
+        timeout= -1;
+    }
+    else if (usec_timeout > 0)
+    {
+        long long msec_timeout= (usec_timeout + 500)/1000;
+
+        if (msec_timeout >= INT_MAX)
+        {
+            timeout= INT_MAX;
+        }
+        else
+        {
+            timeout= (int)msec_timeout;
+        }
+    }
+    // not really.. but it shouldn't be used either...
+    if (timeout_remaining) *timeout_remaining= 0L;
+
+    if (! fill_connection_buffers() && timeout>0)
+    {
+        bool had_activity= Backend::getBackend()->doOneStep( timeout );
+        return fill_connection_buffers();
+    }
+    return true;
+} // to T2NServerBase::fill_buffer(long long,long long*)
+
+
+
+/*
+** creator functions:
+*/
+
+
+/**
+ * @brief creates a server object with unix domain server socket.
+ * @param path path of the unix domain socket.
+ * @param mode mode for the socket.
+ * @return shared pointer with the new server object; empty if none could be created..
+ */
+T2NServerBasePtr createT2NUnixServerPort(const std::string& path, int mode)
+{
+    SCOPETRACKER();
+    boost::shared_ptr< T2NUnixServer > result( new T2NUnixServer(path,mode) );
+    if (!result->isOpen())
+    {
+        module_logger().error(HERE)
+            << "failed to open unix domain server socket on \"" << path << "\"";
+    }
+    return result;
+} // eo createT2NUnixServerPort(const std::string&,int)
+
+
+/**
+ * @brief creates a client object connected to a server via unix daomain socket.
+ * @param path path of cthe unix domain socket.
+ * @return shared pointer with the new client object; empty if none could be created..
+ */
+T2NClientConnectionPtr createT2NUnixClientConnection(const std::string& path)
+{
+    typedef IOExportWrapper< SimpleIo::UnixIOSocket > MyIo;
+    typedef boost::shared_ptr< MyIo > MyIoPtr;
+    SCOPETRACKER();
+    MyIoPtr connection( new MyIo(path) );
+    boost::shared_ptr< RealT2NClientConnection > result( new RealT2NClientConnection( connection ) );
+    if (not result->isOpen())
+    {
+        module_logger().error(HERE)
+            << "failed to open unix domain client socket on \"" << path << "\"";
+        return T2NClientConnectionPtr();
+    }
+    return result;
+} // eo createT2NUnixClientConnection(const std::string&)
+
+
+} // eo namespace I2n