| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef REMOTING_PROTOCOL_WEBRTC_TRANSPORT_H_ |
| #define REMOTING_PROTOCOL_WEBRTC_TRANSPORT_H_ |
| |
| #include <memory> |
| #include <string> |
| #include <tuple> |
| #include <vector> |
| |
| #include "base/callback.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/threading/thread_checker.h" |
| #include "base/timer/timer.h" |
| #include "crypto/hmac.h" |
| #include "remoting/base/session_options.h" |
| #include "remoting/protocol/peer_connection_controls.h" |
| #include "remoting/protocol/session_options_provider.h" |
| #include "remoting/protocol/transport.h" |
| #include "remoting/protocol/webrtc_data_stream_adapter.h" |
| #include "remoting/protocol/webrtc_event_log_data.h" |
| #include "remoting/signaling/signal_strategy.h" |
| #include "third_party/abseil-cpp/absl/types/optional.h" |
| #include "third_party/webrtc/api/peer_connection_interface.h" |
| #include "third_party/webrtc/api/video_codecs/video_encoder_factory.h" |
| |
| namespace base { |
| |
| class Watchdog; |
| |
| } // namespace base |
| |
| namespace remoting { |
| namespace protocol { |
| |
| class TransportContext; |
| class MessagePipe; |
| class WebrtcAudioModule; |
| |
| class WebrtcTransport : public Transport, |
| public SessionOptionsProvider, |
| public PeerConnectionControls { |
| public: |
| class EventHandler { |
| public: |
| virtual ~EventHandler() = default; |
| |
| // Called after |peer_connection| has been created but before handshake. The |
| // handler should create data channels and media streams. Renegotiation will |
| // be required in two cases after this method returns: |
| // 1. When the first data channel is created, if it wasn't created by this |
| // event handler. |
| // 2. Whenever a media stream is added or removed. |
| virtual void OnWebrtcTransportConnecting() = 0; |
| |
| // Called when the transport is connected. |
| virtual void OnWebrtcTransportConnected() = 0; |
| |
| // Called when there is an error connecting the session. |
| virtual void OnWebrtcTransportError(ErrorCode error) = 0; |
| |
| // Called when the transport protocol has been changed. Note that this might |
| // be called before the channels become ready. |
| virtual void OnWebrtcTransportProtocolChanged() = 0; |
| |
| // Called when a new data channel is created by the peer. |
| virtual void OnWebrtcTransportIncomingDataChannel( |
| const std::string& name, |
| std::unique_ptr<MessagePipe> pipe) = 0; |
| |
| // Called when an incoming media stream is added or removed. |
| virtual void OnWebrtcTransportMediaStreamAdded( |
| rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) = 0; |
| virtual void OnWebrtcTransportMediaStreamRemoved( |
| rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) = 0; |
| |
| // Called when the transport route changes (for example, from relayed to |
| // direct connection). Also called on initial connection. |
| virtual void OnWebrtcTransportRouteChanged(const TransportRoute& route) = 0; |
| }; |
| |
| // |video_encoder_factory| can be nullptr if the connection is not used for |
| // sending video. |
| WebrtcTransport( |
| rtc::Thread* worker_thread, |
| scoped_refptr<TransportContext> transport_context, |
| std::unique_ptr<webrtc::VideoEncoderFactory> video_encoder_factory, |
| EventHandler* event_handler); |
| |
| WebrtcTransport(const WebrtcTransport&) = delete; |
| WebrtcTransport& operator=(const WebrtcTransport&) = delete; |
| |
| ~WebrtcTransport() override; |
| |
| webrtc::PeerConnectionInterface* peer_connection(); |
| webrtc::PeerConnectionFactoryInterface* peer_connection_factory(); |
| WebrtcAudioModule* audio_module(); |
| WebrtcEventLogData* rtc_event_log() { return &rtc_event_log_; } |
| |
| // Creates outgoing data channel. The channel is created in CONNECTING state. |
| // The caller must wait for OnMessagePipeOpen() notification before sending |
| // any messages. |
| std::unique_ptr<MessagePipe> CreateOutgoingChannel(const std::string& name); |
| |
| // Transport implementations. |
| void Start(Authenticator* authenticator, |
| SendTransportInfoCallback send_transport_info_callback) override; |
| bool ProcessTransportInfo(jingle_xmpp::XmlElement* transport_info) override; |
| |
| // SessionOptionsProvider implementations. |
| const SessionOptions& session_options() const override; |
| |
| // PeerConnectionControls implementations. |
| void SetPreferredBitrates(absl::optional<int> min_bitrate_bps, |
| absl::optional<int> max_bitrate_bps) override; |
| void RequestIceRestart() override; |
| void RequestSdpRestart() override; |
| |
| void Close(ErrorCode error); |
| |
| void ApplySessionOptions(const SessionOptions& options); |
| |
| // Called when a new audio transceiver has been created by the PeerConnection. |
| void OnAudioTransceiverCreated( |
| rtc::scoped_refptr<webrtc::RtpTransceiverInterface> transceiver); |
| |
| // Called when a new video transceiver has been created by the PeerConnection. |
| void OnVideoTransceiverCreated( |
| rtc::scoped_refptr<webrtc::RtpTransceiverInterface> transceiver); |
| |
| // Transport layer protocol used to connect to the relay server or the peer. |
| // Possible values are those defined in the protocol and relayProtocol fields |
| // in the RTCIceCandidateStats dictionary. Empty if the protocol is not known |
| // yet, "api-error" if failed to get the current protocol. |
| const std::string& transport_protocol() const { return transport_protocol_; } |
| |
| // Since WebRTC uses its own threads, it is difficult to control its behavior |
| // using the standard Chromium threading test classes. For higher-level tests |
| // which do not want to mock out WebRTC, we provide this mechanism to allow |
| // for polling faster (which should mean the teardown work completing faster) |
| // or to zero out the interval and prevent hangs due to PostDelayedTask. |
| static void SetDataChannelPollingIntervalForTests( |
| base::TimeDelta data_channel_state_polling_interval); |
| |
| // Replaces the watchdog that monitors the thread join process when the peer |
| // connection is being torn down. |
| void SetThreadJoinWatchdogForTests(std::unique_ptr<base::Watchdog> watchdog); |
| |
| // Sets a callback to be executed before disarming the thread join watchdog. |
| // Only used for testing. |
| void SetBeforeDisarmThreadJoinWatchdogCallbackForTests(base::OnceClosure cb); |
| |
| private: |
| // PeerConnectionWrapper is responsible for PeerConnection creation, |
| // ownership. It passes all events to the corresponding methods below. This is |
| // necessary to make it possible to close and destroy PeerConnection |
| // asynchronously, as it may be on stack when the transport is destroyed. |
| class PeerConnectionWrapper; |
| friend class PeerConnectionWrapper; |
| |
| void OnLocalSessionDescriptionCreated( |
| std::unique_ptr<webrtc::SessionDescriptionInterface> description, |
| const std::string& error); |
| void OnLocalDescriptionSet(bool success, const std::string& error); |
| void OnRemoteDescriptionSet(bool send_answer, |
| bool success, |
| const std::string& error); |
| |
| // PeerConnection event handlers, called by PeerConnectionWrapper. |
| void OnSignalingChange( |
| webrtc::PeerConnectionInterface::SignalingState new_state); |
| void OnAddStream( |
| rtc::scoped_refptr<webrtc::MediaStreamInterface> stream); |
| void OnRemoveStream( |
| rtc::scoped_refptr<webrtc::MediaStreamInterface> stream); |
| void OnDataChannel( |
| rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel); |
| void OnRenegotiationNeeded(); |
| void OnIceConnectionChange( |
| webrtc::PeerConnectionInterface::IceConnectionState new_state); |
| void OnIceGatheringChange( |
| webrtc::PeerConnectionInterface::IceGatheringState new_state); |
| void OnIceCandidate(const webrtc::IceCandidateInterface* candidate); |
| void OnIceSelectedCandidatePairChanged( |
| const cricket::CandidatePairChangeEvent& event); |
| void OnStatsDelivered( |
| const rtc::scoped_refptr<const webrtc::RTCStatsReport>& report); |
| |
| // Returns the min (first element) and max (second element) bitrate for this |
| // connection, taking into account any relay bitrate cap and client overrides. |
| // The default range is [0, default max bitrate]. Client overrides that go |
| // beyond this bound or exceed the relay server's max bitrate will be ignored. |
| std::tuple<int, int> BitratesForConnection(); |
| |
| // Sets bitrates on the PeerConnection. |
| // Called after SetRemoteDescription(), but also called if the relay status |
| // changes. |
| void SetPeerConnectionBitrates(int min_bitrate_bps, int max_bitrate_bps); |
| |
| // Sets bitrates on the (video) sender. Called when a video sender is created, |
| // but also called if the relay status changes. |
| void SetSenderBitrates(rtc::scoped_refptr<webrtc::RtpSenderInterface> sender, |
| int min_bitrate_bps, |
| int max_bitrate_bps); |
| |
| void RequestRtcStats(); |
| void RequestNegotiation(); |
| void SendOffer(); |
| void EnsurePendingTransportInfoMessage(); |
| void SendTransportInfo(); |
| void AddPendingCandidatesIfPossible(); |
| |
| // Closes the PeerConnection after |control_data_channel| and |
| // |event_data_channel| have closed. Note that |peer_connection_wrapper| is |
| // always destroyed asynchronously to allow the callstack to unwind first. |
| static void ClosePeerConnection( |
| rtc::scoped_refptr<webrtc::DataChannelInterface> control_data_channel, |
| rtc::scoped_refptr<webrtc::DataChannelInterface> event_data_channel, |
| std::unique_ptr<PeerConnectionWrapper> peer_connection_wrapper, |
| base::Time start_time); |
| |
| void StartRtcEventLogging(); |
| void StopRtcEventLogging(); |
| |
| base::ThreadChecker thread_checker_; |
| |
| scoped_refptr<TransportContext> transport_context_; |
| raw_ptr<EventHandler> event_handler_ = nullptr; |
| SendTransportInfoCallback send_transport_info_callback_; |
| |
| crypto::HMAC handshake_hmac_; |
| |
| std::unique_ptr<PeerConnectionWrapper> peer_connection_wrapper_; |
| |
| bool negotiation_pending_ = false; |
| |
| bool connected_ = false; |
| |
| absl::optional<bool> connection_relayed_; |
| |
| std::string transport_protocol_; |
| |
| bool want_ice_restart_ = false; |
| |
| std::unique_ptr<jingle_xmpp::XmlElement> pending_transport_info_message_; |
| base::OneShotTimer transport_info_timer_; |
| |
| std::vector<std::unique_ptr<webrtc::IceCandidateInterface>> |
| pending_incoming_candidates_; |
| |
| std::string preferred_video_codec_; |
| |
| SessionOptions session_options_; |
| |
| // Track the data channels so we can make sure they are closed before we |
| // close the peer connection. This prevents RTCErrors being thrown on the |
| // other side of the WebRTC connection. |
| rtc::scoped_refptr<webrtc::DataChannelInterface> control_data_channel_; |
| rtc::scoped_refptr<webrtc::DataChannelInterface> event_data_channel_; |
| |
| // Preferred bitrates set by the client. nullopt if the client has not |
| // provided any preferred bitrates. |
| absl::optional<int> preferred_min_bitrate_bps_; |
| absl::optional<int> preferred_max_bitrate_bps_; |
| |
| // Stores event log data generated by WebRTC for the PeerConnection. |
| WebrtcEventLogData rtc_event_log_; |
| |
| base::WeakPtrFactory<WebrtcTransport> weak_factory_{this}; |
| }; |
| |
| } // namespace protocol |
| } // namespace remoting |
| |
| #endif // REMOTING_PROTOCOL_WEBRTC_TRANSPORT_H_ |