X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Socket%2FINetAddressing.cc;h=b1efabc4325b3b4e7c97240e3c3499926fba22e5;hb=cf4ebe486e7e0543ac8568d3043f43d95f197a96;hp=d96bd9302bf02d9c94a43aa4a97a6cfefb1e7d14;hpb=2d51a34f79dd18b23c54172444b2cc7433b8f5f0;p=senf.git diff --git a/Socket/INetAddressing.cc b/Socket/INetAddressing.cc index d96bd93..b1efabc 100644 --- a/Socket/INetAddressing.cc +++ b/Socket/INetAddressing.cc @@ -31,12 +31,18 @@ #include #include #include +#include #include +#include +#include //#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 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()) + 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"