media/mtransport/nrinterfaceprioritizer.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     4 #include <map>
     5 #include <set>
     6 #include <string>
     7 #include "logging.h"
     8 #include "nrinterfaceprioritizer.h"
     9 #include "nsCOMPtr.h"
    11 MOZ_MTLOG_MODULE("mtransport")
    13 namespace {
    15 class LocalAddress {
    16 public:
    17   LocalAddress()
    18     : key_(),
    19       is_vpn_(-1),
    20       estimated_speed_(-1),
    21       type_preference_(-1) {}
    23   bool Init(const nr_local_addr& local_addr) {
    24     char buf[MAXIFNAME + 41];
    25     int r = nr_transport_addr_fmt_ifname_addr_string(&local_addr.addr, buf, sizeof(buf));
    26     if (r) {
    27       MOZ_MTLOG(PR_LOG_ERROR, "Error formatting interface address string.");
    28       return false;
    29     }
    30     key_ = buf;
    31     is_vpn_ = (local_addr.interface.type & NR_INTERFACE_TYPE_VPN) != 0 ? 1 : 0;
    32     estimated_speed_ = local_addr.interface.estimated_speed;
    33     type_preference_ = GetNetworkTypePreference(local_addr.interface.type);
    34     return true;
    35   }
    37   bool operator<(const LocalAddress& rhs) const {
    38     // Interface that is "less" here is preferred.
    39     // If type preferences are different, we should simply sort by
    40     // |type_preference_|.
    41     if (type_preference_ != rhs.type_preference_) {
    42       return type_preference_ < rhs.type_preference_;
    43     }
    45     // If type preferences are the same, the next thing we use to sort is vpn.
    46     // If two LocalAddress are different in |is_vpn_|, the LocalAddress that is
    47     // not in vpn gets priority.
    48     if (is_vpn_ != rhs.is_vpn_) {
    49       return is_vpn_ < rhs.is_vpn_;
    50     }
    52     // Compare estimated speed.
    53     if (estimated_speed_ != rhs.estimated_speed_) {
    54       return estimated_speed_ > rhs.estimated_speed_;
    55     }
    57     // All things above are the same, we can at least sort with key.
    58     return key_ < rhs.key_;
    59   }
    61   const std::string& GetKey() const {
    62     return key_;
    63   }
    65 private:
    66   // Getting the preference corresponding to a type. Getting lower number here
    67   // means the type of network is preferred.
    68   static inline int GetNetworkTypePreference(int type) {
    69     if (type & NR_INTERFACE_TYPE_WIRED) {
    70       return 1;
    71     }
    72     if (type & NR_INTERFACE_TYPE_WIFI) {
    73       return 2;
    74     }
    75     if (type & NR_INTERFACE_TYPE_MOBILE) {
    76       return 3;
    77     }
    78     return 4;
    79   }
    81   std::string key_;
    82   int is_vpn_;
    83   int estimated_speed_;
    84   int type_preference_;
    85 };
    87 class InterfacePrioritizer {
    88 public:
    89   InterfacePrioritizer()
    90     : local_addrs_(),
    91       preference_map_(),
    92       sorted_(false) {}
    94   int add(const nr_local_addr *iface) {
    95     LocalAddress addr;
    96     if (!addr.Init(*iface)) {
    97       return R_FAILED;
    98     }
    99     std::pair<std::set<LocalAddress>::iterator, bool> r =
   100       local_addrs_.insert(addr);
   101     if (!r.second) {
   102       return R_ALREADY; // This address is already in the set.
   103     }
   104     sorted_ = false;
   105     return 0;
   106   }
   108   int sort() {
   109     UCHAR tmp_pref = 127;
   110     preference_map_.clear();
   111     for (std::set<LocalAddress>::iterator i = local_addrs_.begin();
   112          i != local_addrs_.end(); ++i) {
   113       if (tmp_pref == 0) {
   114         return R_FAILED;
   115       }
   116       preference_map_.insert(make_pair(i->GetKey(), tmp_pref--));
   117     }
   118     sorted_ = true;
   119     return 0;
   120   }
   122   int getPreference(const char *key, UCHAR *pref) {
   123     if (!sorted_) {
   124       return R_FAILED;
   125     }
   126     std::map<std::string, UCHAR>::iterator i = preference_map_.find(key);
   127     if (i == preference_map_.end()) {
   128       return R_NOT_FOUND;
   129     }
   130     *pref = i->second;
   131     return 0;
   132   }
   134 private:
   135   std::set<LocalAddress> local_addrs_;
   136   std::map<std::string, UCHAR> preference_map_;
   137   bool sorted_;
   138 };
   140 } // anonymous namespace
   142 static int add_interface(void *obj, nr_local_addr *iface) {
   143   InterfacePrioritizer *ip = static_cast<InterfacePrioritizer*>(obj);
   144   return ip->add(iface);
   145 }
   147 static int get_priority(void *obj, const char *key, UCHAR *pref) {
   148   InterfacePrioritizer *ip = static_cast<InterfacePrioritizer*>(obj);
   149   return ip->getPreference(key, pref);
   150 }
   152 static int sort_preference(void *obj) {
   153   InterfacePrioritizer *ip = static_cast<InterfacePrioritizer*>(obj);
   154   return ip->sort();
   155 }
   157 static int destroy(void **objp) {
   158   if (!objp || !*objp) {
   159     return 0;
   160   }
   162   InterfacePrioritizer *ip = static_cast<InterfacePrioritizer*>(*objp);
   163   *objp = 0;
   164   delete ip;
   166   return 0;
   167 }
   169 static nr_interface_prioritizer_vtbl priorizer_vtbl = {
   170   add_interface,
   171   get_priority,
   172   sort_preference,
   173   destroy
   174 };
   176 namespace mozilla {
   178 nr_interface_prioritizer* CreateInterfacePrioritizer() {
   179   nr_interface_prioritizer *ip;
   180   int r = nr_interface_prioritizer_create_int(new InterfacePrioritizer(),
   181                                               &priorizer_vtbl,
   182                                               &ip);
   183   if (r != 0) {
   184     return nullptr;
   185   }
   186   return ip;
   187 }
   189 } // namespace mozilla

mercurial