Commit 04e01ee1 authored by martijn's avatar martijn Committed by Commit bot

This CL adds an IPAddress class intended to replace the current...

This CL adds an IPAddress class intended to replace the current IPAddressNumber typedef. The class wraps a std::vector<uint8_t> containing the actual IP address and exposes a couple of helper methods. This CL only introduces the new class and related tests.

BUG=496258

Review URL: https://codereview.chromium.org/1408803010

Cr-Commit-Position: refs/heads/master@{#363046}
parent 9eb16f68
// Copyright (c) 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/base/ip_address.h"
#include "net/base/ip_address_number.h"
#include "url/gurl.h"
#include "url/url_canon_ip.h"
namespace net {
const size_t IPAddress::kIPv4AddressSize = 4;
const size_t IPAddress::kIPv6AddressSize = 16;
IPAddress::IPAddress() {}
IPAddress::~IPAddress() {}
IPAddress::IPAddress(const uint8_t* address, size_t address_len)
: ip_address_(address, address + address_len) {}
bool IPAddress::IsIPv4() const {
return ip_address_.size() == kIPv4AddressSize;
}
bool IPAddress::IsIPv6() const {
return ip_address_.size() == kIPv6AddressSize;
}
bool IPAddress::IsReserved() const {
return IsIPAddressReserved(ip_address_);
}
bool IPAddress::IsIPv4Mapped() const {
return net::IsIPv4Mapped(ip_address_);
}
std::string IPAddress::ToString() const {
return IPAddressToString(ip_address_);
}
// static
bool IPAddress::FromIPLiteral(const base::StringPiece& ip_literal,
IPAddress* ip_address) {
std::vector<uint8_t> number;
if (!ParseIPLiteralToNumber(ip_literal, &number))
return false;
std::swap(number, ip_address->ip_address_);
return true;
}
bool IPAddress::operator==(const IPAddress& that) const {
return ip_address_ == that.ip_address_;
}
bool IPAddress::operator<(const IPAddress& that) const {
// Sort IPv4 before IPv6.
if (ip_address_.size() != that.ip_address_.size()) {
return ip_address_.size() < that.ip_address_.size();
}
return ip_address_ < that.ip_address_;
}
} // namespace net
// Copyright (c) 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_BASE_IP_ADDRESS_NET_H_
#define NET_BASE_IP_ADDRESS_NET_H_
#include <vector>
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/strings/string_piece.h"
#include "net/base/net_export.h"
namespace net {
class NET_EXPORT IPAddress {
public:
static const size_t kIPv4AddressSize;
static const size_t kIPv6AddressSize;
// Creates a zero-sized, invalid address.
IPAddress();
// Copies the input address to |ip_address_|. The input is expected to be in
// network byte order.
IPAddress(const uint8_t* address, size_t address_len);
~IPAddress();
// Returns true if the IP has |kIPv4AddressSize| elements.
bool IsIPv4() const;
// Returns true if the IP has |kIPv6AddressSize| elements.
bool IsIPv6() const;
// Returns true if an IP address hostname is in a range reserved by the IANA.
// Works with both IPv4 and IPv6 addresses, and only compares against a given
// protocols's reserved ranges.
bool IsReserved() const;
// Returns true if |ip_address_| is an IPv4-mapped IPv6 address.
bool IsIPv4Mapped() const;
// The size in bytes of |ip_address_|.
size_t size() const { return ip_address_.size(); }
// Returns the canonical string representation of an IP address.
// For example: "192.168.0.1" or "::1". The IP address must be
// valid, calling this on an invalid address will result in a crash.
std::string ToString() const;
// Parses an IP address literal (either IPv4 or IPv6) to its numeric value.
// Returns true on success and fills |ip_address| with the numeric value.
static bool FromIPLiteral(const base::StringPiece& ip_literal,
IPAddress* ip_address) WARN_UNUSED_RESULT;
// Returns the underlying byte vector.
const std::vector<uint8_t>& bytes() const { return ip_address_; };
bool operator==(const IPAddress& that) const;
bool operator<(const IPAddress& that) const;
private:
// IPv4 addresses will have length kIPv4AddressSize, whereas IPv6 address
// will have length kIPv6AddressSize.
std::vector<uint8_t> ip_address_;
};
} // namespace net
#endif // NET_BASE_IP_ADDRESS_NET_H_
...@@ -19,6 +19,10 @@ namespace net { ...@@ -19,6 +19,10 @@ namespace net {
// network byte ordering. // network byte ordering.
// //
// IPv4 addresses will have length 4, whereas IPv6 address will have length 16. // IPv4 addresses will have length 4, whereas IPv6 address will have length 16.
//
// TODO(Martijnc): Remove the IPAddressNumber typedef. New code should use
// IPAddress instead and existing code should be switched over.
// https://crbug.com/496258
typedef std::vector<unsigned char> typedef std::vector<unsigned char>
IPAddressNumber; // This is also duplicated in net_util.h IPAddressNumber; // This is also duplicated in net_util.h
typedef std::vector<IPAddressNumber> IPAddressList; typedef std::vector<IPAddressNumber> IPAddressList;
......
// Copyright (c) 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/base/ip_address.h"
#include <vector>
#include "base/strings/string_number_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
namespace {
// Helper to stringize an IP number (used to define expectations).
std::string DumpIPAddress(const IPAddress& v) {
std::string out;
for (size_t i = 0; i < v.bytes().size(); ++i) {
if (i != 0)
out.append(",");
out.append(base::UintToString(v.bytes()[i]));
}
return out;
}
template <size_t N>
IPAddress ArrayToIPAdress(const uint8_t(&address)[N]) {
return IPAddress(address, N);
}
TEST(IPAddressTest, IsIPVersion) {
uint8_t addr1[4] = {192, 168, 0, 1};
IPAddress ip_address1 = ArrayToIPAdress(addr1);
EXPECT_TRUE(ip_address1.IsIPv4());
EXPECT_FALSE(ip_address1.IsIPv6());
uint8_t addr2[16] = {0xFE, 0xDC, 0xBA, 0x98};
IPAddress ip_address2 = ArrayToIPAdress(addr2);
EXPECT_TRUE(ip_address2.IsIPv6());
EXPECT_FALSE(ip_address2.IsIPv4());
IPAddress ip_address3 = IPAddress();
EXPECT_FALSE(ip_address3.IsIPv6());
EXPECT_FALSE(ip_address3.IsIPv4());
}
TEST(IPAddressTest, ToString) {
uint8_t addr1[4] = {0, 0, 0, 0};
IPAddress ip_address1 = ArrayToIPAdress(addr1);
EXPECT_EQ("0.0.0.0", ip_address1.ToString());
uint8_t addr2[4] = {192, 168, 0, 1};
IPAddress ip_address2 = ArrayToIPAdress(addr2);
EXPECT_EQ("192.168.0.1", ip_address2.ToString());
uint8_t addr3[16] = {0xFE, 0xDC, 0xBA, 0x98};
IPAddress ip_address3 = ArrayToIPAdress(addr3);
EXPECT_EQ("fedc:ba98::", ip_address3.ToString());
}
// Test that invalid IP literals fail to parse.
TEST(IPAddressTest, FromIPLiteral_FailParse) {
IPAddress address;
EXPECT_FALSE(IPAddress::FromIPLiteral("bad value", &address));
EXPECT_FALSE(IPAddress::FromIPLiteral("bad:value", &address));
EXPECT_FALSE(IPAddress::FromIPLiteral(std::string(), &address));
EXPECT_FALSE(IPAddress::FromIPLiteral("192.168.0.1:30", &address));
EXPECT_FALSE(IPAddress::FromIPLiteral(" 192.168.0.1 ", &address));
EXPECT_FALSE(IPAddress::FromIPLiteral("[::1]", &address));
}
// Test parsing an IPv4 literal.
TEST(IPAddressTest, FromIPLiteral_IPv4) {
IPAddress address;
EXPECT_TRUE(IPAddress::FromIPLiteral("192.168.0.1", &address));
EXPECT_EQ("192,168,0,1", DumpIPAddress(address));
EXPECT_EQ("192.168.0.1", address.ToString());
}
// Test parsing an IPv6 literal.
TEST(IPAddressTest, FromIPLiteral_IPv6) {
IPAddress address;
EXPECT_TRUE(IPAddress::FromIPLiteral("1:abcd::3:4:ff", &address));
EXPECT_EQ("0,1,171,205,0,0,0,0,0,0,0,3,0,4,0,255", DumpIPAddress(address));
EXPECT_EQ("1:abcd::3:4:ff", address.ToString());
}
TEST(IPAddressTest, IsIPv4Mapped) {
IPAddress ipv4_address;
EXPECT_TRUE(IPAddress::FromIPLiteral("192.168.0.1", &ipv4_address));
EXPECT_FALSE(ipv4_address.IsIPv4Mapped());
IPAddress ipv6_address;
EXPECT_TRUE(IPAddress::FromIPLiteral("::1", &ipv4_address));
EXPECT_FALSE(ipv6_address.IsIPv4Mapped());
IPAddress ipv4mapped_address;
EXPECT_TRUE(IPAddress::FromIPLiteral("::ffff:0101:1", &ipv4mapped_address));
EXPECT_TRUE(ipv4mapped_address.IsIPv4Mapped());
}
TEST(IPAddressTest, IsEqual) {
IPAddress ip_address1;
EXPECT_TRUE(IPAddress::FromIPLiteral("127.0.0.1", &ip_address1));
IPAddress ip_address2;
EXPECT_TRUE(IPAddress::FromIPLiteral("2001:db8:0::42", &ip_address2));
IPAddress ip_address3;
EXPECT_TRUE(IPAddress::FromIPLiteral("127.0.0.1", &ip_address3));
EXPECT_FALSE(ip_address1 == ip_address2);
EXPECT_TRUE(ip_address1 == ip_address3);
}
TEST(IPAddressTest, LessThan) {
// IPv4 vs IPv6
IPAddress ip_address1;
EXPECT_TRUE(IPAddress::FromIPLiteral("127.0.0.1", &ip_address1));
IPAddress ip_address2;
EXPECT_TRUE(IPAddress::FromIPLiteral("2001:db8:0::42", &ip_address2));
EXPECT_TRUE(ip_address1 < ip_address2);
EXPECT_FALSE(ip_address2 < ip_address1);
// Compare equivalent addresses.
IPAddress ip_address3;
EXPECT_TRUE(IPAddress::FromIPLiteral("127.0.0.1", &ip_address3));
EXPECT_FALSE(ip_address1 < ip_address3);
EXPECT_FALSE(ip_address3 < ip_address1);
}
} // anonymous namespace
} // namespace net
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
'base/io_buffer.h', 'base/io_buffer.h',
'base/ip_address_number.cc', 'base/ip_address_number.cc',
'base/ip_address_number.h', 'base/ip_address_number.h',
'base/ip_address.cc',
'base/ip_address.h',
'base/ip_endpoint.cc', 'base/ip_endpoint.cc',
'base/ip_endpoint.h', 'base/ip_endpoint.h',
'base/load_timing_info.cc', 'base/load_timing_info.cc',
...@@ -1290,6 +1292,7 @@ ...@@ -1290,6 +1292,7 @@
'base/host_port_pair_unittest.cc', 'base/host_port_pair_unittest.cc',
'base/int128_unittest.cc', 'base/int128_unittest.cc',
'base/ip_address_number_unittest.cc', 'base/ip_address_number_unittest.cc',
'base/ip_address_unittest.cc',
'base/ip_endpoint_unittest.cc', 'base/ip_endpoint_unittest.cc',
'base/ip_pattern_unittest.cc', 'base/ip_pattern_unittest.cc',
'base/keygen_handler_unittest.cc', 'base/keygen_handler_unittest.cc',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment