From 6a5504db51147456cbd927e24db922284dfac127 Mon Sep 17 00:00:00 2001
From: sbund <sbund@wiback.org>
Date: Mon, 28 Aug 2006 09:33:51 +0000
Subject: [PATCH] further implementation of Socket library

---
 Socket/ClientSocketHandle.ct      |  19 ++++-
 Socket/ClientSocketHandle.cti     |  48 +++++++++++
 Socket/ClientSocketHandle.hh      |  35 +++++---
 Socket/ClientSocketHandle.test.cc |  13 ++-
 Socket/FileHandle.cc              |  40 ++++++----
 Socket/FileHandle.cci             |  61 +++++++++++++-
 Socket/FileHandle.hh              |   6 ++
 Socket/FileHandle.ih              |  10 ++-
 Socket/INetAddress.cc             |  15 ++--
 Socket/INetAddress.hh             |   2 +
 Socket/INetProtocol.cci           |  68 ++++++++++++++++
 Socket/INetProtocol.cti           |  55 +++++++++++++
 Socket/INetProtocol.hh            |  22 ++++-
 Socket/ReadWritePolicy.cci        |   6 +-
 Socket/ReadWritePolicy.cti        |  19 +++--
 Socket/ReadWritePolicy.hh         |  14 +++-
 Socket/SocketHandle.cci           |   6 ++
 Socket/SocketHandle.ih            |   2 +
 Socket/SocketPolicy.test.hh       |  15 +++-
 Socket/SocketProtocol.hh          |   1 +
 Socket/SocketProtocol.test.hh     |   4 +
 Socket/TCPSocketHandle.cc         |   6 ++
 Socket/TCPSocketHandle.hh         |   5 +-
 Socket/TCPSocketHandle.test.cc    | 128 ++++++++++++++++++++++++++++--
 24 files changed, 531 insertions(+), 69 deletions(-)
 create mode 100644 Socket/INetProtocol.cci
 create mode 100644 Socket/INetProtocol.cti

diff --git a/Socket/ClientSocketHandle.ct b/Socket/ClientSocketHandle.ct
index 734148b16..0e33be03d 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 0e3d79623..c2b2c8f89 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 774df2905..a623a5964 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 7d01f4609..a31119a3a 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 ce0214b5a..d16dbb70f 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 b04e7f251..f63792c5a 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 6f21f32ac..0162ec73e 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 0bf15d8db..b6ce3f0fe 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 c95e28b04..b1bde50a4 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 2e6a6c266..37fa31901 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 000000000..5f2e1d350
--- /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 000000000..bf0ca2dee
--- /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 b19556d8c..3f35fbba2 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 bbcf510e5..28a6f223a 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 893354c1c..6a8901952 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 7f13bb6ef..204db53c3 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 686241c63..188279c38 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 afc596747..58d7478b9 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 ec7b05907..42fb5bf14 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 2d25ef76d..ce6f43e7d 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 aa9036d47..d839852ec 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 5ec50d7d1..1a97f8022 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 e7c6ee152..571888047 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 8ee63b866..635f0e0f1 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////////////////////////////////////////
-- 
GitLab