Bumping manifests a=b2g-bump
[gecko.git] / media / mtransport / nrinterfaceprioritizer.cpp
blob33d17017f3835383f85a74864f724f33b8d6c080
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;
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;
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_;
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_;
52 // Compare estimated speed.
53 if (estimated_speed_ != rhs.estimated_speed_) {
54 return estimated_speed_ > rhs.estimated_speed_;
57 // All things above are the same, we can at least sort with key.
58 return key_ < rhs.key_;
61 const std::string& GetKey() const {
62 return key_;
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;
72 if (type & NR_INTERFACE_TYPE_WIFI) {
73 return 2;
75 if (type & NR_INTERFACE_TYPE_MOBILE) {
76 return 3;
78 return 4;
81 std::string key_;
82 int is_vpn_;
83 int estimated_speed_;
84 int type_preference_;
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;
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.
104 sorted_ = false;
105 return 0;
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;
116 preference_map_.insert(make_pair(i->GetKey(), tmp_pref--));
118 sorted_ = true;
119 return 0;
122 int getPreference(const char *key, UCHAR *pref) {
123 if (!sorted_) {
124 return R_FAILED;
126 std::map<std::string, UCHAR>::iterator i = preference_map_.find(key);
127 if (i == preference_map_.end()) {
128 return R_NOT_FOUND;
130 *pref = i->second;
131 return 0;
134 private:
135 std::set<LocalAddress> local_addrs_;
136 std::map<std::string, UCHAR> preference_map_;
137 bool sorted_;
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);
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);
152 static int sort_preference(void *obj) {
153 InterfacePrioritizer *ip = static_cast<InterfacePrioritizer*>(obj);
154 return ip->sort();
157 static int destroy(void **objp) {
158 if (!objp || !*objp) {
159 return 0;
162 InterfacePrioritizer *ip = static_cast<InterfacePrioritizer*>(*objp);
163 *objp = 0;
164 delete ip;
166 return 0;
169 static nr_interface_prioritizer_vtbl priorizer_vtbl = {
170 add_interface,
171 get_priority,
172 sort_preference,
173 destroy
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;
186 return ip;
189 } // namespace mozilla