From: g0dil Date: Tue, 31 Jul 2007 12:26:16 +0000 (+0000) Subject: Socket/Protocols/INet: Add optional resolve-type argument to INet6 adressing classes... X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=2452ac2af5863afb6cfb74e6d2c6e35fc75d1f9a;p=senf.git Socket/Protocols/INet: Add optional resolve-type argument to INet6 adressing classes to support IpV4 mapped addresses Socket/Protocols/INet: removed obsolte INet6SocketAddress constructor git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@366 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Socket/Protocols/INet/INet6Address.cc b/Socket/Protocols/INet/INet6Address.cc index 0def041..03f8944 100644 --- a/Socket/Protocols/INet/INet6Address.cc +++ b/Socket/Protocols/INet/INet6Address.cc @@ -38,7 +38,8 @@ /////////////////////////////////////////////////////////////////////////// // 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) @@ -66,15 +67,21 @@ prefix_ senf::INet6Address senf::INet6Address::from_string(std::string const & s # 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(*(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(*(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) diff --git a/Socket/Protocols/INet/INet6Address.hh b/Socket/Protocols/INet/INet6Address.hh index c40e7cc..2b93f7b 100644 --- a/Socket/Protocols/INet/INet6Address.hh +++ b/Socket/Protocols/INet/INet6Address.hh @@ -99,6 +99,7 @@ namespace senf { static INet6Address const AllRouters; ///< The 'all routers' link-local multicast address enum NoInit_t { noinit }; + enum Resolve_t { ResolveINet6, ResolveINet4 }; /** \brief Possible scope values @@ -128,7 +129,7 @@ namespace senf { 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 @@ -138,9 +139,15 @@ namespace senf { 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 @@ -152,6 +159,11 @@ namespace senf { 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 diff --git a/Socket/Protocols/INet/INet6Address.test.cc b/Socket/Protocols/INet/INet6Address.test.cc index f51c6c4..22340c8 100644 --- a/Socket/Protocols/INet/INet6Address.test.cc +++ b/Socket/Protocols/INet/INet6Address.test.cc @@ -74,6 +74,10 @@ BOOST_AUTO_UNIT_TEST(inet6Address) 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") ); } { diff --git a/Socket/Protocols/INet/INetAddressing.cc b/Socket/Protocols/INet/INetAddressing.cc index 41c0f92..a54cc1c 100644 --- a/Socket/Protocols/INet/INetAddressing.cc +++ b/Socket/Protocols/INet/INetAddressing.cc @@ -73,6 +73,36 @@ prefix_ void senf::INet4SocketAddress::clear() /////////////////////////////////////////////////////////////////////////// // 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(match[Port])); +} + prefix_ bool senf::INet6SocketAddress::operator==(INet6SocketAddress const & other) const { @@ -103,32 +133,6 @@ prefix_ std::string senf::INet6SocketAddress::iface() 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(match[Port])); -} - prefix_ void senf::INet6SocketAddress::assignIface(std::string const & iface) { if (iface.empty()) diff --git a/Socket/Protocols/INet/INetAddressing.cci b/Socket/Protocols/INet/INetAddressing.cci index 320e8ee..a9987e9 100644 --- a/Socket/Protocols/INet/INetAddressing.cci +++ b/Socket/Protocols/INet/INetAddressing.cci @@ -104,12 +104,6 @@ prefix_ senf::INet6SocketAddress::INet6SocketAddress() clear(); } -prefix_ senf::INet6SocketAddress::INet6SocketAddress(std::string const & addr) -{ - clear(); - assignAddr(addr); -} - prefix_ senf::INet6SocketAddress::INet6SocketAddress(INet6Address const & addr, unsigned port) { clear(); @@ -126,14 +120,6 @@ prefix_ senf::INet6SocketAddress::INet6SocketAddress(INet6Address const & addr, 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 { diff --git a/Socket/Protocols/INet/INetAddressing.hh b/Socket/Protocols/INet/INetAddressing.hh index e3a95d3..5389b65 100644 --- a/Socket/Protocols/INet/INetAddressing.hh +++ b/Socket/Protocols/INet/INetAddressing.hh @@ -154,14 +154,17 @@ namespace senf { ///@{ 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 ///@} /////////////////////////////////////////////////////////////////////////// @@ -197,7 +200,6 @@ namespace senf { protected: private: - void assignAddr(std::string const & addr); void assignIface(std::string const & iface); struct sockaddr_in6 sockaddr_; diff --git a/Socket/Protocols/INet/INetAddressing.test.cc b/Socket/Protocols/INet/INetAddressing.test.cc index e512761..ee68de8 100644 --- a/Socket/Protocols/INet/INetAddressing.test.cc +++ b/Socket/Protocols/INet/INetAddressing.test.cc @@ -94,6 +94,9 @@ BOOST_AUTO_UNIT_TEST(inet6SocketAddress) 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 ); } {