/* * libjingle * Copyright 2012 Google Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef TALK_APP_WEBRTC_WEBRTCSESSION_H_ #define TALK_APP_WEBRTC_WEBRTCSESSION_H_ #include #include "talk/app/webrtc/datachannel.h" #include "talk/app/webrtc/dtmfsender.h" #include "talk/app/webrtc/mediastreamprovider.h" #include "talk/app/webrtc/peerconnectioninterface.h" #include "talk/app/webrtc/statstypes.h" #include "talk/media/base/mediachannel.h" #include "webrtc/p2p/base/session.h" #include "talk/session/media/mediasession.h" #include "webrtc/base/sigslot.h" #include "webrtc/base/thread.h" namespace cricket { class BaseChannel; class ChannelManager; class DataChannel; class StatsReport; class Transport; class VideoCapturer; class VideoChannel; class VoiceChannel; } // namespace cricket namespace webrtc { class IceRestartAnswerLatch; class JsepIceCandidate; class MediaStreamSignaling; class WebRtcSessionDescriptionFactory; extern const char kBundleWithoutRtcpMux[]; extern const char kCreateChannelFailed[]; extern const char kInvalidCandidates[]; extern const char kInvalidSdp[]; extern const char kMlineMismatch[]; extern const char kPushDownTDFailed[]; extern const char kSdpWithoutDtlsFingerprint[]; extern const char kSdpWithoutSdesCrypto[]; extern const char kSdpWithoutIceUfragPwd[]; extern const char kSdpWithoutSdesAndDtlsDisabled[]; extern const char kSessionError[]; extern const char kSessionErrorDesc[]; // Maximum number of received video streams that will be processed by webrtc // even if they are not signalled beforehand. extern const int kMaxUnsignalledRecvStreams; // ICE state callback interface. class IceObserver { public: IceObserver() {} // Called any time the IceConnectionState changes virtual void OnIceConnectionChange( PeerConnectionInterface::IceConnectionState new_state) {} // Called any time the IceGatheringState changes virtual void OnIceGatheringChange( PeerConnectionInterface::IceGatheringState new_state) {} // New Ice candidate have been found. virtual void OnIceCandidate(const IceCandidateInterface* candidate) = 0; // All Ice candidates have been found. // TODO(bemasc): Remove this once callers transition to OnIceGatheringChange. // (via PeerConnectionObserver) virtual void OnIceComplete() {} protected: ~IceObserver() {} private: DISALLOW_COPY_AND_ASSIGN(IceObserver); }; class WebRtcSession : public cricket::BaseSession, public AudioProviderInterface, public DataChannelFactory, public VideoProviderInterface, public DtmfProviderInterface, public DataChannelProviderInterface { public: WebRtcSession(cricket::ChannelManager* channel_manager, rtc::Thread* signaling_thread, rtc::Thread* worker_thread, cricket::PortAllocator* port_allocator, MediaStreamSignaling* mediastream_signaling); virtual ~WebRtcSession(); bool Initialize(const PeerConnectionFactoryInterface::Options& options, const MediaConstraintsInterface* constraints, DTLSIdentityServiceInterface* dtls_identity_service, PeerConnectionInterface::IceTransportsType ice_transport); // Deletes the voice, video and data channel and changes the session state // to STATE_RECEIVEDTERMINATE. void Terminate(); void RegisterIceObserver(IceObserver* observer) { ice_observer_ = observer; } virtual cricket::VoiceChannel* voice_channel() { return voice_channel_.get(); } virtual cricket::VideoChannel* video_channel() { return video_channel_.get(); } virtual cricket::DataChannel* data_channel() { return data_channel_.get(); } virtual const MediaStreamSignaling* mediastream_signaling() const { return mediastream_signaling_; } void SetSdesPolicy(cricket::SecurePolicy secure_policy); cricket::SecurePolicy SdesPolicy() const; // Get current ssl role from transport. bool GetSslRole(rtc::SSLRole* role); // Generic error message callback from WebRtcSession. // TODO - It may be necessary to supply error code as well. sigslot::signal0<> SignalError; void CreateOffer( CreateSessionDescriptionObserver* observer, const PeerConnectionInterface::RTCOfferAnswerOptions& options); void CreateAnswer(CreateSessionDescriptionObserver* observer, const MediaConstraintsInterface* constraints); // The ownership of |desc| will be transferred after this call. bool SetLocalDescription(SessionDescriptionInterface* desc, std::string* err_desc); // The ownership of |desc| will be transferred after this call. bool SetRemoteDescription(SessionDescriptionInterface* desc, std::string* err_desc); bool ProcessIceMessage(const IceCandidateInterface* ice_candidate); bool SetIceTransports(PeerConnectionInterface::IceTransportsType type); const SessionDescriptionInterface* local_description() const { return local_desc_.get(); } const SessionDescriptionInterface* remote_description() const { return remote_desc_.get(); } // Get the id used as a media stream track's "id" field from ssrc. virtual bool GetLocalTrackIdBySsrc(uint32 ssrc, std::string* track_id); virtual bool GetRemoteTrackIdBySsrc(uint32 ssrc, std::string* track_id); // AudioMediaProviderInterface implementation. virtual void SetAudioPlayout(uint32 ssrc, bool enable, cricket::AudioRenderer* renderer) OVERRIDE; virtual void SetAudioSend(uint32 ssrc, bool enable, const cricket::AudioOptions& options, cricket::AudioRenderer* renderer) OVERRIDE; virtual void SetAudioPlayoutVolume(uint32 ssrc, double volume) OVERRIDE; // Implements VideoMediaProviderInterface. virtual bool SetCaptureDevice(uint32 ssrc, cricket::VideoCapturer* camera) OVERRIDE; virtual void SetVideoPlayout(uint32 ssrc, bool enable, cricket::VideoRenderer* renderer) OVERRIDE; virtual void SetVideoSend(uint32 ssrc, bool enable, const cricket::VideoOptions* options) OVERRIDE; // Implements DtmfProviderInterface. virtual bool CanInsertDtmf(const std::string& track_id); virtual bool InsertDtmf(const std::string& track_id, int code, int duration); virtual sigslot::signal0<>* GetOnDestroyedSignal(); // Implements DataChannelProviderInterface. virtual bool SendData(const cricket::SendDataParams& params, const rtc::Buffer& payload, cricket::SendDataResult* result) OVERRIDE; virtual bool ConnectDataChannel(DataChannel* webrtc_data_channel) OVERRIDE; virtual void DisconnectDataChannel(DataChannel* webrtc_data_channel) OVERRIDE; virtual void AddSctpDataStream(int sid) OVERRIDE; virtual void RemoveSctpDataStream(int sid) OVERRIDE; virtual bool ReadyToSendData() const OVERRIDE; // Implements DataChannelFactory. rtc::scoped_refptr CreateDataChannel( const std::string& label, const InternalDataChannelInit* config) OVERRIDE; cricket::DataChannelType data_channel_type() const; bool IceRestartPending() const; void ResetIceRestartLatch(); // Called when an SSLIdentity is generated or retrieved by // WebRTCSessionDescriptionFactory. Should happen before setLocalDescription. void OnIdentityReady(rtc::SSLIdentity* identity); // For unit test. bool waiting_for_identity() const; void set_metrics_observer( webrtc::MetricsObserverInterface* metrics_observer) { metrics_observer_ = metrics_observer; } private: // Indicates the type of SessionDescription in a call to SetLocalDescription // and SetRemoteDescription. enum Action { kOffer, kPrAnswer, kAnswer, }; // Invokes ConnectChannels() on transport proxies, which initiates ice // candidates allocation. bool StartCandidatesAllocation(); bool UpdateSessionState(Action action, cricket::ContentSource source, std::string* err_desc); static Action GetAction(const std::string& type); // Transport related callbacks, override from cricket::BaseSession. virtual void OnTransportRequestSignaling(cricket::Transport* transport); virtual void OnTransportConnecting(cricket::Transport* transport); virtual void OnTransportWritable(cricket::Transport* transport); virtual void OnTransportCompleted(cricket::Transport* transport); virtual void OnTransportFailed(cricket::Transport* transport); virtual void OnTransportProxyCandidatesReady( cricket::TransportProxy* proxy, const cricket::Candidates& candidates); virtual void OnCandidatesAllocationDone(); // Creates local session description with audio and video contents. bool CreateDefaultLocalDescription(); // Enables media channels to allow sending of media. void EnableChannels(); // Creates a JsepIceCandidate and adds it to the local session description // and notify observers. Called when a new local candidate have been found. void ProcessNewLocalCandidate(const std::string& content_name, const cricket::Candidates& candidates); // 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); // Uses all remote candidates in |remote_desc| in this session. bool UseCandidatesInSessionDescription( const SessionDescriptionInterface* remote_desc); // Uses |candidate| in this session. bool UseCandidate(const IceCandidateInterface* candidate); // Deletes the corresponding channel of contents that don't exist in |desc|. // |desc| can be null. This means that all channels are deleted. void RemoveUnusedChannelsAndTransports( const cricket::SessionDescription* desc); // Allocates media channels based on the |desc|. If |desc| doesn't have // the BUNDLE option, this method will disable BUNDLE in PortAllocator. // This method will also delete any existing media channels before creating. bool CreateChannels(const cricket::SessionDescription* desc); // Helper methods to create media channels. bool CreateVoiceChannel(const cricket::ContentInfo* content); bool CreateVideoChannel(const cricket::ContentInfo* content); bool CreateDataChannel(const cricket::ContentInfo* content); // Copy the candidates from |saved_candidates_| to |dest_desc|. // The |saved_candidates_| will be cleared after this function call. void CopySavedCandidates(SessionDescriptionInterface* dest_desc); // Listens to SCTP CONTROL messages on unused SIDs and process them as OPEN // messages. void OnDataChannelMessageReceived(cricket::DataChannel* channel, const cricket::ReceiveDataParams& params, const rtc::Buffer& payload); std::string BadStateErrMsg(State state); void SetIceConnectionState(PeerConnectionInterface::IceConnectionState state); bool ValidateBundleSettings(const cricket::SessionDescription* desc); bool HasRtcpMuxEnabled(const cricket::ContentInfo* content); // Below methods are helper methods which verifies SDP. bool ValidateSessionDescription(const SessionDescriptionInterface* sdesc, cricket::ContentSource source, std::string* err_desc); // Check if a call to SetLocalDescription is acceptable with |action|. bool ExpectSetLocalDescription(Action action); // Check if a call to SetRemoteDescription is acceptable with |action|. bool ExpectSetRemoteDescription(Action action); // Verifies a=setup attribute as per RFC 5763. bool ValidateDtlsSetupAttribute(const cricket::SessionDescription* desc, Action action); // Returns true if we are ready to push down the remote candidate. // |remote_desc| is the new remote description, or NULL if the current remote // description should be used. Output |valid| is true if the candidate media // index is valid. bool ReadyToUseRemoteCandidate(const IceCandidateInterface* candidate, const SessionDescriptionInterface* remote_desc, bool* valid); std::string GetSessionErrorMsg(); // Invoked when OnTransportCompleted is signaled to gather the usage // of IPv4/IPv6 as best connection. void ReportBestConnectionState(cricket::Transport* transport); rtc::scoped_ptr voice_channel_; rtc::scoped_ptr video_channel_; rtc::scoped_ptr data_channel_; cricket::ChannelManager* channel_manager_; MediaStreamSignaling* mediastream_signaling_; IceObserver* ice_observer_; PeerConnectionInterface::IceConnectionState ice_connection_state_; rtc::scoped_ptr local_desc_; rtc::scoped_ptr remote_desc_; // Candidates that arrived before the remote description was set. std::vector saved_candidates_; // If the remote peer is using a older version of implementation. bool older_version_remote_peer_; bool dtls_enabled_; // Specifies which kind of data channel is allowed. This is controlled // by the chrome command-line flag and constraints: // 1. If chrome command-line switch 'enable-sctp-data-channels' is enabled, // constraint kEnableDtlsSrtp is true, and constaint kEnableRtpDataChannels is // not set or false, SCTP is allowed (DCT_SCTP); // 2. If constraint kEnableRtpDataChannels is true, RTP is allowed (DCT_RTP); // 3. If both 1&2 are false, data channel is not allowed (DCT_NONE). cricket::DataChannelType data_channel_type_; rtc::scoped_ptr ice_restart_latch_; rtc::scoped_ptr webrtc_session_desc_factory_; sigslot::signal0<> SignalVoiceChannelDestroyed; sigslot::signal0<> SignalVideoChannelDestroyed; sigslot::signal0<> SignalDataChannelDestroyed; // Member variables for caching global options. cricket::AudioOptions audio_options_; cricket::VideoOptions video_options_; MetricsObserverInterface* metrics_observer_; DISALLOW_COPY_AND_ASSIGN(WebRtcSession); }; } // namespace webrtc #endif // TALK_APP_WEBRTC_WEBRTCSESSION_H_