1 /*
2  *  Copyright 2019 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 #ifndef P2P_BASE_BASIC_ICE_CONTROLLER_H_
12 #define P2P_BASE_BASIC_ICE_CONTROLLER_H_
13 
14 #include <algorithm>
15 #include <map>
16 #include <set>
17 #include <utility>
18 #include <vector>
19 
20 #include "p2p/base/ice_controller_factory_interface.h"
21 #include "p2p/base/ice_controller_interface.h"
22 #include "p2p/base/p2p_transport_channel.h"
23 
24 namespace cricket {
25 
26 class BasicIceController : public IceControllerInterface {
27  public:
28   explicit BasicIceController(const IceControllerFactoryArgs& args);
29   virtual ~BasicIceController();
30 
31   void SetIceConfig(const IceConfig& config) override;
32   void SetSelectedConnection(const Connection* selected_connection) override;
33   void AddConnection(const Connection* connection) override;
34   void OnConnectionDestroyed(const Connection* connection) override;
connections()35   rtc::ArrayView<const Connection*> connections() const override {
36     return rtc::ArrayView<const Connection*>(
37         const_cast<const Connection**>(connections_.data()),
38         connections_.size());
39   }
40 
41   bool HasPingableConnection() const override;
42 
43   PingResult SelectConnectionToPing(int64_t last_ping_sent_ms) override;
44 
45   bool GetUseCandidateAttr(const Connection* conn,
46                            NominationMode mode,
47                            IceMode remote_ice_mode) const override;
48 
49   SwitchResult ShouldSwitchConnection(IceControllerEvent reason,
50                                       const Connection* connection) override;
51   SwitchResult SortAndSwitchConnection(IceControllerEvent reason) override;
52 
53   std::vector<const Connection*> PruneConnections() override;
54 
55   // These methods are only for tests.
56   const Connection* FindNextPingableConnection() override;
57   void MarkConnectionPinged(const Connection* conn) override;
58 
59  private:
60   // A transport channel is weak if the current best connection is either
61   // not receiving or not writable, or if there is no best connection at all.
weak()62   bool weak() const {
63     return !selected_connection_ || selected_connection_->weak();
64   }
65 
weak_ping_interval()66   int weak_ping_interval() const {
67     return std::max(config_.ice_check_interval_weak_connectivity_or_default(),
68                     config_.ice_check_min_interval_or_default());
69   }
70 
strong_ping_interval()71   int strong_ping_interval() const {
72     return std::max(config_.ice_check_interval_strong_connectivity_or_default(),
73                     config_.ice_check_min_interval_or_default());
74   }
75 
check_receiving_interval()76   int check_receiving_interval() const {
77     return std::max(MIN_CHECK_RECEIVING_INTERVAL,
78                     config_.receiving_timeout_or_default() / 10);
79   }
80 
81   const Connection* FindOldestConnectionNeedingTriggeredCheck(int64_t now);
82   // Between |conn1| and |conn2|, this function returns the one which should
83   // be pinged first.
84   const Connection* MorePingable(const Connection* conn1,
85                                  const Connection* conn2);
86   // Select the connection which is Relay/Relay. If both of them are,
87   // UDP relay protocol takes precedence.
88   const Connection* MostLikelyToWork(const Connection* conn1,
89                                      const Connection* conn2);
90   // Compare the last_ping_sent time and return the one least recently pinged.
91   const Connection* LeastRecentlyPinged(const Connection* conn1,
92                                         const Connection* conn2);
93 
94   bool IsPingable(const Connection* conn, int64_t now) const;
95   bool IsBackupConnection(const Connection* conn) const;
96   // Whether a writable connection is past its ping interval and needs to be
97   // pinged again.
98   bool WritableConnectionPastPingInterval(const Connection* conn,
99                                           int64_t now) const;
100   int CalculateActiveWritablePingInterval(const Connection* conn,
101                                           int64_t now) const;
102 
103   std::map<const rtc::Network*, const Connection*> GetBestConnectionByNetwork()
104       const;
105   std::vector<const Connection*> GetBestWritableConnectionPerNetwork() const;
106 
107   bool ReadyToSend(const Connection* connection) const;
108   bool PresumedWritable(const Connection* conn) const;
109 
110   int CompareCandidatePairNetworks(
111       const Connection* a,
112       const Connection* b,
113       absl::optional<rtc::AdapterType> network_preference) const;
114 
115   // The methods below return a positive value if |a| is preferable to |b|,
116   // a negative value if |b| is preferable, and 0 if they're equally preferable.
117   // If |receiving_unchanged_threshold| is set, then when |b| is receiving and
118   // |a| is not, returns a negative value only if |b| has been in receiving
119   // state and |a| has been in not receiving state since
120   // |receiving_unchanged_threshold| and sets
121   // |missed_receiving_unchanged_threshold| to true otherwise.
122   int CompareConnectionStates(
123       const Connection* a,
124       const Connection* b,
125       absl::optional<int64_t> receiving_unchanged_threshold,
126       bool* missed_receiving_unchanged_threshold) const;
127   int CompareConnectionCandidates(const Connection* a,
128                                   const Connection* b) const;
129   // Compares two connections based on the connection states
130   // (writable/receiving/connected), nomination states, last data received time,
131   // and static preferences. Does not include latency. Used by both sorting
132   // and ShouldSwitchSelectedConnection().
133   // Returns a positive value if |a| is better than |b|.
134   int CompareConnections(const Connection* a,
135                          const Connection* b,
136                          absl::optional<int64_t> receiving_unchanged_threshold,
137                          bool* missed_receiving_unchanged_threshold) const;
138 
139   SwitchResult HandleInitialSelectDampening(IceControllerEvent reason,
140                                             const Connection* new_connection);
141 
142   std::function<IceTransportState()> ice_transport_state_func_;
143   std::function<IceRole()> ice_role_func_;
144   std::function<bool(const Connection*)> is_connection_pruned_func_;
145 
146   IceConfig config_;
147   const IceFieldTrials* field_trials_;
148 
149   // |connections_| is a sorted list with the first one always be the
150   // |selected_connection_| when it's not nullptr. The combination of
151   // |pinged_connections_| and |unpinged_connections_| has the same
152   // connections as |connections_|. These 2 sets maintain whether a
153   // connection should be pinged next or not.
154   const Connection* selected_connection_ = nullptr;
155   std::vector<const Connection*> connections_;
156   std::set<const Connection*> pinged_connections_;
157   std::set<const Connection*> unpinged_connections_;
158 
159   // Timestamp for when we got the first selectable connection.
160   int64_t initial_select_timestamp_ms_ = 0;
161 };
162 
163 }  // namespace cricket
164 
165 #endif  // P2P_BASE_BASIC_ICE_CONTROLLER_H_
166