diff --git a/Socket/ClientSocketHandle.ct b/Socket/ClientSocketHandle.ct index 734148b166885e23bfa05a93a107162950cbb1f4..0e33be03d7dddc008fc8fcff0bb0afebaecc6ed9 100644 --- a/Socket/ClientSocketHandle.ct +++ b/Socket/ClientSocketHandle.ct @@ -25,6 +25,7 @@ //#include "ClientSocketHandle.ih" // Custom includes +#include <fcntl.h> #define prefix_ ///////////////////////////////ct.p//////////////////////////////////////// @@ -40,7 +41,8 @@ prefix_ std::string satcom::lib::ClientSocketHandle<Policy>::read() template <class Policy> prefix_ void satcom::lib::ClientSocketHandle<Policy>::read(std::string & buffer) { - unsigned nread = this->protocol().available(); + unsigned nread = available(); + // TODO: handle case where nread == 0 and socket is blocking // FIXME: This is not necessary correct and more or less a hack ... buffer.assign(nread,0); unsigned rv = this->read(const_cast<char *>(buffer.data()),nread); @@ -62,14 +64,25 @@ template <class Policy> prefix_ void satcom::lib::ClientSocketHandle<Policy>:: readfrom(std::string & buffer, typename Policy::AddressingPolicy::Address & from) { - unsigned nread = this->protocol().available(); - // FIXME: s.o. + unsigned nread = available(); + // TODO: handle case where nread == 0 and socket is blocking + // FIXME: This is not necessary correct and more or less a hack ... buffer.assign(nread,0); unsigned rv = this->readfrom(const_cast<char *>(buffer.data()), nread, from); if (rv < nread) buffer.erase(buffer.begin()+rv,buffer.end()); } +template <class Policy> +prefix_ unsigned satcom::lib::ClientSocketHandle<Policy>::available() +{ + unsigned nread = this->protocol().available(); + if (nread == 0 && this->blocking()) { + this->waitReadable(); + nread = this->protocol().available(); + } + return nread; +} ///////////////////////////////ct.e//////////////////////////////////////// #undef prefix_ diff --git a/Socket/ClientSocketHandle.cti b/Socket/ClientSocketHandle.cti index 0e3d796239a551fc429ffb3a2a84b874e335c791..c2b2c8f8911c4354e9219f3e0d2132314bf842a3 100644 --- a/Socket/ClientSocketHandle.cti +++ b/Socket/ClientSocketHandle.cti @@ -100,6 +100,54 @@ writeto(typename boost::call_traits<typename Policy::AddressingPolicy::Address>: return Policy::WritePolicy::writeto(*this, addr, buffer, size); } +/////////////////////////////////////////////////////////////////////////// +// addressing + +template <class Policy> +prefix_ typename Policy::AddressingPolicy::Address +satcom::lib::ClientSocketHandle<Policy>::peer() +{ + typename Policy::AddressingPolicy::Address addr; + this->peer(addr); + return addr; +} + +template <class Policy> +prefix_ void satcom::lib::ClientSocketHandle<Policy>:: +peer(typename Policy::AddressingPolicy::Address & addr) +{ + Policy::AddressingPolicy::peer(*this,addr); +} + +template <class Policy> +prefix_ typename Policy::AddressingPolicy::Address +satcom::lib::ClientSocketHandle<Policy>::local() +{ + typename Policy::AddressingPolicy::Address addr; + this->local(addr); + return addr; +} + +template <class Policy> +prefix_ void satcom::lib::ClientSocketHandle<Policy>:: +local(typename Policy::AddressingPolicy::Address & addr) +{ + Policy::AddressingPolicy::local(*this,addr); +} + +template <class Policy> +prefix_ void satcom::lib::ClientSocketHandle<Policy>::connect(AddressParam addr) +{ + Policy::AddressingPolicy::connect(*this,addr); +} + +template <class Policy> +prefix_ void satcom::lib::ClientSocketHandle<Policy>:: +bind(typename boost::call_traits<typename Policy::AddressingPolicy::Address>::param_type addr) +{ + Policy::AddressingPolicy::bind(*this,addr); +} + ///////////////////////////////cti.e/////////////////////////////////////// #undef prefix_ diff --git a/Socket/ClientSocketHandle.hh b/Socket/ClientSocketHandle.hh index 774df290537846f00f7446c34f979078d47dfa2e..a623a5964a104eaf62f2b52666398df551d2cf0a 100644 --- a/Socket/ClientSocketHandle.hh +++ b/Socket/ClientSocketHandle.hh @@ -43,6 +43,9 @@ namespace lib { /////////////////////////////////////////////////////////////////////////// // Types + typedef typename Policy::AddressingPolicy::Address Address; + typedef typename boost::call_traits<Address>::param_type AddressParam; + /////////////////////////////////////////////////////////////////////////// ///\name Structors and default members ///@{ @@ -74,22 +77,35 @@ namespace lib { unsigned read (char * buffer, unsigned size); // read from unconnected socket returning peer address - std::pair<std::string, typename Policy::AddressingPolicy::Address> + std::pair<std::string, Address> readfrom (); - void readfrom (std::string & buffer, - typename Policy::AddressingPolicy::Address & from); - unsigned readfrom (char * buffer, unsigned size, - typename Policy::AddressingPolicy::Address & from); + void readfrom (std::string & buffer, Address & from); + unsigned readfrom (char * buffer, unsigned size, Address & from); // write to connected socket unsigned write (std::string const & data); unsigned write (char const * buffer, unsigned size); // write to unconnected socket - unsigned writeto (typename boost::call_traits<typename Policy::AddressingPolicy::Address>::param_type addr, - std::string const & data); - unsigned writeto (typename boost::call_traits<typename Policy::AddressingPolicy::Address>::param_type addr, - char const * buffer, unsigned size); + unsigned writeto (AddressParam addr, std::string const & data); + unsigned writeto (AddressParam addr, char const * buffer, unsigned size); + + ///@} + + /////////////////////////////////////////////////////////////////////////// + ///\name Addressing + ///@{ + + void connect (AddressParam addr); + void bind (AddressParam addr); + + typename Policy::AddressingPolicy::Address + peer (); + void peer (Address & addr); + + typename Policy::AddressingPolicy::Address + local (); + void local (Address & addr); ///@} @@ -97,6 +113,7 @@ namespace lib { explicit ClientSocketHandle(std::auto_ptr<SocketProtocol> protocol); private: + unsigned available(); }; diff --git a/Socket/ClientSocketHandle.test.cc b/Socket/ClientSocketHandle.test.cc index 7d01f460996dd8e8e0da90f1600b11b8b385fe57..a31119a3a15b0c01464afb39d520661e98196fac 100644 --- a/Socket/ClientSocketHandle.test.cc +++ b/Socket/ClientSocketHandle.test.cc @@ -85,13 +85,13 @@ BOOST_AUTO_UNIT_TEST(clientSocketHandle) BOOST_CHECK_EQUAL( myh.readfrom().first, "TEST-READ" ); { std::string buf("FOO-BAR"); - satcom::lib::nil addr; + unsigned addr; myh.readfrom(buf,addr); BOOST_CHECK_EQUAL( buf, "TEST-READ" ); } { char buf[11]; - satcom::lib::nil addr; + unsigned addr; ::strcpy(buf,"0123456789"); BOOST_CHECK_EQUAL( myh.readfrom(buf,10,addr), 9u ); BOOST_CHECK_EQUAL( buf, "TEST-READ9" ); @@ -100,8 +100,13 @@ BOOST_AUTO_UNIT_TEST(clientSocketHandle) BOOST_CHECK_EQUAL( myh.write("TEST-WRITE"), 10u ); BOOST_CHECK_EQUAL( myh.write("TEST"), 0u ); BOOST_CHECK_EQUAL( myh.write("TEST-WRITE9",10), 10u ); - BOOST_CHECK_EQUAL( myh.writeto(satcom::lib::nil(),"TEST-WRITE"), 10u ); - BOOST_CHECK_EQUAL( myh.writeto(satcom::lib::nil(),"TEST-WRITE9",10), 10u ); + BOOST_CHECK_EQUAL( myh.writeto(0,"TEST-WRITE"), 10u ); + BOOST_CHECK_EQUAL( myh.writeto(0,"TEST-WRITE9",10), 10u ); + + BOOST_CHECK_NO_THROW( myh.connect(0) ); + BOOST_CHECK_NO_THROW( myh.bind(0) ); + BOOST_CHECK_EQUAL( myh.peer(), 1u ); + BOOST_CHECK_EQUAL( myh.local(), 2u ); } ///////////////////////////////cc.e//////////////////////////////////////// diff --git a/Socket/FileHandle.cc b/Socket/FileHandle.cc index ce0214b5aa3a2a3536bc12e47acd41c0febc0ea2..d16dbb70fa98a327b0a1c1d2d8dea62d94145e50 100644 --- a/Socket/FileHandle.cc +++ b/Socket/FileHandle.cc @@ -29,35 +29,43 @@ #include <sys/poll.h> #include <string.h> #include <errno.h> +#include <fcntl.h> #include "Utils/Exception.hh" #define prefix_ ///////////////////////////////cc.p//////////////////////////////////////// -namespace { - bool pollCheck(int fd, int event) - { - struct ::pollfd pfd; - ::memset(&pfd,0,sizeof(pfd)); - pfd.fd = fd; - pfd.events = event; - int rv = ::poll(&pfd,1,0); - if (rv<0) - throw satcom::lib::SystemException(errno); - return rv>0; - } +prefix_ bool satcom::lib::FileBody::blocking() + const +{ + int flags = ::fcntl(fd(),F_GETFL); + if (flags < 0) throw SystemException(errno); + return ! (flags & O_NONBLOCK); } -prefix_ bool satcom::lib::FileBody::readable() +prefix_ bool satcom::lib::FileBody::blocking(bool status) const { - return pollCheck(fd(),POLLIN); + int flags = ::fcntl(fd(),F_GETFL); + if (flags < 0) throw SystemException(errno); + bool old = flags & O_NONBLOCK; + if (status) flags &= ~O_NONBLOCK; + else flags |= O_NONBLOCK; + if (::fcntl(fd(), F_SETFL, flags) < 0) throw SystemException(errno); + return ! old; } -prefix_ bool satcom::lib::FileBody::writeable() +prefix_ bool satcom::lib::FileBody::pollCheck(int fd, bool incoming, bool block) const { - return pollCheck(fd(),POLLOUT); + struct ::pollfd pfd; + ::memset(&pfd,0,sizeof(pfd)); + pfd.fd = fd; + pfd.events = incoming?POLLIN:POLLOUT; + int rv = ::poll(&pfd,1,block?-1:0); + if (rv<0) + throw satcom::lib::SystemException(errno); + return rv>0; } ///////////////////////////////cc.e//////////////////////////////////////// diff --git a/Socket/FileHandle.cci b/Socket/FileHandle.cci index b04e7f25169ffc930350c58e411899c4170573b3..f63792c5abbb656e2f7ce6266d7fb037e0ef9da7 100644 --- a/Socket/FileHandle.cci +++ b/Socket/FileHandle.cci @@ -79,6 +79,12 @@ prefix_ void satcom::lib::FileBody::terminate() prefix_ void satcom::lib::FileBody::flush() {} +prefix_ bool satcom::lib::FileBody::eof() + const +{ + return false; +} + prefix_ bool satcom::lib::FileBody::valid() const { @@ -88,7 +94,31 @@ prefix_ bool satcom::lib::FileBody::valid() prefix_ bool satcom::lib::FileBody::ok() const { - return valid(); + return valid() && !eof(); +} + +prefix_ bool satcom::lib::FileBody::readable() + const +{ + return pollCheck(fd(),true); +} + +prefix_ void satcom::lib::FileBody::waitReadable() + const +{ + pollCheck(fd(),true,true); +} + +prefix_ bool satcom::lib::FileBody::writeable() + const +{ + return pollCheck(fd(),false); +} + +prefix_ void satcom::lib::FileBody::waitWritable() + const +{ + pollCheck(fd(),false,true); } /////////////////////////////////////////////////////////////////////////// @@ -115,12 +145,41 @@ prefix_ bool satcom::lib::FileHandle::readable() return body().readable(); } +prefix_ void satcom::lib::FileHandle::waitReadable() + const +{ + body().waitReadable(); +} + prefix_ bool satcom::lib::FileHandle::writeable() const { return body().writeable(); } +prefix_ void satcom::lib::FileHandle::waitWritable() + const +{ + body().waitWritable(); +} + +prefix_ bool satcom::lib::FileHandle::blocking() + const +{ + return body().blocking(); +} + +prefix_ bool satcom::lib::FileHandle::blocking(bool status) +{ + return body().blocking(status); +} + +prefix_ bool satcom::lib::FileHandle::eof() + const +{ + return body().eof(); +} + prefix_ bool satcom::lib::FileHandle::valid() const { diff --git a/Socket/FileHandle.hh b/Socket/FileHandle.hh index 6f21f32ac5dc4249536fcead63d12628c3a430fd..0162ec73e50f6b2dac23b195d279999b737530f0 100644 --- a/Socket/FileHandle.hh +++ b/Socket/FileHandle.hh @@ -62,8 +62,14 @@ namespace lib { void flush(); bool readable() const; + void waitReadable() const; bool writeable() const; + void waitWritable() const; + bool blocking() const; + bool blocking(bool status); + + bool eof() const; bool valid() const; operator bool () const; diff --git a/Socket/FileHandle.ih b/Socket/FileHandle.ih index 0bf15d8db948d5a43d1ffa74c9a419e99d11f8f5..b6ce3f0fe95e86667cf9b96856e202e79385cdfe 100644 --- a/Socket/FileHandle.ih +++ b/Socket/FileHandle.ih @@ -63,14 +63,22 @@ namespace lib { virtual void flush(); bool readable() const; + void waitReadable() const; bool writeable() const; + void waitWritable() const; + bool blocking() const; + bool blocking(bool status) const; + + virtual bool eof() const; virtual bool valid() const; - virtual bool ok() const; + bool ok() const; protected: private: + bool pollCheck(int fd, bool incoming, bool block=false) const; + int fd_; }; diff --git a/Socket/INetAddress.cc b/Socket/INetAddress.cc index c95e28b044b617490455599968ef5ebc1a4bb434..b1bde50a41bd50c5f40a767faea2f858f6d705a7 100644 --- a/Socket/INetAddress.cc +++ b/Socket/INetAddress.cc @@ -37,15 +37,13 @@ prefix_ satcom::lib::INet4Address::INet4Address() { - ::memset(&addr,0,sizeof(addr)); - addr.sin_family = AF_INET; + clear(); } prefix_ satcom::lib::INet4Address const & satcom::lib::INet4Address::operator=(std::string const & address) { - ::memset(&addr,0,sizeof(addr)); - addr.sin_family = AF_INET; + clear(); // TODO: gethostbyname einbauen unsigned i = address.find(':'); if (i == std::string::npos) @@ -65,8 +63,7 @@ satcom::lib::INet4Address::operator=(std::string const & address) prefix_ satcom::lib::INet4Address const & satcom::lib::INet4Address::operator=(std::pair<std::string, unsigned> const & address) { - ::memset(&addr,0,sizeof(addr)); - addr.sin_family = AF_INET; + clear(); // TODO: gethostbyname einbauen if (::inet_aton(address.first.c_str(), &addr.sin_addr) == 0) throw InvalidINetAddressException(); @@ -82,6 +79,12 @@ prefix_ std::string satcom::lib::INet4Address::str() return s.str(); } +prefix_ void satcom::lib::INet4Address::clear() +{ + ::memset(&addr,0,sizeof(addr)); + addr.sin_family = AF_INET; +} + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_ //#include "INetAddress.mpp" diff --git a/Socket/INetAddress.hh b/Socket/INetAddress.hh index 2e6a6c2660ac48d5d12bf6e5fffb8439ae1bd138..37fa31901e59650172d5cc1e58cdc854105c36c6 100644 --- a/Socket/INetAddress.hh +++ b/Socket/INetAddress.hh @@ -52,6 +52,8 @@ namespace lib { // TODO: Interface + void clear(); + struct sockaddr * sockaddr_p(); struct sockaddr const * sockaddr_p() const; unsigned sockaddr_len() const; diff --git a/Socket/INetProtocol.cci b/Socket/INetProtocol.cci new file mode 100644 index 0000000000000000000000000000000000000000..5f2e1d350d1e2fda0e855f7f19b85e3576c854b3 --- /dev/null +++ b/Socket/INetProtocol.cci @@ -0,0 +1,68 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of inline non-template functions + +// Custom includes +#include <sys/socket.h> +#include "Utils/Exception.hh" + +#define prefix_ inline +///////////////////////////////cci.p/////////////////////////////////////// + +prefix_ void satcom::lib::INet4AddressingPolicy::local(FileHandle handle, Address & addr) +{ + addr.clear(); + socklen_t l (addr.sockaddr_len()); + if (::getsockname(handle.fd(),addr.sockaddr_p(),&l) < 0) + throw SystemException(errno); +} + +prefix_ void satcom::lib::INet4AddressingPolicy::bind(FileHandle handle, Address const & addr) +{ + if (::bind(handle.fd(),addr.sockaddr_p(),addr.sockaddr_len()) < 0) + throw SystemException(errno); +} + +prefix_ void satcom::lib::INet4AddressingPolicy::do_peer(FileHandle handle, Address & addr) +{ + addr.clear(); + socklen_t l (addr.sockaddr_len()); + if (::getpeername(handle.fd(),addr.sockaddr_p(),&l) < 0) + throw SystemException(errno); +} + +prefix_ void satcom::lib::INet4AddressingPolicy::do_connect(FileHandle handle, + Address const & addr) +{ + if (::connect(handle.fd(),addr.sockaddr_p(),addr.sockaddr_len()) < 0) + throw SystemException(errno); +} + +///////////////////////////////cci.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/INetProtocol.cti b/Socket/INetProtocol.cti new file mode 100644 index 0000000000000000000000000000000000000000..bf0ca2dee117f0e70168ddec6cca6d56728406c4 --- /dev/null +++ b/Socket/INetProtocol.cti @@ -0,0 +1,55 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of inline template functions + +//#include "INetProtocol.ih" + +// Custom includes + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +template <class Policy> +prefix_ void satcom::lib::INet4AddressingPolicy:: +peer(ClientSocketHandle<Policy> handle, Address & addr, + typename IfCommunicationPolicyIs<Policy,ConnectedCommunicationPolicy>::type *) +{ + do_peer(handle,addr); +} + +template <class Policy> +prefix_ void satcom::lib::INet4AddressingPolicy:: +connect(ClientSocketHandle<Policy> handle, Address const & addr, + typename IfCommunicationPolicyIs<Policy,ConnectedCommunicationPolicy>::type *) +{ + do_connect(handle,addr); +} + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/INetProtocol.hh b/Socket/INetProtocol.hh index b19556d8cc89555f0dfa5a594409a7412a64b63e..3f35fbba2a7ef8bfc9225cf4e1f2242c7aa205aa 100644 --- a/Socket/INetProtocol.hh +++ b/Socket/INetProtocol.hh @@ -26,6 +26,8 @@ // Custom includes #include "SocketPolicy.hh" #include "INetAddress.hh" +#include "ClientSocketHandle.hh" +#include "CommunicationPolicy.hh" //#include "INetProtocol.mpp" ///////////////////////////////hh.p//////////////////////////////////////// @@ -36,11 +38,27 @@ namespace lib { struct INet4AddressingPolicy : public AddressingPolicyBase { typedef INet4Address Address; + + template <class Policy> + static void peer(ClientSocketHandle<Policy> handle, Address & addr, + typename IfCommunicationPolicyIs<Policy,ConnectedCommunicationPolicy>::type * = 0); + static void local(FileHandle handle, Address & addr); + + template <class Policy> + static void connect(ClientSocketHandle<Policy> handle, Address const & addr, + typename IfCommunicationPolicyIs<Policy,ConnectedCommunicationPolicy>::type * = 0); + static void bind(FileHandle handle, Address const & addr); + + private: + static void do_peer(FileHandle handle, Address & addr); + static void do_connect(FileHandle handle, Address const & addr); }; struct INet6AddressingPolicy : public AddressingPolicyBase { typedef INet6Address Address; + + // TODO: Implement }; class IPv4Protocol @@ -52,9 +70,9 @@ namespace lib { }} ///////////////////////////////hh.e//////////////////////////////////////// -//#include "INetProtocol.cci" +#include "INetProtocol.cci" //#include "INetProtocol.ct" -//#include "INetProtocol.cti" +#include "INetProtocol.cti" #endif diff --git a/Socket/ReadWritePolicy.cci b/Socket/ReadWritePolicy.cci index bbcf510e5aae65f2c05751769b37a55d125f8709..28a6f223a0f48208f92eb3e7c8cba8d8641324d5 100644 --- a/Socket/ReadWritePolicy.cci +++ b/Socket/ReadWritePolicy.cci @@ -38,10 +38,10 @@ prefix_ unsigned satcom::lib::ReadablePolicy::read(FileHandle handle, char * buf return rv; } -prefix_ unsigned satcom::lib::WriteablePolicy::write(int fd, char * buffer, unsigned size, - ConnectedCommunicationPolicy*) +prefix_ unsigned satcom::lib::WriteablePolicy::do_write(FileHandle handle, char const * buffer, + unsigned size) { - int rv = ::write(fd, buffer, size); + int rv = ::write(handle.fd(), buffer, size); if (rv < 0) throw SystemException(errno); return rv; diff --git a/Socket/ReadWritePolicy.cti b/Socket/ReadWritePolicy.cti index 893354c1c0f94fb7e59e0978a106b99eefc8d61f..6a8901952312b4d347313c2de865b78ab96441c2 100644 --- a/Socket/ReadWritePolicy.cti +++ b/Socket/ReadWritePolicy.cti @@ -35,7 +35,7 @@ template <class Policy> prefix_ unsigned satcom::lib::ReadablePolicy:: readfrom(ClientSocketHandle<Policy> handle, char * buffer, unsigned size, typename Policy::AddressingPolicy::Address & address, - IfCommunicationPolicyIs<Policy,UnconnectedCommunicationPolicy>::type *) + typename IfCommunicationPolicyIs<Policy,UnconnectedCommunicationPolicy>::type *) { int rv = ::recvfrom(handle.fd(),buffer, size, 0, address.sockaddr_p(), address.sockaddr_len()); @@ -46,22 +46,21 @@ readfrom(ClientSocketHandle<Policy> handle, char * buffer, unsigned size, template <class Policy> prefix_ unsigned satcom::lib::WriteablePolicy:: -write(ClientSocketHandle<Policy> handle, char * buffer, unsigned size, - IfCommunicationPolicyIs<Policy,ConnectedCommunicationPolicy>::type *) +write(ClientSocketHandle<Policy> handle, char const * buffer, unsigned size, + typename IfCommunicationPolicyIs<Policy,ConnectedCommunicationPolicy>::type *) { - int rv = ::write(handle.fd(), buffer, size); - if (rv < 0) - throw SystemException(errno); - return rv; + return do_write(handle,buffer,size); } template <class Policy> prefix_ unsigned satcom::lib::WriteablePolicy:: -writeto(ClientSocketHandle<Policy> handle, char * buffer, unsigned size, - IfCommunicationPolicyIs<Policy,UnconnectedCommunicationPolicy>::type *) +writeto(ClientSocketHandle<Policy> handle, + typename boost::call_traits<typename Policy::AddressingPolicy::Address>::param_type addr, + char const * buffer, unsigned size, + typename IfCommunicationPolicyIs<Policy,UnconnectedCommunicationPolicy>::type *) { int rv = ::sendto(handle.fd(), buffer, size, 0, - address.sockaddr_p(), address.sockaddr_len()); + addr.sockaddr_p(), addr.sockaddr_len()); if (rv < 0) throw SystemException(errno); return rv; diff --git a/Socket/ReadWritePolicy.hh b/Socket/ReadWritePolicy.hh index 7f13bb6ef19bde222536af03fd1e06ce78b47d17..204db53c322b117c1fb3bfa158a5fb04d9d1e5a0 100644 --- a/Socket/ReadWritePolicy.hh +++ b/Socket/ReadWritePolicy.hh @@ -32,6 +32,7 @@ ///////////////////////////////hh.p//////////////////////////////////////// // TODO: ReadWritePolicy.test.cc ... +// TODO: EINTR, EAGAIN etc handling ... namespace satcom { namespace lib { @@ -51,11 +52,16 @@ namespace lib { struct WriteablePolicy : public WritePolicyBase { template <class Policy> - static unsigned write(ClientSocketHandle<Policy> handle, char * buffer, unsigned size, + static unsigned write(ClientSocketHandle<Policy> handle, char const * buffer, unsigned size, typename IfCommunicationPolicyIs<Policy,ConnectedCommunicationPolicy>::type * = 0); template <class Policy> - static unsigned writeto(ClientSocketHandle<Policy> handle, char * buffer, unsigned size, + static unsigned writeto(ClientSocketHandle<Policy> handle, + typename boost::call_traits<typename Policy::AddressingPolicy::Address>::param_type addr, + char const * buffer, unsigned size, typename IfCommunicationPolicyIs<Policy,UnconnectedCommunicationPolicy>::type * = 0); + + private: + static unsigned do_write(FileHandle handle, char const * buffer, unsigned size); }; struct NotWriteablePolicy : public WritePolicyBase @@ -65,9 +71,9 @@ namespace lib { ///////////////////////////////hh.e//////////////////////////////////////// -//#include "ReadWritePolicy.cci" +#include "ReadWritePolicy.cci" //#include "ReadWritePolicy.ct" -//#include "ReadWritePolicy.cti" +#include "ReadWritePolicy.cti" #endif diff --git a/Socket/SocketHandle.cci b/Socket/SocketHandle.cci index 686241c63428ea6f6a261946b10dff6ae8d28994..188279c38996556d5a6ede9550ebdc6275614006 100644 --- a/Socket/SocketHandle.cci +++ b/Socket/SocketHandle.cci @@ -41,6 +41,12 @@ prefix_ satcom::lib::SocketProtocol const & satcom::lib::SocketBody::protocol() return *protocol_; } +prefix_ bool satcom::lib::SocketBody::eof() + const +{ + return protocol().eof(); +} + ///////////////////////////////cci.e/////////////////////////////////////// #undef prefix_ diff --git a/Socket/SocketHandle.ih b/Socket/SocketHandle.ih index afc5967475669c2ed618e5b13d722ec6cb9a457e..58d7478b997430c6e64d03c412329d0d0ce849a0 100644 --- a/Socket/SocketHandle.ih +++ b/Socket/SocketHandle.ih @@ -57,6 +57,8 @@ namespace lib { SocketProtocol const & protocol() const; + virtual bool eof() const; + protected: private: diff --git a/Socket/SocketPolicy.test.hh b/Socket/SocketPolicy.test.hh index ec7b0590770cfc3f8509badd85e1d6a401e16fc1..42fb5bf143756ea68ccee431e8439f19236a057f 100644 --- a/Socket/SocketPolicy.test.hh +++ b/Socket/SocketPolicy.test.hh @@ -36,7 +36,16 @@ namespace test { struct SomeAddressingPolicy : public satcom::lib::AddressingPolicyBase { - typedef satcom::lib::nil Address; + typedef unsigned Address; + + static void peer(FileHandle handle, unsigned & addr) + { addr=1; } + static void local(FileHandle, unsigned & addr) + { addr=2; } + static void connect(FileHandle, unsigned addr) + {} + static void bind(FileHandle, unsigned addr) + {} }; struct SomeFramingPolicy : public satcom::lib::FramingPolicyBase @@ -57,7 +66,7 @@ namespace test { } static unsigned readfrom(FileHandle handle, char * buffer, unsigned size, - satcom::lib::nil & address) + unsigned & address) { return read(handle,buffer,size); } @@ -73,7 +82,7 @@ namespace test { return 0; } - static unsigned writeto(FileHandle handle, satcom::lib::nil const & address, + static unsigned writeto(FileHandle handle, unsigned address, char const * buffer, unsigned size) { return write(handle,buffer,size); diff --git a/Socket/SocketProtocol.hh b/Socket/SocketProtocol.hh index 2d25ef76d9f19a0b668249a70fa0675bc7862e72..ce6f43e7d5235be83e97a1af39ea91bffd4b9e8b 100644 --- a/Socket/SocketProtocol.hh +++ b/Socket/SocketProtocol.hh @@ -62,6 +62,7 @@ namespace lib { /////////////////////////////////////////////////////////////////////////// virtual unsigned available() const = 0; + virtual bool eof() const = 0; protected: diff --git a/Socket/SocketProtocol.test.hh b/Socket/SocketProtocol.test.hh index aa9036d47c233677fbfb56f3c1a5e57da72ae1f9..d839852ecbb5f768f5c4af75fb92cb292ca6748e 100644 --- a/Socket/SocketProtocol.test.hh +++ b/Socket/SocketProtocol.test.hh @@ -46,6 +46,10 @@ namespace test { unsigned available() const { return Policy::ReadPolicy::TEST_SIZE; } + + bool eof() const { + return false; + } }; }}} diff --git a/Socket/TCPSocketHandle.cc b/Socket/TCPSocketHandle.cc index 5ec50d7d1e20adbea09f263c1eac02efbcc96a99..1a97f8022dbd9eb9246beded3df097ee1339658e 100644 --- a/Socket/TCPSocketHandle.cc +++ b/Socket/TCPSocketHandle.cc @@ -96,6 +96,12 @@ prefix_ unsigned satcom::lib::TCPv4SocketProtocol::available() return n; } +prefix_ bool satcom::lib::TCPv4SocketProtocol::eof() + const +{ + return body().readable() && available()==0; +} + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_ //#include "TCPSocketHandle.mpp" diff --git a/Socket/TCPSocketHandle.hh b/Socket/TCPSocketHandle.hh index e7c6ee152f6e2088511628cc01e0a5c6db6dd23e..571888047e7dc337c03c6883f6d1c4fc03fa76b5 100644 --- a/Socket/TCPSocketHandle.hh +++ b/Socket/TCPSocketHandle.hh @@ -64,6 +64,7 @@ namespace lib { void connect(std::string host, unsigned port) const; unsigned available() const; + bool eof() const; }; typedef ProtocolClientSocketHandle<TCPv4SocketProtocol> TCPv4ClientSocketHandle; @@ -82,7 +83,9 @@ namespace lib { : public ConcreteSocketProtocol<TCPv6Socket_Policy>, public IPv6Protocol, public TCPProtocol - {}; + { + // TODO: Implement + }; typedef ProtocolClientSocketHandle<TCPv6SocketProtocol> TCPv6ClientSocketHandle; typedef ProtocolServerSocketHandle<TCPv6SocketProtocol> TCPv6ServerSocketHandle; diff --git a/Socket/TCPSocketHandle.test.cc b/Socket/TCPSocketHandle.test.cc index 8ee63b86665e565c90e4ef11d9decdfd0a53ca0d..635f0e0f1739a4cd5e4a87fbd0914482ee4f45a9 100644 --- a/Socket/TCPSocketHandle.test.cc +++ b/Socket/TCPSocketHandle.test.cc @@ -26,7 +26,14 @@ //#include "TCPSocketHandle.test.ih" // Custom includes +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/wait.h> +#include <unistd.h> +#include <sys/socket.h> +#include <netinet/in.h> #include "TCPSocketHandle.hh" +#include <iostream> #include <boost/test/auto_unit_test.hpp> #include <boost/test/test_tools.hpp> @@ -34,15 +41,124 @@ #define prefix_ ///////////////////////////////cc.p//////////////////////////////////////// -BOOST_AUTO_UNIT_TEST(tcpSocketHandle) +namespace { + + void error(char const * fn, char const * proc="") + { + std::cerr << "\n" << proc << fn << ": " << strerror(errno) << std::endl; + } + + void fail(char const * fn) + { + error(fn,"server: "); + _exit(1); + } + + void server() + { + int serv = socket(PF_INET,SOCK_STREAM,0); + if (serv<0) fail("socket()"); + int v = 1; + if (setsockopt(serv,SOL_SOCKET,SO_REUSEADDR,&v,sizeof(v))<0) + fail("setsockopt()"); + struct sockaddr_in sin; + sin.sin_family = AF_INET; + sin.sin_port = htons(12345); + sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + if (bind(serv,(struct sockaddr *)&sin,sizeof(sin))<0) fail("bind()"); + if (listen(serv,1)<0) fail("listen()"); + int sock = accept(serv,0,0); + if (sock < 0) fail("accept()"); + + /////////////////////////////////////////////////////////////////////////// + + char buffer[1024]; + while (1) { + int n = read(sock,buffer,1024); + if (n == 4 && strncmp(buffer,"QUIT",4) == 0) + break; + write(sock,buffer,n); + } + + /////////////////////////////////////////////////////////////////////////// + + if (shutdown(sock, SHUT_RDWR) < 0) fail("shutdown()"); + if (close(sock) < 0) fail("close()"); + if (close(serv) < 0) fail("close()"); + } + + int server_pid = 0; + + void start_server() + { + server_pid = ::fork(); + if (server_pid < 0) BOOST_FAIL("fork()"); + if (server_pid == 0) { + server(); + _exit(0); + } + } + + void wait_server() + { + int status; + if (waitpid(server_pid,&status,0)<0) + BOOST_FAIL("waitpid()"); + BOOST_CHECK_EQUAL( status , 0 ); + } + + void stop_server() + { + kill(server_pid,9); + wait_server(); + } + +} + +BOOST_AUTO_UNIT_TEST(tcpv4ClientSocketHandle) { - satcom::lib::TCPv4ClientSocketHandle sock; + { + satcom::lib::TCPv4ClientSocketHandle sock; + + BOOST_CHECK_THROW( sock.connect(satcom::lib::INet4Address("127.0.0.1:12345")), satcom::lib::SystemException ); + BOOST_CHECK_THROW( sock.protocol().connect("127.0.0.1:12345"), satcom::lib::SystemException ); + BOOST_CHECK_THROW( sock.protocol().connect("127.0.0.1",12345), satcom::lib::SystemException ); + } + + { + start_server(); + satcom::lib::TCPv4ClientSocketHandle sock; + BOOST_CHECK_NO_THROW( sock.bind(satcom::lib::INet4Address("127.0.0.1:23456")) ); + BOOST_CHECK_NO_THROW( sock.connect(satcom::lib::INet4Address("127.0.0.1:12345")) ); + BOOST_CHECK( sock.peer() == satcom::lib::INet4Address("127.0.0.1:12345") ); + BOOST_CHECK( sock.local() == satcom::lib::INet4Address("127.0.0.1:23456") ); + BOOST_CHECK( sock.blocking() ); + BOOST_CHECK_NO_THROW( sock.write("TEST-WRITE") ); + BOOST_CHECK_EQUAL( sock.read(), "TEST-WRITE" ); + BOOST_CHECK( !sock.eof() ); + sock.write("QUIT"); + sleep(1); + stop_server(); + BOOST_CHECK_EQUAL( sock.read(), "" ); + BOOST_CHECK( sock.eof() ); + BOOST_CHECK( !sock ); - BOOST_CHECK_THROW( sock.protocol().connect(satcom::lib::INet4Address("127.0.0.1:12345")), satcom::lib::SystemException ); - BOOST_CHECK_THROW( sock.protocol().connect("127.0.0.1:12345"), satcom::lib::SystemException ); - BOOST_CHECK_THROW( sock.protocol().connect("127.0.0.1",12345), satcom::lib::SystemException ); +// BOOST_CHECK_EQUAL( sock.write("x"), 1u ); +// BOOST_CHECK_EQUAL( sock.write("TEST-WRITE"), 10u ); +// int v = -1; +// ioctl(sock.fd(),TIOCOUTQ,&v,sizeof(v)); +// std::cerr << v << "\n"; +// sleep(10); +// ioctl(sock.fd(),TIOCOUTQ,&v,sizeof(v)); +// std::cerr << v << "\n"; +// BOOST_CHECK_EQUAL( sock.write("TEST-WRITE"), 10u ); +// ioctl(sock.fd(),TIOCOUTQ,&v,sizeof(v)); +// std::cerr << v << "\n"; +// sleep(10); +// ioctl(sock.fd(),TIOCOUTQ,&v,sizeof(v)); +// std::cerr << v << "\n"; + } - // TODO: Richtige connection testen } ///////////////////////////////cc.e////////////////////////////////////////