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/. */
8 #include "nrinterfaceprioritizer.h"
11 MOZ_MTLOG_MODULE("mtransport")
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
));
27 MOZ_MTLOG(PR_LOG_ERROR
, "Error formatting interface address string.");
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
);
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 {
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
) {
72 if (type
& NR_INTERFACE_TYPE_WIFI
) {
75 if (type
& NR_INTERFACE_TYPE_MOBILE
) {
87 class InterfacePrioritizer
{
89 InterfacePrioritizer()
94 int add(const nr_local_addr
*iface
) {
96 if (!addr
.Init(*iface
)) {
99 std::pair
<std::set
<LocalAddress
>::iterator
, bool> r
=
100 local_addrs_
.insert(addr
);
102 return R_ALREADY
; // This address is already in the set.
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
) {
116 preference_map_
.insert(make_pair(i
->GetKey(), tmp_pref
--));
122 int getPreference(const char *key
, UCHAR
*pref
) {
126 std::map
<std::string
, UCHAR
>::iterator i
= preference_map_
.find(key
);
127 if (i
== preference_map_
.end()) {
135 std::set
<LocalAddress
> local_addrs_
;
136 std::map
<std::string
, UCHAR
> preference_map_
;
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
);
157 static int destroy(void **objp
) {
158 if (!objp
|| !*objp
) {
162 InterfacePrioritizer
*ip
= static_cast<InterfacePrioritizer
*>(*objp
);
169 static nr_interface_prioritizer_vtbl priorizer_vtbl
= {
178 nr_interface_prioritizer
* CreateInterfacePrioritizer() {
179 nr_interface_prioritizer
*ip
;
180 int r
= nr_interface_prioritizer_create_int(new InterfacePrioritizer(),
189 } // namespace mozilla