switch to new MPL based Fraunhofer FOKUS Public License
[senf.git] / senf / Socket / Protocols / INet / INet4Address.cc
1 // $Id$
2 //
3 // Copyright (C) 2007
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at 
9 // http://senf.berlios.de/license.html
10 //
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on, 
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
14 //
15 // Software distributed under the License is distributed on an "AS IS" basis, 
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
17 // for the specific language governing rights and limitations under the License.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
24 //
25 // Contributor(s):
26 //   Stefan Bund <g0dil@berlios.de>
27
28 /** \file
29     \brief INet4Address non-inline non-template implementation */
30
31 #include "INet4Address.hh"
32 //#include "INet4Address.ih"
33
34 // Custom includes
35 #include <arpa/inet.h>
36 #include <netdb.h>
37 #include <sys/socket.h>
38 #include <boost/lexical_cast.hpp>
39 #if defined(_REENTRANT) && !defined(__GLIBC__)
40 #include <boost/thread/mutex.hpp>
41 #endif
42 #include <senf/Socket/Protocols/AddressExceptions.hh>
43
44 //#include "INet4Address.mpp"
45 #define prefix_
46 //-/////////////////////////////////////////////////////////////////////////////////////////////////
47
48 //-/////////////////////////////////////////////////////////////////////////////////////////////////
49 // senf::INet4Address::INet4Address
50
51 prefix_ senf::INet4Address::INet4Address(address_type value)
52 {
53     iref() = htonl(value);
54 }
55
56 prefix_ senf::INet4Address senf::INet4Address::from_string(std::string const & s)
57 {
58     struct in_addr ina;
59     if (::inet_pton(AF_INET,s.c_str(),&ina) > 0)
60         return INet4Address::from_inaddr(ina.s_addr);
61
62     if  (s.empty())
63         throw AddressSyntaxException() << ": empty string";
64
65     int herr (0);
66
67     // If available, we use the reentrant GNU variant. This has the additional advantage, that we
68     // can explicitly ask for IPv4 addresses
69
70 #   ifdef __GLIBC__
71
72     struct hostent entbuf;
73     char buffer[4096];
74     struct hostent * ent (0);
75     ::gethostbyname2_r(s.c_str(), AF_INET, &entbuf, buffer, sizeof(buffer), &ent, &herr);
76
77 #   else // ! __GLIBC__
78
79 #   ifdef _REENTRANT
80     static boost::mutex mutex;
81     boost::mutex::scoped_lock lock(mutex);
82 #   endif
83     struct hostent * ent (::gethostbyname(s.c_str()));
84     herr = h_errno;
85
86 #   endif // __GLIBC__
87
88     if (!ent)
89         throw UnknownHostnameException(s);
90     if (ent->h_addrtype != AF_INET)
91         throw UnknownHostnameException(s);
92
93     // We are only interested in the first address ...
94     return INet4Address::from_inaddr(
95         reinterpret_cast<in_addr*>(*(ent->h_addr_list))->s_addr);
96 }
97
98 prefix_ bool senf::INet4Address::local()
99     const
100 {
101     address_type l (address());
102     return
103         (l & 0xFF000000u) == 0x0A000000u ||
104         (l & 0xFFF00000u) == 0xAC100000u ||
105         (l & 0xFFFF0000u) == 0xA9FE0000u ||
106         (l & 0xFFFF0000u) == 0xC0A80000u;
107 }
108
109 prefix_ bool senf::INet4Address::loopback()
110     const
111 {
112     return (address() & 0xFF000000u) == 0x7F000000u;
113 }
114
115 prefix_ bool senf::INet4Address::multicast()
116     const
117 {
118     return (address() & 0xF0000000u) == 0xE0000000u;
119 }
120
121 prefix_ senf::INet4Address::address_type senf::INet4Address::address()
122     const
123 {
124     return ntohl(iref());
125 }
126
127 senf::INet4Address const senf::INet4Address::None;
128 senf::INet4Address const senf::INet4Address::Loopback (0x7F000001u);
129 senf::INet4Address const senf::INet4Address::Broadcast (0xFFFFFFFFu);
130
131 //-/////////////////////////////////////////////////////////////////////////////////////////////////
132 // senf::INet4Network
133
134 prefix_ senf::INet4Network::INet4Network(std::string const & s)
135 {
136     std::string::size_type i (s.find('/'));
137     if (i == std::string::npos)
138         throw AddressSyntaxException(s);
139     try {
140         prefix_len_ = boost::lexical_cast<unsigned>(std::string(s,i+1));
141     } catch (boost::bad_lexical_cast const &) {
142         throw AddressSyntaxException(s);
143     }
144     address_ = INet4Address(INet4Address::from_string(std::string(s, 0, i)).address() & mask());
145 }
146
147 //-/////////////////////////////////////////////////////////////////////////////////////////////////
148 // namespace members
149
150 prefix_ std::ostream & senf::operator<<(std::ostream & os, INet4Address const & addr)
151 {
152     ::in_addr ina;
153     char buffer[16];
154     ina.s_addr = addr.inaddr();
155     ::inet_ntop(AF_INET,&ina,buffer,16);
156     buffer[15] = 0;
157     os << buffer;
158     return os;
159 }
160
161 prefix_ std::istream & senf::operator>>(std::istream & is, INet4Address & addr)
162 {
163     std::string s;
164     if (!(is >> s))
165         return is;
166     try {
167         addr = INet4Address::from_string(s);
168     }
169     catch (AddressException &) {
170         is.setstate(std::ios::failbit);
171     }
172     return is;
173 }
174
175 prefix_ std::istream & senf::operator>>(std::istream & is, INet4Network & addr)
176 {
177     std::string s;
178     if (!(is >> s))
179         return is;
180     try {
181         addr = INet4Network(s);
182     }
183     catch (AddressException &) {
184         is.setstate(std::ios::failbit);
185     }
186     return is;
187 }
188
189 //-/////////////////////////////////////////////////////////////////////////////////////////////////
190 #undef prefix_
191 //#include "INet4Address.mpp"
192
193 \f
194 // Local Variables:
195 // mode: c++
196 // fill-column: 100
197 // comment-column: 40
198 // c-file-style: "senf"
199 // indent-tabs-mode: nil
200 // ispell-local-dictionary: "american"
201 // compile-command: "scons -u test"
202 // End: