deadbeef | 49f34fd | 2016-12-06 16:22:06 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2004 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 WEBRTC_P2P_BASE_JSEPTRANSPORT_H_ |
| 12 | #define WEBRTC_P2P_BASE_JSEPTRANSPORT_H_ |
| 13 | |
| 14 | #include <map> |
| 15 | #include <memory> |
| 16 | #include <string> |
| 17 | #include <vector> |
| 18 | |
kwiberg | 84f6a3f | 2017-09-05 08:43:13 -0700 | [diff] [blame] | 19 | #include "webrtc/api/optional.h" |
deadbeef | 49f34fd | 2016-12-06 16:22:06 -0800 | [diff] [blame] | 20 | #include "webrtc/p2p/base/candidate.h" |
| 21 | #include "webrtc/p2p/base/p2pconstants.h" |
| 22 | #include "webrtc/p2p/base/sessiondescription.h" |
| 23 | #include "webrtc/p2p/base/transportinfo.h" |
Edward Lemur | c20978e | 2017-07-06 19:44:34 +0200 | [diff] [blame] | 24 | #include "webrtc/rtc_base/constructormagic.h" |
| 25 | #include "webrtc/rtc_base/messagequeue.h" |
Edward Lemur | c20978e | 2017-07-06 19:44:34 +0200 | [diff] [blame] | 26 | #include "webrtc/rtc_base/rtccertificate.h" |
| 27 | #include "webrtc/rtc_base/sigslot.h" |
| 28 | #include "webrtc/rtc_base/sslstreamadapter.h" |
deadbeef | 49f34fd | 2016-12-06 16:22:06 -0800 | [diff] [blame] | 29 | |
| 30 | namespace cricket { |
| 31 | |
zhihuang | b2cdd93 | 2017-01-19 16:54:25 -0800 | [diff] [blame] | 32 | class DtlsTransportInternal; |
hbos | 06495bc | 2017-01-02 08:08:18 -0800 | [diff] [blame] | 33 | enum class IceCandidatePairState; |
deadbeef | 49f34fd | 2016-12-06 16:22:06 -0800 | [diff] [blame] | 34 | |
| 35 | typedef std::vector<Candidate> Candidates; |
| 36 | |
| 37 | // TODO(deadbeef): Move all of these enums, POD types and utility methods to |
| 38 | // another header file. |
| 39 | |
| 40 | // TODO(deadbeef): Unify with PeerConnectionInterface::IceConnectionState |
| 41 | // once /talk/ and /webrtc/ are combined, and also switch to ENUM_NAME naming |
| 42 | // style. |
| 43 | enum IceConnectionState { |
| 44 | kIceConnectionConnecting = 0, |
| 45 | kIceConnectionFailed, |
| 46 | kIceConnectionConnected, // Writable, but still checking one or more |
| 47 | // connections |
| 48 | kIceConnectionCompleted, |
| 49 | }; |
| 50 | |
| 51 | enum DtlsTransportState { |
| 52 | // Haven't started negotiating. |
| 53 | DTLS_TRANSPORT_NEW = 0, |
| 54 | // Have started negotiating. |
| 55 | DTLS_TRANSPORT_CONNECTING, |
| 56 | // Negotiated, and has a secure connection. |
| 57 | DTLS_TRANSPORT_CONNECTED, |
| 58 | // Transport is closed. |
| 59 | DTLS_TRANSPORT_CLOSED, |
| 60 | // Failed due to some error in the handshake process. |
| 61 | DTLS_TRANSPORT_FAILED, |
| 62 | }; |
| 63 | |
| 64 | // TODO(deadbeef): Unify with PeerConnectionInterface::IceConnectionState |
| 65 | // once /talk/ and /webrtc/ are combined, and also switch to ENUM_NAME naming |
| 66 | // style. |
| 67 | enum IceGatheringState { |
| 68 | kIceGatheringNew = 0, |
| 69 | kIceGatheringGathering, |
| 70 | kIceGatheringComplete, |
| 71 | }; |
| 72 | |
| 73 | enum ContinualGatheringPolicy { |
| 74 | // All port allocator sessions will stop after a writable connection is found. |
| 75 | GATHER_ONCE = 0, |
| 76 | // The most recent port allocator session will keep on running. |
| 77 | GATHER_CONTINUALLY, |
| 78 | // The most recent port allocator session will keep on running, and it will |
| 79 | // try to recover connectivity if the channel becomes disconnected. |
| 80 | GATHER_CONTINUALLY_AND_RECOVER, |
| 81 | }; |
| 82 | |
| 83 | // Stats that we can return about the connections for a transport channel. |
| 84 | // TODO(hta): Rename to ConnectionStats |
| 85 | struct ConnectionInfo { |
hbos | 06495bc | 2017-01-02 08:08:18 -0800 | [diff] [blame] | 86 | ConnectionInfo(); |
deadbeef | 49f34fd | 2016-12-06 16:22:06 -0800 | [diff] [blame] | 87 | |
| 88 | bool best_connection; // Is this the best connection we have? |
| 89 | bool writable; // Has this connection received a STUN response? |
| 90 | bool receiving; // Has this connection received anything? |
| 91 | bool timeout; // Has this connection timed out? |
| 92 | bool new_connection; // Is this a newly created connection? |
| 93 | size_t rtt; // The STUN RTT for this connection. |
| 94 | size_t sent_total_bytes; // Total bytes sent on this connection. |
| 95 | size_t sent_bytes_second; // Bps over the last measurement interval. |
| 96 | size_t sent_discarded_packets; // Number of outgoing packets discarded due to |
| 97 | // socket errors. |
| 98 | size_t sent_total_packets; // Number of total outgoing packets attempted for |
| 99 | // sending. |
| 100 | size_t sent_ping_requests_total; // Number of STUN ping request sent. |
| 101 | size_t sent_ping_requests_before_first_response; // Number of STUN ping |
| 102 | // sent before receiving the first response. |
| 103 | size_t sent_ping_responses; // Number of STUN ping response sent. |
| 104 | |
| 105 | size_t recv_total_bytes; // Total bytes received on this connection. |
| 106 | size_t recv_bytes_second; // Bps over the last measurement interval. |
| 107 | size_t recv_ping_requests; // Number of STUN ping request received. |
| 108 | size_t recv_ping_responses; // Number of STUN ping response received. |
| 109 | Candidate local_candidate; // The local candidate for this connection. |
| 110 | Candidate remote_candidate; // The remote candidate for this connection. |
| 111 | void* key; // A static value that identifies this conn. |
hbos | 06495bc | 2017-01-02 08:08:18 -0800 | [diff] [blame] | 112 | // https://w3c.github.io/webrtc-stats/#dom-rtcicecandidatepairstats-state |
| 113 | IceCandidatePairState state; |
| 114 | // https://w3c.github.io/webrtc-stats/#dom-rtcicecandidatepairstats-priority |
| 115 | uint64_t priority; |
hbos | 92eaec6 | 2017-02-27 01:38:08 -0800 | [diff] [blame] | 116 | // https://w3c.github.io/webrtc-stats/#dom-rtcicecandidatepairstats-nominated |
| 117 | bool nominated; |
hbos | bf8d3e5 | 2017-02-28 06:34:47 -0800 | [diff] [blame] | 118 | // https://w3c.github.io/webrtc-stats/#dom-rtcicecandidatepairstats-totalroundtriptime |
| 119 | uint64_t total_round_trip_time_ms; |
| 120 | // https://w3c.github.io/webrtc-stats/#dom-rtcicecandidatepairstats-currentroundtriptime |
| 121 | rtc::Optional<uint32_t> current_round_trip_time_ms; |
deadbeef | 49f34fd | 2016-12-06 16:22:06 -0800 | [diff] [blame] | 122 | }; |
| 123 | |
| 124 | // Information about all the connections of a channel. |
| 125 | typedef std::vector<ConnectionInfo> ConnectionInfos; |
| 126 | |
| 127 | // Information about a specific channel |
| 128 | struct TransportChannelStats { |
| 129 | int component = 0; |
| 130 | ConnectionInfos connection_infos; |
| 131 | int srtp_crypto_suite = rtc::SRTP_INVALID_CRYPTO_SUITE; |
| 132 | int ssl_cipher_suite = rtc::TLS_NULL_WITH_NULL_NULL; |
hbos | 7064d59 | 2017-01-16 07:38:02 -0800 | [diff] [blame] | 133 | DtlsTransportState dtls_state = DTLS_TRANSPORT_NEW; |
deadbeef | 49f34fd | 2016-12-06 16:22:06 -0800 | [diff] [blame] | 134 | }; |
| 135 | |
| 136 | // Information about all the channels of a transport. |
| 137 | // TODO(hta): Consider if a simple vector is as good as a map. |
| 138 | typedef std::vector<TransportChannelStats> TransportChannelStatsList; |
| 139 | |
| 140 | // Information about the stats of a transport. |
| 141 | struct TransportStats { |
| 142 | std::string transport_name; |
| 143 | TransportChannelStatsList channel_stats; |
| 144 | }; |
| 145 | |
| 146 | // ICE Nomination mode. |
| 147 | enum class NominationMode { |
| 148 | REGULAR, // Nominate once per ICE restart (Not implemented yet). |
| 149 | AGGRESSIVE, // Nominate every connection except that it will behave as if |
| 150 | // REGULAR when the remote is an ICE-LITE endpoint. |
| 151 | SEMI_AGGRESSIVE // Our current implementation of the nomination algorithm. |
| 152 | // The details are described in P2PTransportChannel. |
| 153 | }; |
| 154 | |
| 155 | // Information about ICE configuration. |
| 156 | // TODO(deadbeef): Use rtc::Optional to represent unset values, instead of |
| 157 | // -1. |
| 158 | struct IceConfig { |
| 159 | // The ICE connection receiving timeout value in milliseconds. |
| 160 | int receiving_timeout = -1; |
| 161 | // Time interval in milliseconds to ping a backup connection when the ICE |
| 162 | // channel is strongly connected. |
| 163 | int backup_connection_ping_interval = -1; |
| 164 | |
| 165 | ContinualGatheringPolicy continual_gathering_policy = GATHER_ONCE; |
| 166 | |
| 167 | bool gather_continually() const { |
| 168 | return continual_gathering_policy == GATHER_CONTINUALLY || |
| 169 | continual_gathering_policy == GATHER_CONTINUALLY_AND_RECOVER; |
| 170 | } |
| 171 | |
| 172 | // Whether we should prioritize Relay/Relay candidate when nothing |
| 173 | // is writable yet. |
| 174 | bool prioritize_most_likely_candidate_pairs = false; |
| 175 | |
| 176 | // Writable connections are pinged at a slower rate once stablized. |
| 177 | int stable_writable_connection_ping_interval = -1; |
| 178 | |
| 179 | // If set to true, this means the ICE transport should presume TURN-to-TURN |
| 180 | // candidate pairs will succeed, even before a binding response is received. |
| 181 | bool presume_writable_when_fully_relayed = false; |
| 182 | |
| 183 | // Interval to check on all networks and to perform ICE regathering on any |
| 184 | // active network having no connection on it. |
| 185 | rtc::Optional<int> regather_on_failed_networks_interval; |
| 186 | |
Steve Anton | 300bf8e | 2017-07-14 10:13:10 -0700 | [diff] [blame] | 187 | // Interval to perform ICE regathering on all networks |
| 188 | // The delay in milliseconds is sampled from the uniform distribution [a, b] |
| 189 | rtc::Optional<rtc::IntervalRange> regather_all_networks_interval_range; |
| 190 | |
deadbeef | 49f34fd | 2016-12-06 16:22:06 -0800 | [diff] [blame] | 191 | // The time period in which we will not switch the selected connection |
| 192 | // when a new connection becomes receiving but the selected connection is not |
| 193 | // in case that the selected connection may become receiving soon. |
| 194 | rtc::Optional<int> receiving_switching_delay; |
| 195 | |
| 196 | // TODO(honghaiz): Change the default to regular nomination. |
| 197 | // Default nomination mode if the remote does not support renomination. |
| 198 | NominationMode default_nomination_mode = NominationMode::SEMI_AGGRESSIVE; |
| 199 | |
skvlad | 5107246 | 2017-02-02 11:50:14 -0800 | [diff] [blame] | 200 | // ICE checks (STUN pings) will not be sent at higher rate (lower interval) |
| 201 | // than this, no matter what other settings there are. |
| 202 | // Measure in milliseconds. |
| 203 | rtc::Optional<int> ice_check_min_interval; |
| 204 | |
deadbeef | 49f34fd | 2016-12-06 16:22:06 -0800 | [diff] [blame] | 205 | IceConfig() {} |
| 206 | IceConfig(int receiving_timeout_ms, |
| 207 | int backup_connection_ping_interval, |
| 208 | ContinualGatheringPolicy gathering_policy, |
| 209 | bool prioritize_most_likely_candidate_pairs, |
| 210 | int stable_writable_connection_ping_interval_ms, |
| 211 | bool presume_writable_when_fully_relayed, |
| 212 | int regather_on_failed_networks_interval_ms, |
| 213 | int receiving_switching_delay_ms) |
| 214 | : receiving_timeout(receiving_timeout_ms), |
| 215 | backup_connection_ping_interval(backup_connection_ping_interval), |
| 216 | continual_gathering_policy(gathering_policy), |
| 217 | prioritize_most_likely_candidate_pairs( |
| 218 | prioritize_most_likely_candidate_pairs), |
| 219 | stable_writable_connection_ping_interval( |
| 220 | stable_writable_connection_ping_interval_ms), |
| 221 | presume_writable_when_fully_relayed( |
| 222 | presume_writable_when_fully_relayed), |
| 223 | regather_on_failed_networks_interval( |
| 224 | regather_on_failed_networks_interval_ms), |
| 225 | receiving_switching_delay(receiving_switching_delay_ms) {} |
| 226 | }; |
| 227 | |
| 228 | bool BadTransportDescription(const std::string& desc, std::string* err_desc); |
| 229 | |
| 230 | bool IceCredentialsChanged(const std::string& old_ufrag, |
| 231 | const std::string& old_pwd, |
| 232 | const std::string& new_ufrag, |
| 233 | const std::string& new_pwd); |
| 234 | |
| 235 | // If a candidate is not acceptable, returns false and sets error. |
| 236 | bool VerifyCandidate(const Candidate& candidate, std::string* error); |
| 237 | bool VerifyCandidates(const Candidates& candidates, std::string* error); |
| 238 | |
| 239 | // Helper class used by TransportController that processes |
| 240 | // TransportDescriptions. A TransportDescription represents the |
| 241 | // transport-specific properties of an SDP m= section, processed according to |
| 242 | // JSEP. Each transport consists of DTLS and ICE transport channels for RTP |
| 243 | // (and possibly RTCP, if rtcp-mux isn't used). |
| 244 | // |
| 245 | // On Threading: Transport performs work solely on the network thread, and so |
| 246 | // its methods should only be called on the network thread. |
| 247 | // |
| 248 | // TODO(deadbeef): Move this into /pc/ and out of /p2p/base/, since it's |
| 249 | // PeerConnection-specific. |
| 250 | class JsepTransport : public sigslot::has_slots<> { |
| 251 | public: |
| 252 | // |mid| is just used for log statements in order to identify the Transport. |
| 253 | // Note that |certificate| is allowed to be null since a remote description |
| 254 | // may be set before a local certificate is generated. |
| 255 | JsepTransport(const std::string& mid, |
| 256 | const rtc::scoped_refptr<rtc::RTCCertificate>& certificate); |
| 257 | |
| 258 | // Returns the MID of this transport. |
| 259 | const std::string& mid() const { return mid_; } |
| 260 | |
| 261 | // Add or remove channel that is affected when a local/remote transport |
| 262 | // description is set on this transport. Need to add all channels before |
| 263 | // setting a transport description. |
zhihuang | b2cdd93 | 2017-01-19 16:54:25 -0800 | [diff] [blame] | 264 | bool AddChannel(DtlsTransportInternal* dtls, int component); |
deadbeef | 49f34fd | 2016-12-06 16:22:06 -0800 | [diff] [blame] | 265 | bool RemoveChannel(int component); |
| 266 | bool HasChannels() const; |
| 267 | |
| 268 | bool ready_for_remote_candidates() const { |
| 269 | return local_description_set_ && remote_description_set_; |
| 270 | } |
| 271 | |
| 272 | // Must be called before applying local session description. |
| 273 | // Needed in order to verify the local fingerprint. |
| 274 | void SetLocalCertificate( |
| 275 | const rtc::scoped_refptr<rtc::RTCCertificate>& certificate); |
| 276 | |
| 277 | // Get a copy of the local certificate provided by SetLocalCertificate. |
| 278 | bool GetLocalCertificate( |
| 279 | rtc::scoped_refptr<rtc::RTCCertificate>* certificate) const; |
| 280 | |
| 281 | // Set the local TransportDescription to be used by DTLS and ICE channels |
| 282 | // that are part of this Transport. |
| 283 | bool SetLocalTransportDescription(const TransportDescription& description, |
| 284 | ContentAction action, |
| 285 | std::string* error_desc); |
| 286 | |
| 287 | // Set the remote TransportDescription to be used by DTLS and ICE channels |
| 288 | // that are part of this Transport. |
| 289 | bool SetRemoteTransportDescription(const TransportDescription& description, |
| 290 | ContentAction action, |
| 291 | std::string* error_desc); |
| 292 | |
deadbeef | d1a38b5 | 2016-12-10 13:15:33 -0800 | [diff] [blame] | 293 | // Set the "needs-ice-restart" flag as described in JSEP. After the flag is |
| 294 | // set, offers should generate new ufrags/passwords until an ICE restart |
| 295 | // occurs. |
| 296 | // |
| 297 | // This and the below method can be called safely from any thread as long as |
| 298 | // SetXTransportDescription is not in progress. |
| 299 | void SetNeedsIceRestartFlag(); |
| 300 | // Returns true if the ICE restart flag above was set, and no ICE restart has |
| 301 | // occurred yet for this transport (by applying a local description with |
| 302 | // changed ufrag/password). |
| 303 | bool NeedsIceRestart() const; |
| 304 | |
deadbeef | d8cfa1a | 2017-03-27 10:33:26 -0700 | [diff] [blame] | 305 | // Returns role if negotiated, or empty Optional if it hasn't been negotiated |
| 306 | // yet. |
| 307 | rtc::Optional<rtc::SSLRole> GetSslRole() const; |
deadbeef | 49f34fd | 2016-12-06 16:22:06 -0800 | [diff] [blame] | 308 | |
| 309 | // TODO(deadbeef): Make this const. See comment in transportcontroller.h. |
| 310 | bool GetStats(TransportStats* stats); |
| 311 | |
| 312 | // The current local transport description, possibly used |
| 313 | // by the transport controller. |
| 314 | const TransportDescription* local_description() const { |
| 315 | return local_description_.get(); |
| 316 | } |
| 317 | |
| 318 | // The current remote transport description, possibly used |
| 319 | // by the transport controller. |
| 320 | const TransportDescription* remote_description() const { |
| 321 | return remote_description_.get(); |
| 322 | } |
| 323 | |
| 324 | // TODO(deadbeef): The methods below are only public for testing. Should make |
| 325 | // them utility functions or objects so they can be tested independently from |
| 326 | // this class. |
| 327 | |
| 328 | // Returns false if the certificate's identity does not match the fingerprint, |
| 329 | // or either is NULL. |
| 330 | bool VerifyCertificateFingerprint(const rtc::RTCCertificate* certificate, |
| 331 | const rtc::SSLFingerprint* fingerprint, |
| 332 | std::string* error_desc) const; |
| 333 | |
deadbeef | 49f34fd | 2016-12-06 16:22:06 -0800 | [diff] [blame] | 334 | private: |
deadbeef | 49f34fd | 2016-12-06 16:22:06 -0800 | [diff] [blame] | 335 | // Negotiates the transport parameters based on the current local and remote |
| 336 | // transport description, such as the ICE role to use, and whether DTLS |
| 337 | // should be activated. |
| 338 | // |
| 339 | // Called when an answer TransportDescription is applied. |
deadbeef | d8cfa1a | 2017-03-27 10:33:26 -0700 | [diff] [blame] | 340 | bool NegotiateTransportDescription(ContentAction local_description_type, |
deadbeef | 49f34fd | 2016-12-06 16:22:06 -0800 | [diff] [blame] | 341 | std::string* error_desc); |
| 342 | |
deadbeef | d8cfa1a | 2017-03-27 10:33:26 -0700 | [diff] [blame] | 343 | // Negotiates the SSL role based off the offer and answer as specified by |
| 344 | // RFC 4145, section-4.1. Returns false if the SSL role cannot be determined |
| 345 | // from the local description and remote description. |
| 346 | bool NegotiateRole(ContentAction local_description_type, |
| 347 | std::string* error_desc); |
| 348 | |
deadbeef | 49f34fd | 2016-12-06 16:22:06 -0800 | [diff] [blame] | 349 | // Pushes down the transport parameters from the local description, such |
| 350 | // as the ICE ufrag and pwd. |
zhihuang | b2cdd93 | 2017-01-19 16:54:25 -0800 | [diff] [blame] | 351 | bool ApplyLocalTransportDescription(DtlsTransportInternal* dtls_transport, |
deadbeef | 49f34fd | 2016-12-06 16:22:06 -0800 | [diff] [blame] | 352 | std::string* error_desc); |
| 353 | |
| 354 | // Pushes down the transport parameters from the remote description to the |
| 355 | // transport channel. |
zhihuang | b2cdd93 | 2017-01-19 16:54:25 -0800 | [diff] [blame] | 356 | bool ApplyRemoteTransportDescription(DtlsTransportInternal* dtls_transport, |
deadbeef | 49f34fd | 2016-12-06 16:22:06 -0800 | [diff] [blame] | 357 | std::string* error_desc); |
| 358 | |
| 359 | // Pushes down the transport parameters obtained via negotiation. |
zhihuang | b2cdd93 | 2017-01-19 16:54:25 -0800 | [diff] [blame] | 360 | bool ApplyNegotiatedTransportDescription( |
| 361 | DtlsTransportInternal* dtls_transport, |
| 362 | std::string* error_desc); |
deadbeef | 49f34fd | 2016-12-06 16:22:06 -0800 | [diff] [blame] | 363 | |
| 364 | const std::string mid_; |
deadbeef | d1a38b5 | 2016-12-10 13:15:33 -0800 | [diff] [blame] | 365 | // needs-ice-restart bit as described in JSEP. |
| 366 | bool needs_ice_restart_ = false; |
deadbeef | 49f34fd | 2016-12-06 16:22:06 -0800 | [diff] [blame] | 367 | rtc::scoped_refptr<rtc::RTCCertificate> certificate_; |
deadbeef | d8cfa1a | 2017-03-27 10:33:26 -0700 | [diff] [blame] | 368 | rtc::Optional<rtc::SSLRole> ssl_role_; |
deadbeef | 49f34fd | 2016-12-06 16:22:06 -0800 | [diff] [blame] | 369 | std::unique_ptr<rtc::SSLFingerprint> remote_fingerprint_; |
| 370 | std::unique_ptr<TransportDescription> local_description_; |
| 371 | std::unique_ptr<TransportDescription> remote_description_; |
| 372 | bool local_description_set_ = false; |
| 373 | bool remote_description_set_ = false; |
| 374 | |
| 375 | // Candidate component => DTLS channel |
zhihuang | b2cdd93 | 2017-01-19 16:54:25 -0800 | [diff] [blame] | 376 | std::map<int, DtlsTransportInternal*> channels_; |
deadbeef | 49f34fd | 2016-12-06 16:22:06 -0800 | [diff] [blame] | 377 | |
| 378 | RTC_DISALLOW_COPY_AND_ASSIGN(JsepTransport); |
| 379 | }; |
| 380 | |
| 381 | } // namespace cricket |
| 382 | |
| 383 | #endif // WEBRTC_P2P_BASE_JSEPTRANSPORT_H_ |