diff --git a/Packets/DefaultBundle/IpV4Packet.cc b/Packets/DefaultBundle/IpV4Packet.cc index 8f7c0643937f06cef9e2864204b349ac91834234..6b163a6d55262164213cadd12c7b17ffc57761ba 100644 --- a/Packets/DefaultBundle/IpV4Packet.cc +++ b/Packets/DefaultBundle/IpV4Packet.cc @@ -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" diff --git a/Packets/Packet.cci b/Packets/Packet.cci index d9dcfc0fbd63ac82bbdf43c80539993393d604b9..72f794364245450f3e4f6de6870e3cb433862c7e 100644 --- a/Packets/Packet.cci +++ b/Packets/Packet.cci @@ -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"); diff --git a/Packets/ParseListS.ct b/Packets/ParseListS.ct index ba893600ba50016bac8f3f51506169840efb7300..1c010366e4dd6747b4c9c2834713b55835561b23 100644 --- a/Packets/ParseListS.ct +++ b/Packets/ParseListS.ct @@ -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); diff --git a/Scheduler/ReadHelper.ct b/Scheduler/ReadHelper.ct index 3ac3df5f55a0d3e8364cddb878ad158ec1a2da52..40ac19936dcb6e2c31d470ddf1ac9a306eee0d6b 100644 --- a/Scheduler/ReadHelper.ct +++ b/Scheduler/ReadHelper.ct @@ -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> diff --git a/Scheduler/Scheduler.cc b/Scheduler/Scheduler.cc index f692402b2f88572078f0a4da1e5d7077716d2ed3..e4bc1a09fbc42d59e55994089e0094e67e8c28dc 100644 --- a/Scheduler/Scheduler.cc +++ b/Scheduler/Scheduler.cc @@ -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)); } - } } diff --git a/Scheduler/Scheduler.hh b/Scheduler/Scheduler.hh index 1887f5deffa51c913fee8ebbe6d3d3266e76f1f0..8fe4f152a2134dc2435b2526fa57995c76970874 100644 --- a/Scheduler/Scheduler.hh +++ b/Scheduler/Scheduler.hh @@ -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; }; diff --git a/Scheduler/Scheduler.test.cc b/Scheduler/Scheduler.test.cc index 78aaa4d29c602e0545b394160fe5f7ce094c5252..104268b2f9ec0cec74cba8df3c003ae81828981a 100644 --- a/Scheduler/Scheduler.test.cc +++ b/Scheduler/Scheduler.test.cc @@ -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" ); diff --git a/Scheduler/WriteHelper.ct b/Scheduler/WriteHelper.ct index 2fa26020aca199ab7786dc6768caa8410ad92973..9dfa7479367a818fafb89ffb6454b1de154b0b4c 100644 --- a/Scheduler/WriteHelper.ct +++ b/Scheduler/WriteHelper.ct @@ -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> diff --git a/Socket/ClientSocketHandle.cti b/Socket/ClientSocketHandle.cti index 859139948f268c42ae5461c07edcb2b1cb87234a..d836823498b11d3b68ddb95652358c5a117fc287 100644 --- a/Socket/ClientSocketHandle.cti +++ b/Socket/ClientSocketHandle.cti @@ -98,6 +98,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>:: diff --git a/Socket/ClientSocketHandle.hh b/Socket/ClientSocketHandle.hh index 368e3cdb3d1c86bd0015beaaacbd9fcaa9b37893..38e7ea0388adf701bbacd3bad337baf3b180994f 100644 --- a/Socket/ClientSocketHandle.hh +++ b/Socket/ClientSocketHandle.hh @@ -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 diff --git a/Socket/CommunicationPolicy.cc b/Socket/CommunicationPolicy.cc index b7ddb9f5156a675ae9ab9e6a6ee09ca0940ac416..eedc8fb4e9442ee63a1a8ee880f5aa8e69390a8e 100644 --- a/Socket/CommunicationPolicy.cc +++ b/Socket/CommunicationPolicy.cc @@ -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); } diff --git a/Socket/CommunicationPolicy.cti b/Socket/CommunicationPolicy.cti index b801ae11fd6eb881b85fc1b59bd62f9bc38118e3..233dc3bfbb811229d8349a20022ac85179782675 100644 --- a/Socket/CommunicationPolicy.cti +++ b/Socket/CommunicationPolicy.cti @@ -31,6 +31,14 @@ #define prefix_ inline ///////////////////////////////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, diff --git a/Socket/CommunicationPolicy.hh b/Socket/CommunicationPolicy.hh index fe899262f7027af85044068d0ad38e3d8149028f..9c0af83e8b8d8508e3528240ae67d3342143eff4 100644 --- a/Socket/CommunicationPolicy.hh +++ b/Socket/CommunicationPolicy.hh @@ -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); }; diff --git a/Socket/FileHandle.cci b/Socket/FileHandle.cci index a727beee0ac8b02957e5979afd192e0cead2fae9..37c269d6f9c9416aa1b32bcd4b612005398f31c2 100644 --- a/Socket/FileHandle.cci +++ b/Socket/FileHandle.cci @@ -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_; } diff --git a/Socket/FileHandle.hh b/Socket/FileHandle.hh index 303916b539e0764235016d9fc22c915064a0f6fd..86cb10f65e460782678fd2e3d19693e3ac17a4e9 100644 --- a/Socket/FileHandle.hh +++ b/Socket/FileHandle.hh @@ -28,40 +28,30 @@ \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 diff --git a/Socket/FileHandle.test.cc b/Socket/FileHandle.test.cc index 262bf0ce05fcf1f45d665206c76ed9dc86bd3cb4..547bdbff745dc0cc9c7a19a66370cbded258c0f0 100644 --- a/Socket/FileHandle.test.cc +++ b/Socket/FileHandle.test.cc @@ -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()); diff --git a/Socket/INetAddressing.cci b/Socket/INetAddressing.cci index 8af052f7a420905b66c6140f782e7990e4dbec2a..eb366ef3925bb140de5a50b115faf7d2d803cdf3 100644 --- a/Socket/INetAddressing.cci +++ b/Socket/INetAddressing.cci @@ -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() diff --git a/Socket/INetAddressing.hh b/Socket/INetAddressing.hh index de661cbd193d2699549cbfebcc09966821155603..db2be656d0eefdc633043a84c7c4f682668c4173 100644 --- a/Socket/INetAddressing.hh +++ b/Socket/INetAddressing.hh @@ -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 diff --git a/Socket/ProtocolClientSocketHandle.cti b/Socket/ProtocolClientSocketHandle.cti index a3e383ebd4e2efac42f9ee260d3be6d34ceedd96..2123198a4a443c7334748e8adc32a54f7256df7b 100644 --- a/Socket/ProtocolClientSocketHandle.cti +++ b/Socket/ProtocolClientSocketHandle.cti @@ -34,6 +34,11 @@ #define prefix_ inline ///////////////////////////////cti.p/////////////////////////////////////// +template <class SocketProtocol> +prefix_ senf::ProtocolClientSocketHandle<SocketProtocol>:: +ProtocolClientSocketHandle(UninitializedType) +{} + template <class SocketProtocol> prefix_ senf::ProtocolClientSocketHandle<SocketProtocol>::ProtocolClientSocketHandle() : ClientSocketHandle<typename SocketProtocol::Policy>( diff --git a/Socket/ProtocolClientSocketHandle.hh b/Socket/ProtocolClientSocketHandle.hh index f9e456de01c47557d9d151fc0bb403cbc2834ad5..375db13f1de7856bbf0407f1a0bede6f43e383b8 100644 --- a/Socket/ProtocolClientSocketHandle.hh +++ b/Socket/ProtocolClientSocketHandle.hh @@ -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); + ///@} /////////////////////////////////////////////////////////////////////////// diff --git a/Socket/ProtocolServerSocketHandle.cti b/Socket/ProtocolServerSocketHandle.cti index 9c7a44907fb17a02c8850bf2113bf95c41d61a90..67abd4c8bbcf3f9cb13ea1ad5f36b7739a7c7079 100644 --- a/Socket/ProtocolServerSocketHandle.cti +++ b/Socket/ProtocolServerSocketHandle.cti @@ -34,6 +34,11 @@ #define prefix_ inline ///////////////////////////////cti.p/////////////////////////////////////// +template <class SocketProtocol> +prefix_ senf::ProtocolServerSocketHandle<SocketProtocol>:: +ProtocolServerSocketHandle(UninitializedType) +{} + template <class SocketProtocol> prefix_ senf::ProtocolServerSocketHandle<SocketProtocol>::ProtocolServerSocketHandle() : ServerSocketHandle<typename SocketProtocol::Policy>( diff --git a/Socket/ProtocolServerSocketHandle.hh b/Socket/ProtocolServerSocketHandle.hh index c4bc01ace05e8a49cc8c65a22e2e2b1f377dd8fc..af6db4780a2cf56adcd973662c6ac932a9edd57e 100644 --- a/Socket/ProtocolServerSocketHandle.hh +++ b/Socket/ProtocolServerSocketHandle.hh @@ -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); ///@} /////////////////////////////////////////////////////////////////////////// diff --git a/Socket/ServerSocketHandle.cti b/Socket/ServerSocketHandle.cti index 03764f369978d6ef667b904c91389352084c278d..1706074d3cf65a4014ed2b9abad22dc0f720820b 100644 --- a/Socket/ServerSocketHandle.cti +++ b/Socket/ServerSocketHandle.cti @@ -34,6 +34,10 @@ #define prefix_ inline ///////////////////////////////cti.p/////////////////////////////////////// +template <class Policy> +prefix_ senf::ServerSocketHandle<Policy>::ServerSocketHandle() +{} + template <class SocketPolicy> template <class OtherPolicy> prefix_ senf::ServerSocketHandle<SocketPolicy>:: diff --git a/Socket/ServerSocketHandle.hh b/Socket/ServerSocketHandle.hh index b0960362d961211535b2391588249fc0953124c2..76b2510a3f3ec5bd63d0f8822306d5fa262134ce 100644 --- a/Socket/ServerSocketHandle.hh +++ b/Socket/ServerSocketHandle.hh @@ -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, diff --git a/Socket/SocketHandle.cti b/Socket/SocketHandle.cti index 56c14729488a4fd2e1a62d2add7cb428dbef27cf..3df213cdb03ef328f3f67c04cc6e69622b4ed7ec 100644 --- a/Socket/SocketHandle.cti +++ b/Socket/SocketHandle.cti @@ -34,6 +34,10 @@ #define prefix_ inline ///////////////////////////////cti.p/////////////////////////////////////// +template <class SocketPolicy> +prefix_ senf::SocketHandle<SocketPolicy>::SocketHandle() +{} + template <class SocketPolicy> template <class OtherPolicy> prefix_ senf::SocketHandle<SocketPolicy>::SocketHandle(SocketHandle<OtherPolicy> other, diff --git a/Socket/SocketHandle.hh b/Socket/SocketHandle.hh index 8cd567fd6c98c81bc387b33738bc7d063a4f970a..ce67d0e78de687ac990791fbd23e19ad73aacac9 100644 --- a/Socket/SocketHandle.hh +++ b/Socket/SocketHandle.hh @@ -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>