Home | History | Annotate | Download | only in base
      1 /*
      2  *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #ifdef HAVE_CONFIG_H
     12 #include "config.h"
     13 #endif
     14 
     15 #include "webrtc/base/network.h"
     16 
     17 #if defined(WEBRTC_POSIX)
     18 // linux/if.h can't be included at the same time as the posix sys/if.h, and
     19 // it's transitively required by linux/route.h, so include that version on
     20 // linux instead of the standard posix one.
     21 #if defined(WEBRTC_LINUX)
     22 #include <linux/if.h>
     23 #include <linux/route.h>
     24 #elif !defined(__native_client__)
     25 #include <net/if.h>
     26 #endif
     27 #include <sys/socket.h>
     28 #include <sys/utsname.h>
     29 #include <sys/ioctl.h>
     30 #include <unistd.h>
     31 #include <errno.h>
     32 
     33 #if defined(WEBRTC_ANDROID)
     34 #include "webrtc/base/ifaddrs-android.h"
     35 #elif !defined(__native_client__)
     36 #include <ifaddrs.h>
     37 #endif
     38 
     39 #endif  // WEBRTC_POSIX
     40 
     41 #if defined(WEBRTC_WIN)
     42 #include "webrtc/base/win32.h"
     43 #include <Iphlpapi.h>
     44 #endif
     45 
     46 #include <stdio.h>
     47 
     48 #include <algorithm>
     49 
     50 #include "webrtc/base/logging.h"
     51 #include "webrtc/base/scoped_ptr.h"
     52 #include "webrtc/base/socket.h"  // includes something that makes windows happy
     53 #include "webrtc/base/stream.h"
     54 #include "webrtc/base/stringencode.h"
     55 #include "webrtc/base/thread.h"
     56 
     57 namespace rtc {
     58 namespace {
     59 
     60 const uint32 kUpdateNetworksMessage = 1;
     61 const uint32 kSignalNetworksMessage = 2;
     62 
     63 // Fetch list of networks every two seconds.
     64 const int kNetworksUpdateIntervalMs = 2000;
     65 
     66 const int kHighestNetworkPreference = 127;
     67 
     68 typedef struct {
     69   Network* net;
     70   std::vector<InterfaceAddress> ips;
     71 } AddressList;
     72 
     73 bool CompareNetworks(const Network* a, const Network* b) {
     74   if (a->prefix_length() == b->prefix_length()) {
     75     if (a->name() == b->name()) {
     76       return a->prefix() < b->prefix();
     77     }
     78   }
     79   return a->name() < b->name();
     80 }
     81 
     82 bool SortNetworks(const Network* a, const Network* b) {
     83   // Network types will be preferred above everything else while sorting
     84   // Networks.
     85 
     86   // Networks are sorted first by type.
     87   if (a->type() != b->type()) {
     88     return a->type() < b->type();
     89   }
     90 
     91   IPAddress ip_a = a->GetBestIP();
     92   IPAddress ip_b = b->GetBestIP();
     93 
     94   // After type, networks are sorted by IP address precedence values
     95   // from RFC 3484-bis
     96   if (IPAddressPrecedence(ip_a) != IPAddressPrecedence(ip_b)) {
     97     return IPAddressPrecedence(ip_a) > IPAddressPrecedence(ip_b);
     98   }
     99 
    100   // TODO(mallinath) - Add VPN and Link speed conditions while sorting.
    101 
    102   // Networks are sorted last by key.
    103   return a->key() > b->key();
    104 }
    105 
    106 std::string AdapterTypeToString(AdapterType type) {
    107   switch (type) {
    108     case ADAPTER_TYPE_UNKNOWN:
    109       return "Unknown";
    110     case ADAPTER_TYPE_ETHERNET:
    111       return "Ethernet";
    112     case ADAPTER_TYPE_WIFI:
    113       return "Wifi";
    114     case ADAPTER_TYPE_CELLULAR:
    115       return "Cellular";
    116     case ADAPTER_TYPE_VPN:
    117       return "VPN";
    118     default:
    119       ASSERT(false);
    120       return std::string();
    121   }
    122 }
    123 
    124 }  // namespace
    125 
    126 std::string MakeNetworkKey(const std::string& name, const IPAddress& prefix,
    127                            int prefix_length) {
    128   std::ostringstream ost;
    129   ost << name << "%" << prefix.ToString() << "/" << prefix_length;
    130   return ost.str();
    131 }
    132 
    133 NetworkManager::NetworkManager() {
    134 }
    135 
    136 NetworkManager::~NetworkManager() {
    137 }
    138 
    139 NetworkManagerBase::NetworkManagerBase() : ipv6_enabled_(true) {
    140 }
    141 
    142 NetworkManagerBase::~NetworkManagerBase() {
    143   for (NetworkMap::iterator i = networks_map_.begin();
    144        i != networks_map_.end(); ++i) {
    145     delete i->second;
    146   }
    147 }
    148 
    149 void NetworkManagerBase::GetNetworks(NetworkList* result) const {
    150   *result = networks_;
    151 }
    152 
    153 void NetworkManagerBase::MergeNetworkList(const NetworkList& new_networks,
    154                                           bool* changed) {
    155   // AddressList in this map will track IP addresses for all Networks
    156   // with the same key.
    157   std::map<std::string, AddressList> consolidated_address_list;
    158   NetworkList list(new_networks);
    159 
    160   // Result of Network merge. Element in this list should have unique key.
    161   NetworkList merged_list;
    162   std::sort(list.begin(), list.end(), CompareNetworks);
    163 
    164   *changed = false;
    165 
    166   if (networks_.size() != list.size())
    167     *changed = true;
    168 
    169   // First, build a set of network-keys to the ipaddresses.
    170   for (uint32 i = 0; i < list.size(); ++i) {
    171     bool might_add_to_merged_list = false;
    172     std::string key = MakeNetworkKey(list[i]->name(),
    173                                      list[i]->prefix(),
    174                                      list[i]->prefix_length());
    175     if (consolidated_address_list.find(key) ==
    176         consolidated_address_list.end()) {
    177       AddressList addrlist;
    178       addrlist.net = list[i];
    179       consolidated_address_list[key] = addrlist;
    180       might_add_to_merged_list = true;
    181     }
    182     const std::vector<InterfaceAddress>& addresses = list[i]->GetIPs();
    183     AddressList& current_list = consolidated_address_list[key];
    184     for (std::vector<InterfaceAddress>::const_iterator it = addresses.begin();
    185          it != addresses.end();
    186          ++it) {
    187       current_list.ips.push_back(*it);
    188     }
    189     if (!might_add_to_merged_list) {
    190       delete list[i];
    191     }
    192   }
    193 
    194   // Next, look for existing network objects to re-use.
    195   for (std::map<std::string, AddressList>::iterator it =
    196          consolidated_address_list.begin();
    197        it != consolidated_address_list.end();
    198        ++it) {
    199     const std::string& key = it->first;
    200     Network* net = it->second.net;
    201     NetworkMap::iterator existing = networks_map_.find(key);
    202     if (existing == networks_map_.end()) {
    203       // This network is new. Place it in the network map.
    204       merged_list.push_back(net);
    205       networks_map_[key] = net;
    206       // Also, we might have accumulated IPAddresses from the first
    207       // step, set it here.
    208       net->SetIPs(it->second.ips, true);
    209       *changed = true;
    210     } else {
    211       // This network exists in the map already. Reset its IP addresses.
    212       *changed = existing->second->SetIPs(it->second.ips, *changed);
    213       merged_list.push_back(existing->second);
    214       if (existing->second != net) {
    215         delete net;
    216       }
    217     }
    218   }
    219   networks_ = merged_list;
    220 
    221   // If the network lists changes, we resort it.
    222   if (changed) {
    223     std::sort(networks_.begin(), networks_.end(), SortNetworks);
    224     // Now network interfaces are sorted, we should set the preference value
    225     // for each of the interfaces we are planning to use.
    226     // Preference order of network interfaces might have changed from previous
    227     // sorting due to addition of higher preference network interface.
    228     // Since we have already sorted the network interfaces based on our
    229     // requirements, we will just assign a preference value starting with 127,
    230     // in decreasing order.
    231     int pref = kHighestNetworkPreference;
    232     for (NetworkList::const_iterator iter = networks_.begin();
    233          iter != networks_.end(); ++iter) {
    234       (*iter)->set_preference(pref);
    235       if (pref > 0) {
    236         --pref;
    237       } else {
    238         LOG(LS_ERROR) << "Too many network interfaces to handle!";
    239         break;
    240       }
    241     }
    242   }
    243 }
    244 
    245 BasicNetworkManager::BasicNetworkManager()
    246     : thread_(NULL), sent_first_update_(false), start_count_(0),
    247       ignore_non_default_routes_(false) {
    248 }
    249 
    250 BasicNetworkManager::~BasicNetworkManager() {
    251 }
    252 
    253 #if defined(__native_client__)
    254 
    255 bool BasicNetworkManager::CreateNetworks(bool include_ignored,
    256                                          NetworkList* networks) const {
    257   ASSERT(false);
    258   LOG(LS_WARNING) << "BasicNetworkManager doesn't work on NaCl yet";
    259   return false;
    260 }
    261 
    262 #elif defined(WEBRTC_POSIX)
    263 void BasicNetworkManager::ConvertIfAddrs(struct ifaddrs* interfaces,
    264                                          bool include_ignored,
    265                                          NetworkList* networks) const {
    266   NetworkMap current_networks;
    267   for (struct ifaddrs* cursor = interfaces;
    268        cursor != NULL; cursor = cursor->ifa_next) {
    269     IPAddress prefix;
    270     IPAddress mask;
    271     IPAddress ip;
    272     int scope_id = 0;
    273 
    274     // Some interfaces may not have address assigned.
    275     if (!cursor->ifa_addr || !cursor->ifa_netmask)
    276       continue;
    277 
    278     switch (cursor->ifa_addr->sa_family) {
    279       case AF_INET: {
    280         ip = IPAddress(
    281             reinterpret_cast<sockaddr_in*>(cursor->ifa_addr)->sin_addr);
    282         mask = IPAddress(
    283             reinterpret_cast<sockaddr_in*>(cursor->ifa_netmask)->sin_addr);
    284         break;
    285       }
    286       case AF_INET6: {
    287         if (ipv6_enabled()) {
    288           ip = IPAddress(
    289               reinterpret_cast<sockaddr_in6*>(cursor->ifa_addr)->sin6_addr);
    290           mask = IPAddress(
    291               reinterpret_cast<sockaddr_in6*>(cursor->ifa_netmask)->sin6_addr);
    292           scope_id =
    293               reinterpret_cast<sockaddr_in6*>(cursor->ifa_addr)->sin6_scope_id;
    294           break;
    295         } else {
    296           continue;
    297         }
    298       }
    299       default: {
    300         continue;
    301       }
    302     }
    303 
    304     int prefix_length = CountIPMaskBits(mask);
    305     prefix = TruncateIP(ip, prefix_length);
    306     std::string key = MakeNetworkKey(std::string(cursor->ifa_name),
    307                                      prefix, prefix_length);
    308     NetworkMap::iterator existing_network = current_networks.find(key);
    309     if (existing_network == current_networks.end()) {
    310       scoped_ptr<Network> network(new Network(cursor->ifa_name,
    311                                               cursor->ifa_name,
    312                                               prefix,
    313                                               prefix_length));
    314       network->set_scope_id(scope_id);
    315       network->AddIP(ip);
    316       bool ignored = ((cursor->ifa_flags & IFF_LOOPBACK) ||
    317                       IsIgnoredNetwork(*network));
    318       network->set_ignored(ignored);
    319       if (include_ignored || !network->ignored()) {
    320         networks->push_back(network.release());
    321       }
    322     } else {
    323       (*existing_network).second->AddIP(ip);
    324     }
    325   }
    326 }
    327 
    328 bool BasicNetworkManager::CreateNetworks(bool include_ignored,
    329                                          NetworkList* networks) const {
    330   struct ifaddrs* interfaces;
    331   int error = getifaddrs(&interfaces);
    332   if (error != 0) {
    333     LOG_ERR(LERROR) << "getifaddrs failed to gather interface data: " << error;
    334     return false;
    335   }
    336 
    337   ConvertIfAddrs(interfaces, include_ignored, networks);
    338 
    339   freeifaddrs(interfaces);
    340   return true;
    341 }
    342 
    343 #elif defined(WEBRTC_WIN)
    344 
    345 unsigned int GetPrefix(PIP_ADAPTER_PREFIX prefixlist,
    346               const IPAddress& ip, IPAddress* prefix) {
    347   IPAddress current_prefix;
    348   IPAddress best_prefix;
    349   unsigned int best_length = 0;
    350   while (prefixlist) {
    351     // Look for the longest matching prefix in the prefixlist.
    352     if (prefixlist->Address.lpSockaddr == NULL ||
    353         prefixlist->Address.lpSockaddr->sa_family != ip.family()) {
    354       prefixlist = prefixlist->Next;
    355       continue;
    356     }
    357     switch (prefixlist->Address.lpSockaddr->sa_family) {
    358       case AF_INET: {
    359         sockaddr_in* v4_addr =
    360             reinterpret_cast<sockaddr_in*>(prefixlist->Address.lpSockaddr);
    361         current_prefix = IPAddress(v4_addr->sin_addr);
    362         break;
    363       }
    364       case AF_INET6: {
    365           sockaddr_in6* v6_addr =
    366               reinterpret_cast<sockaddr_in6*>(prefixlist->Address.lpSockaddr);
    367           current_prefix = IPAddress(v6_addr->sin6_addr);
    368           break;
    369       }
    370       default: {
    371         prefixlist = prefixlist->Next;
    372         continue;
    373       }
    374     }
    375     if (TruncateIP(ip, prefixlist->PrefixLength) == current_prefix &&
    376         prefixlist->PrefixLength > best_length) {
    377       best_prefix = current_prefix;
    378       best_length = prefixlist->PrefixLength;
    379     }
    380     prefixlist = prefixlist->Next;
    381   }
    382   *prefix = best_prefix;
    383   return best_length;
    384 }
    385 
    386 bool BasicNetworkManager::CreateNetworks(bool include_ignored,
    387                                          NetworkList* networks) const {
    388   NetworkMap current_networks;
    389   // MSDN recommends a 15KB buffer for the first try at GetAdaptersAddresses.
    390   size_t buffer_size = 16384;
    391   scoped_ptr<char[]> adapter_info(new char[buffer_size]);
    392   PIP_ADAPTER_ADDRESSES adapter_addrs =
    393       reinterpret_cast<PIP_ADAPTER_ADDRESSES>(adapter_info.get());
    394   int adapter_flags = (GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_ANYCAST |
    395                        GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_INCLUDE_PREFIX);
    396   int ret = 0;
    397   do {
    398     adapter_info.reset(new char[buffer_size]);
    399     adapter_addrs = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(adapter_info.get());
    400     ret = GetAdaptersAddresses(AF_UNSPEC, adapter_flags,
    401                                0, adapter_addrs,
    402                                reinterpret_cast<PULONG>(&buffer_size));
    403   } while (ret == ERROR_BUFFER_OVERFLOW);
    404   if (ret != ERROR_SUCCESS) {
    405     return false;
    406   }
    407   int count = 0;
    408   while (adapter_addrs) {
    409     if (adapter_addrs->OperStatus == IfOperStatusUp) {
    410       PIP_ADAPTER_UNICAST_ADDRESS address = adapter_addrs->FirstUnicastAddress;
    411       PIP_ADAPTER_PREFIX prefixlist = adapter_addrs->FirstPrefix;
    412       std::string name;
    413       std::string description;
    414 #ifdef _DEBUG
    415       name = ToUtf8(adapter_addrs->FriendlyName,
    416                     wcslen(adapter_addrs->FriendlyName));
    417 #endif
    418       description = ToUtf8(adapter_addrs->Description,
    419                            wcslen(adapter_addrs->Description));
    420       for (; address; address = address->Next) {
    421 #ifndef _DEBUG
    422         name = rtc::ToString(count);
    423 #endif
    424 
    425         IPAddress ip;
    426         int scope_id = 0;
    427         scoped_ptr<Network> network;
    428         switch (address->Address.lpSockaddr->sa_family) {
    429           case AF_INET: {
    430             sockaddr_in* v4_addr =
    431                 reinterpret_cast<sockaddr_in*>(address->Address.lpSockaddr);
    432             ip = IPAddress(v4_addr->sin_addr);
    433             break;
    434           }
    435           case AF_INET6: {
    436             if (ipv6_enabled()) {
    437               sockaddr_in6* v6_addr =
    438                   reinterpret_cast<sockaddr_in6*>(address->Address.lpSockaddr);
    439               scope_id = v6_addr->sin6_scope_id;
    440               ip = IPAddress(v6_addr->sin6_addr);
    441               break;
    442             } else {
    443               continue;
    444             }
    445           }
    446           default: {
    447             continue;
    448           }
    449         }
    450 
    451         IPAddress prefix;
    452         int prefix_length = GetPrefix(prefixlist, ip, &prefix);
    453         std::string key = MakeNetworkKey(name, prefix, prefix_length);
    454         NetworkMap::iterator existing_network = current_networks.find(key);
    455         if (existing_network == current_networks.end()) {
    456           scoped_ptr<Network> network(new Network(name,
    457                                                   description,
    458                                                   prefix,
    459                                                   prefix_length));
    460           network->set_scope_id(scope_id);
    461           network->AddIP(ip);
    462           bool ignore = ((adapter_addrs->IfType == IF_TYPE_SOFTWARE_LOOPBACK) ||
    463                          IsIgnoredNetwork(*network));
    464           network->set_ignored(ignore);
    465           if (include_ignored || !network->ignored()) {
    466             networks->push_back(network.release());
    467           }
    468         } else {
    469           (*existing_network).second->AddIP(ip);
    470         }
    471       }
    472       // Count is per-adapter - all 'Networks' created from the same
    473       // adapter need to have the same name.
    474       ++count;
    475     }
    476     adapter_addrs = adapter_addrs->Next;
    477   }
    478   return true;
    479 }
    480 #endif  // WEBRTC_WIN
    481 
    482 #if defined(WEBRTC_LINUX)
    483 bool IsDefaultRoute(const std::string& network_name) {
    484   FileStream fs;
    485   if (!fs.Open("/proc/net/route", "r", NULL)) {
    486     LOG(LS_WARNING) << "Couldn't read /proc/net/route, skipping default "
    487                     << "route check (assuming everything is a default route).";
    488     return true;
    489   } else {
    490     std::string line;
    491     while (fs.ReadLine(&line) == SR_SUCCESS) {
    492       char iface_name[256];
    493       unsigned int iface_ip, iface_gw, iface_mask, iface_flags;
    494       if (sscanf(line.c_str(),
    495                  "%255s %8X %8X %4X %*d %*u %*d %8X",
    496                  iface_name, &iface_ip, &iface_gw,
    497                  &iface_flags, &iface_mask) == 5 &&
    498           network_name == iface_name &&
    499           iface_mask == 0 &&
    500           (iface_flags & (RTF_UP | RTF_HOST)) == RTF_UP) {
    501         return true;
    502       }
    503     }
    504   }
    505   return false;
    506 }
    507 #endif
    508 
    509 bool BasicNetworkManager::IsIgnoredNetwork(const Network& network) const {
    510   // Ignore networks on the explicit ignore list.
    511   for (size_t i = 0; i < network_ignore_list_.size(); ++i) {
    512     if (network.name() == network_ignore_list_[i]) {
    513       return true;
    514     }
    515   }
    516 #if defined(WEBRTC_POSIX)
    517   // Filter out VMware interfaces, typically named vmnet1 and vmnet8
    518   if (strncmp(network.name().c_str(), "vmnet", 5) == 0 ||
    519       strncmp(network.name().c_str(), "vnic", 4) == 0) {
    520     return true;
    521   }
    522 #if defined(WEBRTC_LINUX)
    523   // Make sure this is a default route, if we're ignoring non-defaults.
    524   if (ignore_non_default_routes_ && !IsDefaultRoute(network.name())) {
    525     return true;
    526   }
    527 #endif
    528 #elif defined(WEBRTC_WIN)
    529   // Ignore any HOST side vmware adapters with a description like:
    530   // VMware Virtual Ethernet Adapter for VMnet1
    531   // but don't ignore any GUEST side adapters with a description like:
    532   // VMware Accelerated AMD PCNet Adapter #2
    533   if (strstr(network.description().c_str(), "VMnet") != NULL) {
    534     return true;
    535   }
    536 #endif
    537 
    538   // Ignore any networks with a 0.x.y.z IP
    539   if (network.prefix().family() == AF_INET) {
    540     return (network.prefix().v4AddressAsHostOrderInteger() < 0x01000000);
    541   }
    542   return false;
    543 }
    544 
    545 void BasicNetworkManager::StartUpdating() {
    546   thread_ = Thread::Current();
    547   if (start_count_) {
    548     // If network interfaces are already discovered and signal is sent,
    549     // we should trigger network signal immediately for the new clients
    550     // to start allocating ports.
    551     if (sent_first_update_)
    552       thread_->Post(this, kSignalNetworksMessage);
    553   } else {
    554     thread_->Post(this, kUpdateNetworksMessage);
    555   }
    556   ++start_count_;
    557 }
    558 
    559 void BasicNetworkManager::StopUpdating() {
    560   ASSERT(Thread::Current() == thread_);
    561   if (!start_count_)
    562     return;
    563 
    564   --start_count_;
    565   if (!start_count_) {
    566     thread_->Clear(this);
    567     sent_first_update_ = false;
    568   }
    569 }
    570 
    571 void BasicNetworkManager::OnMessage(Message* msg) {
    572   switch (msg->message_id) {
    573     case kUpdateNetworksMessage:  {
    574       DoUpdateNetworks();
    575       break;
    576     }
    577     case kSignalNetworksMessage:  {
    578       SignalNetworksChanged();
    579       break;
    580     }
    581     default:
    582       ASSERT(false);
    583   }
    584 }
    585 
    586 void BasicNetworkManager::DoUpdateNetworks() {
    587   if (!start_count_)
    588     return;
    589 
    590   ASSERT(Thread::Current() == thread_);
    591 
    592   NetworkList list;
    593   if (!CreateNetworks(false, &list)) {
    594     SignalError();
    595   } else {
    596     bool changed;
    597     MergeNetworkList(list, &changed);
    598     if (changed || !sent_first_update_) {
    599       SignalNetworksChanged();
    600       sent_first_update_ = true;
    601     }
    602   }
    603 
    604   thread_->PostDelayed(kNetworksUpdateIntervalMs, this, kUpdateNetworksMessage);
    605 }
    606 
    607 void BasicNetworkManager::DumpNetworks(bool include_ignored) {
    608   NetworkList list;
    609   CreateNetworks(include_ignored, &list);
    610   LOG(LS_INFO) << "NetworkManager detected " << list.size() << " networks:";
    611   for (size_t i = 0; i < list.size(); ++i) {
    612     const Network* network = list[i];
    613     if (!network->ignored() || include_ignored) {
    614       LOG(LS_INFO) << network->ToString() << ": "
    615                    << network->description()
    616                    << ((network->ignored()) ? ", Ignored" : "");
    617     }
    618   }
    619   // Release the network list created previously.
    620   // Do this in a seperated for loop for better readability.
    621   for (size_t i = 0; i < list.size(); ++i) {
    622     delete list[i];
    623   }
    624 }
    625 
    626 Network::Network(const std::string& name, const std::string& desc,
    627                  const IPAddress& prefix, int prefix_length)
    628     : name_(name), description_(desc), prefix_(prefix),
    629       prefix_length_(prefix_length),
    630       key_(MakeNetworkKey(name, prefix, prefix_length)), scope_id_(0),
    631       ignored_(false), type_(ADAPTER_TYPE_UNKNOWN), preference_(0) {
    632 }
    633 
    634 Network::Network(const std::string& name, const std::string& desc,
    635                  const IPAddress& prefix, int prefix_length, AdapterType type)
    636     : name_(name), description_(desc), prefix_(prefix),
    637       prefix_length_(prefix_length),
    638       key_(MakeNetworkKey(name, prefix, prefix_length)), scope_id_(0),
    639       ignored_(false), type_(type), preference_(0) {
    640 }
    641 
    642 // Sets the addresses of this network. Returns true if the address set changed.
    643 // Change detection is short circuited if the changed argument is true.
    644 bool Network::SetIPs(const std::vector<InterfaceAddress>& ips, bool changed) {
    645   changed = changed || ips.size() != ips_.size();
    646   // Detect changes with a nested loop; n-squared but we expect on the order
    647   // of 2-3 addresses per network.
    648   for (std::vector<InterfaceAddress>::const_iterator it = ips.begin();
    649       !changed && it != ips.end();
    650       ++it) {
    651     bool found = false;
    652     for (std::vector<InterfaceAddress>::iterator inner_it = ips_.begin();
    653          !found && inner_it != ips_.end();
    654          ++inner_it) {
    655       if (*it == *inner_it) {
    656         found = true;
    657       }
    658     }
    659     changed = !found;
    660   }
    661   ips_ = ips;
    662   return changed;
    663 }
    664 
    665 // Select the best IP address to use from this Network.
    666 IPAddress Network::GetBestIP() const {
    667   if (ips_.size() == 0) {
    668     return IPAddress();
    669   }
    670 
    671   if (prefix_.family() == AF_INET) {
    672     return static_cast<IPAddress>(ips_.at(0));
    673   }
    674 
    675   InterfaceAddress selected_ip, ula_ip;
    676 
    677   for (size_t i = 0; i < ips_.size(); i++) {
    678     // Ignore any address which has been deprecated already.
    679     if (ips_[i].ipv6_flags() & IPV6_ADDRESS_FLAG_DEPRECATED)
    680       continue;
    681 
    682     // ULA address should only be returned when we have no other
    683     // global IP.
    684     if (IPIsULA(static_cast<const IPAddress&>(ips_[i]))) {
    685       ula_ip = ips_[i];
    686       continue;
    687     }
    688     selected_ip = ips_[i];
    689 
    690     // Search could stop once a temporary non-deprecated one is found.
    691     if (ips_[i].ipv6_flags() & IPV6_ADDRESS_FLAG_TEMPORARY)
    692       break;
    693   }
    694 
    695   // No proper global IPv6 address found, use ULA instead.
    696   if (IPIsUnspec(selected_ip) && !IPIsUnspec(ula_ip)) {
    697     selected_ip = ula_ip;
    698   }
    699 
    700   return static_cast<IPAddress>(selected_ip);
    701 }
    702 
    703 std::string Network::ToString() const {
    704   std::stringstream ss;
    705   // Print out the first space-terminated token of the network desc, plus
    706   // the IP address.
    707   ss << "Net[" << description_.substr(0, description_.find(' '))
    708      << ":" << prefix_.ToSensitiveString() << "/" << prefix_length_
    709      << ":" << AdapterTypeToString(type_) << "]";
    710   return ss.str();
    711 }
    712 
    713 }  // namespace rtc
    714