1 /* 2 * Copyright 2017 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 PC_JSEP_TRANSPORT_CONTROLLER_H_ 12 #define PC_JSEP_TRANSPORT_CONTROLLER_H_ 13 14 #include <map> 15 #include <memory> 16 #include <string> 17 #include <utility> 18 #include <vector> 19 20 #include "api/candidate.h" 21 #include "api/crypto/crypto_options.h" 22 #include "api/ice_transport_factory.h" 23 #include "api/peer_connection_interface.h" 24 #include "api/rtc_event_log/rtc_event_log.h" 25 #include "media/sctp/sctp_transport_internal.h" 26 #include "p2p/base/dtls_transport.h" 27 #include "p2p/base/dtls_transport_factory.h" 28 #include "p2p/base/p2p_transport_channel.h" 29 #include "pc/channel.h" 30 #include "pc/dtls_srtp_transport.h" 31 #include "pc/dtls_transport.h" 32 #include "pc/jsep_transport.h" 33 #include "pc/rtp_transport.h" 34 #include "pc/srtp_transport.h" 35 #include "rtc_base/async_invoker.h" 36 #include "rtc_base/constructor_magic.h" 37 #include "rtc_base/ref_counted_object.h" 38 #include "rtc_base/third_party/sigslot/sigslot.h" 39 40 namespace rtc { 41 class Thread; 42 class PacketTransportInternal; 43 } // namespace rtc 44 45 namespace webrtc { 46 47 class JsepTransportController : public sigslot::has_slots<> { 48 public: 49 // Used when the RtpTransport/DtlsTransport of the m= section is changed 50 // because the section is rejected or BUNDLE is enabled. 51 class Observer { 52 public: ~Observer()53 virtual ~Observer() {} 54 55 // Returns true if media associated with |mid| was successfully set up to be 56 // demultiplexed on |rtp_transport|. Could return false if two bundled m= 57 // sections use the same SSRC, for example. 58 // 59 // If a data channel transport must be negotiated, |data_channel_transport| 60 // and |negotiation_state| indicate negotiation status. If 61 // |data_channel_transport| is null, the data channel transport should not 62 // be used. Otherwise, the value is a pointer to the transport to be used 63 // for data channels on |mid|, if any. 64 // 65 // The observer should not send data on |data_channel_transport| until 66 // |negotiation_state| is provisional or final. It should not delete 67 // |data_channel_transport| or any fallback transport until 68 // |negotiation_state| is final. 69 virtual bool OnTransportChanged( 70 const std::string& mid, 71 RtpTransportInternal* rtp_transport, 72 rtc::scoped_refptr<DtlsTransport> dtls_transport, 73 DataChannelTransportInterface* data_channel_transport) = 0; 74 }; 75 76 struct Config { 77 // If |redetermine_role_on_ice_restart| is true, ICE role is redetermined 78 // upon setting a local transport description that indicates an ICE 79 // restart. 80 bool redetermine_role_on_ice_restart = true; 81 rtc::SSLProtocolVersion ssl_max_version = rtc::SSL_PROTOCOL_DTLS_12; 82 // |crypto_options| is used to determine if created DTLS transports 83 // negotiate GCM crypto suites or not. 84 webrtc::CryptoOptions crypto_options; 85 PeerConnectionInterface::BundlePolicy bundle_policy = 86 PeerConnectionInterface::kBundlePolicyBalanced; 87 PeerConnectionInterface::RtcpMuxPolicy rtcp_mux_policy = 88 PeerConnectionInterface::kRtcpMuxPolicyRequire; 89 bool disable_encryption = false; 90 bool enable_external_auth = false; 91 // Used to inject the ICE/DTLS transports created externally. 92 webrtc::IceTransportFactory* ice_transport_factory = nullptr; 93 cricket::DtlsTransportFactory* dtls_transport_factory = nullptr; 94 Observer* transport_observer = nullptr; 95 // Must be provided and valid for the lifetime of the 96 // JsepTransportController instance. 97 std::function<void(const rtc::CopyOnWriteBuffer& packet, 98 int64_t packet_time_us)> 99 rtcp_handler; 100 bool active_reset_srtp_params = false; 101 RtcEventLog* event_log = nullptr; 102 103 // Factory for SCTP transports. 104 cricket::SctpTransportInternalFactory* sctp_factory = nullptr; 105 }; 106 107 // The ICE related events are signaled on the |signaling_thread|. 108 // All the transport related methods are called on the |network_thread|. 109 JsepTransportController(rtc::Thread* signaling_thread, 110 rtc::Thread* network_thread, 111 cricket::PortAllocator* port_allocator, 112 AsyncResolverFactory* async_resolver_factory, 113 Config config); 114 virtual ~JsepTransportController(); 115 116 // The main method to be called; applies a description at the transport 117 // level, creating/destroying transport objects as needed and updating their 118 // properties. This includes RTP, DTLS, and ICE (but not SCTP). At least not 119 // yet? May make sense to in the future. 120 RTCError SetLocalDescription(SdpType type, 121 const cricket::SessionDescription* description); 122 123 RTCError SetRemoteDescription(SdpType type, 124 const cricket::SessionDescription* description); 125 126 // Get transports to be used for the provided |mid|. If bundling is enabled, 127 // calling GetRtpTransport for multiple MIDs may yield the same object. 128 RtpTransportInternal* GetRtpTransport(const std::string& mid) const; 129 cricket::DtlsTransportInternal* GetDtlsTransport(const std::string& mid); 130 const cricket::DtlsTransportInternal* GetRtcpDtlsTransport( 131 const std::string& mid) const; 132 // Gets the externally sharable version of the DtlsTransport. 133 rtc::scoped_refptr<webrtc::DtlsTransport> LookupDtlsTransportByMid( 134 const std::string& mid); 135 rtc::scoped_refptr<SctpTransport> GetSctpTransport( 136 const std::string& mid) const; 137 138 DataChannelTransportInterface* GetDataChannelTransport( 139 const std::string& mid) const; 140 141 /********************* 142 * ICE-related methods 143 ********************/ 144 // This method is public to allow PeerConnection to update it from 145 // SetConfiguration. 146 void SetIceConfig(const cricket::IceConfig& config); 147 // Set the "needs-ice-restart" flag as described in JSEP. After the flag is 148 // set, offers should generate new ufrags/passwords until an ICE restart 149 // occurs. 150 void SetNeedsIceRestartFlag(); 151 // Returns true if the ICE restart flag above was set, and no ICE restart has 152 // occurred yet for this transport (by applying a local description with 153 // changed ufrag/password). If the transport has been deleted as a result of 154 // bundling, returns false. 155 bool NeedsIceRestart(const std::string& mid) const; 156 // Start gathering candidates for any new transports, or transports doing an 157 // ICE restart. 158 void MaybeStartGathering(); 159 RTCError AddRemoteCandidates( 160 const std::string& mid, 161 const std::vector<cricket::Candidate>& candidates); 162 RTCError RemoveRemoteCandidates( 163 const std::vector<cricket::Candidate>& candidates); 164 165 /********************** 166 * DTLS-related methods 167 *********************/ 168 // Specifies the identity to use in this session. 169 // Can only be called once. 170 bool SetLocalCertificate( 171 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate); 172 rtc::scoped_refptr<rtc::RTCCertificate> GetLocalCertificate( 173 const std::string& mid) const; 174 // Caller owns returned certificate chain. This method mainly exists for 175 // stats reporting. 176 std::unique_ptr<rtc::SSLCertChain> GetRemoteSSLCertChain( 177 const std::string& mid) const; 178 // Get negotiated role, if one has been negotiated. 179 absl::optional<rtc::SSLRole> GetDtlsRole(const std::string& mid) const; 180 181 // TODO(deadbeef): GetStats isn't const because all the way down to 182 // OpenSSLStreamAdapter, GetSslCipherSuite and GetDtlsSrtpCryptoSuite are not 183 // const. Fix this. 184 bool GetStats(const std::string& mid, cricket::TransportStats* stats); 185 initial_offerer()186 bool initial_offerer() const { return initial_offerer_ && *initial_offerer_; } 187 188 void SetActiveResetSrtpParams(bool active_reset_srtp_params); 189 190 // For now the rollback only removes mid to transport mappings 191 // and deletes unused transports, but doesn't consider anything more complex. 192 void RollbackTransports(); 193 194 // All of these signals are fired on the signaling thread. 195 196 // If any transport failed => failed, 197 // Else if all completed => completed, 198 // Else if all connected => connected, 199 // Else => connecting 200 sigslot::signal1<cricket::IceConnectionState> SignalIceConnectionState; 201 202 sigslot::signal1<PeerConnectionInterface::PeerConnectionState> 203 SignalConnectionState; 204 sigslot::signal1<PeerConnectionInterface::IceConnectionState> 205 SignalStandardizedIceConnectionState; 206 207 // If all transports done gathering => complete, 208 // Else if any are gathering => gathering, 209 // Else => new 210 sigslot::signal1<cricket::IceGatheringState> SignalIceGatheringState; 211 212 // (mid, candidates) 213 sigslot::signal2<const std::string&, const std::vector<cricket::Candidate>&> 214 SignalIceCandidatesGathered; 215 216 sigslot::signal1<const cricket::IceCandidateErrorEvent&> 217 SignalIceCandidateError; 218 219 sigslot::signal1<const std::vector<cricket::Candidate>&> 220 SignalIceCandidatesRemoved; 221 222 sigslot::signal1<const cricket::CandidatePairChangeEvent&> 223 SignalIceCandidatePairChanged; 224 225 sigslot::signal1<rtc::SSLHandshakeError> SignalDtlsHandshakeError; 226 227 private: 228 RTCError ApplyDescription_n(bool local, 229 SdpType type, 230 const cricket::SessionDescription* description); 231 RTCError ValidateAndMaybeUpdateBundleGroup( 232 bool local, 233 SdpType type, 234 const cricket::SessionDescription* description); 235 RTCError ValidateContent(const cricket::ContentInfo& content_info); 236 237 void HandleRejectedContent(const cricket::ContentInfo& content_info, 238 const cricket::SessionDescription* description); 239 bool HandleBundledContent(const cricket::ContentInfo& content_info); 240 241 bool SetTransportForMid(const std::string& mid, 242 cricket::JsepTransport* jsep_transport); 243 void RemoveTransportForMid(const std::string& mid); 244 245 cricket::JsepTransportDescription CreateJsepTransportDescription( 246 const cricket::ContentInfo& content_info, 247 const cricket::TransportInfo& transport_info, 248 const std::vector<int>& encrypted_extension_ids, 249 int rtp_abs_sendtime_extn_id); 250 bundled_mid()251 absl::optional<std::string> bundled_mid() const { 252 absl::optional<std::string> bundled_mid; 253 if (bundle_group_ && bundle_group_->FirstContentName()) { 254 bundled_mid = *(bundle_group_->FirstContentName()); 255 } 256 return bundled_mid; 257 } 258 IsBundled(const std::string & mid)259 bool IsBundled(const std::string& mid) const { 260 return bundle_group_ && bundle_group_->HasContentName(mid); 261 } 262 263 bool ShouldUpdateBundleGroup(SdpType type, 264 const cricket::SessionDescription* description); 265 266 std::vector<int> MergeEncryptedHeaderExtensionIdsForBundle( 267 const cricket::SessionDescription* description); 268 std::vector<int> GetEncryptedHeaderExtensionIds( 269 const cricket::ContentInfo& content_info); 270 271 int GetRtpAbsSendTimeHeaderExtensionId( 272 const cricket::ContentInfo& content_info); 273 274 // This method takes the BUNDLE group into account. If the JsepTransport is 275 // destroyed because of BUNDLE, it would return the transport which other 276 // transports are bundled on (In current implementation, it is the first 277 // content in the BUNDLE group). 278 const cricket::JsepTransport* GetJsepTransportForMid( 279 const std::string& mid) const; 280 cricket::JsepTransport* GetJsepTransportForMid(const std::string& mid); 281 282 // Get the JsepTransport without considering the BUNDLE group. Return nullptr 283 // if the JsepTransport is destroyed. 284 const cricket::JsepTransport* GetJsepTransportByName( 285 const std::string& transport_name) const; 286 cricket::JsepTransport* GetJsepTransportByName( 287 const std::string& transport_name); 288 289 // Creates jsep transport. Noop if transport is already created. 290 // Transport is created either during SetLocalDescription (|local| == true) or 291 // during SetRemoteDescription (|local| == false). Passing |local| helps to 292 // differentiate initiator (caller) from answerer (callee). 293 RTCError MaybeCreateJsepTransport( 294 bool local, 295 const cricket::ContentInfo& content_info, 296 const cricket::SessionDescription& description); 297 298 void MaybeDestroyJsepTransport(const std::string& mid); 299 void DestroyAllJsepTransports_n(); 300 301 void SetIceRole_n(cricket::IceRole ice_role); 302 303 cricket::IceRole DetermineIceRole( 304 cricket::JsepTransport* jsep_transport, 305 const cricket::TransportInfo& transport_info, 306 SdpType type, 307 bool local); 308 309 std::unique_ptr<cricket::DtlsTransportInternal> CreateDtlsTransport( 310 const cricket::ContentInfo& content_info, 311 cricket::IceTransportInternal* ice); 312 rtc::scoped_refptr<webrtc::IceTransportInterface> CreateIceTransport( 313 const std::string& transport_name, 314 bool rtcp); 315 316 std::unique_ptr<webrtc::RtpTransport> CreateUnencryptedRtpTransport( 317 const std::string& transport_name, 318 rtc::PacketTransportInternal* rtp_packet_transport, 319 rtc::PacketTransportInternal* rtcp_packet_transport); 320 std::unique_ptr<webrtc::SrtpTransport> CreateSdesTransport( 321 const std::string& transport_name, 322 cricket::DtlsTransportInternal* rtp_dtls_transport, 323 cricket::DtlsTransportInternal* rtcp_dtls_transport); 324 std::unique_ptr<webrtc::DtlsSrtpTransport> CreateDtlsSrtpTransport( 325 const std::string& transport_name, 326 cricket::DtlsTransportInternal* rtp_dtls_transport, 327 cricket::DtlsTransportInternal* rtcp_dtls_transport); 328 329 // Collect all the DtlsTransports, including RTP and RTCP, from the 330 // JsepTransports. JsepTransportController can iterate all the DtlsTransports 331 // and update the aggregate states. 332 std::vector<cricket::DtlsTransportInternal*> GetDtlsTransports(); 333 334 // Handlers for signals from Transport. 335 void OnTransportWritableState_n(rtc::PacketTransportInternal* transport); 336 void OnTransportReceivingState_n(rtc::PacketTransportInternal* transport); 337 void OnTransportGatheringState_n(cricket::IceTransportInternal* transport); 338 void OnTransportCandidateGathered_n(cricket::IceTransportInternal* transport, 339 const cricket::Candidate& candidate); 340 void OnTransportCandidateError_n( 341 cricket::IceTransportInternal* transport, 342 const cricket::IceCandidateErrorEvent& event); 343 void OnTransportCandidatesRemoved_n(cricket::IceTransportInternal* transport, 344 const cricket::Candidates& candidates); 345 void OnTransportRoleConflict_n(cricket::IceTransportInternal* transport); 346 void OnTransportStateChanged_n(cricket::IceTransportInternal* transport); 347 void OnTransportCandidatePairChanged_n( 348 const cricket::CandidatePairChangeEvent& event); 349 void UpdateAggregateStates_n(); 350 351 void OnRtcpPacketReceived_n(rtc::CopyOnWriteBuffer* packet, 352 int64_t packet_time_us); 353 354 void OnDtlsHandshakeError(rtc::SSLHandshakeError error); 355 356 rtc::Thread* const signaling_thread_ = nullptr; 357 rtc::Thread* const network_thread_ = nullptr; 358 cricket::PortAllocator* const port_allocator_ = nullptr; 359 AsyncResolverFactory* const async_resolver_factory_ = nullptr; 360 361 std::map<std::string, std::unique_ptr<cricket::JsepTransport>> 362 jsep_transports_by_name_; 363 // This keeps track of the mapping between media section 364 // (BaseChannel/SctpTransport) and the JsepTransport underneath. 365 std::map<std::string, cricket::JsepTransport*> mid_to_transport_; 366 // Keep track of mids that have been mapped to transports. Used for rollback. 367 std::vector<std::string> pending_mids_ RTC_GUARDED_BY(network_thread_); 368 // Aggregate states for Transports. 369 // standardized_ice_connection_state_ is intended to replace 370 // ice_connection_state, see bugs.webrtc.org/9308 371 cricket::IceConnectionState ice_connection_state_ = 372 cricket::kIceConnectionConnecting; 373 PeerConnectionInterface::IceConnectionState 374 standardized_ice_connection_state_ = 375 PeerConnectionInterface::kIceConnectionNew; 376 PeerConnectionInterface::PeerConnectionState combined_connection_state_ = 377 PeerConnectionInterface::PeerConnectionState::kNew; 378 cricket::IceGatheringState ice_gathering_state_ = cricket::kIceGatheringNew; 379 380 Config config_; 381 382 const cricket::SessionDescription* local_desc_ = nullptr; 383 const cricket::SessionDescription* remote_desc_ = nullptr; 384 absl::optional<bool> initial_offerer_; 385 386 absl::optional<cricket::ContentGroup> bundle_group_; 387 388 cricket::IceConfig ice_config_; 389 cricket::IceRole ice_role_ = cricket::ICEROLE_CONTROLLING; 390 uint64_t ice_tiebreaker_ = rtc::CreateRandomId64(); 391 rtc::scoped_refptr<rtc::RTCCertificate> certificate_; 392 rtc::AsyncInvoker invoker_; 393 394 RTC_DISALLOW_COPY_AND_ASSIGN(JsepTransportController); 395 }; 396 397 } // namespace webrtc 398 399 #endif // PC_JSEP_TRANSPORT_CONTROLLER_H_ 400