root/trunk/whisperlib/net/base/address.cc

Revision 7, 7.0 kB (checked in by whispercastorg, 2 years ago)

version 0.2.0

Line 
1 // Copyright (c) 2009, Whispersoft s.r.l.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Whispersoft s.r.l. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Author: Cosmin Tudorache  & Catalin Popescu
31
32 #include <arpa/inet.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35
36 #include "net/base/address.h"
37 #include "common/base/strutil.h"
38
39 namespace net {
40
41 const uint8 IpAddress::kInvalidIpV6[16] = {
42   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
43 };
44
45 void IpAddress::Addr(sockaddr_storage* addr) const {
46   memset(addr, 0, sizeof(*addr));
47   if ( is_ipv4_ ) {
48     addr->ss_family = AF_INET;
49     sockaddr_in* p = reinterpret_cast<sockaddr_in*>(addr);
50     // addr_.ipv4_ is in host byte order
51     p->sin_addr.s_addr = htonl(addr_.ipv4_);
52   } else {
53     addr->ss_family = AF_INET6;
54     sockaddr_in6* p = reinterpret_cast<sockaddr_in6*>(addr);
55     // addr_.ipv6_ is in network byte order
56     memcpy(p->sin6_addr.s6_addr, addr_.ipv6_, 16);
57   }
58 }
59
60 const char* IpAddress::ToString(char* buf, size_t buf_len) const {
61   if ( is_ipv4_ ) {
62     int32 ipv4 = htonl(addr_.ipv4_);
63     return inet_ntop(AF_INET,
64                      reinterpret_cast<const void*>(&ipv4), buf, buf_len);
65   }
66   // ipv6
67   return inet_ntop(AF_INET6,
68                    reinterpret_cast<const void*>(addr_.ipv6_), buf, buf_len);
69 }
70
71 string IpAddress::ToString() const {
72   char addr[60];
73   if ( addr != ToString(addr, sizeof(addr)) ) {
74     return "ERROR";
75   } else {
76     return string(addr);
77   }
78 }
79
80 HostPort::HostPort(const struct sockaddr_storage* addr)
81   : ip_(), port_(kInvalidPort) {
82   if ( addr->ss_family == AF_INET ) {
83     const struct sockaddr_in* p =
84         reinterpret_cast<const struct sockaddr_in*>(addr);
85     ip_.set_ipv4(ntohl(p->sin_addr.s_addr));
86     port_ = ntohs(p->sin_port);
87   } else if ( addr->ss_family == AF_INET6 ) {
88     const struct sockaddr_in6* p =
89         reinterpret_cast<const struct sockaddr_in6*>(addr);
90     ip_.set_ipv6(p->sin6_addr.s6_addr);
91     port_ = ntohs(p->sin6_port);
92   }
93 }
94
95 void HostPort::Parse(const char* addr, HostPort* hp) {
96   hp->set_ipv4(IpAddress::kInvalidIpV4);
97   hp->set_port(HostPort::kInvalidPort);
98
99   char* sport = strrchr(addr, ':');
100   if ( sport == NULL ) {
101     hp->ip_ = IpAddress(addr);
102   } else {
103     string saddr(addr, sport - addr);
104     ++sport;
105     *(hp->mutable_ip_object()) = IpAddress(saddr.c_str());
106     const uint32 port = strtoul(sport, &sport, 0);
107     if ( port < 0x10000 ) {
108       hp->set_port(port);
109     }
110   }
111 }
112
113 void HostPort::SockAddr(struct sockaddr_storage* addr) const {
114   ip_.Addr(addr);
115   if ( ip_.is_ipv4() ) {
116     sockaddr_in* p = reinterpret_cast<sockaddr_in*>(addr);
117     p->sin_port = htons(port_);
118   } else {
119     sockaddr_in6* p = reinterpret_cast<sockaddr_in6*>(addr);
120     p->sin6_port = htons(port_);
121   }
122 }
123
124 const char* HostPort::ToString(char* buf, size_t buf_len) const {
125   strncpy(buf, ToString().c_str(), buf_len);
126   return buf;
127 }
128
129 string HostPort::ToString() const {
130   return strutil::StringPrintf("%s:%d",
131                                ip_.ToString().c_str(),
132                                static_cast<int>(port_));
133 }
134
135 // Adds an ip or a range to the filter. Returns true on OK
136 bool IpV4Filter::Add(const char* p) {
137   const char* slash = strchr(p, '/');
138   IpAddress ip;
139   int32 bits = 32;
140   if ( slash != NULL ) {
141     ip = IpAddress(string(p, slash - p).c_str());
142     slash++;
143     bits = static_cast<int32>(strtol(slash, const_cast<char**>(&slash), 10));
144   } else {
145     ip = IpAddress(p);
146   }
147   return Add(ip, bits);
148 }
149
150 bool IpV4Filter::Add(const IpAddress& ip, int32 bits) {
151   if ( ip.IsInvalid() || !ip.is_ipv4() ) {
152     return false;
153   }
154   if ( bits > 32 || bits < 0 ) {
155     return false;
156   }
157   const int32 shift_bits = 32 - bits;
158   uint32 first_ip = ip.ipv4() & (0xffffffff << shift_bits);   // host order
159   // CHECK THIS CRAP OUT:
160   // when bits == 32 => 0xffffffff >> bits == 0xffffffff
161   // when bits == 31 => 0xffffffff >> bits == 0x1
162   uint32 last_ip = (shift_bits == 0 ?
163                     first_ip : first_ip | (0xffffffff >> bits));
164   FilterMap::iterator first_it = filter_.lower_bound(first_ip);
165   if ( first_it != filter_.end() &&
166        first_it->first > first_ip ) {
167     --first_it;
168   }
169   FilterMap::iterator last_it = filter_.upper_bound(last_ip);
170
171   const bool skip_insert_first =
172     (first_it != filter_.end() && first_it->second == MARK_BEGIN) ||
173     first_ip == last_ip;
174   bool skip_insert_last =
175     (last_it != filter_.end() && last_it->second == MARK_END);
176   FilterMap::iterator it = first_it;
177   if ( it != filter_.end() ) {
178     ++it;
179   }
180   while ( it != last_it ) {
181     FilterMap::iterator crt = it;
182     ++it;
183     filter_.erase(crt);
184   }
185   int32 first_found_ip = first_it->first;
186   if ( !skip_insert_first ) {
187     if ( first_it->first == first_ip &&
188          ((first_it->second & MARK_END) == MARK_END) ) {
189       if ( first_ip != last_ip ) {
190         filter_.erase(first_it);
191       } else {
192         skip_insert_last = true;
193       }
194     }
195     if ( first_found_ip != first_ip ) {
196       filter_.insert(make_pair(first_ip, MARK_BEGIN));
197     }
198   }
199   if ( !skip_insert_last ) {
200     if ( first_ip != last_ip ) {
201       filter_.insert(make_pair(last_ip, MARK_END));
202     } else {
203       filter_.insert(make_pair(last_ip, MARK_BOTH));
204     }
205   }
206   return true;
207 }
208
209 // Matching function - returns true if it matches
210 bool IpV4Filter::Matches(const IpAddress& ip) const {
211   if ( ip.IsInvalid() || !ip.is_ipv4() ) {
212     return false;
213   }
214   FilterMap::const_iterator first_it = filter_.lower_bound(ip.ipv4());
215   if ( first_it != filter_.end() &&
216        first_it->first > ip.ipv4() ) {
217     --first_it;
218   }
219   return ( first_it != filter_.end() &&
220            first_it->first <= ip.ipv4() &&
221            (first_it->second == MARK_BEGIN || first_it->first == ip.ipv4()) );
222 }
223 }
Note: See TracBrowser for help on using the browser.