Several FIXME items:
g0dil [Mon, 11 Jun 2007 23:29:13 +0000 (23:29 +0000)]
* Allow empty FileHandle/SocketHandle etc instances
* Make ServerSocketHandle::listen depend on AddressingPolicy
* Replace all occurences of inet_ntoa with inet_ntop (thread safety)
* Fix handling of exceptions in ReadHelper/WriteHelper
* Fix Scheduler ERR/HUP semantics

git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@256 270642c3-0616-0410-b53a-bc976706d245

26 files changed:
Packets/DefaultBundle/IpV4Packet.cc
Packets/Packet.cci
Packets/ParseListS.ct
Scheduler/ReadHelper.ct
Scheduler/Scheduler.cc
Scheduler/Scheduler.hh
Scheduler/Scheduler.test.cc
Scheduler/WriteHelper.ct
Socket/ClientSocketHandle.cti
Socket/ClientSocketHandle.hh
Socket/CommunicationPolicy.cc
Socket/CommunicationPolicy.cti
Socket/CommunicationPolicy.hh
Socket/FileHandle.cci
Socket/FileHandle.hh
Socket/FileHandle.test.cc
Socket/INetAddressing.cci
Socket/INetAddressing.hh
Socket/ProtocolClientSocketHandle.cti
Socket/ProtocolClientSocketHandle.hh
Socket/ProtocolServerSocketHandle.cti
Socket/ProtocolServerSocketHandle.hh
Socket/ServerSocketHandle.cti
Socket/ServerSocketHandle.hh
Socket/SocketHandle.cti
Socket/SocketHandle.hh

index 8f7c064..6b163a6 100644 (file)
@@ -56,9 +56,10 @@ prefix_ void senf::IpV4Packet::v_dump(std::ostream & os)
 {
     struct in_addr in;
     in.s_addr = htonl(source());
-    std::string src (inet_ntoa(in));
+    char buffer[128];
+    std::string src (inet_ntop(AF_INET,&in,buffer,128));
     in.s_addr = htonl(destination());
-    std::string dst (inet_ntoa(in));
+    std::string dst (inet_ntop(AF_INET,&in,buffer,128));
     os << "Internet protocol Version 4:\n"
        << "  version       : " << version() << "\n"
        << "  IHL           : " << ihl() << "\n"
index d9dcfc0..72f7943 100644 (file)
@@ -154,9 +154,8 @@ prefix_ senf::Packet::ptr senf::Packet::head()
 
 prefix_  senf::Packet::~Packet()
 {
-    /** \fixme This is bad ... we cannot check this since this
-        assertion fails at the moment if the Packet constructor throws
-        ... hrmpf ... we really need to initialize refcount_ to 0 and
+    /** \todo This is sad ... we cannot check this since this assertion fails at the moment if the
+        Packet constructor throws ... hrmpf ... we really should initialize refcount_ to 0 and
         remove the 'false' argument to the ptr constructor in create */
     // BOOST_ASSERT( !this->refcount_  && !this->impl_ );
     SATCOM_PKF_REFC_MSG("] Packet::~Packet (" << this << ")\n");
index ba89360..1c01036 100644 (file)
@@ -80,9 +80,8 @@ template <class Parser, class Sentinel, class Container>
 template <class Value>
 prefix_ void
 senf::Parse_ListS_wrapper<Parser,Sentinel,Container>::insert(iterator pos,
-                                                                    Value const & t)
+                                                             Value const & t)
 {
-    /** \fixme What, if pos == end() / default constructed iterator ? */
     size_type ix (pos.raw()-container_.begin());
     container_.insert(pos.raw(),t.bytes(),0);
     Parser(container_.begin()+ix).value(t);
@@ -92,7 +91,7 @@ template <class Parser, class Sentinel, class Container>
 template <class Value>
 prefix_ void
 senf::Parse_ListS_wrapper<Parser,Sentinel,Container>::insert(iterator pos, size_type n,
-                                                                    Value const & t)
+                                                             Value const & t)
 {
     size_type ix (pos.raw()-container_.begin());
     container_.insert(pos.raw(),n*t.bytes(),0);
@@ -105,8 +104,8 @@ template <class Parser, class Sentinel, class Container>
 template <class InputIterator>
 prefix_ void
 senf::Parse_ListS_wrapper<Parser,Sentinel,Container>::insert(iterator pos,
-                                                                    InputIterator f,
-                                                                    InputIterator l)
+                                                             InputIterator f,
+                                                             InputIterator l)
 {
     /** \todo Optimize this for random-access and multi-pass iterators */
     for (;f!=l;++f,++pos) insert(pos,*f);
index 3ac3df5..40ac199 100644 (file)
@@ -69,7 +69,6 @@ template <class Handle>
 prefix_ void senf::ReadHelper<Handle>::process(Handle handle,
                                                       senf::Scheduler::EventId event)
 {
-    /** \fixme Move the done() calls to outside the try/catch block */
     try {
         if (event != senf::Scheduler::EV_READ)
             throw SystemException(EPIPE);
@@ -82,13 +81,15 @@ prefix_ void senf::ReadHelper<Handle>::process(Handle handle,
                 tail_.assign(data_,n,std::string::npos);
                 data_.erase(n);
             }
-            done();
         }
     }
     catch (senf::SystemException const & ex) {
         errno_ = ex.err;
         done();
+        return;
     }
+    if (complete_)
+        done();
 }
 
 template <class Handle>
index f692402..e4bc1a0 100644 (file)
@@ -116,8 +116,6 @@ prefix_ void senf::Scheduler::do_add(int fd, SimpleCallback const & cb, int even
     if (eventMask & EV_READ)  i->second.cb_read = cb;
     if (eventMask & EV_PRIO)  i->second.cb_prio = cb;
     if (eventMask & EV_WRITE) i->second.cb_write = cb;
-    if (eventMask & EV_HUP)   i->second.cb_hup = cb;
-    if (eventMask & EV_ERR)   i->second.cb_err = cb;
 
     epoll_event ev;
     memset(&ev,0,sizeof(ev));
@@ -137,8 +135,6 @@ prefix_ void senf::Scheduler::do_remove(int fd, int eventMask)
     if (eventMask & EV_READ)  i->second.cb_read = 0;
     if (eventMask & EV_PRIO)  i->second.cb_prio = 0;
     if (eventMask & EV_WRITE) i->second.cb_write = 0;
-    if (eventMask & EV_HUP)   i->second.cb_hup = 0;
-    if (eventMask & EV_ERR)   i->second.cb_err = 0;
 
     epoll_event ev;
     memset(&ev,0,sizeof(ev));
@@ -163,8 +159,6 @@ prefix_ int senf::Scheduler::EventSpec::epollMask()
     if (cb_read)  mask |= EPOLLIN;
     if (cb_prio)  mask |= EPOLLPRI;
     if (cb_write) mask |= EPOLLOUT;
-    if (cb_hup)   mask |= EPOLLHUP;
-    if (cb_err)   mask |= EPOLLERR;
     return mask;
 }
 
@@ -185,50 +179,46 @@ prefix_ void senf::Scheduler::process()
         struct epoll_event ev;
         int events = epoll_wait(epollFd_, &ev, 1, timeout);
         if (events<0)
-            // Hmm ... man epoll says, it will NOT return with EINTR ??
+            // Hmm ... man epoll says, it will NOT return with EINTR. I hope, this is true :-)
             throw SystemException(errno);
         if (events==0)
-            // Timeout .. it will be run when reachiung the top of the loop
+            // Timeout .. the handler will be run when going back to the loop top
             continue;
 
         FdTable::iterator i = fdTable_.find(ev.data.fd);
         BOOST_ASSERT (i != fdTable_.end() );
-        EventSpec const & spec (i->second);
+        // \todo Make this more efficient. Instead of copying the event-spec it should be
+        // revalidated by monitoring add/remove calls
+        EventSpec spec (i->second);
+
+        unsigned extraFlags (0);
+        if (ev.events & EPOLLHUP) extraFlags |= EV_HUP;
+        if (ev.events & EPOLLERR) extraFlags |= EV_ERR;
 
         if (ev.events & EPOLLIN) {
             BOOST_ASSERT(spec.cb_read);
-            spec.cb_read(EV_READ);
+            spec.cb_read(EventId(EV_READ | extraFlags));
         }
         else if (ev.events & EPOLLPRI) {
             BOOST_ASSERT(spec.cb_prio);
-            spec.cb_prio(EV_PRIO);
+            spec.cb_prio(EventId(EV_PRIO | extraFlags));
         }
         else if (ev.events & EPOLLOUT) {
             BOOST_ASSERT(spec.cb_write);
-            spec.cb_write(EV_WRITE);
-        }
-
-        else if (ev.events & EPOLLHUP) {
-            if (spec.cb_hup)
-                spec.cb_hup(EV_HUP);
-            else if (ev.events & EPOLLERR) {
-                /** \fixme This is stupid, if cb_write and cb_read are
-                    the same. The same below. We really have to
-                    exactly define sane semantics of what to do on
-                    EPOLLHUP and EPOLLERR. */
-                if (spec.cb_write) spec.cb_write(EV_HUP);
-                if (spec.cb_read) spec.cb_read(EV_HUP);
-            }
+            spec.cb_write(EventId(EV_WRITE | extraFlags));
         }
-        else if (ev.events & EPOLLERR && ! ev.events & EPOLLHUP) {
-            if (spec.cb_err)
-                spec.cb_err(EV_ERR);
-            else {
-                if (spec.cb_write) spec.cb_write(EV_ERR);
-                if (spec.cb_read) spec.cb_read(EV_ERR);
-            }
+        else {
+            // This branch is only taken, if HUP or ERR is signaled but none of IN/OUT/PRI. 
+            // In this case we will signal all registered callbacks. The callbacks must be
+            // prepared to be called multiple times if they are registered to more than
+            // one event.
+            if (spec.cb_write) 
+                spec.cb_write(EventId(extraFlags));
+            if (spec.cb_prio) 
+                spec.cb_prio(EventId(extraFlags));
+            if (spec.cb_read) 
+                spec.cb_read(EventId(extraFlags));
         }
-
     }
 }
 
index 1887f5d..8fe4f15 100644 (file)
@@ -76,8 +76,9 @@ namespace senf {
 
         /// \brief Types of file descriptor events */
         enum EventId { EV_NONE=0,
-                       EV_READ=1, EV_PRIO=2, EV_WRITE=4, EV_HUP=8, EV_ERR=16,
-                       EV_ALL=31 };
+                       EV_READ=1, EV_PRIO=2, EV_WRITE=4, 
+                       EV_ALL=7,
+                       EV_HUP=8, EV_ERR=16 };
 
         /** \brief Template typedef for Callback type
 
@@ -180,8 +181,6 @@ namespace senf {
             SimpleCallback cb_read;
             SimpleCallback cb_prio;
             SimpleCallback cb_write;
-            SimpleCallback cb_hup;
-            SimpleCallback cb_err;
 
             int epollMask() const;
         };
index 78aaa4d..104268b 100644 (file)
@@ -143,7 +143,7 @@ namespace {
     void callback(int fd, Scheduler::EventId ev)
     {
         event = ev;
-        switch (event) {
+        switch (event & Scheduler::EV_ALL) {
         case Scheduler::EV_READ:
             size = recv(fd,buffer,1024,0);
             break;
@@ -155,11 +155,6 @@ namespace {
             size = write(fd,buffer,size);
             Scheduler::instance().terminate();
             break;
-        case Scheduler::EV_HUP:
-        case Scheduler::EV_ERR:
-        case Scheduler::EV_NONE:
-        case Scheduler::EV_ALL:
-            ;
         }
         Scheduler::instance().terminate();
     }
@@ -246,7 +241,7 @@ BOOST_AUTO_UNIT_TEST(scheduler)
     BOOST_CHECK_NO_THROW( Scheduler::instance().remove(handle,Scheduler::EV_WRITE) );
     event = Scheduler::EV_NONE;
     BOOST_CHECK_NO_THROW( Scheduler::instance().process() );
-    BOOST_CHECK_EQUAL( event, Scheduler::EV_READ );
+    BOOST_CHECK_EQUAL( event, Scheduler::EventId(Scheduler::EV_READ|Scheduler::EV_HUP) );
     BOOST_REQUIRE_EQUAL( size, 2 );
     buffer[size]=0;
     BOOST_CHECK_EQUAL( buffer, "OK" );
index 2fa2602..9dfa747 100644 (file)
@@ -75,20 +75,23 @@ template <class Handle>
 prefix_ void senf::WriteHelper<Handle>::process(Handle handle,
                                                        senf::Scheduler::EventId event)
 {
-    /** \fixme Move the done() calls to outside the try/catch block */
+    bool complete_ (false);
     try {
         if (event != senf::Scheduler::EV_WRITE)
             throw senf::SystemException(EPIPE);
         offset_ += handle.write(data_.data()+offset_,data_.size()-offset_);
         if (offset_ >= data_.size()) {
             data_.erase();
-            done();
+            complete_ = true;
         }
     }
     catch (senf::SystemException const & ex) {
         errno_ = ex.err;
         done();
+        return;
     }
+    if (complete_)
+        done();
 }
 
 template <class Handle>
index 8591399..d836823 100644 (file)
@@ -99,6 +99,10 @@ writeto(Handle & handle, ForwardReadableRange & range, typename Handle::Address
 // structors
 
 template <class Policy>
+prefix_ senf::ClientSocketHandle<Policy>::ClientSocketHandle()
+{}
+
+template <class Policy>
 template <class OtherPolicy>
 prefix_ senf::ClientSocketHandle<Policy>::
 ClientSocketHandle(ClientSocketHandle<OtherPolicy> other,
index 368e3cd..38e7ea0 100644 (file)
@@ -79,13 +79,6 @@ namespace senf {
         typelist of Poclicy classes which can be accessed. You use protocol<ProtocolClass>() to
         access a protocol class. \c Policies can of course be underspecified or even empty.
 
-        \idea add more flexible read/write members for a) boost::arrays and arrays of other types b)
-        std::vector (which uses contiguous memory ..) c) other random-access containers (we should
-        use some configurable trait class to identify containers with contiguous storage). Probably
-        we should just use a generic Boost.Range interface. Here we again come to the point: make
-        all except the most basic members be non-member algorithms ? this would make the
-        configuration of such extenden members more flexible.
-
         \see \ref policy_group \n
              \ref protocol_group
       */
@@ -116,11 +109,14 @@ namespace senf {
         ///\name Structors and default members
         ///@{
 
-        // no default constructor
+        // default default constructor
         // default copy constructor
         // default copy assignment
         // default destructor
 
+        // here to implement
+        ClientSocketHandle();
+
         // conversion constructors
         template <class OtherPolicy>
         ClientSocketHandle(ClientSocketHandle<OtherPolicy> other,
@@ -181,14 +177,15 @@ namespace senf {
                                              \param[in/out] range Range to store data in 
                                              \returns past-the-end iterator pointer to after the
                                                  last read character 
-                                             \see \ref read() */
+                                             \see \ref read() \n
+                                                  <a href="http://www.boost.org/libs/range/index.html">Boost.Range</a> */
         template <class ForwardWritableRange>
         typename boost::range_iterator<ForwardWritableRange>::type
                      read         (ForwardWritableRange & range);
                                         ///< Read data into range
-                                        /**< \see 
-                                             read(ForwardWritableRange const &) \n
-                                             read() */
+                                        /**< \see read(ForwardWritableRange const &) \n
+                                                  read() \n
+                                                  <a href="http://www.boost.org/libs/range/index.html">Boost.Range</a>  */
         template <class Sequence>
         void         read         (Sequence & container, unsigned limit);
                                         ///< Read data into container
@@ -243,14 +240,15 @@ namespace senf {
                                                  received
                                              \returns past-the-end iterator pointer to after the
                                                  last read character 
-                                             \see \ref readfrom() */
+                                             \see \ref readfrom() \n
+                                                  <a href="http://www.boost.org/libs/range/index.html">Boost.Range</a>  */
         template <class ForwardWritableRange>
         typename boost::range_iterator<ForwardWritableRange>::type
                      readfrom     (ForwardWritableRange & range, Address & from);
                                         ///< Read data into range
-                                        /**< \see 
-                                             readfrom(ForwardWritableRange const&,Address&) \n
-                                             readfrom() */
+                                        /**< \see readfrom(ForwardWritableRange const&,Address&) \n
+                                                  readfrom()  \n
+                                                  <a href="http://www.boost.org/libs/range/index.html">Boost.Range</a> */
         template <class Sequence>
         void         readfrom     (Sequence & container, Address & from, unsigned limit);
                                         ///< Read data into container
@@ -303,7 +301,8 @@ namespace senf {
                                         /**< \param[in] start beginning of area to write
                                              \param[in] end past-the-end pointer to area to write
                                              \returns past-the-end pointer after last byte written
-                                             \see \ref write() */
+                                             \see \ref write() \n
+                                                  <a href="http://www.boost.org/libs/range/index.html">Boost.Range</a>  */
 
         /** \brief Write data to unconnected socket
 
@@ -332,7 +331,8 @@ namespace senf {
                                              \param[in] start address of buffer to write
                                              \param[in] end past-the-end pointer after data to write
                                              \returns past-the-end iterator after last byte written
-                                             \see \ref writeto() */
+                                             \see \ref writeto() \n
+                                                  <a href="http://www.boost.org/libs/range/index.html">Boost.Range</a>  */
 
         ///////////////////////////////////////////////////////////////////////////
         ///\name Addressing
index b7ddb9f..eedc8fb 100644 (file)
@@ -38,8 +38,8 @@
 #define prefix_
 ///////////////////////////////cc.p////////////////////////////////////////
 
-prefix_ void senf::ConnectedCommunicationPolicy::listen(FileHandle handle,
-                                                               unsigned backlog)
+prefix_ void senf::ConnectedCommunicationPolicy::do_listen(FileHandle handle,
+                                                           unsigned backlog)
 {
     ::listen(handle.fd(),backlog);
 }
index b801ae1..233dc3b 100644 (file)
 ///////////////////////////////cti.p///////////////////////////////////////
 
 template <class Policy>
+prefix_ void senf::ConnectedCommunicationPolicy::
+listen(ServerSocketHandle<Policy> handle, unsigned backlog,
+       typename IfAddressingPolicyIsNot<Policy,NoAddressingPolicy>::type *)
+{
+    do_listen(handle, backlog);
+}
+
+template <class Policy>
 prefix_ int senf::ConnectedCommunicationPolicy::
 accept(ServerSocketHandle<Policy> handle,
        typename ServerSocketHandle<Policy>::Address & address,
index fe89926..9c0af83 100644 (file)
@@ -51,14 +51,12 @@ namespace senf {
      */
     struct ConnectedCommunicationPolicy : public CommunicationPolicyBase
     {
-        static void listen(FileHandle handle, unsigned backlog);
+        template <class Policy>
+        static void listen(ServerSocketHandle<Policy> handle, unsigned backlog,
+                           typename IfAddressingPolicyIsNot<Policy,NoAddressingPolicy>::type * = 0);
                                         ///< Enable establishing new connections on the socket
                                         /**< \param[in] handle socket handle to enable reception on
-                                             \param[in] backlog size of backlog queue
-
-                                             \fixme listen probably makes no sense without accept,
-                                                 so listen() should depend on AddressingPolicy
-                                                 too. */
+                                             \param[in] backlog size of backlog queue */
         template <class Policy>
         static int accept(ServerSocketHandle<Policy> handle,
                           typename ServerSocketHandle<Policy>::Address & address,
@@ -74,6 +72,7 @@ namespace senf {
                                                  peer
                                              \returns file descriptor of new client socket */
     private:
+        static void do_listen(FileHandle handle, unsigned backlog);
         static int do_accept(FileHandle handle, struct sockaddr * addr, unsigned len);
     };
 
index a727bee..37c269d 100644 (file)
@@ -171,7 +171,7 @@ prefix_ bool senf::FileHandle::eof()
 prefix_ bool senf::FileHandle::valid()
     const
 {
-    return body().valid();
+    return body_ && body().valid();
 }
 
 prefix_ bool senf::FileHandle::boolean_test()
@@ -186,18 +186,24 @@ prefix_ int senf::FileHandle::fd()
     return body().fd();
 }
 
+prefix_ senf::FileHandle::FileHandle()
+    : body_(0)
+{}
+
 prefix_  senf::FileHandle::FileHandle(std::auto_ptr<FileBody> body)
     : body_(body.release())
 {}
 
 prefix_ senf::FileBody & senf::FileHandle::body()
 {
+    BOOST_ASSERT(body_);
     return *body_;
 }
 
 prefix_ senf::FileBody const & senf::FileHandle::body()
     const
 {
+    BOOST_ASSERT(body_);
     return *body_;
 }
 
index 303916b..86cb10f 100644 (file)
 
     \image html FhHierarchy.png
 
-    The senf::FileHandle class is the base of a hierarchy of socket
-    handle classes (realized as templates). These classes provide an
-    interface to the complete socket API. While going down the
-    inheritance hierarchy, the interface will be more and more
-    complete.
-
-    The most complete interface is provided by
-    senf::ProtocolClientSocketHandle and
-    senf::ProtocolServerSocketHandle. The template Arguments specifies
-    the Protocol class of the underlying socket type. These are the
-    \e only classes having public constructors and are therefore the
-    only classes, which may be created by the library user. You will
-    normally use these classes by naming a specific socket typedef
-    (e.g. senf::TCPv4ClientSocketHandle).
-
-    However, to aid writing flexible and generic code, the socket
-    library provides the senf::ClientSocketHandle and
-    senf::ServerSocketHandle class templates. These templates
-    implement a family of closely related classes based on the
-    specification of the socket policy. This policy specification may
-    be \e incomplete (see below). Instances of
-    senf::ClientSocketHandle/senf::ServerSocketHandle can be assigned
-    and converted to different ClientSocketHandle/ServerSocketHandle
-    types as long as the policy specifications are compatible.
-
-    \attention It is very important, to (almost) always pass the socket
-    handle <em>by value</em>. The socket handle is a very lightweight
-    class and designed to be used like an ordinary built-in type. This
-    is very important in combination with the policy interface.
-
-    \note The FileHandle hierarchy below the SocketHandle template is
-    \e not meant to be user extensible. To add new socket types, you
-    should introduce new protocol and/or policy classes, the
-    SocketHandle classes should not be changed.
+    The senf::FileHandle class is the base of a hierarchy of socket handle classes (realized as
+    templates). These classes provide an interface to the complete socket API. While going down the
+    inheritance hierarchy, the interface will be more and more complete.
+
+    The most complete interface is provided by senf::ProtocolClientSocketHandle and
+    senf::ProtocolServerSocketHandle. The template Arguments specifies the Protocol class of the
+    underlying socket type. These are the \e only classes having public constructors and are
+    therefore the only classes, which may be created by the library user. You will normally use
+    these classes by naming a specific socket typedef (e.g. senf::TCPv4ClientSocketHandle).
+
+    However, to aid writing flexible and generic code, the socket library provides the
+    senf::ClientSocketHandle and senf::ServerSocketHandle class templates. These templates implement
+    a family of closely related classes based on the specification of the socket policy. This policy
+    specification may be \e incomplete (see below). Instances of
+    senf::ClientSocketHandle/senf::ServerSocketHandle can be assigned and converted to different
+    ClientSocketHandle/ServerSocketHandle types as long as the policy specifications are compatible.
+
+    \attention It is very important, to (almost) always pass the socket handle <em>by
+    value</em>. The socket handle is a very lightweight class and designed to be used like an
+    ordinary built-in type. This is very important in combination with the policy interface.
+
+    \note The FileHandle hierarchy below the SocketHandle template is \e not meant to be user
+    extensible. To add new socket types, you should introduce new protocol and/or policy classes,
+    the SocketHandle classes should not be changed.
  */
 
 #ifndef HH_FileHandle_
@@ -108,9 +98,6 @@ namespace senf {
         will have to call the protected FileHandle constructor passing a new senf::FileBody
         instance. This instance may either be a simple senf::FileBody or a class derived from
         senf::FileBody.
-
-        \fixme Add public default constructor to allow declaration of (empty) senf::FileHandle
-        variables.
      */
     class FileHandle
         : public SafeBool<FileHandle>
@@ -123,7 +110,9 @@ namespace senf {
         ///\name Structors and default members
         ///@{
 
-        // protected default constructor
+        FileHandle();
+
+        // my default constructor
         // default copy constructor
         // default copy assignment
         // default destructor
index 262bf0c..547bdbf 100644 (file)
@@ -41,7 +41,8 @@ namespace {
     class FHandle : public senf::FileHandle
     {
     public:
-        FHandle(int fd=-1)
+        FHandle() {}
+        FHandle(int fd)
             : senf::FileHandle(std::auto_ptr<senf::FileBody>(
                                           new senf::FileBody(fd))) {}
         FHandle(std::string name)
@@ -66,7 +67,9 @@ BOOST_AUTO_UNIT_TEST(fileHandle)
             BOOST_CHECK(fh);
             BOOST_CHECK(!!fh);
 
-            FHandle fh2(fh);
+            FHandle fh2;
+            BOOST_CHECK( ! fh2.valid() );
+            fh2 = fh;
             BOOST_CHECK_EQUAL(fh.fd(), fh2.fd());
 
             BOOST_CHECK(fh.writeable());
index 8af052f..eb366ef 100644 (file)
@@ -58,8 +58,8 @@ prefix_ bool senf::INet4Address::operator==(INet4Address const & other)
 prefix_ std::string senf::INet4Address::host()
     const
 {
-    /** \fixme thread safety? */
-    return std::string(::inet_ntoa(addr_.sin_addr));
+    char buffer[128];
+    return std::string(::inet_ntop(AF_INET,&addr_.sin_addr,buffer,128));
 }
 
 prefix_ unsigned senf::INet4Address::port()
index de661cb..db2be65 100644 (file)
@@ -59,9 +59,7 @@ namespace senf {
         INet4Address();
         INet4Address(char const * address); ///< Set address and port
                                         /**< See INet4Address(std::string)
-                                             \throws InvalidINetAddressException
-                                             \fixme Why do I need this version? Shouldn't the
-                                             std::string version be enough ? */
+                                             \throws InvalidINetAddressException */
         INet4Address(std::string address); ///< Set address and port
                                         /**< This constructor expects a string of the form
                                              'xxx.xxx.xxx.xxx:pppp'. The constructor will use this
index a3e383e..2123198 100644 (file)
 ///////////////////////////////cti.p///////////////////////////////////////
 
 template <class SocketProtocol>
+prefix_ senf::ProtocolClientSocketHandle<SocketProtocol>::
+ProtocolClientSocketHandle(UninitializedType)
+{}
+
+template <class SocketProtocol>
 prefix_ senf::ProtocolClientSocketHandle<SocketProtocol>::ProtocolClientSocketHandle()
     : ClientSocketHandle<typename SocketProtocol::Policy>(
         std::auto_ptr<senf::SocketProtocol>(new SocketProtocol()))
index f9e456d..375db13 100644 (file)
@@ -65,6 +65,7 @@ namespace senf {
         // Types
 
         typedef SocketProtocol Protocol; ///< The sockets protocol
+        enum UninitializedType { Uninitialized }; ///< Flag to call 'uninitialized' constructor
 
         ///////////////////////////////////////////////////////////////////////////
         ///\name Structors and default members
@@ -84,6 +85,17 @@ namespace senf {
 #       define BOOST_PP_ITERATION_PARAMS_1 (4, (1, 9, "Socket/ProtocolClientSocketHandle.mpp", 1))
 #       include BOOST_PP_ITERATE()
 
+        /** \brief Create uninitialized socket variable
+
+            This special constructor is called when passing
+            ProtocolClientSocketHandle::Uninitialized as only argument to the constructor. This will
+            create an in-\ref valid() socket handle which can however be assigned later with another
+            socket instance.
+
+            \implementation The socket handle will have no \c body allocated.
+         */
+        ProtocolClientSocketHandle(UninitializedType);
+
         ///@}
         ///////////////////////////////////////////////////////////////////////////
 
index 9c7a449..67abd4c 100644 (file)
 ///////////////////////////////cti.p///////////////////////////////////////
 
 template <class SocketProtocol>
+prefix_ senf::ProtocolServerSocketHandle<SocketProtocol>::
+ProtocolServerSocketHandle(UninitializedType)
+{}
+
+template <class SocketProtocol>
 prefix_ senf::ProtocolServerSocketHandle<SocketProtocol>::ProtocolServerSocketHandle()
     : ServerSocketHandle<typename SocketProtocol::Policy>(
         std::auto_ptr<senf::SocketProtocol>(new SocketProtocol()))
index c4bc01a..af6db47 100644 (file)
@@ -69,6 +69,7 @@ namespace senf {
         // Types
 
         typedef SocketProtocol Protocol; ///< The socket protocol
+        enum UninitializedType { Uninitialized }; ///< Flag to call 'uninitialized' constructor
 
         ///////////////////////////////////////////////////////////////////////////
         ///\name Structors and default members
@@ -89,6 +90,16 @@ namespace senf {
 #       define BOOST_PP_ITERATION_PARAMS_1 (4, (1, 9, "Socket/ProtocolServerSocketHandle.mpp", 1))
 #       include BOOST_PP_ITERATE()
 
+        /** \brief Create uninitialized socket variable
+
+            This special constructor is called when passing
+            ProtocolServerSocketHandle::Uninitialized as only argument to the constructor. This will
+            create an in-\ref valid() socket handle which can however be assigned later with another
+            socket instance.
+
+            \implementation The socket handle will have no \c body allocated.
+         */
+        ProtocolServerSocketHandle(UninitializedType);
         ///@}
         ///////////////////////////////////////////////////////////////////////////
 
index 03764f3..1706074 100644 (file)
 #define prefix_ inline
 ///////////////////////////////cti.p///////////////////////////////////////
 
+template <class Policy>
+prefix_ senf::ServerSocketHandle<Policy>::ServerSocketHandle()
+{}
+
 template <class SocketPolicy>
 template <class OtherPolicy>
 prefix_ senf::ServerSocketHandle<SocketPolicy>::
index b096036..76b2510 100644 (file)
@@ -96,11 +96,14 @@ namespace senf {
         ///\name Structors and default members
         ///@{
 
-        // no default constructor
+        // default default constructor
         // default copy constructor
         // default copy assignment
         // default destructor
 
+        // here to implement
+        ServerSocketHandle();
+
         // conversion constructors
         template <class OtherPolicy>
         ServerSocketHandle(ServerSocketHandle<OtherPolicy> other,
index 56c1472..3df213c 100644 (file)
 ///////////////////////////////cti.p///////////////////////////////////////
 
 template <class SocketPolicy>
+prefix_ senf::SocketHandle<SocketPolicy>::SocketHandle()
+{}
+
+template <class SocketPolicy>
 template <class OtherPolicy>
 prefix_ senf::SocketHandle<SocketPolicy>::SocketHandle(SocketHandle<OtherPolicy> other,
                                                               typename IsCompatible<OtherPolicy>::type *)
index 8cd567f..ce67d0e 100644 (file)
@@ -89,10 +89,14 @@ namespace senf {
         ///\name Structors and default members
         ///@{
 
+        // default default constructor
         // default copy constructor
         // default copy assignment
         // default destructor
 
+        // here to implement
+        SocketHandle();
+
         // conversion constructors
 
         template <class OtherPolicy>