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
diff --git a/webrtc/base/ipaddress.cc b/webrtc/base/ipaddress.cc
index 4441e16..4f311d5 100644
--- a/webrtc/base/ipaddress.cc
+++ b/webrtc/base/ipaddress.cc
@@ -186,6 +186,30 @@
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 @@
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:
diff --git a/webrtc/base/ipaddress.h b/webrtc/base/ipaddress.h
index e7d649a..12db5c5 100644
--- a/webrtc/base/ipaddress.h
+++ b/webrtc/base/ipaddress.h
@@ -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 @@
::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 @@
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 @@
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);
diff --git a/webrtc/base/ipaddress_unittest.cc b/webrtc/base/ipaddress_unittest.cc
index 657595f..e847335 100644
--- a/webrtc/base/ipaddress_unittest.cc
+++ b/webrtc/base/ipaddress_unittest.cc
@@ -856,4 +856,41 @@
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
diff --git a/webrtc/base/network.cc b/webrtc/base/network.cc
index 686de97..8c84c2e 100644
--- a/webrtc/base/network.cc
+++ b/webrtc/base/network.cc
@@ -67,7 +67,7 @@
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 @@
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 @@
// 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 @@
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
diff --git a/webrtc/base/network.h b/webrtc/base/network.h
index 855b1b7..4cdd4d8 100644
--- a/webrtc/base/network.h
+++ b/webrtc/base/network.h
@@ -189,22 +189,27 @@
// 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 @@
IPAddress prefix_;
int prefix_length_;
std::string key_;
- std::vector<IPAddress> ips_;
+ std::vector<InterfaceAddress> ips_;
int scope_id_;
bool ignored_;
AdapterType type_;