Socket/Protocols/INet: Implemented INet4Network
[senf.git] / Socket / Protocols / INet / INet4Address.hh
1 // $Id$
2 //
3 // Copyright (C) 2007 
4 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
5 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
6 //     Stefan Bund <g0dil@berlios.de>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 /** \file
24     \brief INet4Address public header */
25
26 #ifndef HH_INet4Address_
27 #define HH_INet4Address_ 1
28
29 // Custom includes
30 #include <iostream>
31 #include <string>
32 #include <boost/cstdint.hpp>
33 #include <boost/function.hpp>
34 #include <boost/array.hpp>
35 #include <boost/operators.hpp>
36 #include "Utils/SafeBool.hh"
37
38 //#include "INet4Address.mpp"
39 ///////////////////////////////hh.p////////////////////////////////////////
40
41 namespace senf {
42     
43     /** \brief IpV4 Internet address
44         
45         INet4Address represents a simple IP address. It is modelled as a fixed-size
46         container/sequence of 4 bytes.
47
48         \see CheckINet4Network
49
50         \implementation We awkwardly need to use static named constructors (<tt>from_</tt> members)
51             instead of ordinarily overloaded constructors for one simple reason: <tt>char *</tt>
52             doubles as string literal and as arbitrary data iterator. The iterator constructor can
53             therefore not be distinguished from initialization with a string literal. Therefore we
54             need to disambiguate using the named constructors.
55
56         \todo Add additional classes for CIDR addresses and networks and network math.
57         \ingroup addr_group
58       */
59     class INet4Address
60         : public boost::array<boost::uint8_t,4>, 
61           public ComparableSafeBool<INet4Address>
62     {
63     public:
64         ///////////////////////////////////////////////////////////////////////////
65         // Types
66         
67         typedef uint32_t address_type;  ///< Address representation as number in host byte order
68         typedef uint32_t inaddr_type;   ///< Legacy address representation in network byte order
69         typedef boost::function<void (INet4Address const &)> Callback;
70                                         ///< Callback for asynchronous from_string call
71
72         static INet4Address const None; ///< The empty (0) address
73         static INet4Address const Loopback; ///< The loopback (127.0.0.1) address
74         static INet4Address const Broadcast; ////< The global broadcast (255.255.255.255) address
75
76         enum NoInit_t { noinit };
77
78         ///////////////////////////////////////////////////////////////////////////
79         ///\name Structors and default members
80         ///@{
81
82         INet4Address();                 ///< Construct an empty address
83         explicit INet4Address(NoInit_t); ///< Construct uninitialized (!) address
84         explicit INet4Address(address_type value);
85                                         ///< Construct an address constant
86
87         static INet4Address from_string(std::string const & s);
88                                         ///< Convert string to address
89                                         /**< This member will try to convert the given string into
90                                              an IP address. from_string() supports all standard IP
91                                              literal representations as well es hostnames.
92                                              \attention This call may block if \a s represents a
93                                                  hostname which must be looked up via some network
94                                                  protocol like DNS or NIS
95                                              \throws SyntaxException if the address cannot be
96                                                  converted for some reason
97                                              \param[in] s Address literal or hostname */
98         
99         static void from_string(std::string const & s, Callback const & cb);
100                                         ///< Convert string to address (async/non-blocking)
101                                         /**< This member works like
102                                              from_string(std::string const &). However unlike
103                                              from_string(std::string const &), this call will not
104                                              block. Instead it will call \a cb passing the
105                                              INet4Address instance as soon as the address has been
106                                              resolved (which may be immediate if the address
107                                              represents an IP literal). \par
108                                              On error, the address passed to \a cb will be empty.
109                                              \param[in] s Address literal or hostname
110                                              \param[in] cb Callback to pass the address to 
111                                              \fixme Implement */
112
113         template <class InputIterator> 
114         static INet4Address from_data(InputIterator i);
115                                         ///< Construct address from 4 bytes of raw data
116                                         /**< from_data will build an address from 4 bytes of raw
117                                              data as accessed by the iterator. The data must be in
118                                              network byte order. */
119         static INet4Address from_inaddr(inaddr_type v);
120                                         ///< Construct address from integer in network byte order
121                                         /**< This call is used when interfacing with other legacy
122                                              code to convert a network byte order address in an
123                                              integer number into an INet4Address. */
124
125         ///@}
126         ///////////////////////////////////////////////////////////////////////////
127         ///\name Accessors
128         ///@{
129
130         bool local() const;             ///< \c true, if address is locally administered
131                                         /**< This call checks, if the address is within one of the
132                                              IANA private ranges. */
133         bool loopback() const;          ///< \c true, if address is within the loopback network
134                                         /**< Checks, whether the address is in the IANA loopback
135                                              network 10.0.0.0/8 */
136         bool multicast() const;         ///< \c true, if address is a multicast address
137                                         /**< Checks, whether the address is in the 224.0.0.0/4
138                                              network reserved for multicast addresses by the
139                                              IANA. */
140         bool broadcast() const;         ///< \c true, if address is 255.255.255.255
141         bool boolean_test() const;      ///< \c true, if address is non-empty (!= 0.0.0.0)
142
143         inaddr_type inaddr() const;     ///< Return the raw network byte order address
144                                         /**< This member is used to interact with legacy code. 
145                                              \return */
146         address_type address() const;   ///< Return address represented as integer number
147                                         /**< This member returns the address as an integer number in
148                                              host byte order. This representation allows simple
149                                              network math operations. */
150
151         ////@}
152
153         struct SyntaxException : public std::exception
154         { virtual char const * what() const throw() { return "invalid INet4 address syntax"; } };
155
156     private:
157         enum InAddr_t { IsInAddr };
158         INet4Address(inaddr_type addr, InAddr_t);
159         inaddr_type & iref();
160         inaddr_type iref() const;
161     };
162
163     /** \brief Output INet4Address instance as it's string representation
164         \related INet4Address
165      */
166     std::ostream & operator<<(std::ostream & os, INet4Address const & addr);
167
168     /** \brief CHeck INet4Address against a fixed network prefix
169
170         This helper allows to easily and efficiently check an INet4Address against an arbitrary but
171         constant network prefix. The network prefix is represented by
172         
173         \par ""
174             <tt>senf::CheckINet4Network<</tt> <i>addr</i> <tt>,</tt> <i>prefix-len</i> <tt>></tt>
175         
176         Where \a addr is the v4 Internet address as a 32-bit unsigned integer number in host byte
177         order and \a prefix_len is the length of the network prefix. The class exposes a single
178         static member <tt>match(</tt> <i>addr</i> <tt>)</tt> which matches the INet4Address \a addr
179         against the prefix:
180
181         \code
182         if (senf::CheckINet4Network<0x7F000000u,8u>::match(addr)) {
183             // 'addr' is within the 127.0.0.0/8 loopback network
184             ...
185         }
186         \endcode
187
188         \implementation This is implemented the way it is so the syntax is identical to the
189             CheckINet6Network syntax.
190      */
191     template <boost::uint32_t address, unsigned prefix_len>
192     class CheckINet4Network
193     {
194     public:
195         static bool match(INet4Address const & addr);
196     };
197
198     /** \brief IpV4 network prefix
199
200         This class represents an IpV4 network prefix in CIDR notation. 
201       */
202     class INet4Network
203         : public boost::equality_comparable<INet4Network>, 
204           public ComparableSafeBool<INet4Network>
205     {
206     public:
207         ///////////////////////////////////////////////////////////////////////////
208         // Types
209
210         ///////////////////////////////////////////////////////////////////////////
211         ///\name Structors and default members
212         ///@{
213
214         INet4Network();                 ///< Construct empty (0.0.0.0/0) network
215         INet4Network(INet4Address address, unsigned prefix_len);
216                                         ///< Construct network from given address and prefix length
217         explicit INet4Network(std::string s); ///< Construct network from CIDR notation
218
219         ///@}
220         ///////////////////////////////////////////////////////////////////////////
221
222         INet4Address const & address() const; ///< Get the networks address
223         unsigned prefix_len() const;    ///< Get the networks prefix length
224
225         bool boolean_test() const;      ///< \c true, if INet4Network is non-empty
226         bool operator==(INet4Network const & other) const;
227                                         ///< Compare to networks for equality
228         
229         bool match(INet4Address addr) const; ///< \c true, if the network includes \a addr
230         bool match(INet4Network net) const; ///< \c true, if the network includes \a net
231                                         /**< The is true, if \a net is sub-network (or the same as)
232                                              \c this. */
233
234     protected:
235
236     private:
237         boost::uint32_t mask() const;
238
239         unsigned prefix_len_;
240         INet4Address address_;
241     };
242
243     /** \brief Output INet4Network instance as it's string representation
244         \related INet4Network
245      */
246     std::ostream & operator<<(std::ostream & os, INet4Network const & addr);
247         
248 }
249
250 ///////////////////////////////hh.e////////////////////////////////////////
251 #include "INet4Address.cci"
252 #include "INet4Address.ct"
253 #include "INet4Address.cti"
254 #endif
255
256 \f
257 // Local Variables:
258 // mode: c++
259 // fill-column: 100
260 // comment-column: 40
261 // c-file-style: "senf"
262 // indent-tabs-mode: nil
263 // ispell-local-dictionary: "american"
264 // compile-command: "scons -u test"
265 // End: