Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(18)

Side by Side Diff: net/base/ip_address.cc

Issue 2881673002: Avoid heap allocations in IPAddress (Closed)
Patch Set: Rename and Assign Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/base/ip_address.h ('k') | net/base/ip_address_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/base/ip_address.h" 5 #include "net/base/ip_address.h"
6 6
7 #include <limits.h> 7 #include <algorithm>
8 #include <climits>
8 9
10 #include "base/containers/stack_container.h"
9 #include "base/strings/string_piece.h" 11 #include "base/strings/string_piece.h"
10 #include "base/strings/string_split.h" 12 #include "base/strings/string_split.h"
11 #include "base/strings/stringprintf.h" 13 #include "base/strings/stringprintf.h"
12 #include "net/base/parse_number.h" 14 #include "net/base/parse_number.h"
13 #include "url/gurl.h" 15 #include "url/gurl.h"
14 #include "url/url_canon_ip.h" 16 #include "url/url_canon_ip.h"
15 17
18 namespace net {
16 namespace { 19 namespace {
17 20
18 // The prefix for IPv6 mapped IPv4 addresses. 21 // The prefix for IPv6 mapped IPv4 addresses.
19 // https://tools.ietf.org/html/rfc4291#section-2.5.5.2 22 // https://tools.ietf.org/html/rfc4291#section-2.5.5.2
20 const uint8_t kIPv4MappedPrefix[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF}; 23 const uint8_t kIPv4MappedPrefix[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF};
21 24
22 // Note that this function assumes: 25 // Note that this function assumes:
23 // * |ip_address| is at least |prefix_length_in_bits| (bits) long; 26 // * |ip_address| is at least |prefix_length_in_bits| (bits) long;
24 // * |ip_prefix| is at least |prefix_length_in_bits| (bits) long. 27 // * |ip_prefix| is at least |prefix_length_in_bits| (bits) long.
25 bool IPAddressPrefixCheck(const std::vector<uint8_t>& ip_address, 28 bool IPAddressPrefixCheck(const IPAddressBytes& ip_address,
26 const uint8_t* ip_prefix, 29 const uint8_t* ip_prefix,
27 size_t prefix_length_in_bits) { 30 size_t prefix_length_in_bits) {
28 // Compare all the bytes that fall entirely within the prefix. 31 // Compare all the bytes that fall entirely within the prefix.
29 size_t num_entire_bytes_in_prefix = prefix_length_in_bits / 8; 32 size_t num_entire_bytes_in_prefix = prefix_length_in_bits / 8;
30 for (size_t i = 0; i < num_entire_bytes_in_prefix; ++i) { 33 for (size_t i = 0; i < num_entire_bytes_in_prefix; ++i) {
31 if (ip_address[i] != ip_prefix[i]) 34 if (ip_address[i] != ip_prefix[i])
32 return false; 35 return false;
33 } 36 }
34 37
35 // In case the prefix was not a multiple of 8, there will be 1 byte 38 // In case the prefix was not a multiple of 8, there will be 1 byte
36 // which is only partially masked. 39 // which is only partially masked.
37 size_t remaining_bits = prefix_length_in_bits % 8; 40 size_t remaining_bits = prefix_length_in_bits % 8;
38 if (remaining_bits != 0) { 41 if (remaining_bits != 0) {
39 uint8_t mask = 0xFF << (8 - remaining_bits); 42 uint8_t mask = 0xFF << (8 - remaining_bits);
40 size_t i = num_entire_bytes_in_prefix; 43 size_t i = num_entire_bytes_in_prefix;
41 if ((ip_address[i] & mask) != (ip_prefix[i] & mask)) 44 if ((ip_address[i] & mask) != (ip_prefix[i] & mask))
42 return false; 45 return false;
43 } 46 }
44 return true; 47 return true;
45 } 48 }
46 49
47 // Returns true if |ip_address| matches any of the reserved IPv4 ranges. This 50 // Returns true if |ip_address| matches any of the reserved IPv4 ranges. This
48 // method operates on a blacklist of reserved IPv4 ranges. Some ranges are 51 // method operates on a blacklist of reserved IPv4 ranges. Some ranges are
49 // consolidated. 52 // consolidated.
50 // Sources for info: 53 // Sources for info:
51 // www.iana.org/assignments/ipv4-address-space/ipv4-address-space.xhtml 54 // www.iana.org/assignments/ipv4-address-space/ipv4-address-space.xhtml
52 // www.iana.org/assignments/iana-ipv4-special-registry/ 55 // www.iana.org/assignments/iana-ipv4-special-registry/
53 // iana-ipv4-special-registry.xhtml 56 // iana-ipv4-special-registry.xhtml
54 bool IsReservedIPv4(const std::vector<uint8_t>& ip_address) { 57 bool IsReservedIPv4(const IPAddressBytes& ip_address) {
55 // Different IP versions have different range reservations. 58 // Different IP versions have different range reservations.
56 DCHECK_EQ(net::IPAddress::kIPv4AddressSize, ip_address.size()); 59 DCHECK_EQ(IPAddress::kIPv4AddressSize, ip_address.size());
57 struct { 60 struct {
58 const uint8_t address[4]; 61 const uint8_t address[4];
59 size_t prefix_length_in_bits; 62 size_t prefix_length_in_bits;
60 } static const kReservedIPv4Ranges[] = { 63 } static const kReservedIPv4Ranges[] = {
61 {{0, 0, 0, 0}, 8}, {{10, 0, 0, 0}, 8}, {{100, 64, 0, 0}, 10}, 64 {{0, 0, 0, 0}, 8}, {{10, 0, 0, 0}, 8}, {{100, 64, 0, 0}, 10},
62 {{127, 0, 0, 0}, 8}, {{169, 254, 0, 0}, 16}, {{172, 16, 0, 0}, 12}, 65 {{127, 0, 0, 0}, 8}, {{169, 254, 0, 0}, 16}, {{172, 16, 0, 0}, 12},
63 {{192, 0, 2, 0}, 24}, {{192, 88, 99, 0}, 24}, {{192, 168, 0, 0}, 16}, 66 {{192, 0, 2, 0}, 24}, {{192, 88, 99, 0}, 24}, {{192, 168, 0, 0}, 16},
64 {{198, 18, 0, 0}, 15}, {{198, 51, 100, 0}, 24}, {{203, 0, 113, 0}, 24}, 67 {{198, 18, 0, 0}, 15}, {{198, 51, 100, 0}, 24}, {{203, 0, 113, 0}, 24},
65 {{224, 0, 0, 0}, 3}}; 68 {{224, 0, 0, 0}, 3}};
66 69
67 for (const auto& range : kReservedIPv4Ranges) { 70 for (const auto& range : kReservedIPv4Ranges) {
68 if (IPAddressPrefixCheck(ip_address, range.address, 71 if (IPAddressPrefixCheck(ip_address, range.address,
69 range.prefix_length_in_bits)) { 72 range.prefix_length_in_bits)) {
70 return true; 73 return true;
71 } 74 }
72 } 75 }
73 76
74 return false; 77 return false;
75 } 78 }
76 79
77 // Returns true if |ip_address| matches any of the reserved IPv6 ranges. This 80 // Returns true if |ip_address| matches any of the reserved IPv6 ranges. This
78 // method operates on a whitelist of non-reserved IPv6 ranges. All IPv6 81 // method operates on a whitelist of non-reserved IPv6 ranges. All IPv6
79 // addresses outside these ranges are reserved. 82 // addresses outside these ranges are reserved.
80 // Sources for info: 83 // Sources for info:
81 // www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml 84 // www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml
82 bool IsReservedIPv6(const std::vector<uint8_t>& ip_address) { 85 bool IsReservedIPv6(const IPAddressBytes& ip_address) {
83 // Different IP versions have different range reservations. 86 // Different IP versions have different range reservations.
84 DCHECK_EQ(net::IPAddress::kIPv6AddressSize, ip_address.size()); 87 DCHECK_EQ(IPAddress::kIPv6AddressSize, ip_address.size());
85 struct { 88 struct {
86 const uint8_t address_prefix[2]; 89 const uint8_t address_prefix[2];
87 size_t prefix_length_in_bits; 90 size_t prefix_length_in_bits;
88 } static const kPublicIPv6Ranges[] = { 91 } static const kPublicIPv6Ranges[] = {
89 // 2000::/3 -- Global Unicast 92 // 2000::/3 -- Global Unicast
90 {{0x20, 0}, 3}, 93 {{0x20, 0}, 3},
91 // ff00::/8 -- Multicast 94 // ff00::/8 -- Multicast
92 {{0xff, 0}, 8}, 95 {{0xff, 0}, 8},
93 }; 96 };
94 97
95 for (const auto& range : kPublicIPv6Ranges) { 98 for (const auto& range : kPublicIPv6Ranges) {
96 if (IPAddressPrefixCheck(ip_address, range.address_prefix, 99 if (IPAddressPrefixCheck(ip_address, range.address_prefix,
97 range.prefix_length_in_bits)) { 100 range.prefix_length_in_bits)) {
98 return false; 101 return false;
99 } 102 }
100 } 103 }
101 104
102 return true; 105 return true;
103 } 106 }
104 107
105 bool ParseIPLiteralToBytes(const base::StringPiece& ip_literal, 108 bool ParseIPLiteralToBytes(const base::StringPiece& ip_literal,
106 std::vector<uint8_t>* bytes) { 109 IPAddressBytes* bytes) {
107 // |ip_literal| could be either an IPv4 or an IPv6 literal. If it contains 110 // |ip_literal| could be either an IPv4 or an IPv6 literal. If it contains
108 // a colon however, it must be an IPv6 address. 111 // a colon however, it must be an IPv6 address.
109 if (ip_literal.find(':') != base::StringPiece::npos) { 112 if (ip_literal.find(':') != base::StringPiece::npos) {
110 // GURL expects IPv6 hostnames to be surrounded with brackets. 113 // GURL expects IPv6 hostnames to be surrounded with brackets.
111 std::string host_brackets = "["; 114 std::string host_brackets = "[";
112 ip_literal.AppendToString(&host_brackets); 115 ip_literal.AppendToString(&host_brackets);
113 host_brackets.push_back(']'); 116 host_brackets.push_back(']');
114 url::Component host_comp(0, host_brackets.size()); 117 url::Component host_comp(0, host_brackets.size());
115 118
116 // Try parsing the hostname as an IPv6 literal. 119 // Try parsing the hostname as an IPv6 literal.
117 bytes->resize(16); // 128 bits. 120 bytes->Resize(16); // 128 bits.
118 return url::IPv6AddressToNumber(host_brackets.data(), host_comp, 121 return url::IPv6AddressToNumber(host_brackets.data(), host_comp,
119 bytes->data()); 122 bytes->data());
120 } 123 }
121 124
122 // Otherwise the string is an IPv4 address. 125 // Otherwise the string is an IPv4 address.
123 bytes->resize(4); // 32 bits. 126 bytes->Resize(4); // 32 bits.
124 url::Component host_comp(0, ip_literal.size()); 127 url::Component host_comp(0, ip_literal.size());
125 int num_components; 128 int num_components;
126 url::CanonHostInfo::Family family = url::IPv4AddressToNumber( 129 url::CanonHostInfo::Family family = url::IPv4AddressToNumber(
127 ip_literal.data(), host_comp, bytes->data(), &num_components); 130 ip_literal.data(), host_comp, bytes->data(), &num_components);
128 return family == url::CanonHostInfo::IPV4; 131 return family == url::CanonHostInfo::IPV4;
129 } 132 }
130 133
131 } // namespace 134 } // namespace
132 135
133 namespace net { 136 IPAddressBytes::IPAddressBytes() : size_(0) {}
137
138 IPAddressBytes::IPAddressBytes(const uint8_t* data, size_t data_len)
139 : size_(data_len) {
140 Assign(data, data_len);
141 }
142
143 IPAddressBytes::~IPAddressBytes() {}
144 IPAddressBytes::IPAddressBytes(IPAddressBytes const& other) = default;
145
146 void IPAddressBytes::Assign(const uint8_t* data, size_t data_len) {
147 CHECK_GE(16u, data_len);
148 std::copy_n(data, data_len, bytes_.data());
eroman 2017/05/22 22:46:53 This is missing: size_ = data_len;
Ryan Hamilton 2017/05/23 04:39:28 *facepalm* Fixed and unit tests added.
149 }
150
151 bool IPAddressBytes::operator<(const IPAddressBytes& other) const {
152 if (size_ == other.size_)
153 return std::lexicographical_compare(begin(), end(), other.begin(),
154 other.end());
155 return size_ < other.size_;
156 }
157
158 bool IPAddressBytes::operator==(const IPAddressBytes& other) const {
159 return size_ == other.size_ && std::equal(begin(), end(), other.begin());
160 }
161
162 bool IPAddressBytes::operator!=(const IPAddressBytes& other) const {
163 return !(*this == other);
164 }
134 165
135 IPAddress::IPAddress() {} 166 IPAddress::IPAddress() {}
136 167
137 IPAddress::IPAddress(const std::vector<uint8_t>& address)
138 : ip_address_(address) {}
139
140 IPAddress::IPAddress(const IPAddress& other) = default; 168 IPAddress::IPAddress(const IPAddress& other) = default;
141 169
142 IPAddress::IPAddress(const uint8_t* address, size_t address_len) 170 IPAddress::IPAddress(const uint8_t* address, size_t address_len)
143 : ip_address_(address, address + address_len) {} 171 : ip_address_(address, address_len) {}
144 172
145 IPAddress::IPAddress(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3) { 173 IPAddress::IPAddress(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3) {
146 ip_address_.reserve(4);
147 ip_address_.push_back(b0); 174 ip_address_.push_back(b0);
148 ip_address_.push_back(b1); 175 ip_address_.push_back(b1);
149 ip_address_.push_back(b2); 176 ip_address_.push_back(b2);
150 ip_address_.push_back(b3); 177 ip_address_.push_back(b3);
151 } 178 }
152 179
153 IPAddress::IPAddress(uint8_t b0, 180 IPAddress::IPAddress(uint8_t b0,
154 uint8_t b1, 181 uint8_t b1,
155 uint8_t b2, 182 uint8_t b2,
156 uint8_t b3, 183 uint8_t b3,
157 uint8_t b4, 184 uint8_t b4,
158 uint8_t b5, 185 uint8_t b5,
159 uint8_t b6, 186 uint8_t b6,
160 uint8_t b7, 187 uint8_t b7,
161 uint8_t b8, 188 uint8_t b8,
162 uint8_t b9, 189 uint8_t b9,
163 uint8_t b10, 190 uint8_t b10,
164 uint8_t b11, 191 uint8_t b11,
165 uint8_t b12, 192 uint8_t b12,
166 uint8_t b13, 193 uint8_t b13,
167 uint8_t b14, 194 uint8_t b14,
168 uint8_t b15) { 195 uint8_t b15) {
169 const uint8_t address[] = {b0, b1, b2, b3, b4, b5, b6, b7, 196 ip_address_.push_back(b0);
170 b8, b9, b10, b11, b12, b13, b14, b15}; 197 ip_address_.push_back(b1);
171 ip_address_ = std::vector<uint8_t>(std::begin(address), std::end(address)); 198 ip_address_.push_back(b2);
199 ip_address_.push_back(b3);
200 ip_address_.push_back(b4);
201 ip_address_.push_back(b5);
202 ip_address_.push_back(b6);
203 ip_address_.push_back(b7);
204 ip_address_.push_back(b8);
205 ip_address_.push_back(b9);
206 ip_address_.push_back(b10);
207 ip_address_.push_back(b11);
208 ip_address_.push_back(b12);
209 ip_address_.push_back(b13);
210 ip_address_.push_back(b14);
211 ip_address_.push_back(b15);
172 } 212 }
173 213
174 IPAddress::~IPAddress() {} 214 IPAddress::~IPAddress() {}
175 215
176 bool IPAddress::IsIPv4() const { 216 bool IPAddress::IsIPv4() const {
177 return ip_address_.size() == kIPv4AddressSize; 217 return ip_address_.size() == kIPv4AddressSize;
178 } 218 }
179 219
180 bool IPAddress::IsIPv6() const { 220 bool IPAddress::IsIPv6() const {
181 return ip_address_.size() == kIPv6AddressSize; 221 return ip_address_.size() == kIPv6AddressSize;
(...skipping 19 matching lines...) Expand all
201 } 241 }
202 242
203 return !empty(); 243 return !empty();
204 } 244 }
205 245
206 bool IPAddress::IsIPv4MappedIPv6() const { 246 bool IPAddress::IsIPv4MappedIPv6() const {
207 return IsIPv6() && IPAddressStartsWith(*this, kIPv4MappedPrefix); 247 return IsIPv6() && IPAddressStartsWith(*this, kIPv4MappedPrefix);
208 } 248 }
209 249
210 bool IPAddress::AssignFromIPLiteral(const base::StringPiece& ip_literal) { 250 bool IPAddress::AssignFromIPLiteral(const base::StringPiece& ip_literal) {
211 std::vector<uint8_t> number; 251 IPAddressBytes number;
212 252
253 // TODO(rch): change the contract so ip_address_ is cleared on failure,
254 // to avoid needing this temporary at all.
213 if (!ParseIPLiteralToBytes(ip_literal, &number)) 255 if (!ParseIPLiteralToBytes(ip_literal, &number))
214 return false; 256 return false;
215 257
216 std::swap(number, ip_address_); 258 ip_address_ = number;
217 return true; 259 return true;
218 } 260 }
219 261
262 std::vector<uint8_t> IPAddress::CopyBytesToVector() const {
263 return std::vector<uint8_t>(ip_address_.begin(), ip_address_.end());
264 }
265
220 // static 266 // static
221 IPAddress IPAddress::IPv4Localhost() { 267 IPAddress IPAddress::IPv4Localhost() {
222 static const uint8_t kLocalhostIPv4[] = {127, 0, 0, 1}; 268 static const uint8_t kLocalhostIPv4[] = {127, 0, 0, 1};
223 return IPAddress(kLocalhostIPv4); 269 return IPAddress(kLocalhostIPv4);
224 } 270 }
225 271
226 // static 272 // static
227 IPAddress IPAddress::IPv6Localhost() { 273 IPAddress IPAddress::IPv6Localhost() {
228 static const uint8_t kLocalhostIPv6[] = {0, 0, 0, 0, 0, 0, 0, 0, 274 static const uint8_t kLocalhostIPv6[] = {0, 0, 0, 0, 0, 0, 0, 0,
229 0, 0, 0, 0, 0, 0, 0, 1}; 275 0, 0, 0, 0, 0, 0, 0, 1};
230 return IPAddress(kLocalhostIPv6); 276 return IPAddress(kLocalhostIPv6);
231 } 277 }
232 278
233 // static 279 // static
234 IPAddress IPAddress::AllZeros(size_t num_zero_bytes) { 280 IPAddress IPAddress::AllZeros(size_t num_zero_bytes) {
235 return IPAddress(std::vector<uint8_t>(num_zero_bytes)); 281 CHECK_LE(num_zero_bytes, 16u);
282 IPAddress result;
283 for (size_t i = 0; i < num_zero_bytes; ++i)
284 result.ip_address_.push_back(0u);
285 return result;
236 } 286 }
237 287
238 // static 288 // static
239 IPAddress IPAddress::IPv4AllZeros() { 289 IPAddress IPAddress::IPv4AllZeros() {
240 return AllZeros(kIPv4AddressSize); 290 return AllZeros(kIPv4AddressSize);
241 } 291 }
242 292
243 // static 293 // static
244 IPAddress IPAddress::IPv6AllZeros() { 294 IPAddress IPAddress::IPv6AllZeros() {
245 return AllZeros(kIPv6AddressSize); 295 return AllZeros(kIPv6AddressSize);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 340
291 std::string IPAddressToPackedString(const IPAddress& address) { 341 std::string IPAddressToPackedString(const IPAddress& address) {
292 return std::string(reinterpret_cast<const char*>(address.bytes().data()), 342 return std::string(reinterpret_cast<const char*>(address.bytes().data()),
293 address.size()); 343 address.size());
294 } 344 }
295 345
296 IPAddress ConvertIPv4ToIPv4MappedIPv6(const IPAddress& address) { 346 IPAddress ConvertIPv4ToIPv4MappedIPv6(const IPAddress& address) {
297 DCHECK(address.IsIPv4()); 347 DCHECK(address.IsIPv4());
298 // IPv4-mapped addresses are formed by: 348 // IPv4-mapped addresses are formed by:
299 // <80 bits of zeros> + <16 bits of ones> + <32-bit IPv4 address>. 349 // <80 bits of zeros> + <16 bits of ones> + <32-bit IPv4 address>.
300 std::vector<uint8_t> bytes; 350 base::StackVector<uint8_t, 16> bytes;
301 bytes.reserve(16); 351 bytes->insert(bytes->end(), std::begin(kIPv4MappedPrefix),
302 bytes.insert(bytes.end(), std::begin(kIPv4MappedPrefix), 352 std::end(kIPv4MappedPrefix));
303 std::end(kIPv4MappedPrefix)); 353 bytes->insert(bytes->end(), address.bytes().begin(), address.bytes().end());
304 bytes.insert(bytes.end(), address.bytes().begin(), address.bytes().end()); 354 return IPAddress(bytes->data(), bytes->size());
305 return IPAddress(bytes);
306 } 355 }
307 356
308 IPAddress ConvertIPv4MappedIPv6ToIPv4(const IPAddress& address) { 357 IPAddress ConvertIPv4MappedIPv6ToIPv4(const IPAddress& address) {
309 DCHECK(address.IsIPv4MappedIPv6()); 358 DCHECK(address.IsIPv4MappedIPv6());
310 359
311 return IPAddress(std::vector<uint8_t>( 360 base::StackVector<uint8_t, 16> bytes;
312 address.bytes().begin() + arraysize(kIPv4MappedPrefix), 361 bytes->insert(bytes->end(),
313 address.bytes().end())); 362 address.bytes().begin() + arraysize(kIPv4MappedPrefix),
363 address.bytes().end());
364 return IPAddress(bytes->data(), bytes->size());
314 } 365 }
315 366
316 bool IPAddressMatchesPrefix(const IPAddress& ip_address, 367 bool IPAddressMatchesPrefix(const IPAddress& ip_address,
317 const IPAddress& ip_prefix, 368 const IPAddress& ip_prefix,
318 size_t prefix_length_in_bits) { 369 size_t prefix_length_in_bits) {
319 // Both the input IP address and the prefix IP address should be either IPv4 370 // Both the input IP address and the prefix IP address should be either IPv4
320 // or IPv6. 371 // or IPv6.
321 DCHECK(ip_address.IsValid()); 372 DCHECK(ip_address.IsValid());
322 DCHECK(ip_prefix.IsValid()); 373 DCHECK(ip_prefix.IsValid());
323 374
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
391 if (diff & (1 << (CHAR_BIT - 1))) 442 if (diff & (1 << (CHAR_BIT - 1)))
392 return i * CHAR_BIT + j; 443 return i * CHAR_BIT + j;
393 diff <<= 1; 444 diff <<= 1;
394 } 445 }
395 NOTREACHED(); 446 NOTREACHED();
396 } 447 }
397 return a1.size() * CHAR_BIT; 448 return a1.size() * CHAR_BIT;
398 } 449 }
399 450
400 unsigned MaskPrefixLength(const IPAddress& mask) { 451 unsigned MaskPrefixLength(const IPAddress& mask) {
401 std::vector<uint8_t> all_ones(mask.size(), 0xFF); 452 base::StackVector<uint8_t, 16> all_ones;
402 return CommonPrefixLength(mask, IPAddress(all_ones)); 453 all_ones->resize(mask.size(), 0xFF);
454 return CommonPrefixLength(mask,
455 IPAddress(all_ones->data(), all_ones->size()));
403 } 456 }
404 457
405 } // namespace net 458 } // namespace net
OLDNEW
« no previous file with comments | « net/base/ip_address.h ('k') | net/base/ip_address_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698