Add a new class InterfaceAddress inherited from IPAddress to keep track of IPv6 Address flags.

Skeleton put in place in Network::GetFilterIPs() which will be used to
filter addresses

BUG=3773
R=jiayl@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/23439004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@7126 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
guoweis@webrtc.org 2014-09-09 23:42:40 +00:00
parent 87ff9c8efa
commit fa603981f2
5 changed files with 156 additions and 26 deletions

View File

@ -186,6 +186,30 @@ void IPAddress::set_strip_sensitive(bool enable) {
strip_sensitive_ = enable;
}
bool InterfaceAddress::operator==(const InterfaceAddress &other) const {
return ipv6_flags_ == other.ipv6_flags() &&
static_cast<const IPAddress&>(*this) == other;
}
bool InterfaceAddress::operator!=(const InterfaceAddress &other) const {
return !((*this) == other);
}
const InterfaceAddress& InterfaceAddress::operator=(
const InterfaceAddress& other) {
ipv6_flags_ = other.ipv6_flags_;
static_cast<IPAddress&>(*this) = other;
return *this;
}
std::ostream& operator<<(std::ostream& os, const InterfaceAddress& ip) {
os << static_cast<const IPAddress&>(ip);
if (ip.family() == AF_INET6)
os << "|flags:0x" << std::hex << ip.ipv6_flags();
return os;
}
bool IsPrivateV4(uint32 ip_in_host_order) {
return ((ip_in_host_order >> 24) == 127) ||
@ -235,6 +259,17 @@ bool IPFromString(const std::string& str, IPAddress* out) {
return true;
}
bool IPFromString(const std::string& str, int flags,
InterfaceAddress* out) {
IPAddress ip;
if (!IPFromString(str, &ip)) {
return false;
}
*out = InterfaceAddress(ip, flags);
return true;
}
bool IPIsAny(const IPAddress& ip) {
switch (ip.family()) {
case AF_INET:

View File

@ -33,6 +33,19 @@
namespace rtc {
enum IPv6AddressFlag {
IPV6_ADDRESS_FLAG_NONE = 0x00,
// Temporary address is dynamic by nature and will not carry MAC
// address.
IPV6_ADDRESS_FLAG_TEMPORARY = 1 << 0,
// Temporary address could become deprecated once the preferred
// lifetime is reached. It is still valid but just shouldn't be used
// to create new connection.
IPV6_ADDRESS_FLAG_DEPRECATED = 1 << 1,
};
// Version-agnostic IP address class, wraps a union of in_addr and in6_addr.
class IPAddress {
public:
@ -40,12 +53,12 @@ class IPAddress {
::memset(&u_, 0, sizeof(u_));
}
explicit IPAddress(const in_addr &ip4) : family_(AF_INET) {
explicit IPAddress(const in_addr& ip4) : family_(AF_INET) {
memset(&u_, 0, sizeof(u_));
u_.ip4 = ip4;
}
explicit IPAddress(const in6_addr &ip6) : family_(AF_INET6) {
explicit IPAddress(const in6_addr& ip6) : family_(AF_INET6) {
u_.ip6 = ip6;
}
@ -54,22 +67,22 @@ class IPAddress {
u_.ip4.s_addr = HostToNetwork32(ip_in_host_byte_order);
}
IPAddress(const IPAddress &other) : family_(other.family_) {
IPAddress(const IPAddress& other) : family_(other.family_) {
::memcpy(&u_, &other.u_, sizeof(u_));
}
~IPAddress() {}
virtual ~IPAddress() {}
const IPAddress & operator=(const IPAddress &other) {
const IPAddress & operator=(const IPAddress& other) {
family_ = other.family_;
::memcpy(&u_, &other.u_, sizeof(u_));
return *this;
}
bool operator==(const IPAddress &other) const;
bool operator!=(const IPAddress &other) const;
bool operator <(const IPAddress &other) const;
bool operator >(const IPAddress &other) const;
bool operator==(const IPAddress& other) const;
bool operator!=(const IPAddress& other) const;
bool operator <(const IPAddress& other) const;
bool operator >(const IPAddress& other) const;
friend std::ostream& operator<<(std::ostream& os, const IPAddress& addr);
int family() const { return family_; }
@ -108,8 +121,38 @@ class IPAddress {
static bool strip_sensitive_;
};
// IP class which could represent IPv6 address flags which is only
// meaningful in IPv6 case.
class InterfaceAddress : public IPAddress {
public:
InterfaceAddress() : ipv6_flags_(IPV6_ADDRESS_FLAG_NONE) {}
InterfaceAddress(IPAddress ip)
: IPAddress(ip), ipv6_flags_(IPV6_ADDRESS_FLAG_NONE) {}
InterfaceAddress(IPAddress addr, int ipv6_flags)
: IPAddress(addr), ipv6_flags_(ipv6_flags) {}
InterfaceAddress(const in6_addr& ip6, int ipv6_flags)
: IPAddress(ip6), ipv6_flags_(ipv6_flags) {}
const InterfaceAddress & operator=(const InterfaceAddress& other);
bool operator==(const InterfaceAddress& other) const;
bool operator!=(const InterfaceAddress& other) const;
int ipv6_flags() const { return ipv6_flags_; }
friend std::ostream& operator<<(std::ostream& os,
const InterfaceAddress& addr);
private:
int ipv6_flags_;
};
bool IPFromAddrInfo(struct addrinfo* info, IPAddress* out);
bool IPFromString(const std::string& str, IPAddress* out);
bool IPFromString(const std::string& str, int flags,
InterfaceAddress* out);
bool IPIsAny(const IPAddress& ip);
bool IPIsLoopback(const IPAddress& ip);
bool IPIsPrivate(const IPAddress& ip);

View File

@ -856,4 +856,41 @@ TEST(IPAddressTest, TestToSensitiveString) {
IPAddress::set_strip_sensitive(false);
}
TEST(IPAddressTest, TestInterfaceAddress) {
in6_addr addr;
InterfaceAddress addr1(kIPv6PublicAddr,
IPV6_ADDRESS_FLAG_TEMPORARY);
EXPECT_EQ(addr1.ipv6_flags(), IPV6_ADDRESS_FLAG_TEMPORARY);
EXPECT_EQ(addr1.family(), AF_INET6);
addr = addr1.ipv6_address();
EXPECT_TRUE(IN6_ARE_ADDR_EQUAL(&addr, &kIPv6PublicAddr));
InterfaceAddress addr2 = addr1;
EXPECT_EQ(addr1, addr2);
EXPECT_EQ(addr2.ipv6_flags(), IPV6_ADDRESS_FLAG_TEMPORARY);
addr = addr2.ipv6_address();
EXPECT_TRUE(IN6_ARE_ADDR_EQUAL(&addr, &kIPv6PublicAddr));
InterfaceAddress addr3(addr1);
EXPECT_EQ(addr1, addr3);
EXPECT_EQ(addr3.ipv6_flags(), IPV6_ADDRESS_FLAG_TEMPORARY);
addr = addr3.ipv6_address();
EXPECT_TRUE(IN6_ARE_ADDR_EQUAL(&addr, &kIPv6PublicAddr));
InterfaceAddress addr4(kIPv6PublicAddr,
IPV6_ADDRESS_FLAG_DEPRECATED);
EXPECT_NE(addr1, addr4);
// When you compare them as IPAddress, since operator==
// is not virtual, it'll be equal.
IPAddress *paddr1 = &addr1;
IPAddress *paddr4 = &addr4;
EXPECT_EQ(*paddr1, *paddr4);
InterfaceAddress addr5(kIPv6LinkLocalAddr,
IPV6_ADDRESS_FLAG_TEMPORARY);
EXPECT_NE(addr1, addr5);
}
} // namespace rtc

View File

@ -67,7 +67,7 @@ const int kHighestNetworkPreference = 127;
typedef struct {
Network* net;
std::vector<IPAddress> ips;
std::vector<InterfaceAddress> ips;
} AddressList;
bool CompareNetworks(const Network* a, const Network* b) {
@ -176,9 +176,9 @@ void NetworkManagerBase::MergeNetworkList(const NetworkList& new_networks,
consolidated_address_list[key] = addrlist;
might_add_to_merged_list = true;
}
const std::vector<IPAddress>& addresses = list[i]->GetIPs();
const std::vector<InterfaceAddress>& addresses = list[i]->GetIPs();
AddressList& current_list = consolidated_address_list[key];
for (std::vector<IPAddress>::const_iterator it = addresses.begin();
for (std::vector<InterfaceAddress>::const_iterator it = addresses.begin();
it != addresses.end();
++it) {
current_list.ips.push_back(*it);
@ -648,15 +648,15 @@ std::string Network::ToString() const {
// Sets the addresses of this network. Returns true if the address set changed.
// Change detection is short circuited if the changed argument is true.
bool Network::SetIPs(const std::vector<IPAddress>& ips, bool changed) {
bool Network::SetIPs(const std::vector<InterfaceAddress>& ips, bool changed) {
changed = changed || ips.size() != ips_.size();
// Detect changes with a nested loop; n-squared but we expect on the order
// of 2-3 addresses per network.
for (std::vector<IPAddress>::const_iterator it = ips.begin();
for (std::vector<InterfaceAddress>::const_iterator it = ips.begin();
!changed && it != ips.end();
++it) {
bool found = false;
for (std::vector<IPAddress>::iterator inner_it = ips_.begin();
for (std::vector<InterfaceAddress>::iterator inner_it = ips_.begin();
!found && inner_it != ips_.end();
++inner_it) {
if (*it == *inner_it) {
@ -669,4 +669,14 @@ bool Network::SetIPs(const std::vector<IPAddress>& ips, bool changed) {
return changed;
}
// TODO(guoweis): will change the name to a more meaningful name as
// this is not simply return the first address once the logic of ipv6
// address selection is complete.
IPAddress Network::ip() const {
if (ips_.size() == 0) {
return IPAddress();
}
return static_cast<IPAddress>(ips_.at(0));
}
} // namespace rtc

View File

@ -189,22 +189,27 @@ class Network {
// Returns the Network's current idea of the 'best' IP it has.
// 'Best' currently means the first one added.
// TODO: We should be preferring temporary addresses.
// Returns an unset IP if this network has no active addresses.
IPAddress ip() const {
if (ips_.size() == 0) {
return IPAddress();
}
return ips_.at(0);
}
// Here is the rule on how we mark the IPv6 address as ignorable for webrtc.
// 1) return all global temporary dynamic and non-deprecrated ones.
// 2) if #1 not available, return global dynamic ones.
// 3) if #2 not available, return global ones.
// 4) if #3 not available, use ULA ipv6 as last resort.
// Note that when not specifying any flag, it's treated as case global
// dynamic IPv6 address
// TODO(guoweis): will change the name to a more meaningful name as
// this is not simply return the first address once the logic of ipv6
// address selection is complete.
IPAddress ip() const;
// Adds an active IP address to this network. Does not check for duplicates.
void AddIP(const IPAddress& ip) { ips_.push_back(ip); }
void AddIP(const InterfaceAddress& ip) { ips_.push_back(ip); }
// Sets the network's IP address list. Returns true if new IP addresses were
// detected. Passing true to already_changed skips this check.
bool SetIPs(const std::vector<IPAddress>& ips, bool already_changed);
bool SetIPs(const std::vector<InterfaceAddress>& ips, bool already_changed);
// Get the list of IP Addresses associated with this network.
const std::vector<IPAddress>& GetIPs() { return ips_;}
const std::vector<InterfaceAddress>& GetIPs() const { return ips_;}
// Clear the network's list of addresses.
void ClearIPs() { ips_.clear(); }
@ -231,7 +236,7 @@ class Network {
IPAddress prefix_;
int prefix_length_;
std::string key_;
std::vector<IPAddress> ips_;
std::vector<InterfaceAddress> ips_;
int scope_id_;
bool ignored_;
AdapterType type_;