Add TCPv6 SocketHandle implementation
g0dil [Thu, 15 Feb 2007 13:42:40 +0000 (13:42 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@200 270642c3-0616-0410-b53a-bc976706d245

12 files changed:
Example.dox
Mainpage.dox
Socket/INetAddressing.cc
Socket/INetAddressing.hh
Socket/INetProtocol.cc
Socket/INetProtocol.hh
Socket/TCPSocketHandle.cc
Socket/TCPSocketHandle.hh
doclib/doxy-header-overview.html
doclib/doxy-header.html
doclib/filter.pl
doclib/senf.css

index e42aac5..f2d86f6 100644 (file)
     application, check out the library, go to the \c Sniffer directory
     and execute
 
-    <pre class="fragment">
-      # scons -u
-      # ./Sniffer</pre>
+    <pre>
+    # scons -u
+    # ./Sniffer
+    </pre>
 
     \see \ref components \n
          \ref build \n
index b472354..03e5784 100644 (file)
     mailing lists</a>.
 
     \see \ref usage\n
-         \ref example\n
-         <a href="xref.html">Current status: Cross reference of action points</a>\n
-         <a class="ext" href="http://developer.berlios.de/projects/senf">The BerliOS project page</a>\n
-         <a class="ext" href="http://openfacts.berlios.de/index-en.phtml?title=SENF+Network+Framework">The SENF Wiki at BerliOS</a>
+         \ref example
 */
 
 /** \page usage Using the SENF framework
@@ -94,8 +91,9 @@
     repository. Change to your development directory and use the
     following subversion command
 
-    <pre class="fragment">
-      $ svn checkout http://svn.berlios.de/svnroot/repos/senf/trunk senf</pre>
+    <pre>
+    $ svn checkout http://svn.berlios.de/svnroot/repos/senf/trunk senf
+    </pre>
 
     This will create a new directory \c senf within the current
     directory. For further documentation on the use of Subversion, see
     To build the library, execute all unit tests and build the Sniffer
     test application, use
 
-    <pre class="fragment">
-      $ scons
-      $ scons all_tests</pre>
+    <pre>
+    $ scons
+    $ scons all_tests
+    </pre>
 
     in the \c senf directory. This assumes, that you want to build the
     library with your default gcc and requires the boost libraries to
     check out the needed directories from the BerliOS SENF
     repository. Change to the 'Foo' directory and type
     
-      <pre class="fragment">
-        $ svn propedit svn:externals .</pre>
+    <pre>
+    $ svn propedit svn:externals .
+    </pre>
 
     The default editor (probably VI) will be started with the current
     value of the svn:externals property (which will probably be
     For example, if you want to use the \c Scheduler and \c Socket
     module, the file will look like
 
-      <pre class="fragment">
-        senfscons http://svn.berlios.de/svnroot/repos/senf/trunk/senfscons
-        Utils http://svn.berlios.de/svnroot/repos/senf/trunk/Utils
-        Scheduler http://svn.berlios.de/svnroot/repos/senf/trunk/Scheduler
-        Socket http://svn.berlios.de/svnroot/repos/senf/trunk/Socket</pre>
+    <pre>
+    senfscons http://svn.berlios.de/svnroot/repos/senf/trunk/senfscons
+    Utils http://svn.berlios.de/svnroot/repos/senf/trunk/Utils
+    Scheduler http://svn.berlios.de/svnroot/repos/senf/trunk/Scheduler
+    Socket http://svn.berlios.de/svnroot/repos/senf/trunk/Socket
+    </pre>
 
     exit the editor and the property will be set. Now run
 
-      <pre class="fragment">
-        $ svn update</pre>
+    <pre>
+    $ svn update
+    </pre>
 
     and the code will be checked out into the corresponding
     directories. 
     add \c SConfig to the list of files ignored by Subversion in the
     project root. In the project root execute
 
-    <pre class="fragment">
-      $ svn propedit svn:ignore .</pre>
+    <pre>
+    $ svn propedit svn:ignore .
+    </pre>
 
     and add \c SConfig as a new line to the property.
 
 
     You should now be able to build your project using
 
-    <pre class="fragment">
-      $ scons</pre>
+    <pre>
+    $ scons
+    </pre>
 
     If you have not changed the \c SConstruct file, this will build
     all modules you have importet into your project. To build and
     execute the unit tests, use
 
-    <pre class="fragment">
-      $ scons all_tests</pre>
+    <pre>
+    $ scons all_tests
+    </pre>
 
     you can also build only a subdirectory by changing to it and
     running
     
-    <pre class="fragment">
-      $ scons -u [target]</pre>
+    <pre>
+    $ scons -u [target]
+    </pre>
 
     \see <a href="../../senfscons/doc/html/index.html">SENFSCons reference</a> \n
          <a class="ext" href="http://www.scons.org/documentation.php">SCons documentation</a> \n
index b1efabc..301d86c 100644 (file)
@@ -148,14 +148,6 @@ prefix_ void senf::INet6SocketAddress::clear()
     sockaddr_.sin6_family = AF_INET6;
 }
 
-prefix_ void senf::INet6SocketAddress::address(std::string const & addr)
-{
-    if (addr[0]=='[')
-       assignAddr(addr);
-    else
-       host(addr);
-}
-
 prefix_ std::string senf::INet6SocketAddress::address()
     const
 {
index d97c83c..4a8deca 100644 (file)
@@ -107,7 +107,16 @@ namespace senf {
 
     /** \brief IPv6 network address
 
-       \todo Implement
+       INet6Address represents a 128bit IPv6 network address. This class supports all standard
+       numeric string representations of IPv6 addresses. This class does not integrate with \c
+       gethostbyname() and so does not support host names.
+
+       The conversion constructors allow the use of string constants whereever an INet6Address is
+       expected. Especially, it is possible to assign a string to an address to change it's value.
+
+       \implementation The <tt>char const *</tt> constructor overload is needed to support
+           string-literals where an INet6Address is expected (the C++ standard does not allow
+           chaining conversion constructors like char const * -> std::string -ยป INet6Address)
      */
     class INet6Address
     {
@@ -127,17 +136,19 @@ namespace senf {
         ///@}
         ///////////////////////////////////////////////////////////////////////////
 
-       void clear();
-       std::string address() const;
+       void clear();                   ///< Clear address
+       std::string address() const;    ///< Return printable address representation
 
-       bool operator==(INet6Address const & other) const;
-       bool operator!=(INet6Address const & other) const;
+       bool operator==(INet6Address const & other) const; ///< Compare addresses for equality
+       bool operator!=(INet6Address const & other) const; ///< Inverse of above
 
-       struct in6_addr & addr();
-       struct in6_addr const & addr() const;
-       struct in6_addr * addr_p();
+       struct in6_addr & addr();       ///< Access internal address representation
+       struct in6_addr const & addr() const; 
+                                        ///< Access internal address representation in const context
+       struct in6_addr * addr_p();     ///< Get pointer to internal address repr
        struct in6_addr const * addr_p() const;
-       unsigned addr_len() const;
+                                        ///< Get const pointer to internal address repr
+       unsigned addr_len() const;      ///< Size of an IPv6 address (16 bytes)
 
     protected:
 
@@ -145,14 +156,40 @@ namespace senf {
        struct in6_addr addr_;
     };
 
+    
+    /** \brief Output INet6Address instance as it's string representation
+     */
     std::ostream & operator<<(std::ostream & os, INet6Address const & addr);
 
     /** \brief IPv6 socket address
 
+       This class wrapps the standard \c sockaddr_in6 structure. INet6SocketAddress provides access
+       to all members of the sockaddr_in6 structure. Additionally, INet6SocketAddress supports the
+       string representation
+
+       \par "" <tt>[</tt> <i>address</i> [ <tt>\@</tt> <i>interface</i> ] <tt>]:</tt> <i>port</i>
+
+       Where \e address is an arbitrary numeric IPv6 address, \e interface is an optional network
+       interface name and \e port is the port number. The interface specification is only valid if
+       \e address is link-local address. The URL representation of an IPv6 address is as above
+       without the optional interface spec.
+
+       INet6SocketAddress supports conversion constructors from it's string
+       representation. Therefore, wherever a INet6SocketAddress instance is expected, a string may
+       be used instead.
+
        \implementation The sockaddr_in6 structure has an sin6_flowinfo member. However RFC3493 does
-       not give the use of this field and specifies, that the field should be ignored ... so that's
-       what we do. Furthermore, the GNU libc reference states, that this field is not implemented
-       in the library.
+           not give the use of this field and specifies, that the field should be ignored ... so
+           that's what we do. Furthermore, the GNU libc reference states, that this field is not
+           implemented in the library.
+
+       \implementation We need to return the address in host() by value since we need to return a
+           INet6Address. However, sockaddr_in6 does not have one ...
+
+       \implementation The <tt>char const *</tt> constructor overload is needed to support
+           string-literals where an INet6SocketAddress is expected (the C++ standard does not allow
+           chaining conversion constructors like <tt>char const *</tt> -> \c std::string -> \c
+           INet6SocketAddress) 
 
        \idea Implement a INet6Address_ref class which has an interface identical to INet6Address
        and is convertible to INet6Address (the latter has a conversion constructor taking the
@@ -170,32 +207,35 @@ namespace senf {
         ///\name Structors and default members
         ///@{
 
-        INet6SocketAddress();
-        INet6SocketAddress(std::string const & addr);
-        INet6SocketAddress(char const * addr);
+        INet6SocketAddress();           ///< Create empty instance
+        INet6SocketAddress(std::string const & addr); 
+                                        ///< Initialize/convert from string represenation
+        INet6SocketAddress(char const * addr); ///< Same as above to support string literals
        INet6SocketAddress(INet6Address const & addr, unsigned port);
+                                        ///< Initialize from address and port
        INet6SocketAddress(INet6Address const & addr, unsigned port, std::string const & iface);
+                                        ///< Initialize explicitly from given parameters
        INet6SocketAddress(std::string const & addr, std::string const & iface);
+                                        ///< Initialize from URL representation and explit interface
 
         ///@}
         ///////////////////////////////////////////////////////////////////////////
 
-       bool operator==(INet6SocketAddress const & other) const;
-       bool operator!=(INet6SocketAddress const & other) const;
+       bool operator==(INet6SocketAddress const & other) const; ///< Check addresses for equality
+       bool operator!=(INet6SocketAddress const & other) const; ///< Inverse of above
 
-       void clear();
+       void clear();                   ///< Clear socket address
 
-       std::string address() const;
-       void address(std::string const & addr);
+       std::string address() const;    ///< Get printable address representation
 
-       INet6Address host() const;
-       void host(INet6Address const & addr);
+       INet6Address host() const;      ///< Get address
+       void host(INet6Address const & addr); ///< Change address
        
-       unsigned port() const;
-       void port(unsigned poirt);
+       unsigned port() const;          ///< Get port number
+       void port(unsigned poirt);      ///< Change port number
        
-       std::string iface() const;
-       void iface(std::string const & iface);
+       std::string iface() const;      ///< Get interface name
+       void iface(std::string const & iface); ///< Change interface
        
         ///\name Generic SocketAddress interface
         ///@{
@@ -215,6 +255,8 @@ namespace senf {
        struct sockaddr_in6 sockaddr_;
     };
 
+    /** \brief Output INet6SocketAddress instance as it's string representation
+     */
     std::ostream & operator<<(std::ostream & os, INet6SocketAddress const & addr);
 
     /** \brief Signal invalid INet address syntax
@@ -257,7 +299,7 @@ namespace senf {
     /** \brief Addressing policy supporting IPv6 addressing
        
        \par Address Type:
-           INet6Address
+           INet6SocketAddress
        
        This addressing policy implements addressing using Internet V6
        addresses.
@@ -265,8 +307,6 @@ namespace senf {
        The various members are directly importet from
        GenericAddressingPolicy which see for a detailed
        documentation.
-
-       \todo implement
      */
     struct INet6AddressingPolicy
         : public AddressingPolicyBase,
index 4006369..ca93fa9 100644 (file)
@@ -37,7 +37,7 @@
 ///////////////////////////////cc.p////////////////////////////////////////
 
 ///////////////////////////////////////////////////////////////////////////
-// senf::INet4Protocol
+// senf::IPv4Protocol
 
 prefix_ void senf::IPv4Protocol::connect(INet4Address const & address)
     const
@@ -148,6 +148,22 @@ prefix_ void senf::IPv4Protocol::mcTTL(unsigned value)
         throw SystemException(errno);
 }
 
+///////////////////////////////////////////////////////////////////////////
+// senf::IPv6Protocol
+
+prefix_ void senf::IPv6Protocol::connect(INet6SocketAddress const & address)
+    const
+{
+    if (::connect(body().fd(),address.sockaddr_p(), address.sockaddr_len()) < 0)
+        throw SystemException(errno);
+}
+
+prefix_ void senf::IPv6Protocol::bind(INet6SocketAddress const & address)
+    const
+{
+    if (::bind(body().fd(),address.sockaddr_p(), address.sockaddr_len()) < 0)
+        throw SystemException(errno);
+}
 
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
index 482f88e..e1116bd 100644 (file)
@@ -127,12 +127,20 @@ namespace senf {
        
        This protocol facet introduces all the socket api protocol members which are related to IPv6
        addressing.
-
-       \todo implement
      */
     class IPv6Protocol
         : public virtual SocketProtocol
-    {};
+    {
+    public:
+        void connect(INet6SocketAddress const & address) const; ///< Connect to remote address
+                                        /**< \todo make this obsolete by allowing access to the
+                                            ClientSocketHandle from ConcreateSocketProtocol 
+                                            \param[in] address Address to connect to */
+        void bind(INet6SocketAddress const & address) const; ///< Set local socket address
+                                        /**< \todo make this obsolete by allowing access to the
+                                            ClientSocketHandle from ConcreateSocketProtocol 
+                                            \param[in] address Address to set */
+    };
 
     /// @}
 
index 7202fe3..3023e2a 100644 (file)
@@ -38,6 +38,9 @@
 #define prefix_
 ///////////////////////////////cc.p////////////////////////////////////////
 
+///////////////////////////////////////////////////////////////////////////
+// senf::TCPv4SocketProtocol
+
 prefix_ void senf::TCPv4SocketProtocol::init_client()
     const
 {
@@ -81,6 +84,52 @@ prefix_ std::auto_ptr<senf::SocketProtocol> senf::TCPv4SocketProtocol::clone()
     return std::auto_ptr<SocketProtocol>(new TCPv4SocketProtocol());
 }
 
+///////////////////////////////////////////////////////////////////////////
+// senf::TCPv6SocketProtocol::
+
+prefix_ void senf::TCPv6SocketProtocol::init_client()
+    const
+{
+    int sock = ::socket(PF_INET6,SOCK_STREAM,0);
+    if (sock < 0)
+        throw SystemException(errno);
+    body().fd(sock);
+}
+
+prefix_ void
+senf::TCPv6SocketProtocol::init_client(INet6Address const & address)
+    const
+{
+    init_client();
+    connect(address);
+}
+
+prefix_ void senf::TCPv6SocketProtocol::init_server()
+    const
+{
+    int sock = ::socket(PF_INET,SOCK_STREAM,0);
+    if (sock < 0)
+        throw SystemException(errno);
+    body().fd(sock);
+}
+
+prefix_ void senf::TCPv6SocketProtocol::init_server(INet6Address const & address,
+                                                           unsigned backlog)
+    const
+{
+    init_server();
+    bind(address);
+    reuseaddr(true);
+    if (::listen(body().fd(),backlog) < 0)
+        throw SystemException(errno);
+}
+
+prefix_ std::auto_ptr<senf::SocketProtocol> senf::TCPv6SocketProtocol::clone()
+    const
+{
+    return std::auto_ptr<SocketProtocol>(new TCPv6SocketProtocol());
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 //#include "TCPSocketHandle.mpp"
index 484e622..f94e439 100644 (file)
@@ -160,8 +160,6 @@ namespace senf {
        ProtocolServerSocketHandle via the Socket Handle typedefs above.
 
        \see TCPv4SocketProtocol
-       
-       \todo Implement
      */
     class TCPv6SocketProtocol
         : public ConcreteSocketProtocol<TCPv6Socket_Policy>, 
@@ -170,6 +168,47 @@ namespace senf {
           public BSDSocketProtocol,
           public AddressableBSDSocketProtocol
     {
+        ///////////////////////////////////////////////////////////////////////////
+        // internal interface
+
+       ///\name Constructors
+       ///@{
+
+        void init_client() const;       ///< Create unconnected client socket
+                                       /**< \note This member is implicitly called from the
+                                            ProtocolClientSocketHandle::ProtocolClientSocketHandle()
+                                            constructor */
+        void init_client(INet4Address const & address) const;
+                                        ///< Create client socket and connect
+                                        /**< Creates a new client socket and connects to the given
+                                            address. 
+                                            
+                                            \param[in] address remote address to connect to */
+                                       /**< \note This member is implicitly called from the
+                                            ProtocolClientSocketHandle::ProtocolClientSocketHandle()
+                                            constructor */
+        void init_server() const;       ///< Create server socket
+                                       /**< \note This member is implicitly called from the
+                                            ProtocolServerSocketHandle::ProtocolServerSocketHandle()
+                                            constructor */
+        void init_server(INet4Address const & address, unsigned backlog=1) const;
+                                        ///< Create server socket and listen
+                                        /**< Creates a new server socket, binds to \a address end
+                                            starts listening for new connections with a backlog of
+                                            \a backlog connections. It also enables reuseaddr().
+
+                                            \param[in] address address to listen on
+                                            \param[in] backlog size of the listen backlog */
+                                       /**< \note This member is implicitly called from the
+                                            ProtocolServerSocketHandle::ProtocolServerSocketHandle()
+                                            constructor */
+
+       ///@}
+       ///\name Abstract Interface Implementation
+
+        std::auto_ptr<SocketProtocol> clone() const;
+       
+       ///@}
     };
 
     typedef ProtocolClientSocketHandle<TCPv6SocketProtocol> TCPv6ClientSocketHandle;
index e0f52b3..0a43bb6 100644 (file)
@@ -17,11 +17,9 @@ div.tabs ul li.$projectname a { background-color: #EDE497; }
 
 <div id="content1">
   <div id="content2">
-    <div class="tabs">
+    <div class="tabs menu">
       <ul>
         <li class="Overview"><a href="../../doc/html/index.html">Overview</a></li>
-        <li><a class="ext" href="http://developer.berlios.de/projects/senf">SENF @ BerliOS</a></li>
-
         <li class="libSocket"><a href="../../Socket/doc/html/index.html">libSocket</a></li>
         <li class="libPackets"><a href="../../Packets/doc/html/index.html">libPackets</a></li>
         <li class="libScheduler"><a href="../../Scheduler/doc/html/index.html">libScheduler</a></li>
@@ -29,3 +27,12 @@ div.tabs ul li.$projectname a { background-color: #EDE497; }
         <li class="SENFSCons"><a href="../../senfscons/doc/html/index.html">SENFSCons</a></li>
       </ul>
     </div>
+
+    <div class="tabs">
+      <ul>
+       <li><a href="xref.html">Open Issues</a></li>
+       <li><a class="ext" href="http://svn.berlios.de/wsvn/senf/?op=log&rev=0&sc=0&isdir=1">SVN ChangeLog</a></li>
+        <li><a class="ext" href="http://developer.berlios.de/projects/senf">SENF @ BerliOS</a></li>
+       <li><a class="ext" href="http://openfacts.berlios.de/index-en.phtml?title=SENF+Network+Framework">Wiki</a></li>
+      </ul>
+    </div>
\ No newline at end of file
index a630f59..8eab863 100644 (file)
@@ -17,11 +17,9 @@ div.tabs ul li.$projectname a { background-color: #EDE497; }
 
 <div id="content1">
   <div id="content2">
-    <div class="tabs">
+    <div class="tabs menu">
       <ul>
         <li class="Overview"><a href="../../../doc/html/index.html">Overview</a></li>
-        <li><a class="ext" href="http://developer.berlios.de/projects/senf">SENF @ BerliOS</a></li>
-
         <li class="libSocket"><a href="../../../Socket/doc/html/index.html">libSocket</a></li>
         <li class="libPackets"><a href="../../../Packets/doc/html/index.html">libPackets</a></li>
         <li class="libScheduler"><a href="../../../Scheduler/doc/html/index.html">libScheduler</a></li>
index eb9214d..dd192c8 100755 (executable)
@@ -6,6 +6,9 @@ while (s/\t/' 'x(8-length($`)%8)/e) {}
 if (/^\s*\\code$/ .. /\\endcode/ && !/^$/) {
     $i=length($1) if /^(\s*)\\code$/;
     print substr($_,$i),"\n";
+} elsif (s/^(\s*)<pre>$/$1<pre class="fragment">/ .. /<\/pre>/ && !/^$/) {
+    $i=length($1) if /^(\s*)<pre class="fragment">$/;
+    print substr($_,$i),"\n";
 } else {
     print $_,"\n";
 }
index 270f997..ad630ac 100644 (file)
@@ -14,24 +14,24 @@ body {
 
 #head h1 {
        margin: 0 0 0 100px;
-        padding: 6px 0 0 0;
+       padding: 6px 0 0 42px;
        height: 33px;
-        background-color: #DECD40;
+       background-color: #DECD40;
        border-bottom: 1px solid #AF9D00;
-        font-size: 22px;
+       font-size: 22px;
        font-weight: bold;
-        color: white;
+       color: white;
        white-space: nowrap;
        text-align: left;
 }
 
 #head h2 {
        margin: 0 0 0 100px;
-       padding: 4px 0 0 0;
+       padding: 4px 0 0 42px;
        height: 18px;
        background-color: #EDE497;
        color: #726921;
-        font-size: 13px;
+       font-size: 13px;
        font-weight: normal;
        white-space: nowrap;
 }
@@ -42,7 +42,7 @@ body {
 }
 
 #content2 { 
-        /* need non-zero top padding here to prevent margin propagation */
+       /* need non-zero top padding here to prevent margin propagation */
        padding: 10px 0 0 142px;
        max-width: 62em;
 }
@@ -57,7 +57,7 @@ a:contains("http://") {
 }
 
 a.ext {
-        font-style: italic;
+       font-style: italic;
 }
 
 div.tabs { 
@@ -66,7 +66,7 @@ div.tabs {
        clear: left;
        background-color: #FDF7C3;
        border: 1px solid #AF9D00;
-        margin: 0 0 10px -132px;
+       margin: 0 0 10px -132px;
        width: 120px; 
        overflow: hidden;
 }
@@ -88,7 +88,7 @@ div.tabs ul li {
 div.tabs ul li a { 
        display: block;
        padding: 2px 5px;
-        font-size: 13px;
+       font-size: 13px;
        color: #726921;
        text-decoration: none;
        white-space: nowrap;
@@ -97,17 +97,17 @@ div.tabs ul li a {
 
 div.tabs ul li a:visited, div.tabs ul li a:active { 
        color: #726921;
-        text-decoration: none;
+       text-decoration: none;
 }
 
 div.tabs li.current a {
        background-position: 100% -150px;
-       border-width     : 0px;
+       border-width: 0px;
 }
 
 div.tabs li.current span {
        background-position: 0% -150px;
-       padding-bottom   : 6px;
+       padding-bottom: 6px;
 }
 
 div.tabs ul li a:hover, div.tabs ul li.current a { 
@@ -126,7 +126,7 @@ div.tabs ul li a:hover, div.tabs ul li.current a {
 }
 
 #footer span { 
-        font-size: 10px;
+       font-size: 10px;
 }
 
 #footer a, #footer a:active, #footer a:visited {