/* * Copyright 2012 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 PC_PEER_CONNECTION_H_ #define PC_PEER_CONNECTION_H_ #include #include #include #include #include #include #include #include #include "absl/types/optional.h" #include "api/adaptation/resource.h" #include "api/async_dns_resolver.h" #include "api/async_resolver_factory.h" #include "api/audio_options.h" #include "api/candidate.h" #include "api/crypto/crypto_options.h" #include "api/data_channel_interface.h" #include "api/dtls_transport_interface.h" #include "api/ice_transport_interface.h" #include "api/jsep.h" #include "api/media_stream_interface.h" #include "api/media_types.h" #include "api/packet_socket_factory.h" #include "api/peer_connection_interface.h" #include "api/rtc_error.h" #include "api/rtc_event_log/rtc_event_log.h" #include "api/rtc_event_log_output.h" #include "api/rtp_parameters.h" #include "api/rtp_receiver_interface.h" #include "api/rtp_sender_interface.h" #include "api/rtp_transceiver_interface.h" #include "api/scoped_refptr.h" #include "api/sctp_transport_interface.h" #include "api/sequence_checker.h" #include "api/set_local_description_observer_interface.h" #include "api/set_remote_description_observer_interface.h" #include "api/stats/rtc_stats_collector_callback.h" #include "api/transport/bitrate_settings.h" #include "api/transport/data_channel_transport_interface.h" #include "api/transport/enums.h" #include "api/turn_customizer.h" #include "api/video/video_bitrate_allocator_factory.h" #include "call/call.h" #include "media/base/media_channel.h" #include "media/base/media_engine.h" #include "p2p/base/ice_transport_internal.h" #include "p2p/base/port.h" #include "p2p/base/port_allocator.h" #include "p2p/base/transport_description.h" #include "pc/channel.h" #include "pc/channel_interface.h" #include "pc/channel_manager.h" #include "pc/connection_context.h" #include "pc/data_channel_controller.h" #include "pc/data_channel_utils.h" #include "pc/dtls_transport.h" #include "pc/jsep_transport_controller.h" #include "pc/peer_connection_internal.h" #include "pc/peer_connection_message_handler.h" #include "pc/rtc_stats_collector.h" #include "pc/rtp_receiver.h" #include "pc/rtp_sender.h" #include "pc/rtp_transceiver.h" #include "pc/rtp_transmission_manager.h" #include "pc/rtp_transport_internal.h" #include "pc/sctp_data_channel.h" #include "pc/sctp_transport.h" #include "pc/sdp_offer_answer.h" #include "pc/session_description.h" #include "pc/stats_collector.h" #include "pc/stream_collection.h" #include "pc/transceiver_list.h" #include "pc/transport_stats.h" #include "pc/usage_pattern.h" #include "rtc_base/checks.h" #include "rtc_base/copy_on_write_buffer.h" #include "rtc_base/network/sent_packet.h" #include "rtc_base/rtc_certificate.h" #include "rtc_base/ssl_certificate.h" #include "rtc_base/ssl_stream_adapter.h" #include "rtc_base/task_utils/pending_task_safety_flag.h" #include "rtc_base/third_party/sigslot/sigslot.h" #include "rtc_base/thread.h" #include "rtc_base/thread_annotations.h" #include "rtc_base/unique_id_generator.h" #include "rtc_base/weak_ptr.h" namespace webrtc { // PeerConnection is the implementation of the PeerConnection object as defined // by the PeerConnectionInterface API surface. // The class currently is solely responsible for the following: // - Managing the session state machine (signaling state). // - Creating and initializing lower-level objects, like PortAllocator and // BaseChannels. // - Owning and managing the life cycle of the RtpSender/RtpReceiver and track // objects. // - Tracking the current and pending local/remote session descriptions. // The class currently is jointly responsible for the following: // - Parsing and interpreting SDP. // - Generating offers and answers based on the current state. // - The ICE state machine. // - Generating stats. class PeerConnection : public PeerConnectionInternal, public JsepTransportController::Observer, public sigslot::has_slots<> { public: // Creates a PeerConnection and initializes it with the given values. // If the initialization fails, the function releases the PeerConnection // and returns nullptr. // // Note that the function takes ownership of dependencies, and will // either use them or release them, whether it succeeds or fails. static RTCErrorOr> Create( rtc::scoped_refptr context, const PeerConnectionFactoryInterface::Options& options, std::unique_ptr event_log, std::unique_ptr call, const PeerConnectionInterface::RTCConfiguration& configuration, PeerConnectionDependencies dependencies); rtc::scoped_refptr local_streams() override; rtc::scoped_refptr remote_streams() override; bool AddStream(MediaStreamInterface* local_stream) override; void RemoveStream(MediaStreamInterface* local_stream) override; RTCErrorOr> AddTrack( rtc::scoped_refptr track, const std::vector& stream_ids) override; bool RemoveTrack(RtpSenderInterface* sender) override; RTCError RemoveTrackNew( rtc::scoped_refptr sender) override; RTCErrorOr> AddTransceiver( rtc::scoped_refptr track) override; RTCErrorOr> AddTransceiver( rtc::scoped_refptr track, const RtpTransceiverInit& init) override; RTCErrorOr> AddTransceiver( cricket::MediaType media_type) override; RTCErrorOr> AddTransceiver( cricket::MediaType media_type, const RtpTransceiverInit& init) override; rtc::scoped_refptr CreateSender( const std::string& kind, const std::string& stream_id) override; std::vector> GetSenders() const override; std::vector> GetReceivers() const override; std::vector> GetTransceivers() const override; rtc::scoped_refptr CreateDataChannel( const std::string& label, const DataChannelInit* config) override; // WARNING: LEGACY. See peerconnectioninterface.h bool GetStats(StatsObserver* observer, webrtc::MediaStreamTrackInterface* track, StatsOutputLevel level) override; // Spec-complaint GetStats(). See peerconnectioninterface.h void GetStats(RTCStatsCollectorCallback* callback) override; void GetStats( rtc::scoped_refptr selector, rtc::scoped_refptr callback) override; void GetStats( rtc::scoped_refptr selector, rtc::scoped_refptr callback) override; void ClearStatsCache() override; SignalingState signaling_state() override; IceConnectionState ice_connection_state() override; IceConnectionState standardized_ice_connection_state() override; PeerConnectionState peer_connection_state() override; IceGatheringState ice_gathering_state() override; absl::optional can_trickle_ice_candidates() override; const SessionDescriptionInterface* local_description() const override; const SessionDescriptionInterface* remote_description() const override; const SessionDescriptionInterface* current_local_description() const override; const SessionDescriptionInterface* current_remote_description() const override; const SessionDescriptionInterface* pending_local_description() const override; const SessionDescriptionInterface* pending_remote_description() const override; void RestartIce() override; // JSEP01 void CreateOffer(CreateSessionDescriptionObserver* observer, const RTCOfferAnswerOptions& options) override; void CreateAnswer(CreateSessionDescriptionObserver* observer, const RTCOfferAnswerOptions& options) override; void SetLocalDescription( std::unique_ptr desc, rtc::scoped_refptr observer) override; void SetLocalDescription( rtc::scoped_refptr observer) override; // TODO(https://crbug.com/webrtc/11798): Delete these methods in favor of the // ones taking SetLocalDescriptionObserverInterface as argument. void SetLocalDescription(SetSessionDescriptionObserver* observer, SessionDescriptionInterface* desc) override; void SetLocalDescription(SetSessionDescriptionObserver* observer) override; void SetRemoteDescription( std::unique_ptr desc, rtc::scoped_refptr observer) override; // TODO(https://crbug.com/webrtc/11798): Delete this methods in favor of the // ones taking SetRemoteDescriptionObserverInterface as argument. void SetRemoteDescription(SetSessionDescriptionObserver* observer, SessionDescriptionInterface* desc) override; PeerConnectionInterface::RTCConfiguration GetConfiguration() override; RTCError SetConfiguration( const PeerConnectionInterface::RTCConfiguration& configuration) override; bool AddIceCandidate(const IceCandidateInterface* candidate) override; void AddIceCandidate(std::unique_ptr candidate, std::function callback) override; bool RemoveIceCandidates( const std::vector& candidates) override; RTCError SetBitrate(const BitrateSettings& bitrate) override; void SetAudioPlayout(bool playout) override; void SetAudioRecording(bool recording) override; rtc::scoped_refptr LookupDtlsTransportByMid( const std::string& mid) override; rtc::scoped_refptr LookupDtlsTransportByMidInternal( const std::string& mid); rtc::scoped_refptr GetSctpTransport() const override; void AddAdaptationResource(rtc::scoped_refptr resource) override; bool StartRtcEventLog(std::unique_ptr output, int64_t output_period_ms) override; bool StartRtcEventLog(std::unique_ptr output) override; void StopRtcEventLog() override; void Close() override; rtc::Thread* signaling_thread() const final { return context_->signaling_thread(); } // PeerConnectionInternal implementation. rtc::Thread* network_thread() const final { return context_->network_thread(); } rtc::Thread* worker_thread() const final { return context_->worker_thread(); } std::string session_id() const override { return session_id_; } bool initial_offerer() const override { RTC_DCHECK_RUN_ON(signaling_thread()); return transport_controller_ && transport_controller_->initial_offerer(); } std::vector< rtc::scoped_refptr>> GetTransceiversInternal() const override { RTC_DCHECK_RUN_ON(signaling_thread()); return rtp_manager()->transceivers()->List(); } sigslot::signal1& SignalSctpDataChannelCreated() override { return data_channel_controller_.SignalSctpDataChannelCreated(); } std::vector GetDataChannelStats() const override; absl::optional sctp_transport_name() const override; absl::optional sctp_mid() const override; cricket::CandidateStatsList GetPooledCandidateStats() const override; std::map GetTransportStatsByNames( const std::set& transport_names) override; Call::Stats GetCallStats() override; bool GetLocalCertificate( const std::string& transport_name, rtc::scoped_refptr* certificate) override; std::unique_ptr GetRemoteSSLCertChain( const std::string& transport_name) override; bool IceRestartPending(const std::string& content_name) const override; bool NeedsIceRestart(const std::string& content_name) const override; bool GetSslRole(const std::string& content_name, rtc::SSLRole* role) override; // Functions needed by DataChannelController void NoteDataAddedEvent() { NoteUsageEvent(UsageEvent::DATA_ADDED); } // Returns the observer. Will crash on CHECK if the observer is removed. PeerConnectionObserver* Observer() const; bool IsClosed() const { RTC_DCHECK_RUN_ON(signaling_thread()); return !sdp_handler_ || sdp_handler_->signaling_state() == PeerConnectionInterface::kClosed; } // Get current SSL role used by SCTP's underlying transport. bool GetSctpSslRole(rtc::SSLRole* role); // Handler for the "channel closed" signal void OnSctpDataChannelClosed(DataChannelInterface* channel); bool ShouldFireNegotiationNeededEvent(uint32_t event_id) override; // Functions needed by SdpOfferAnswerHandler StatsCollector* stats() { RTC_DCHECK_RUN_ON(signaling_thread()); return stats_.get(); } DataChannelController* data_channel_controller() { RTC_DCHECK_RUN_ON(signaling_thread()); return &data_channel_controller_; } bool dtls_enabled() const { RTC_DCHECK_RUN_ON(signaling_thread()); return dtls_enabled_; } const PeerConnectionInterface::RTCConfiguration* configuration() const { RTC_DCHECK_RUN_ON(signaling_thread()); return &configuration_; } PeerConnectionMessageHandler* message_handler() { RTC_DCHECK_RUN_ON(signaling_thread()); return &message_handler_; } RtpTransmissionManager* rtp_manager() { return rtp_manager_.get(); } const RtpTransmissionManager* rtp_manager() const { return rtp_manager_.get(); } cricket::ChannelManager* channel_manager() const; JsepTransportController* transport_controller() { return transport_controller_.get(); } cricket::PortAllocator* port_allocator() { return port_allocator_.get(); } Call* call_ptr() { return call_ptr_; } ConnectionContext* context() { return context_.get(); } const PeerConnectionFactoryInterface::Options* options() const { return &options_; } void SetIceConnectionState(IceConnectionState new_state); void NoteUsageEvent(UsageEvent event); // Asynchronously adds a remote candidate on the network thread. void AddRemoteCandidate(const std::string& mid, const cricket::Candidate& candidate); // Report the UMA metric SdpFormatReceived for the given remote description. void ReportSdpFormatReceived( const SessionDescriptionInterface& remote_description); // Report the UMA metric BundleUsage for the given remote description. void ReportSdpBundleUsage( const SessionDescriptionInterface& remote_description); // Returns true if the PeerConnection is configured to use Unified Plan // semantics for creating offers/answers and setting local/remote // descriptions. If this is true the RtpTransceiver API will also be available // to the user. If this is false, Plan B semantics are assumed. // TODO(bugs.webrtc.org/8530): Flip the default to be Unified Plan once // sufficient time has passed. bool IsUnifiedPlan() const { RTC_DCHECK_RUN_ON(signaling_thread()); return is_unified_plan_; } bool ValidateBundleSettings( const cricket::SessionDescription* desc, const std::map& bundle_groups_by_mid); // Returns the MID for the data section associated with the // SCTP data channel, if it has been set. If no data // channels are configured this will return nullopt. absl::optional GetDataMid() const; void SetSctpDataMid(const std::string& mid); void ResetSctpDataMid(); // Asynchronously calls SctpTransport::Start() on the network thread for // |sctp_mid()| if set. Called as part of setting the local description. void StartSctpTransport(int local_port, int remote_port, int max_message_size); // Returns the CryptoOptions for this PeerConnection. This will always // return the RTCConfiguration.crypto_options if set and will only default // back to the PeerConnectionFactory settings if nothing was set. CryptoOptions GetCryptoOptions(); // Internal implementation for AddTransceiver family of methods. If // |fire_callback| is set, fires OnRenegotiationNeeded callback if successful. RTCErrorOr> AddTransceiver( cricket::MediaType media_type, rtc::scoped_refptr track, const RtpTransceiverInit& init, bool fire_callback = true); // Returns rtp transport, result can not be nullptr. RtpTransportInternal* GetRtpTransport(const std::string& mid); // Returns true if SRTP (either using DTLS-SRTP or SDES) is required by // this session. bool SrtpRequired() const; bool SetupDataChannelTransport_n(const std::string& mid) RTC_RUN_ON(network_thread()); void TeardownDataChannelTransport_n() RTC_RUN_ON(network_thread()); cricket::ChannelInterface* GetChannel(const std::string& content_name) RTC_RUN_ON(network_thread()); // Functions made public for testing. void ReturnHistogramVeryQuicklyForTesting() { RTC_DCHECK_RUN_ON(signaling_thread()); return_histogram_very_quickly_ = true; } void RequestUsagePatternReportForTesting(); protected: // Available for rtc::scoped_refptr creation PeerConnection(rtc::scoped_refptr context, const PeerConnectionFactoryInterface::Options& options, bool is_unified_plan, std::unique_ptr event_log, std::unique_ptr call, PeerConnectionDependencies& dependencies, bool dtls_enabled); ~PeerConnection() override; private: RTCError Initialize( const PeerConnectionInterface::RTCConfiguration& configuration, PeerConnectionDependencies dependencies); void InitializeTransportController_n( const RTCConfiguration& configuration, const PeerConnectionDependencies& dependencies) RTC_RUN_ON(network_thread()); rtc::scoped_refptr> FindTransceiverBySender(rtc::scoped_refptr sender) RTC_RUN_ON(signaling_thread()); void SetStandardizedIceConnectionState( PeerConnectionInterface::IceConnectionState new_state) RTC_RUN_ON(signaling_thread()); void SetConnectionState( PeerConnectionInterface::PeerConnectionState new_state) RTC_RUN_ON(signaling_thread()); // Called any time the IceGatheringState changes. void OnIceGatheringChange(IceGatheringState new_state) RTC_RUN_ON(signaling_thread()); // New ICE candidate has been gathered. void OnIceCandidate(std::unique_ptr candidate) RTC_RUN_ON(signaling_thread()); // Gathering of an ICE candidate failed. void OnIceCandidateError(const std::string& address, int port, const std::string& url, int error_code, const std::string& error_text) RTC_RUN_ON(signaling_thread()); // Some local ICE candidates have been removed. void OnIceCandidatesRemoved(const std::vector& candidates) RTC_RUN_ON(signaling_thread()); void OnSelectedCandidatePairChanged( const cricket::CandidatePairChangeEvent& event) RTC_RUN_ON(signaling_thread()); void OnNegotiationNeeded(); // Returns the specified SCTP DataChannel in sctp_data_channels_, // or nullptr if not found. SctpDataChannel* FindDataChannelBySid(int sid) const RTC_RUN_ON(signaling_thread()); // Called when first configuring the port allocator. struct InitializePortAllocatorResult { bool enable_ipv6; }; InitializePortAllocatorResult InitializePortAllocator_n( const cricket::ServerAddresses& stun_servers, const std::vector& turn_servers, const RTCConfiguration& configuration); // Called when SetConfiguration is called to apply the supported subset // of the configuration on the network thread. bool ReconfigurePortAllocator_n( const cricket::ServerAddresses& stun_servers, const std::vector& turn_servers, IceTransportsType type, int candidate_pool_size, PortPrunePolicy turn_port_prune_policy, webrtc::TurnCustomizer* turn_customizer, absl::optional stun_candidate_keepalive_interval, bool have_local_description); // Starts output of an RTC event log to the given output object. // This function should only be called from the worker thread. bool StartRtcEventLog_w(std::unique_ptr output, int64_t output_period_ms); // Stops recording an RTC event log. // This function should only be called from the worker thread. void StopRtcEventLog_w(); // Returns true and the TransportInfo of the given |content_name| // from |description|. Returns false if it's not available. static bool GetTransportDescription( const cricket::SessionDescription* description, const std::string& content_name, cricket::TransportDescription* info); // Returns the media index for a local ice candidate given the content name. // Returns false if the local session description does not have a media // content called |content_name|. bool GetLocalCandidateMediaIndex(const std::string& content_name, int* sdp_mline_index) RTC_RUN_ON(signaling_thread()); // JsepTransportController signal handlers. void OnTransportControllerConnectionState(cricket::IceConnectionState state) RTC_RUN_ON(signaling_thread()); void OnTransportControllerGatheringState(cricket::IceGatheringState state) RTC_RUN_ON(signaling_thread()); void OnTransportControllerCandidatesGathered( const std::string& transport_name, const std::vector& candidates) RTC_RUN_ON(signaling_thread()); void OnTransportControllerCandidateError( const cricket::IceCandidateErrorEvent& event) RTC_RUN_ON(signaling_thread()); void OnTransportControllerCandidatesRemoved( const std::vector& candidates) RTC_RUN_ON(signaling_thread()); void OnTransportControllerCandidateChanged( const cricket::CandidatePairChangeEvent& event) RTC_RUN_ON(signaling_thread()); void OnTransportControllerDtlsHandshakeError(rtc::SSLHandshakeError error); // Invoked when TransportController connection completion is signaled. // Reports stats for all transports in use. void ReportTransportStats() RTC_RUN_ON(network_thread()); // Gather the usage of IPv4/IPv6 as best connection. static void ReportBestConnectionState(const cricket::TransportStats& stats); static void ReportNegotiatedCiphers( bool dtls_enabled, const cricket::TransportStats& stats, const std::set& media_types); void ReportIceCandidateCollected(const cricket::Candidate& candidate) RTC_RUN_ON(signaling_thread()); void ReportUsagePattern() const RTC_RUN_ON(signaling_thread()); void ReportRemoteIceCandidateAdded(const cricket::Candidate& candidate); // JsepTransportController::Observer override. // // Called by |transport_controller_| when processing transport information // from a session description, and the mapping from m= sections to transports // changed (as a result of BUNDLE negotiation, or m= sections being // rejected). bool OnTransportChanged( const std::string& mid, RtpTransportInternal* rtp_transport, rtc::scoped_refptr dtls_transport, DataChannelTransportInterface* data_channel_transport) override; std::function InitializeRtcpCallback(); const rtc::scoped_refptr context_; const PeerConnectionFactoryInterface::Options options_; PeerConnectionObserver* observer_ RTC_GUARDED_BY(signaling_thread()) = nullptr; const bool is_unified_plan_; // The EventLog needs to outlive |call_| (and any other object that uses it). std::unique_ptr event_log_ RTC_GUARDED_BY(worker_thread()); // Points to the same thing as `event_log_`. Since it's const, we may read the // pointer (but not touch the object) from any thread. RtcEventLog* const event_log_ptr_ RTC_PT_GUARDED_BY(worker_thread()); IceConnectionState ice_connection_state_ RTC_GUARDED_BY(signaling_thread()) = kIceConnectionNew; PeerConnectionInterface::IceConnectionState standardized_ice_connection_state_ RTC_GUARDED_BY(signaling_thread()) = kIceConnectionNew; PeerConnectionInterface::PeerConnectionState connection_state_ RTC_GUARDED_BY(signaling_thread()) = PeerConnectionState::kNew; IceGatheringState ice_gathering_state_ RTC_GUARDED_BY(signaling_thread()) = kIceGatheringNew; PeerConnectionInterface::RTCConfiguration configuration_ RTC_GUARDED_BY(signaling_thread()); const std::unique_ptr async_dns_resolver_factory_; std::unique_ptr port_allocator_; // TODO(bugs.webrtc.org/9987): Accessed on both // signaling and network thread. const std::unique_ptr ice_transport_factory_; // TODO(bugs.webrtc.org/9987): Accessed on the // signaling thread but the underlying raw // pointer is given to // |jsep_transport_controller_| and used on the // network thread. const std::unique_ptr tls_cert_verifier_ RTC_GUARDED_BY(network_thread()); // The unique_ptr belongs to the worker thread, but the Call object manages // its own thread safety. std::unique_ptr call_ RTC_GUARDED_BY(worker_thread()); ScopedTaskSafety signaling_thread_safety_; rtc::scoped_refptr network_thread_safety_; rtc::scoped_refptr worker_thread_safety_; // Points to the same thing as `call_`. Since it's const, we may read the // pointer from any thread. // TODO(bugs.webrtc.org/11992): Remove this workaround (and potential dangling // pointer). Call* const call_ptr_; std::unique_ptr stats_ RTC_GUARDED_BY(signaling_thread()); // A pointer is passed to senders_ rtc::scoped_refptr stats_collector_ RTC_GUARDED_BY(signaling_thread()); const std::string session_id_; std::unique_ptr transport_controller_; // TODO(bugs.webrtc.org/9987): Accessed on both // signaling and network thread. // |sctp_mid_| is the content name (MID) in SDP. // Note: this is used as the data channel MID by both SCTP and data channel // transports. It is set when either transport is initialized and unset when // both transports are deleted. // There is one copy on the signaling thread and another copy on the // networking thread. Changes are always initiated from the signaling // thread, but applied first on the networking thread via an invoke(). absl::optional sctp_mid_s_ RTC_GUARDED_BY(signaling_thread()); absl::optional sctp_mid_n_ RTC_GUARDED_BY(network_thread()); std::string sctp_transport_name_s_ RTC_GUARDED_BY(signaling_thread()); // The machinery for handling offers and answers. Const after initialization. std::unique_ptr sdp_handler_ RTC_GUARDED_BY(signaling_thread()); const bool dtls_enabled_; UsagePattern usage_pattern_ RTC_GUARDED_BY(signaling_thread()); bool return_histogram_very_quickly_ RTC_GUARDED_BY(signaling_thread()) = false; DataChannelController data_channel_controller_; // Machinery for handling messages posted to oneself PeerConnectionMessageHandler message_handler_; // Administration of senders, receivers and transceivers // Accessed on both signaling and network thread. Const after Initialize(). std::unique_ptr rtp_manager_; rtc::WeakPtrFactory weak_factory_; // Did the connectionState ever change to `connected`? // Used to gather metrics only the first such state change. bool was_ever_connected_ RTC_GUARDED_BY(signaling_thread()) = false; }; } // namespace webrtc #endif // PC_PEER_CONNECTION_H_