-// $Id$
+// Copyright (C) 2007
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+// Stefan Bund <g0dil@berlios.de>
//
-// Copyright (C) 2006
+// 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
+/** \file
+ \brief GenericSockAddr inline non-template implementation */
// Custom includes
#include <sstream>
#include <string.h>
#include <sys/socket.h>
+#include <net/if.h>
#include <boost/lexical_cast.hpp>
+#include <boost/tokenizer.hpp>
+#include <boost/range.hpp>
//#include "INetAddressing.mpp"
#define prefix_
///////////////////////////////cc.p////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+// senf::INet4Address
+
prefix_ senf::INet4Address::INet4Address(std::string host, unsigned port)
{
clear();
}
}
+///////////////////////////////////////////////////////////////////////////
+// senf::INet6Address
+
+prefix_ senf::INet6Address::INet6Address(std::string const & addr)
+{
+ if (inet_pton(AF_INET6,addr.c_str(),&addr_) <= 0)
+ throw InvalidINetAddressException();
+}
+
+prefix_ senf::INet6Address::INet6Address(char const * addr)
+{
+ if (inet_pton(AF_INET6,addr,&addr_) <= 0)
+ throw InvalidINetAddressException();
+}
+
+prefix_ void senf::INet6Address::clear()
+{
+ ::memset(&addr_,0,sizeof(addr_));
+}
+
+prefix_ std::string senf::INet6Address::address()
+ const
+{
+ char buffer[8*5];
+ BOOST_ASSERT( inet_ntop(AF_INET6, &addr_, buffer, sizeof(buffer)) );
+ return std::string(buffer);
+}
+
+prefix_ bool senf::INet6Address::operator==(INet6Address const & other)
+ const
+{
+ return ::memcmp(&addr_,&other.addr_,sizeof(addr_))==0;
+}
+
+prefix_ bool senf::INet6Address::operator!=(INet6Address const & other)
+ const
+{
+ return !operator==(other);
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::INet6SocketAddress
+
+prefix_ bool senf::INet6SocketAddress::operator==(INet6SocketAddress const & other)
+ const
+{
+ return ::memcmp(&sockaddr_.sin6_addr, &other.sockaddr_.sin6_addr, sizeof(sockaddr_.sin6_addr))==0 &&
+ sockaddr_.sin6_port == other.sockaddr_.sin6_port &&
+ sockaddr_.sin6_scope_id == other.sockaddr_.sin6_scope_id;
+}
+
+prefix_ bool senf::INet6SocketAddress::operator!=(INet6SocketAddress const & other)
+ const
+{
+ return ! operator==(other);
+}
+
+prefix_ void senf::INet6SocketAddress::clear()
+{
+ ::memset(&sockaddr_,0,sizeof(sockaddr_));
+ 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
+{
+ std::stringstream ss;
+ ss << '[' << host();
+ if (sockaddr_.sin6_scope_id != 0)
+ ss << '@' << iface()
+ << "]:" << port();
+ return ss.str();
+}
+
+prefix_ std::string senf::INet6SocketAddress::iface()
+ const
+{
+ if (sockaddr_.sin6_scope_id == 0)
+ return "";
+ char buffer[IFNAMSIZ];
+ BOOST_ASSERT( if_indextoname(sockaddr_.sin6_scope_id,buffer) );
+ return std::string(buffer);
+}
+
+prefix_ void senf::INet6SocketAddress::assignAddr(std::string const & addr)
+{
+ // Format of addr: "[" address [ "@" interface ] "]" ":" port
+ typedef boost::char_separator<char> separator;
+ typedef boost::tokenizer<separator> tokenizer;
+ // we don't add ':' to the list of separators since that would give as the IPv6 address
+ // as a list of tokens. We just strip the : from the port number manually
+ separator sep ("", "@[]");
+ tokenizer tokens (addr, sep);
+ tokenizer::iterator token (tokens.begin());
+ if (token == tokens.end()
+ || *token != "["
+ || ++token == tokens.end()
+ || inet_pton(AF_INET6, std::string(boost::begin(*token),boost::end(*token)).c_str(),
+ &sockaddr_.sin6_addr) <= 0
+ || ++token == tokens.end())
+ throw InvalidINetAddressException();
+ if (*token == "@") {
+ if (++token == tokens.end())
+ throw InvalidINetAddressException();
+ assignIface(std::string(boost::begin(*token),boost::end(*token)));
+ if (++token == tokens.end()
+ || *token != "]")
+ throw InvalidINetAddressException();
+ } else if (*token != "]")
+ throw InvalidINetAddressException();
+ if (++token == tokens.end()
+ || *boost::begin(*token) != ':')
+ throw InvalidINetAddressException();
+ try {
+ sockaddr_.sin6_port = htons(
+ boost::lexical_cast<unsigned>(std::string(boost::next(boost::begin(*token)),
+ boost::end(*token))));
+ } catch(boost::bad_lexical_cast const &) {
+ throw InvalidINetAddressException();
+ }
+ if (++token != tokens.end())
+ throw InvalidINetAddressException();
+}
+
+prefix_ void senf::INet6SocketAddress::assignIface(std::string const & iface)
+{
+ if (iface.empty())
+ sockaddr_.sin6_scope_id = 0;
+ else {
+ sockaddr_.sin6_scope_id = if_nametoindex(iface.c_str());
+ if (sockaddr_.sin6_scope_id == 0)
+ throw InvalidINetAddressException();
+ }
+}
+
///////////////////////////////cc.e////////////////////////////////////////
#undef prefix_
//#include "INetAddressing.mpp"
#define prefix_ inline
///////////////////////////////cci.p///////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+// senf::INet4Address
+
prefix_ senf::INet4Address::INet4Address()
{
clear();
return os;
}
+///////////////////////////////////////////////////////////////////////////
+// senf::INet6Address
+
+prefix_ senf::INet6Address::INet6Address()
+{
+ clear();
+}
+
+prefix_ senf::INet6Address::INet6Address(struct in6_addr const & addr)
+{
+ addr_ = addr;
+}
+
+prefix_ struct in6_addr & senf::INet6Address::addr()
+{
+ return addr_;
+}
+
+prefix_ struct in6_addr const & senf::INet6Address::addr()
+ const
+{
+ return addr_;
+}
+
+prefix_ struct in6_addr * senf::INet6Address::addr_p()
+{
+ return & addr_;
+}
+
+prefix_ struct in6_addr const * senf::INet6Address::addr_p()
+ const
+{
+ return & addr_;
+}
+
+prefix_ unsigned senf::INet6Address::addr_len()
+ const
+{
+ return sizeof(addr_);
+}
+
+prefix_ std::ostream & senf::operator<<(std::ostream & os, INet6Address const & addr)
+{
+ os << addr.address();
+ return os;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::INet6SocketAddress
+
+prefix_ senf::INet6SocketAddress::INet6SocketAddress()
+{
+ clear();
+}
+
+prefix_ senf::INet6SocketAddress::INet6SocketAddress(std::string const & addr)
+{
+ clear();
+ assignAddr(addr);
+}
+
+prefix_ senf::INet6SocketAddress::INet6SocketAddress(char const * addr)
+{
+ clear();
+ assignAddr(addr);
+}
+
+prefix_ senf::INet6SocketAddress::INet6SocketAddress(INet6Address const & addr, unsigned port)
+{
+ clear();
+ sockaddr_.sin6_addr = addr.addr();
+ sockaddr_.sin6_port = htons(port);
+}
+
+prefix_ senf::INet6SocketAddress::INet6SocketAddress(INet6Address const & addr, unsigned port,
+ std::string const & iface)
+{
+ clear();
+ sockaddr_.sin6_addr = addr.addr();
+ sockaddr_.sin6_port = htons(port);
+ assignIface(iface);
+}
+
+prefix_ senf::INet6SocketAddress::INet6SocketAddress(std::string const & addr,
+ std::string const & iface)
+{
+ clear();
+ assignAddr(addr);
+ assignIface(iface);
+}
+
+prefix_ senf::INet6Address senf::INet6SocketAddress::host()
+ const
+{
+ return INet6Address(sockaddr_.sin6_addr);
+}
+
+prefix_ void senf::INet6SocketAddress::host(INet6Address const & addr)
+{
+ sockaddr_.sin6_addr = addr.addr();
+}
+
+prefix_ unsigned senf::INet6SocketAddress::port()
+ const
+{
+ return ntohs(sockaddr_.sin6_port);
+}
+
+prefix_ void senf::INet6SocketAddress::port(unsigned port)
+{
+ sockaddr_.sin6_port = htons(port);
+}
+
+prefix_ void senf::INet6SocketAddress::iface(std::string const & iface)
+{
+ assignIface(iface);
+}
+
+prefix_ struct sockaddr * senf::INet6SocketAddress::sockaddr_p()
+{
+ return reinterpret_cast<struct sockaddr *>(&sockaddr_);
+}
+
+prefix_ struct sockaddr const * senf::INet6SocketAddress::sockaddr_p()
+ const
+{
+ return reinterpret_cast<struct sockaddr const *>(&sockaddr_);
+}
+
+prefix_ unsigned senf::INet6SocketAddress::sockaddr_len()
+ const
+{
+ return sizeof(sockaddr_);
+}
+
+prefix_ std::ostream & senf::operator<<(std::ostream & os, INet6SocketAddress const & addr)
+{
+ os << addr.address();
+ return os;
+}
+
///////////////////////////////cci.e///////////////////////////////////////
#undef prefix_
*/
std::ostream & operator<<(std::ostream & os, INet4Address const & addr);
- /** \brief IPv6 socket address
+ /** \brief IPv6 network address
\todo Implement
*/
class INet6Address
{
+ public:
+ ///////////////////////////////////////////////////////////////////////////
+ // Types
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///\name Structors and default members
+ ///@{
+
+ INet6Address();
+ INet6Address(std::string const & addr);
+ INet6Address(char const * addr);
+ INet6Address(struct in6_addr const & addr);
+
+ ///@}
+ ///////////////////////////////////////////////////////////////////////////
+
+ void clear();
+ std::string address() const;
+
+ bool operator==(INet6Address const & other) const;
+ bool operator!=(INet6Address const & other) const;
+
+ struct in6_addr & addr();
+ struct in6_addr const & addr() const;
+ struct in6_addr * addr_p();
+ struct in6_addr const * addr_p() const;
+ unsigned addr_len() const;
+
+ protected:
+
+ private:
+ struct in6_addr addr_;
+ };
+
+ std::ostream & operator<<(std::ostream & os, INet6Address const & addr);
+
+ /** \brief IPv6 socket address
+
+ \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.
+
+ \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
+ former as arg). This class however references an external in6_addr instead of containing one
+ itself. This can be used in INet6SocketAddress to increase the performance of some
+ operations.
+ */
+ class INet6SocketAddress
+ {
+ public:
+ ///////////////////////////////////////////////////////////////////////////
+ // Types
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///\name Structors and default members
+ ///@{
+
+ INet6SocketAddress();
+ INet6SocketAddress(std::string const & addr);
+ INet6SocketAddress(char const * addr);
+ INet6SocketAddress(INet6Address const & addr, unsigned port);
+ INet6SocketAddress(INet6Address const & addr, unsigned port, std::string const & iface);
+ INet6SocketAddress(std::string const & addr, std::string const & iface);
+
+ ///@}
+ ///////////////////////////////////////////////////////////////////////////
+
+ bool operator==(INet6SocketAddress const & other) const;
+ bool operator!=(INet6SocketAddress const & other) const;
+
+ void clear();
+
+ std::string address() const;
+ void address(std::string const & addr);
+
+ INet6Address host() const;
+ void host(INet6Address const & addr);
+
+ unsigned port() const;
+ void port(unsigned poirt);
+
+ std::string iface() const;
+ void iface(std::string const & iface);
+
+ ///\name Generic SocketAddress interface
+ ///@{
+
+ struct sockaddr * sockaddr_p();
+ struct sockaddr const * sockaddr_p() const;
+ unsigned sockaddr_len() const;
+
+ ///@}
+
+ protected:
+
+ private:
+ void assignAddr(std::string const & addr);
+ void assignIface(std::string const & iface);
+
+ struct sockaddr_in6 sockaddr_;
};
+ std::ostream & operator<<(std::ostream & os, INet6SocketAddress const & addr);
+
/** \brief Signal invalid INet address syntax
\related INet4Address
\todo implement
*/
- struct INet6AddressingPolicy : public AddressingPolicyBase
+ struct INet6AddressingPolicy
+ : public AddressingPolicyBase,
+ private GenericAddressingPolicy<INet6SocketAddress>
{
- typedef INet6Address Address;
+ typedef INet6SocketAddress Address;
+
+ using GenericAddressingPolicy<INet6SocketAddress>::peer;
+ using GenericAddressingPolicy<INet6SocketAddress>::local;
+ using GenericAddressingPolicy<INet6SocketAddress>::connect;
+ using GenericAddressingPolicy<INet6SocketAddress>::bind;
};
/// @}
BOOST_AUTO_UNIT_TEST(inet6Address)
{
+ using senf::INet6Address;
+ using senf::INet6SocketAddress;
+ using senf::InvalidINetAddressException;
+
+ {
+ INet6Address addr1 ("0102:0304:0506:0708:090A:0B0C:0D0E:0F00");
+ BOOST_CHECK_EQUAL( addr1.addr().s6_addr[0], 1 );
+ BOOST_CHECK_EQUAL( addr1.addr().s6_addr[1], 2 );
+ BOOST_CHECK_EQUAL( addr1.addr().s6_addr[2], 3 );
+ BOOST_CHECK_EQUAL( addr1.addr().s6_addr[3], 4 );
+ BOOST_CHECK_EQUAL( addr1.addr().s6_addr[4], 5 );
+ BOOST_CHECK_EQUAL( addr1.addr().s6_addr[5], 6 );
+ BOOST_CHECK_EQUAL( addr1.addr().s6_addr[6], 7 );
+ BOOST_CHECK_EQUAL( addr1.addr().s6_addr[7], 8 );
+ BOOST_CHECK_EQUAL( addr1.addr().s6_addr[8], 9 );
+ BOOST_CHECK_EQUAL( addr1.addr().s6_addr[9], 10 );
+ BOOST_CHECK_EQUAL( addr1.addr().s6_addr[10], 11 );
+ BOOST_CHECK_EQUAL( addr1.addr().s6_addr[11], 12 );
+ BOOST_CHECK_EQUAL( addr1.addr().s6_addr[12], 13 );
+ BOOST_CHECK_EQUAL( addr1.addr().s6_addr[13], 14 );
+ BOOST_CHECK_EQUAL( addr1.addr().s6_addr[14], 15 );
+ BOOST_CHECK_EQUAL( addr1.addr().s6_addr[15], 0 );
+ INet6Address addr2;
+ BOOST_CHECK_EQUAL( addr2, "::" );
+ addr2 = "::1";
+ BOOST_CHECK( addr1 != addr2 );
+ addr1 ="::1";
+ BOOST_CHECK_EQUAL( addr1, addr2 );
+ BOOST_CHECK_EQUAL( addr1.address(),"::1" );
+ addr1.clear();
+ addr2 = "::";
+ BOOST_CHECK_EQUAL( addr1, addr2 );
+ BOOST_CHECK_THROW( addr1 = "", InvalidINetAddressException );
+ BOOST_CHECK_EQUAL( boost::lexical_cast<std::string>(addr1), "::" );
+ }
+
+ {
+ INet6SocketAddress addr;
+ BOOST_CHECK_EQUAL( addr.host(), "::" );
+ BOOST_CHECK_EQUAL( addr.port(), 0u );
+ BOOST_CHECK_EQUAL( addr.iface(), "" );
+ addr = "[12::21]:12345";
+ BOOST_CHECK_EQUAL( addr.host(), "12::21" );
+ BOOST_CHECK_EQUAL( addr.port(), 12345u );
+ BOOST_CHECK_EQUAL( addr.iface(), "" );
+ BOOST_CHECK_EQUAL( addr, INet6SocketAddress("[12::21]:12345") );
+ }
+
+ {
+ INet6SocketAddress addr ("::1", 1);
+ BOOST_CHECK_EQUAL( addr, "[::1]:1" );
+ BOOST_CHECK_EQUAL( addr.iface(), "" );
+ }
+
+ {
+ INet6SocketAddress addr ("::1", 1, "lo");
+ BOOST_CHECK_EQUAL( addr, "[::1@lo]:1" );
+ BOOST_CHECK_EQUAL( addr.iface(), "lo" );
+ addr.iface("");
+ BOOST_CHECK_EQUAL( addr.iface(), "" );
+ addr.port(100u);
+ BOOST_CHECK_EQUAL( addr.port(), 100u );
+ addr.host("::2");
+ BOOST_CHECK_EQUAL( addr.host(), "::2" );
+ BOOST_CHECK_THROW( addr.address(""), InvalidINetAddressException );
+ BOOST_CHECK_THROW( addr.address("[::1]"), InvalidINetAddressException );
+ BOOST_CHECK_THROW( addr.address("[::1]1234"), InvalidINetAddressException );
+ addr.address("[12::21@lo]:12345");
+ BOOST_CHECK_EQUAL( addr.address(), "[12::21@lo]:12345" );
+ BOOST_CHECK_EQUAL( addr.host(), "12::21" );
+ BOOST_CHECK_EQUAL( addr.port(), 12345u );
+ BOOST_CHECK_EQUAL( addr.iface(), "lo" );
+ BOOST_CHECK_EQUAL( boost::lexical_cast<std::string>(addr), "[12::21@lo]:12345" );
+ }
}
///////////////////////////////cc.e////////////////////////////////////////
# also truncate the backtrace at the first stackframe within the unit
# test subsystem since we are only interested in the user code.
gdb -batch -x .run-test-gdb.cmd ./.test.bin 2>/dev/null | perl -e '
+ $mode=0;
while (<STDIN>) {
- if (/^$/) {
- $_=<STDIN>;
+ if ($mode==0) {
+ if (/^$/) {
+ $mode=1;
+ } else {
+ print;
+ }
+ }
+ elsif ($mode==1) {
if (/^Breakpoint 1, exception/) {
+ $mode=2;
@l=();
- while (<STDIN>) {
- last unless /^#?[0-9]|^ /;
- push @l,$_ if /^#/;
- $l[$#l] .= $_ if /^ /;
- }
+ } else {
+ print "\n";
+ print;
+ $mode=0;
+ }
+ }
+ elsif ($mode==2) {
+ if (/^(#?[0-9]| )/) {
+ push @l,$_ if /^#/;
+ $l[$#l] .= $_ if /^ /;
+ } else {
+ $mode=0;
if (/: fatal error in /) {
for (@l[1..$#l]) {
- last if /^#[0-9]+ +0x[0-9a-f]+ in boost::unit_test/;
+ last if /^#[0-9]+ +0x[0-9a-f]+ in boost::unit_test::ut_detail::invoker/;
print;
}
+ print;
+ } else {
+ redo;
}
}
- else { print "\n"; }
}
- print;
}
-'
\ No newline at end of file
+'