summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/p2p/base/ice_transport_internal.h
blob: 38b6bfe3032bbd3c3c9efbff0408cb0b85f2f86e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
/*
 *  Copyright 2016 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#ifndef P2P_BASE_ICE_TRANSPORT_INTERNAL_H_
#define P2P_BASE_ICE_TRANSPORT_INTERNAL_H_

#include <stdint.h>

#include <string>
#include <utility>
#include <vector>

#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "api/candidate.h"
#include "api/rtc_error.h"
#include "api/transport/enums.h"
#include "p2p/base/connection.h"
#include "p2p/base/packet_transport_internal.h"
#include "p2p/base/port.h"
#include "p2p/base/stun_dictionary.h"
#include "p2p/base/transport_description.h"
#include "rtc_base/network_constants.h"
#include "rtc_base/system/rtc_export.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
#include "rtc_base/time_utils.h"

namespace cricket {

struct IceTransportStats {
  CandidateStatsList candidate_stats_list;
  ConnectionInfos connection_infos;
  // Number of times the selected candidate pair has changed
  // Initially 0 and 1 once the first candidate pair has been selected.
  // The counter is increase also when "unselecting" a connection.
  uint32_t selected_candidate_pair_changes = 0;

  // Bytes/packets sent/received.
  // note: Is not the same as sum(connection_infos.bytes_sent)
  // as connections are created and destroyed while the ICE transport
  // is alive.
  uint64_t bytes_sent = 0;
  uint64_t bytes_received = 0;
  uint64_t packets_sent = 0;
  uint64_t packets_received = 0;

  IceRole ice_role = ICEROLE_UNKNOWN;
  std::string ice_local_username_fragment;
  webrtc::IceTransportState ice_state = webrtc::IceTransportState::kNew;
};

typedef std::vector<Candidate> Candidates;

enum IceConnectionState {
  kIceConnectionConnecting = 0,
  kIceConnectionFailed,
  kIceConnectionConnected,  // Writable, but still checking one or more
                            // connections
  kIceConnectionCompleted,
};

// TODO(deadbeef): Unify with PeerConnectionInterface::IceConnectionState
// once /talk/ and /webrtc/ are combined, and also switch to ENUM_NAME naming
// style.
enum IceGatheringState {
  kIceGatheringNew = 0,
  kIceGatheringGathering,
  kIceGatheringComplete,
};

enum ContinualGatheringPolicy {
  // All port allocator sessions will stop after a writable connection is found.
  GATHER_ONCE = 0,
  // The most recent port allocator session will keep on running.
  GATHER_CONTINUALLY,
};

// ICE Nomination mode.
enum class NominationMode {
  REGULAR,         // Nominate once per ICE restart (Not implemented yet).
  AGGRESSIVE,      // Nominate every connection except that it will behave as if
                   // REGULAR when the remote is an ICE-LITE endpoint.
  SEMI_AGGRESSIVE  // Our current implementation of the nomination algorithm.
                   // The details are described in P2PTransportChannel.
};

// Utility method that checks if various required Candidate fields are filled in
// and contain valid values. If conditions are not met, an RTCError with the
// appropriated error number and description is returned. If the configuration
// is valid RTCError::OK() is returned.
webrtc::RTCError VerifyCandidate(const Candidate& cand);

// Runs through a list of cricket::Candidate instances and calls VerifyCandidate
// for each one, stopping on the first error encounted and returning that error
// value if so. On success returns RTCError::OK().
webrtc::RTCError VerifyCandidates(const Candidates& candidates);

// Information about ICE configuration.
// TODO(deadbeef): Use absl::optional to represent unset values, instead of
// -1.
//
// TODO(bugs.webrtc.org/15609): Define a public API for this.
struct RTC_EXPORT IceConfig {
  // The ICE connection receiving timeout value in milliseconds.
  absl::optional<int> receiving_timeout;
  // Time interval in milliseconds to ping a backup connection when the ICE
  // channel is strongly connected.
  absl::optional<int> backup_connection_ping_interval;

  ContinualGatheringPolicy continual_gathering_policy = GATHER_ONCE;

  bool gather_continually() const {
    return continual_gathering_policy == GATHER_CONTINUALLY;
  }

  // Whether we should prioritize Relay/Relay candidate when nothing
  // is writable yet.
  bool prioritize_most_likely_candidate_pairs = false;

  // Writable connections are pinged at a slower rate once stablized.
  absl::optional<int> stable_writable_connection_ping_interval;

  // If set to true, this means the ICE transport should presume TURN-to-TURN
  // candidate pairs will succeed, even before a binding response is received.
  bool presume_writable_when_fully_relayed = false;

  // If true, after the ICE transport type (as the candidate filter used by the
  // port allocator) is changed such that new types of ICE candidates are
  // allowed by the new filter, e.g. from CF_RELAY to CF_ALL, candidates that
  // have been gathered by the ICE transport but filtered out and not signaled
  // to the upper layers, will be surfaced.
  bool surface_ice_candidates_on_ice_transport_type_changed = false;

  // Interval to check on all networks and to perform ICE regathering on any
  // active network having no connection on it.
  absl::optional<int> regather_on_failed_networks_interval;

  // The time period in which we will not switch the selected connection
  // when a new connection becomes receiving but the selected connection is not
  // in case that the selected connection may become receiving soon.
  absl::optional<int> receiving_switching_delay;

  // TODO(honghaiz): Change the default to regular nomination.
  // Default nomination mode if the remote does not support renomination.
  NominationMode default_nomination_mode = NominationMode::SEMI_AGGRESSIVE;

  // The interval in milliseconds at which ICE checks (STUN pings) will be sent
  // for a candidate pair when it is both writable and receiving (strong
  // connectivity). This parameter overrides the default value given by
  // `STRONG_PING_INTERVAL` in p2ptransport.h if set.
  absl::optional<int> ice_check_interval_strong_connectivity;
  // The interval in milliseconds at which ICE checks (STUN pings) will be sent
  // for a candidate pair when it is either not writable or not receiving (weak
  // connectivity). This parameter overrides the default value given by
  // `WEAK_PING_INTERVAL` in p2ptransport.h if set.
  absl::optional<int> ice_check_interval_weak_connectivity;
  // ICE checks (STUN pings) will not be sent at higher rate (lower interval)
  // than this, no matter what other settings there are.
  // Measure in milliseconds.
  //
  // Note that this parameter overrides both the above check intervals for
  // candidate pairs with strong or weak connectivity, if either of the above
  // interval is shorter than the min interval.
  absl::optional<int> ice_check_min_interval;
  // The min time period for which a candidate pair must wait for response to
  // connectivity checks before it becomes unwritable. This parameter
  // overrides the default value given by `CONNECTION_WRITE_CONNECT_TIMEOUT`
  // in port.h if set, when determining the writability of a candidate pair.
  absl::optional<int> ice_unwritable_timeout;

  // The min number of connectivity checks that a candidate pair must sent
  // without receiving response before it becomes unwritable. This parameter
  // overrides the default value given by `CONNECTION_WRITE_CONNECT_FAILURES` in
  // port.h if set, when determining the writability of a candidate pair.
  absl::optional<int> ice_unwritable_min_checks;

  // The min time period for which a candidate pair must wait for response to
  // connectivity checks it becomes inactive. This parameter overrides the
  // default value given by `CONNECTION_WRITE_TIMEOUT` in port.h if set, when
  // determining the writability of a candidate pair.
  absl::optional<int> ice_inactive_timeout;

  // The interval in milliseconds at which STUN candidates will resend STUN
  // binding requests to keep NAT bindings open.
  absl::optional<int> stun_keepalive_interval;

  absl::optional<rtc::AdapterType> network_preference;

  webrtc::VpnPreference vpn_preference = webrtc::VpnPreference::kDefault;

  IceConfig();
  IceConfig(int receiving_timeout_ms,
            int backup_connection_ping_interval,
            ContinualGatheringPolicy gathering_policy,
            bool prioritize_most_likely_candidate_pairs,
            int stable_writable_connection_ping_interval_ms,
            bool presume_writable_when_fully_relayed,
            int regather_on_failed_networks_interval_ms,
            int receiving_switching_delay_ms);
  ~IceConfig();

  // Helper getters for parameters with implementation-specific default value.
  // By convention, parameters with default value are represented by
  // absl::optional and setting a parameter to null restores its default value.
  int receiving_timeout_or_default() const;
  int backup_connection_ping_interval_or_default() const;
  int stable_writable_connection_ping_interval_or_default() const;
  int regather_on_failed_networks_interval_or_default() const;
  int receiving_switching_delay_or_default() const;
  int ice_check_interval_strong_connectivity_or_default() const;
  int ice_check_interval_weak_connectivity_or_default() const;
  int ice_check_min_interval_or_default() const;
  int ice_unwritable_timeout_or_default() const;
  int ice_unwritable_min_checks_or_default() const;
  int ice_inactive_timeout_or_default() const;
  int stun_keepalive_interval_or_default() const;
};

// TODO(zhihuang): Replace this with
// PeerConnectionInterface::IceConnectionState.
enum class IceTransportState {
  STATE_INIT,
  STATE_CONNECTING,  // Will enter this state once a connection is created
  STATE_COMPLETED,
  STATE_FAILED
};

// IceTransportInternal is an internal abstract class that does ICE.
// Once the public interface is supported,
// (https://www.w3.org/TR/webrtc/#rtcicetransport)
// the IceTransportInterface will be split from this class.
//
// TODO(bugs.webrtc.org/15609): Define a public API for this.
class RTC_EXPORT IceTransportInternal : public rtc::PacketTransportInternal {
 public:
  IceTransportInternal();
  ~IceTransportInternal() override;

  // TODO(bugs.webrtc.org/9308): Remove GetState once all uses have been
  // migrated to GetIceTransportState.
  virtual IceTransportState GetState() const = 0;
  virtual webrtc::IceTransportState GetIceTransportState() const = 0;

  virtual int component() const = 0;

  virtual IceRole GetIceRole() const = 0;

  virtual void SetIceRole(IceRole role) = 0;

  virtual void SetIceTiebreaker(uint64_t tiebreaker) = 0;

  virtual void SetIceCredentials(absl::string_view ice_ufrag,
                                 absl::string_view ice_pwd);

  virtual void SetRemoteIceCredentials(absl::string_view ice_ufrag,
                                       absl::string_view ice_pwd);

  // The ufrag and pwd in `ice_params` must be set
  // before candidate gathering can start.
  virtual void SetIceParameters(const IceParameters& ice_params) = 0;

  virtual void SetRemoteIceParameters(const IceParameters& ice_params) = 0;

  virtual void SetRemoteIceMode(IceMode mode) = 0;

  virtual void SetIceConfig(const IceConfig& config) = 0;

  // Start gathering candidates if not already started, or if an ICE restart
  // occurred.
  virtual void MaybeStartGathering() = 0;

  virtual void AddRemoteCandidate(const Candidate& candidate) = 0;

  virtual void RemoveRemoteCandidate(const Candidate& candidate) = 0;

  virtual void RemoveAllRemoteCandidates() = 0;

  virtual IceGatheringState gathering_state() const = 0;

  // Returns the current stats for this connection.
  virtual bool GetStats(IceTransportStats* ice_transport_stats) = 0;

  // Returns RTT estimate over the currently active connection, or an empty
  // absl::optional if there is none.
  virtual absl::optional<int> GetRttEstimate() = 0;

  // TODO(qingsi): Remove this method once Chrome does not depend on it anymore.
  virtual const Connection* selected_connection() const = 0;

  // Returns the selected candidate pair, or an empty absl::optional if there is
  // none.
  virtual absl::optional<const CandidatePair> GetSelectedCandidatePair()
      const = 0;

  virtual absl::optional<std::reference_wrapper<StunDictionaryWriter>>
  GetDictionaryWriter() {
    return absl::nullopt;
  }

  // Signal Exposed for backwards compatibility.
  sigslot::signal1<IceTransportInternal*> SignalGatheringState;
  void SetGatheringStateCallback(
      absl::AnyInvocable<void(IceTransportInternal*)> callback) {
    RTC_DCHECK(!gathering_state_callback_);
    gathering_state_callback_ = std::move(callback);
  }

  // Handles sending and receiving of candidates.
  sigslot::signal2<IceTransportInternal*, const Candidate&>
      SignalCandidateGathered;

  void SetCandidateErrorCallback(
      absl::AnyInvocable<void(IceTransportInternal*,
                              const IceCandidateErrorEvent&)> callback) {
    RTC_DCHECK(!candidate_error_callback_);
    candidate_error_callback_ = std::move(callback);
  }

  void SetCandidatesRemovedCallback(
      absl::AnyInvocable<void(IceTransportInternal*, const Candidates&)>
          callback) {
    RTC_DCHECK(!candidates_removed_callback_);
    candidates_removed_callback_ = std::move(callback);
  }

  // Deprecated by PacketTransportInternal::SignalNetworkRouteChanged.
  // This signal occurs when there is a change in the way that packets are
  // being routed, i.e. to a different remote location. The candidate
  // indicates where and how we are currently sending media.
  // TODO(zhihuang): Update the Chrome remoting to use the new
  // SignalNetworkRouteChanged.
  sigslot::signal2<IceTransportInternal*, const Candidate&> SignalRouteChange;

  void SetCandidatePairChangeCallback(
      absl::AnyInvocable<void(const cricket::CandidatePairChangeEvent&)>
          callback) {
    RTC_DCHECK(!candidate_pair_change_callback_);
    candidate_pair_change_callback_ = std::move(callback);
  }

  // Invoked when there is conflict in the ICE role between local and remote
  // agents.
  sigslot::signal1<IceTransportInternal*> SignalRoleConflict;

  // Emitted whenever the transport state changed.
  // TODO(bugs.webrtc.org/9308): Remove once all uses have migrated to the new
  // IceTransportState.
  sigslot::signal1<IceTransportInternal*> SignalStateChanged;

  // Emitted whenever the new standards-compliant transport state changed.
  sigslot::signal1<IceTransportInternal*> SignalIceTransportStateChanged;

  // Invoked when the transport is being destroyed.
  sigslot::signal1<IceTransportInternal*> SignalDestroyed;

  // Invoked when remote dictionary has been updated,
  // i.e. modifications to attributes from remote ice agent has
  // reflected in our StunDictionaryView.
  template <typename F>
  void AddDictionaryViewUpdatedCallback(const void* tag, F&& callback) {
    dictionary_view_updated_callback_list_.AddReceiver(
        tag, std::forward<F>(callback));
  }
  void RemoveDictionaryViewUpdatedCallback(const void* tag) {
    dictionary_view_updated_callback_list_.RemoveReceivers(tag);
  }

  // Invoked when local dictionary has been synchronized,
  // i.e. remote ice agent has reported acknowledged updates from us.
  template <typename F>
  void AddDictionaryWriterSyncedCallback(const void* tag, F&& callback) {
    dictionary_writer_synced_callback_list_.AddReceiver(
        tag, std::forward<F>(callback));
  }
  void RemoveDictionaryWriterSyncedCallback(const void* tag) {
    dictionary_writer_synced_callback_list_.RemoveReceivers(tag);
  }

 protected:
  void SendGatheringStateEvent() { SignalGatheringState(this); }

  webrtc::CallbackList<IceTransportInternal*,
                       const StunDictionaryView&,
                       rtc::ArrayView<uint16_t>>
      dictionary_view_updated_callback_list_;
  webrtc::CallbackList<IceTransportInternal*, const StunDictionaryWriter&>
      dictionary_writer_synced_callback_list_;

  absl::AnyInvocable<void(IceTransportInternal*)> gathering_state_callback_;

  absl::AnyInvocable<void(IceTransportInternal*, const IceCandidateErrorEvent&)>
      candidate_error_callback_;

  absl::AnyInvocable<void(IceTransportInternal*, const Candidates&)>
      candidates_removed_callback_;

  absl::AnyInvocable<void(const cricket::CandidatePairChangeEvent&)>
      candidate_pair_change_callback_;

 private:
  // TODO(bugs.webrtc.org/11943): remove when removing Signal
  void SignalGatheringStateFired(IceTransportInternal* transport) {
    if (gathering_state_callback_) {
      gathering_state_callback_(transport);
    }
  }
};

}  // namespace cricket

#endif  // P2P_BASE_ICE_TRANSPORT_INTERNAL_H_