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:
parent
87ff9c8efa
commit
fa603981f2
@ -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:
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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_;
|
||||
|
Loading…
x
Reference in New Issue
Block a user