Skip to content
Snippets Groups Projects
Commit c7595a1e authored by g0dil's avatar g0dil
Browse files

Implement INet6SocketAddress

parent 65a6c1b0
No related branches found
No related tags found
No related merge requests found
// $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
......
......@@ -31,12 +31,18 @@
#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();
......@@ -79,6 +85,149 @@ prefix_ void senf::INet4Address::assignString(std::string address)
}
}
///////////////////////////////////////////////////////////////////////////
// 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"
......
......@@ -30,6 +30,9 @@
#define prefix_ inline
///////////////////////////////cci.p///////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// senf::INet4Address
prefix_ senf::INet4Address::INet4Address()
{
clear();
......@@ -88,6 +91,147 @@ prefix_ std::ostream & senf::operator<<(std::ostream & os, INet4Address const &
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_
......
......@@ -105,14 +105,118 @@ namespace senf {
*/
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
......@@ -164,9 +268,16 @@ namespace senf {
\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;
};
/// @}
......
......@@ -77,6 +77,80 @@ BOOST_AUTO_UNIT_TEST(inet4Address)
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////////////////////////////////////////
......
......@@ -39,25 +39,41 @@ EOF
# 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
'
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment