X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Socket%2FProtocols%2FINet%2FINetAddressing.cc;h=e224408f1bc827a32764ee78eb36985c8873681f;hb=a1fdb7bb122f0b05be809a922d4b7ef5e125fa67;hp=5f58af86e73117f71cc3f24bff0a91ee513ca72c;hpb=fb08e3defcfb7cd8851ede0fab6cad424d168485;p=senf.git diff --git a/Socket/Protocols/INet/INetAddressing.cc b/Socket/Protocols/INet/INetAddressing.cc index 5f58af8..e224408 100644 --- a/Socket/Protocols/INet/INetAddressing.cc +++ b/Socket/Protocols/INet/INetAddressing.cc @@ -1,9 +1,9 @@ // $Id$ // // Copyright (C) 2006 -// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) -// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) -// Stefan Bund +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Stefan Bund // // 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 @@ -33,130 +33,97 @@ #include #include #include -#include -#include +#include +#include "../../../Utils/senfassert.hh" //#include "INetAddressing.mpp" #define prefix_ ///////////////////////////////cc.p//////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// -// senf::INet4Address +// senf::INet4SocketAddress -prefix_ senf::INet4SocketAddress::INet4SocketAddress(std::string const & host, unsigned port) +prefix_ senf::INet4SocketAddress::INet4SocketAddress(std::string const & addr) + : BSDSocketAddress (sizeof(sockaddr_in), AF_INET) { - clear(); - /** \todo gethostbyname support */ - if (::inet_aton(host.c_str(), &addr_.sin_addr) == 0) - throw InvalidINetAddressException(); - addr_.sin_port = htons(port); -} - -prefix_ std::string senf::INet4SocketAddress::str() - const -{ - std::stringstream s; - s << host() << ':' << port(); - return s.str(); -} - -prefix_ void senf::INet4SocketAddress::clear() -{ - ::memset(&addr_,0,sizeof(addr_)); - addr_.sin_family = AF_INET; -} - -prefix_ void senf::INet4SocketAddress::assignString(std::string const & address) -{ - clear(); - unsigned i = address.find(':'); - if (i == std::string::npos) - throw InvalidINetAddressException(); - // The temporary string in the next expr is guaranteed to live - // until end-of-statement - if (::inet_aton(std::string(address,0,i).c_str(), &addr_.sin_addr) == 0) - throw InvalidINetAddressException(); + std::string::size_type portIx = addr.find(':'); try { - // Replace lexical_cast with strtoul ? - addr_.sin_port = htons(boost::lexical_cast< ::u_int16_t >(std::string(address,i+1))); + port( boost::lexical_cast< ::u_int16_t >(portIx == std::string::npos + ? addr : std::string(addr,portIx+1)) ); } catch (boost::bad_lexical_cast const &) { - throw InvalidINetAddressException(); + throw AddressSyntaxException() << "invalid port number"; } + if (portIx != std::string::npos) + address( INet4Address::from_string(std::string(addr,0,portIx)) ); } -/////////////////////////////////////////////////////////////////////////// -// 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) +prefix_ senf::INet4SocketAddress::INet4SocketAddress(INet4Address const & addr, unsigned p) + : BSDSocketAddress (sizeof(sockaddr_in), AF_INET) { - if (inet_pton(AF_INET6,addr,&addr_) <= 0) - throw InvalidINetAddressException(); + address(addr); + port(p); } -prefix_ void senf::INet6Address::clear() +prefix_ senf::INet4SocketAddress::INet4SocketAddress(unsigned p) + : BSDSocketAddress (sizeof(sockaddr_in), AF_INET) { - ::memset(&addr_,0,sizeof(addr_)); + port(p); } -prefix_ std::string senf::INet6Address::address() - const +prefix_ std::ostream & senf::operator<<(std::ostream & os, INet4SocketAddress const & addr) { - char buffer[8*5]; - BOOST_ASSERT( inet_ntop(AF_INET6, &addr_, buffer, sizeof(buffer)) ); - return std::string(buffer); + os << addr.address() << ":" << addr.port(); + return os; } -prefix_ bool senf::INet6Address::operator==(INet6Address const & other) - const +prefix_ std::istream & senf::operator>>(std::istream & is, INet4SocketAddress & addr) { - return ::memcmp(&addr_,&other.addr_,sizeof(addr_))==0; -} - -prefix_ bool senf::INet6Address::operator!=(INet6Address const & other) - const -{ - return !operator==(other); + std::string s; + if (!(is >> s)) + return is; + try { + addr = INet4SocketAddress(s); + } + catch (AddressException &) { + is.setstate(std::ios::failbit); + } + return is; } /////////////////////////////////////////////////////////////////////////// // senf::INet6SocketAddress -prefix_ bool senf::INet6SocketAddress::operator==(INet6SocketAddress const & other) - const +prefix_ senf::INet6SocketAddress::INet6SocketAddress(std::string const & addr, + INet6Address::Resolve_t resolve) + : BSDSocketAddress (sizeof(sockaddr_in6), AF_INET6) { - 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; -} + // Format of addr: "[" address [ "%" interface ] "]" ":" port + // or: host ":" port + // or: port -prefix_ bool senf::INet6SocketAddress::operator!=(INet6SocketAddress const & other) - const -{ - return ! operator==(other); -} + static boost::regex const addressRx ("(?:(?:\\[([^%]+)(?:%(.+))?\\]|(.+)):)?([0-9]+)"); + // Subexpression numbers: + enum { Address = 1, + ZoneId = 2, + Hostname = 3, + Port = 4 }; -prefix_ void senf::INet6SocketAddress::clear() -{ - ::memset(&sockaddr_,0,sizeof(sockaddr_)); - sockaddr_.sin6_family = AF_INET6; -} + boost::smatch match; + if (! regex_match(addr, match, addressRx)) + throw AddressSyntaxException(); -prefix_ std::string senf::INet6SocketAddress::address() - const -{ - std::stringstream ss; - ss << '[' << host(); - if (sockaddr_.sin6_scope_id != 0) - ss << '@' << iface() - << "]:" << port(); - return ss.str(); + if (match[ZoneId].matched) + assignIface(match[ZoneId]); + + sockaddr_.sin6_port = htons(boost::lexical_cast(match[Port])); + + if (match[Address].matched || match[Hostname].matched) { + INet6Address a (INet6Address::from_string( + match[Address].matched ? match[Address] : match[Hostname], + resolve)); + std::copy(a.begin(), a.end(), &sockaddr_.sin6_addr.s6_addr[0]); + } } prefix_ std::string senf::INet6SocketAddress::iface() @@ -165,50 +132,14 @@ prefix_ std::string senf::INet6SocketAddress::iface() if (sockaddr_.sin6_scope_id == 0) return ""; char buffer[IFNAMSIZ]; - BOOST_ASSERT( if_indextoname(sockaddr_.sin6_scope_id,buffer) ); +#ifdef SENF_DEBUG + SENF_ASSERT( if_indextoname(sockaddr_.sin6_scope_id,buffer) ); +#else + if_indextoname(sockaddr_.sin6_scope_id,buffer); +#endif return std::string(buffer); } -prefix_ void senf::INet6SocketAddress::assignAddr(std::string const & addr) -{ - // Format of addr: "[" address [ "@" interface ] "]" ":" port - typedef boost::char_separator separator; - typedef boost::tokenizer 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(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()) @@ -216,15 +147,39 @@ prefix_ void senf::INet6SocketAddress::assignIface(std::string const & iface) else { sockaddr_.sin6_scope_id = if_nametoindex(iface.c_str()); if (sockaddr_.sin6_scope_id == 0) - throw InvalidINetAddressException(); + throw AddressSyntaxException(); } } +prefix_ std::ostream & senf::operator<<(std::ostream & os, INet6SocketAddress const & addr) +{ + os << '[' << addr.address(); + std::string iface (addr.iface()); + if (! iface.empty()) + os << '%' << iface; + os << "]:" << addr.port(); + return os; +} + +prefix_ std::istream & senf::operator>>(std::istream & is, INet6SocketAddress & addr) +{ + std::string s; + if (!(is >> s)) + return is; + try { + addr = INet6SocketAddress(s); + } + catch (AddressException &) { + is.setstate(std::ios::failbit); + } + return is; +} + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_ //#include "INetAddressing.mpp" - + // Local Variables: // mode: c++ // fill-column: 100