INetAddressing.cc

Go to the documentation of this file.
00001 // $Id: INetAddressing.cc 1742 2010-11-04 14:51:56Z g0dil $
00002 //
00003 // Copyright (C) 2006
00004 // Fraunhofer (FOKUS)
00005 // Competence Center NETwork research (NET), St. Augustin, GERMANY
00006 //     Stefan Bund <g0dil@berlios.de>
00007 //
00008 // This program is free software; you can redistribute it and/or modify
00009 // it under the terms of the GNU General Public License as published by
00010 // the Free Software Foundation; either version 2 of the License, or
00011 // (at your option) any later version.
00012 //
00013 // This program is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 // GNU General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU General Public License
00019 // along with this program; if not, write to the
00020 // Free Software Foundation, Inc.,
00021 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00022 
00027 #include "INetAddressing.hh"
00028 //#include "INetAddressing.ih"
00029 
00030 // Custom includes
00031 #include <sstream>
00032 #include <string.h>
00033 #include <sys/socket.h>
00034 #include <net/if.h>
00035 #include <boost/lexical_cast.hpp>
00036 #include <boost/regex.hpp>
00037 #include <senf/Utils/senfassert.hh>
00038 #include <senf/Socket/Protocols/AddressExceptions.hh>
00039 
00040 //#include "INetAddressing.mpp"
00041 #define prefix_
00042 //-/////////////////////////////////////////////////////////////////////////////////////////////////
00043 
00044 //-/////////////////////////////////////////////////////////////////////////////////////////////////
00045 // senf::INet4SocketAddress
00046 
00047 prefix_ senf::INet4SocketAddress::INet4SocketAddress(std::string const & addr)
00048     : BSDSocketAddress (sizeof(sockaddr_in), AF_INET)
00049 {
00050     std::string::size_type portIx = addr.find(':');
00051     try {
00052         port( boost::lexical_cast< ::u_int16_t >(portIx == std::string::npos
00053                                                  ? addr : std::string(addr,portIx+1)) );
00054     }
00055     catch (boost::bad_lexical_cast const &) {
00056         throw AddressSyntaxException(addr) << ": invalid port number";
00057     }
00058     if (portIx != std::string::npos)
00059         address( INet4Address::from_string(std::string(addr,0,portIx)) );
00060 }
00061 
00062 prefix_ senf::INet4SocketAddress::INet4SocketAddress(INet4Address const & addr, unsigned p)
00063     : BSDSocketAddress (sizeof(sockaddr_in), AF_INET)
00064 {
00065     address(addr);
00066     port(p);
00067 }
00068 
00069 prefix_ senf::INet4SocketAddress::INet4SocketAddress(unsigned p)
00070     : BSDSocketAddress (sizeof(sockaddr_in), AF_INET)
00071 {
00072     port(p);
00073 }
00074 
00075 prefix_ std::ostream & senf::operator<<(std::ostream & os, INet4SocketAddress const & addr)
00076 {
00077     os << addr.address() << ":" << addr.port();
00078     return os;
00079 }
00080 
00081 prefix_ std::istream & senf::operator>>(std::istream & is, INet4SocketAddress & addr)
00082 {
00083     std::string s;
00084     if (!(is >> s))
00085         return is;
00086     try {
00087         addr = INet4SocketAddress(s);
00088     }
00089     catch (AddressException &) {
00090         is.setstate(std::ios::failbit);
00091     }
00092     return is;
00093 }
00094 
00095 //-/////////////////////////////////////////////////////////////////////////////////////////////////
00096 // senf::INet6SocketAddress
00097 
00098 prefix_ senf::INet6SocketAddress::INet6SocketAddress(std::string const & addr,
00099                                                      INet6Address::Resolve_t resolve)
00100     : BSDSocketAddress (sizeof(sockaddr_in6), AF_INET6)
00101 {
00102     // Format of addr: "[" address [ "%" interface ] "]" ":" port
00103     //             or: host ":" port
00104     //             or: port
00105 
00106     static boost::regex const addressRx ("(?:(?:\\[([^%]+)(?:%(.+))?\\]|(.+)):)?([0-9]+)");
00107     // Subexpression numbers:
00108     enum { Address  = 1,
00109            ZoneId   = 2,
00110            Hostname = 3,
00111            Port     = 4 };
00112 
00113     boost::smatch match;
00114     if (! regex_match(addr, match, addressRx))
00115         throw AddressSyntaxException(addr);
00116 
00117     if (match[ZoneId].matched)
00118         assignIface(match[ZoneId]);
00119 
00120     sockaddr_.sin6_port = htons(boost::lexical_cast<boost::uint16_t>(match[Port]));
00121 
00122     if (match[Address].matched || match[Hostname].matched) {
00123         INet6Address a (INet6Address::from_string(
00124                             match[Address].matched ? match[Address] : match[Hostname],
00125                             resolve));
00126         std::copy(a.begin(), a.end(), &sockaddr_.sin6_addr.s6_addr[0]);
00127     }
00128 }
00129 
00130 prefix_ std::string senf::INet6SocketAddress::iface()
00131     const
00132 {
00133     if (sockaddr_.sin6_scope_id == 0)
00134         return "";
00135     char buffer[IFNAMSIZ];
00136     SENF_ASSERT_EXPRESSION(if_indextoname(sockaddr_.sin6_scope_id,buffer),
00137                            "Internal failure: Invalid interface index (how does it get here?)");
00138     return std::string(buffer);
00139 }
00140 
00141 prefix_ void senf::INet6SocketAddress::assignIface(std::string const & iface)
00142 {
00143     if (iface.empty())
00144         sockaddr_.sin6_scope_id = 0;
00145     else {
00146         sockaddr_.sin6_scope_id = if_nametoindex(iface.c_str());
00147         if (sockaddr_.sin6_scope_id == 0)
00148             throw AddressSyntaxException(iface);
00149     }
00150 }
00151 
00152 prefix_ std::ostream & senf::operator<<(std::ostream & os, INet6SocketAddress const & addr)
00153 {
00154     os << '[' << addr.address();
00155     std::string iface (addr.iface());
00156     if (! iface.empty())
00157         os << '%' << iface;
00158     os << "]:" << addr.port();
00159     return os;
00160 }
00161 
00162 prefix_ std::istream & senf::operator>>(std::istream & is, INet6SocketAddress & addr)
00163 {
00164     std::string s;
00165     if (!(is >> s))
00166         return is;
00167     try {
00168         addr = INet6SocketAddress(s);
00169     }
00170     catch (AddressException &) {
00171         is.setstate(std::ios::failbit);
00172     }
00173     return is;
00174 }
00175 
00176 //-/////////////////////////////////////////////////////////////////////////////////////////////////
00177 #undef prefix_
00178 //#include "INetAddressing.mpp"
00179 
00180 
00181 // Local Variables:
00182 // mode: c++
00183 // fill-column: 100
00184 // c-file-style: "senf"
00185 // indent-tabs-mode: nil
00186 // ispell-local-dictionary: "american"
00187 // compile-command: "scons -u test"
00188 // comment-column: 40
00189 // End: