///////////////////////////////////////////////////////////////////////////
// senf::INet6Address
-prefix_ senf::INet6Address senf::INet6Address::from_string(std::string const & s)
+prefix_ senf::INet6Address senf::INet6Address::from_string(std::string const & s,
+ Resolve_t resolve)
{
struct in6_addr ina;
if (::inet_pton(AF_INET6,s.c_str(),&ina) > 0)
# endif // __GLIBC__
- if (!ent)
- ///\fixme Need to give better exception here
- throw SyntaxException();
- if (ent->h_addrtype != AF_INET6)
- throw SyntaxException();
-
- // We are only interested in the first address ...
- return senf::INet6Address::from_data(
- &reinterpret_cast<in6_addr*>(*(ent->h_addr_list))->s6_addr[0]);
+ if (ent && ent->h_addrtype == AF_INET6)
+ // We are only interested in the first address ...
+ return senf::INet6Address::from_data(
+ &reinterpret_cast<in6_addr*>(*(ent->h_addr_list))->s6_addr[0]);
+
+ ///\todo Throw better exceptions here ?
+
+ if (resolve == ResolveINet4)
+ try {
+ return from_inet4address(INet4Address::from_string(s));
+ } catch (INet4Address::SyntaxException const & ex) {
+ throw SyntaxException();
+ }
+ else
+ throw SyntaxException();
}
prefix_ std::ostream & senf::operator<<(std::ostream & os, INet6Address const & addr)
static INet6Address const AllRouters; ///< The 'all routers' link-local multicast address
enum NoInit_t { noinit };
+ enum Resolve_t { ResolveINet6, ResolveINet4 };
/** \brief Possible scope values
boost::uint16_t a6=0u, boost::uint16_t a7=0u);
///< Construct an address constant
- static INet6Address from_string(std::string const & s);
+ static INet6Address from_string(std::string const & s, Resolve_t resolve = ResolveINet6);
///< Convert string to address
/**< This member will try to convert the given string into
an IP address. from_string() supports all standard IP
protocol like DNS or NIS
\throws SyntaxException if the address cannot be
converted for some reason
- \param[in] s Address literal or hostname */
-
- static void from_string(std::string const & s, Callback const & cb);
+ \param[in] s Address literal or hostname
+ \param[in] resolve If this is set to \c ResolveINet4,
+ the call will additionally try to interpret \a s as
+ an IpV4 address if no valid IpV6 address is
+ found. The address will be returned as mapped IpV6
+ address. */
+
+ static void from_string(std::string const & s, Callback const & cb,
+ Resolve_t resolve = ResolveINet6);
///< Convert string to address (async/non-blocking)
/**< This member works like
from_string(std::string const &). However unlike
On error, the address passed to \a cb will be empty.
\param[in] s Address literal or hostname
\param[in] cb Callback to pass the address to
+ \param[in] resolve If this is set to \c ResolveINet4,
+ the call will additionally try to interpret \a s as
+ an IpV4 address if no valid IpV6 address is
+ found. The address will be returned as mapped IpV6
+ address.
\fixme Implement */
template <class InputIterator>
BOOST_CHECK_EQUAL( addr3, INet6Address::from_string("1200::21") );
BOOST_CHECK_EQUAL( INet6Address::from_inet4address(INet4Address(0x01020304)),
INet6Address::from_string("::ffff:1.2.3.4") );
+
+ BOOST_CHECK_THROW( INet6Address::from_string("1.2.3.4"), INet6Address::SyntaxException );
+ BOOST_CHECK_EQUAL( INet6Address::from_string("1.2.3.4", INet6Address::ResolveINet4),
+ INet6Address::from_string("::ffff:1.2.3.4") );
}
{
///////////////////////////////////////////////////////////////////////////
// senf::INet6SocketAddress
+prefix_ senf::INet6SocketAddress::INet6SocketAddress(std::string const & addr,
+ INet6Address::Resolve_t resolve)
+{
+ clear();
+
+ // Format of addr: "[" address [ "%" interface ] "]" ":" port
+ // or: host ":" port
+
+ static boost::regex const addressRx ("(?:\\[([a-f0-9A-F:]+)(?:%(.+))?\\]|(.+)):([0-9]+)");
+ // Subexpression numbers:
+ enum { NumericAddr = 1,
+ ZoneId = 2,
+ Hostname = 3,
+ Port = 4 };
+
+ boost::smatch match;
+ if (! regex_match(addr, match, addressRx))
+ throw SyntaxException();
+
+ INet6Address a (INet6Address::from_string(
+ match[NumericAddr].matched ? match[NumericAddr] : match[Hostname],
+ resolve));
+ std::copy(a.begin(), a.end(), &sockaddr_.sin6_addr.s6_addr[0]);
+
+ if (match[ZoneId].matched)
+ assignIface(match[ZoneId]);
+
+ sockaddr_.sin6_port = htons(boost::lexical_cast<boost::uint16_t>(match[Port]));
+}
+
prefix_ bool senf::INet6SocketAddress::operator==(INet6SocketAddress const & other)
const
{
return std::string(buffer);
}
-prefix_ void senf::INet6SocketAddress::assignAddr(std::string const & addr)
-{
- // Format of addr: "[" address [ "%" interface ] "]" ":" port
- // or: host ":" port
-
- static boost::regex const addressRx ("(?:\\[([a-f0-9A-F:]+)(?:%(.+))?\\]|(.+)):([0-9]+)");
- // Subexpression numbers:
- enum { NumericAddr = 1,
- ZoneId = 2,
- Hostname = 3,
- Port = 4 };
-
- boost::smatch match;
- if (! regex_match(addr, match, addressRx))
- throw SyntaxException();
-
- INet6Address a (INet6Address::from_string(
- match[NumericAddr].matched ? match[NumericAddr] : match[Hostname]));
- std::copy(a.begin(), a.end(), &sockaddr_.sin6_addr.s6_addr[0]);
-
- if (match[ZoneId].matched)
- assignIface(match[ZoneId]);
-
- sockaddr_.sin6_port = htons(boost::lexical_cast<boost::uint16_t>(match[Port]));
-}
-
prefix_ void senf::INet6SocketAddress::assignIface(std::string const & iface)
{
if (iface.empty())
clear();
}
-prefix_ senf::INet6SocketAddress::INet6SocketAddress(std::string const & addr)
-{
- clear();
- assignAddr(addr);
-}
-
prefix_ senf::INet6SocketAddress::INet6SocketAddress(INet6Address const & addr, unsigned port)
{
clear();
assignIface(iface);
}
-prefix_ senf::INet6SocketAddress::INet6SocketAddress(std::string const & addr,
- std::string const & iface)
-{
- clear();
- assignAddr(addr);
- assignIface(iface);
-}
-
prefix_ senf::INet6Address senf::INet6SocketAddress::address()
const
{
///@{
INet6SocketAddress(); ///< Create empty instance
- explicit INet6SocketAddress(std::string const & addr);
+ explicit INet6SocketAddress(std::string const & addr,
+ INet6Address::Resolve_t resolve = INet6Address::ResolveINet6);
///< Initialize/convert from string representation
+ /**< \param[in] addr Address to parse
+ \param[in] resolve If this is
+ INet6Address::ResolveINet4, support also IpV4
+ addresses. See INet6Address. */
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
///@}
///////////////////////////////////////////////////////////////////////////
protected:
private:
- void assignAddr(std::string const & addr);
void assignIface(std::string const & iface);
struct sockaddr_in6 sockaddr_;
BOOST_CHECK_EQUAL( addr.iface(), "" );
BOOST_CHECK_EQUAL( addr, INet6SocketAddress("[12::21]:12345") );
BOOST_CHECK_NO_THROW( INet6SocketAddress("www.6bone.net:80") );
+ addr = senf::INet6SocketAddress("1.2.3.4:12345", INet6Address::ResolveINet4);
+ BOOST_CHECK_EQUAL( addr.address(), INet6Address::from_string("::ffff:1.2.3.4") );
+ BOOST_CHECK_EQUAL( addr.port(), 12345u );
}
{