Revert of Moving MediaStreamSignaling logic into PeerConnection. (patchset #10 id:180001 of https://codereview.webrtc.org/1393563002/ )

Reason for revert:
Broke browser_tests on Mac. Still need to investigate the cause.

Original issue's description:
> Moving MediaStreamSignaling logic into PeerConnection.
>
> This needs to happen because in the future, m-lines will be offered
> based on the set of RtpSenders/RtpReceivers, rather than the set of
> tracks that MediaStreamSignaling knows about.
>
> Besides that, MediaStreamSignaling was a "glue class" without
> a clearly defined role, so it going away is good for other
> reasons as well.
>
> Committed: https://crrev.com/97c392935411398b506861601c82e31d95c591f0
> Cr-Commit-Position: refs/heads/master@{#10268}

TBR=pthatcher@webrtc.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true

Review URL: https://codereview.webrtc.org/1403633005

Cr-Commit-Position: refs/heads/master@{#10269}
This commit is contained in:
deadbeef 2015-10-13 16:42:33 -07:00 committed by Commit bot
parent 97c3929354
commit fc648b6d93
23 changed files with 3325 additions and 2997 deletions

View File

@ -31,7 +31,6 @@
#include "talk/app/webrtc/mediastreamprovider.h"
#include "talk/app/webrtc/sctputils.h"
#include "talk/media/sctp/sctpdataengine.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/refcount.h"
@ -44,42 +43,6 @@ enum {
MSG_CHANNELREADY,
};
bool SctpSidAllocator::AllocateSid(rtc::SSLRole role, int* sid) {
int potential_sid = (role == rtc::SSL_CLIENT) ? 0 : 1;
while (!IsSidAvailable(potential_sid)) {
potential_sid += 2;
if (potential_sid > static_cast<int>(cricket::kMaxSctpSid)) {
return false;
}
}
*sid = potential_sid;
used_sids_.insert(potential_sid);
return true;
}
bool SctpSidAllocator::ReserveSid(int sid) {
if (!IsSidAvailable(sid)) {
return false;
}
used_sids_.insert(sid);
return true;
}
void SctpSidAllocator::ReleaseSid(int sid) {
auto it = used_sids_.find(sid);
if (it != used_sids_.end()) {
used_sids_.erase(it);
}
}
bool SctpSidAllocator::IsSidAvailable(int sid) const {
if (sid < 0 || sid > static_cast<int>(cricket::kMaxSctpSid)) {
return false;
}
return used_sids_.find(sid) == used_sids_.end();
}
DataChannel::PacketQueue::PacketQueue() : byte_count_(0) {}
DataChannel::PacketQueue::~PacketQueue() {
@ -294,9 +257,8 @@ void DataChannel::RemotePeerRequestClose() {
void DataChannel::SetSctpSid(int sid) {
ASSERT(config_.id < 0 && sid >= 0 && data_channel_type_ == cricket::DCT_SCTP);
if (config_.id == sid) {
if (config_.id == sid)
return;
}
config_.id = sid;
provider_->AddSctpDataStream(sid);
@ -314,13 +276,6 @@ void DataChannel::OnTransportChannelCreated() {
}
}
// The underlying transport channel was destroyed.
// This function makes sure the DataChannel is disconnected and changes state to
// kClosed.
void DataChannel::OnTransportChannelDestroyed() {
DoClose();
}
void DataChannel::SetSendSsrc(uint32_t send_ssrc) {
ASSERT(data_channel_type_ == cricket::DCT_RTP);
if (send_ssrc_set_) {
@ -339,6 +294,13 @@ void DataChannel::OnMessage(rtc::Message* msg) {
}
}
// The underlaying data engine is closing.
// This function makes sure the DataChannel is disconnected and changes state to
// kClosed.
void DataChannel::OnDataEngineClose() {
DoClose();
}
void DataChannel::OnDataReceived(cricket::DataChannel* channel,
const cricket::ReceiveDataParams& params,
const rtc::Buffer& payload) {
@ -399,12 +361,6 @@ void DataChannel::OnDataReceived(cricket::DataChannel* channel,
}
}
void DataChannel::OnStreamClosedRemotely(uint32_t sid) {
if (data_channel_type_ == cricket::DCT_SCTP && sid == config_.id) {
Close();
}
}
void DataChannel::OnChannelReady(bool writable) {
writable_ = writable;
if (!writable) {
@ -480,17 +436,13 @@ void DataChannel::UpdateState() {
}
void DataChannel::SetState(DataState state) {
if (state_ == state) {
if (state_ == state)
return;
}
state_ = state;
if (observer_) {
observer_->OnStateChange();
}
if (state_ == kClosed) {
SignalClosed(this);
}
}
void DataChannel::DisconnectFromProvider() {

View File

@ -29,7 +29,6 @@
#define TALK_APP_WEBRTC_DATACHANNEL_H_
#include <deque>
#include <set>
#include <string>
#include "talk/app/webrtc/datachannelinterface.h"
@ -84,28 +83,6 @@ struct InternalDataChannelInit : public DataChannelInit {
OpenHandshakeRole open_handshake_role;
};
// Helper class to allocate unique IDs for SCTP DataChannels
class SctpSidAllocator {
public:
// Gets the first unused odd/even id based on the DTLS role. If |role| is
// SSL_CLIENT, the allocated id starts from 0 and takes even numbers;
// otherwise, the id starts from 1 and takes odd numbers.
// Returns false if no id can be allocated.
bool AllocateSid(rtc::SSLRole role, int* sid);
// Attempts to reserve a specific sid. Returns false if it's unavailable.
bool ReserveSid(int sid);
// Indicates that |sid| isn't in use any more, and is thus available again.
void ReleaseSid(int sid);
private:
// Checks if |sid| is available to be assigned to a new SCTP data channel.
bool IsSidAvailable(int sid) const;
std::set<int> used_sids_;
};
// DataChannel is a an implementation of the DataChannelInterface based on
// libjingle's data engine. It provides an implementation of unreliable or
// reliabledata channels. Currently this class is specifically designed to use
@ -152,6 +129,9 @@ class DataChannel : public DataChannelInterface,
// rtc::MessageHandler override.
virtual void OnMessage(rtc::Message* msg);
// Called if the underlying data engine is closing.
void OnDataEngineClose();
// Called when the channel's ready to use. That can happen when the
// underlying DataMediaChannel becomes ready, or when this channel is a new
// stream on an existing DataMediaChannel, and we've finished negotiation.
@ -161,7 +141,6 @@ class DataChannel : public DataChannelInterface,
void OnDataReceived(cricket::DataChannel* channel,
const cricket::ReceiveDataParams& params,
const rtc::Buffer& payload);
void OnStreamClosedRemotely(uint32_t sid);
// The remote peer request that this channel should be closed.
void RemotePeerRequestClose();
@ -172,10 +151,7 @@ class DataChannel : public DataChannelInterface,
// be called once.
void SetSctpSid(int sid);
// Called when the transport channel is created.
// Only needs to be called for SCTP data channels.
void OnTransportChannelCreated();
// Called when the transport channel is destroyed.
void OnTransportChannelDestroyed();
// The following methods are for RTP only.
@ -191,11 +167,6 @@ class DataChannel : public DataChannelInterface,
return data_channel_type_;
}
// Emitted when state transitions to kClosed.
// In the case of SCTP channels, this signal can be used to tell when the
// channel's sid is free.
sigslot::signal1<DataChannel*> SignalClosed;
protected:
DataChannel(DataChannelProviderInterface* client,
cricket::DataChannelType dct,
@ -276,6 +247,16 @@ class DataChannel : public DataChannelInterface,
PacketQueue queued_send_data_;
};
class DataChannelFactory {
public:
virtual rtc::scoped_refptr<DataChannel> CreateDataChannel(
const std::string& label,
const InternalDataChannelInit* config) = 0;
protected:
virtual ~DataChannelFactory() {}
};
// Define proxy for DataChannelInterface.
BEGIN_PROXY_MAP(DataChannel)
PROXY_METHOD1(void, RegisterObserver, DataChannelObserver*)

View File

@ -31,7 +31,6 @@
#include "webrtc/base/gunit.h"
using webrtc::DataChannel;
using webrtc::SctpSidAllocator;
class FakeDataChannelObserver : public webrtc::DataChannelObserver {
public:
@ -507,75 +506,3 @@ TEST_F(SctpDataChannelTest, NeverOpened) {
webrtc_data_channel_->OnTransportChannelCreated();
webrtc_data_channel_->Close();
}
class SctpSidAllocatorTest : public testing::Test {
protected:
SctpSidAllocator allocator_;
};
// Verifies that an even SCTP id is allocated for SSL_CLIENT and an odd id for
// SSL_SERVER.
TEST_F(SctpSidAllocatorTest, SctpIdAllocationBasedOnRole) {
int id;
EXPECT_TRUE(allocator_.AllocateSid(rtc::SSL_SERVER, &id));
EXPECT_EQ(1, id);
EXPECT_TRUE(allocator_.AllocateSid(rtc::SSL_CLIENT, &id));
EXPECT_EQ(0, id);
EXPECT_TRUE(allocator_.AllocateSid(rtc::SSL_SERVER, &id));
EXPECT_EQ(3, id);
EXPECT_TRUE(allocator_.AllocateSid(rtc::SSL_CLIENT, &id));
EXPECT_EQ(2, id);
}
// Verifies that SCTP ids of existing DataChannels are not reused.
TEST_F(SctpSidAllocatorTest, SctpIdAllocationNoReuse) {
int old_id = 1;
EXPECT_TRUE(allocator_.ReserveSid(old_id));
int new_id;
EXPECT_TRUE(allocator_.AllocateSid(rtc::SSL_SERVER, &new_id));
EXPECT_NE(old_id, new_id);
old_id = 0;
EXPECT_TRUE(allocator_.ReserveSid(old_id));
EXPECT_TRUE(allocator_.AllocateSid(rtc::SSL_CLIENT, &new_id));
EXPECT_NE(old_id, new_id);
}
// Verifies that SCTP ids of removed DataChannels can be reused.
TEST_F(SctpSidAllocatorTest, SctpIdReusedForRemovedDataChannel) {
int odd_id = 1;
int even_id = 0;
EXPECT_TRUE(allocator_.ReserveSid(odd_id));
EXPECT_TRUE(allocator_.ReserveSid(even_id));
int allocated_id = -1;
EXPECT_TRUE(allocator_.AllocateSid(rtc::SSL_SERVER, &allocated_id));
EXPECT_EQ(odd_id + 2, allocated_id);
EXPECT_TRUE(allocator_.AllocateSid(rtc::SSL_CLIENT, &allocated_id));
EXPECT_EQ(even_id + 2, allocated_id);
EXPECT_TRUE(allocator_.AllocateSid(rtc::SSL_SERVER, &allocated_id));
EXPECT_EQ(odd_id + 4, allocated_id);
EXPECT_TRUE(allocator_.AllocateSid(rtc::SSL_CLIENT, &allocated_id));
EXPECT_EQ(even_id + 4, allocated_id);
allocator_.ReleaseSid(odd_id);
allocator_.ReleaseSid(even_id);
// Verifies that removed ids are reused.
EXPECT_TRUE(allocator_.AllocateSid(rtc::SSL_SERVER, &allocated_id));
EXPECT_EQ(odd_id, allocated_id);
EXPECT_TRUE(allocator_.AllocateSid(rtc::SSL_CLIENT, &allocated_id));
EXPECT_EQ(even_id, allocated_id);
// Verifies that used higher ids are not reused.
EXPECT_TRUE(allocator_.AllocateSid(rtc::SSL_SERVER, &allocated_id));
EXPECT_EQ(odd_id + 6, allocated_id);
EXPECT_TRUE(allocator_.AllocateSid(rtc::SSL_CLIENT, &allocated_id));
EXPECT_EQ(even_id + 6, allocated_id);
}

File diff suppressed because it is too large Load Diff

View File

@ -25,4 +25,379 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// TODO(deadbeef): Remove this file once Chrome build files don't reference it.
#ifndef TALK_APP_WEBRTC_MEDIASTREAMSIGNALING_H_
#define TALK_APP_WEBRTC_MEDIASTREAMSIGNALING_H_
#include <map>
#include <string>
#include <vector>
#include "talk/app/webrtc/datachannel.h"
#include "talk/app/webrtc/mediastream.h"
#include "talk/app/webrtc/peerconnectioninterface.h"
#include "talk/app/webrtc/streamcollection.h"
#include "talk/session/media/mediasession.h"
#include "webrtc/base/scoped_ref_ptr.h"
#include "webrtc/base/sigslot.h"
namespace rtc {
class Thread;
} // namespace rtc
namespace webrtc {
class RemoteMediaStreamFactory;
// A MediaStreamSignalingObserver is notified when events happen to
// MediaStreams, MediaStreamTracks or DataChannels associated with the observed
// MediaStreamSignaling object. The notifications identify the stream, track or
// channel.
class MediaStreamSignalingObserver {
public:
// Triggered when the remote SessionDescription has a new stream.
virtual void OnAddRemoteStream(MediaStreamInterface* stream) = 0;
// Triggered when the remote SessionDescription removes a stream.
virtual void OnRemoveRemoteStream(MediaStreamInterface* stream) = 0;
// Triggered when the remote SessionDescription has a new data channel.
virtual void OnAddDataChannel(DataChannelInterface* data_channel) = 0;
// Triggered when the remote SessionDescription has a new audio track.
virtual void OnAddRemoteAudioTrack(MediaStreamInterface* stream,
AudioTrackInterface* audio_track,
uint32_t ssrc) = 0;
// Triggered when the remote SessionDescription has a new video track.
virtual void OnAddRemoteVideoTrack(MediaStreamInterface* stream,
VideoTrackInterface* video_track,
uint32_t ssrc) = 0;
// Triggered when the remote SessionDescription has removed an audio track.
virtual void OnRemoveRemoteAudioTrack(MediaStreamInterface* stream,
AudioTrackInterface* audio_track) = 0;
// Triggered when the remote SessionDescription has removed a video track.
virtual void OnRemoveRemoteVideoTrack(MediaStreamInterface* stream,
VideoTrackInterface* video_track) = 0;
// Triggered when the local SessionDescription has a new audio track.
virtual void OnAddLocalAudioTrack(MediaStreamInterface* stream,
AudioTrackInterface* audio_track,
uint32_t ssrc) = 0;
// Triggered when the local SessionDescription has a new video track.
virtual void OnAddLocalVideoTrack(MediaStreamInterface* stream,
VideoTrackInterface* video_track,
uint32_t ssrc) = 0;
// Triggered when the local SessionDescription has removed an audio track.
virtual void OnRemoveLocalAudioTrack(MediaStreamInterface* stream,
AudioTrackInterface* audio_track,
uint32_t ssrc) = 0;
// Triggered when the local SessionDescription has removed a video track.
virtual void OnRemoveLocalVideoTrack(MediaStreamInterface* stream,
VideoTrackInterface* video_track) = 0;
// Triggered when RemoveLocalStream is called. |stream| is no longer used
// when negotiating and all tracks in |stream| should stop providing data to
// this PeerConnection. This doesn't mean that the local session description
// has changed and OnRemoveLocalAudioTrack and OnRemoveLocalVideoTrack is not
// called for each individual track.
virtual void OnRemoveLocalStream(MediaStreamInterface* stream) = 0;
protected:
~MediaStreamSignalingObserver() {}
};
// MediaStreamSignaling works as a glue between MediaStreams and a cricket
// classes for SessionDescriptions.
// It is used for creating cricket::MediaSessionOptions given the local
// MediaStreams and data channels.
//
// It is responsible for creating remote MediaStreams given a remote
// SessionDescription and creating cricket::MediaSessionOptions given
// local MediaStreams.
//
// To signal that a DataChannel should be established:
// 1. Call AddDataChannel with the new DataChannel. Next time
// GetMediaSessionOptions will include the description of the DataChannel.
// 2. When a local session description is set, call UpdateLocalStreams with the
// session description. This will set the SSRC used for sending data on
// this DataChannel.
// 3. When remote session description is set, call UpdateRemoteStream with the
// session description. If the DataChannel label and a SSRC is included in
// the description, the DataChannel is updated with SSRC that will be used
// for receiving data.
// 4. When both the local and remote SSRC of a DataChannel is set the state of
// the DataChannel change to kOpen.
//
// To setup a DataChannel initialized by the remote end.
// 1. When remote session description is set, call UpdateRemoteStream with the
// session description. If a label and a SSRC of a new DataChannel is found
// MediaStreamSignalingObserver::OnAddDataChannel with the label and SSRC is
// triggered.
// 2. Create a DataChannel instance with the label and set the remote SSRC.
// 3. Call AddDataChannel with this new DataChannel. GetMediaSessionOptions
// will include the description of the DataChannel.
// 4. Create a local session description and call UpdateLocalStreams. This will
// set the local SSRC used by the DataChannel.
// 5. When both the local and remote SSRC of a DataChannel is set the state of
// the DataChannel change to kOpen.
//
// To close a DataChannel:
// 1. Call DataChannel::Close. This will change the state of the DataChannel to
// kClosing. GetMediaSessionOptions will not
// include the description of the DataChannel.
// 2. When a local session description is set, call UpdateLocalStreams with the
// session description. The description will no longer contain the
// DataChannel label or SSRC.
// 3. When remote session description is set, call UpdateRemoteStream with the
// session description. The description will no longer contain the
// DataChannel label or SSRC. The DataChannel SSRC is updated with SSRC=0.
// The DataChannel change state to kClosed.
class MediaStreamSignaling : public sigslot::has_slots<> {
public:
typedef std::map<std::string, rtc::scoped_refptr<DataChannel> >
RtpDataChannels;
typedef std::vector<rtc::scoped_refptr<DataChannel>> SctpDataChannels;
MediaStreamSignaling(rtc::Thread* signaling_thread,
MediaStreamSignalingObserver* stream_observer,
cricket::ChannelManager* channel_manager);
virtual ~MediaStreamSignaling();
// Notify all referenced objects that MediaStreamSignaling will be teared
// down. This method must be called prior to the dtor.
void TearDown();
// Set a factory for creating data channels that are initiated by the remote
// peer.
void SetDataChannelFactory(DataChannelFactory* data_channel_factory) {
data_channel_factory_ = data_channel_factory;
}
// Checks if |id| is available to be assigned to a new SCTP data channel.
bool IsSctpSidAvailable(int sid) const;
// Gets the first available SCTP id that is not assigned to any existing
// data channels.
bool AllocateSctpSid(rtc::SSLRole role, int* sid);
// Adds |local_stream| to the collection of known MediaStreams that will be
// offered in a SessionDescription.
bool AddLocalStream(MediaStreamInterface* local_stream);
// Removes |local_stream| from the collection of known MediaStreams that will
// be offered in a SessionDescription.
void RemoveLocalStream(MediaStreamInterface* local_stream);
// Checks if any data channel has been added.
bool HasDataChannels() const;
// Adds |data_channel| to the collection of DataChannels that will be
// be offered in a SessionDescription.
bool AddDataChannel(DataChannel* data_channel);
// After we receive an OPEN message, create a data channel and add it.
bool AddDataChannelFromOpenMessage(const cricket::ReceiveDataParams& params,
const rtc::Buffer& payload);
void RemoveSctpDataChannel(int sid);
// Returns a MediaSessionOptions struct with options decided by |options|,
// the local MediaStreams and DataChannels.
virtual bool GetOptionsForOffer(
const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
cricket::MediaSessionOptions* session_options);
// Returns a MediaSessionOptions struct with options decided by
// |constraints|, the local MediaStreams and DataChannels.
virtual bool GetOptionsForAnswer(
const MediaConstraintsInterface* constraints,
cricket::MediaSessionOptions* options);
// Called when the remote session description has changed. The purpose is to
// update remote MediaStreams and DataChannels with the current
// session state.
// If the remote SessionDescription contain information about a new remote
// MediaStreams a new remote MediaStream is created and
// MediaStreamSignalingObserver::OnAddStream is called.
// If a remote MediaStream is missing from
// the remote SessionDescription MediaStreamSignalingObserver::OnRemoveStream
// is called.
// If the SessionDescription contains information about a new DataChannel,
// MediaStreamSignalingObserver::OnAddDataChannel is called with the
// DataChannel.
void OnRemoteDescriptionChanged(const SessionDescriptionInterface* desc);
// Called when the local session description has changed. The purpose is to
// update local and remote MediaStreams and DataChannels with the current
// session state.
// If |desc| indicates that the media type should be rejected, the method
// ends the remote MediaStreamTracks.
// It also updates local DataChannels with information about its local SSRC.
void OnLocalDescriptionChanged(const SessionDescriptionInterface* desc);
// Called when the audio channel closes.
void OnAudioChannelClose();
// Called when the video channel closes.
void OnVideoChannelClose();
// Called when the data channel closes.
void OnDataChannelClose();
// Returns all current known local MediaStreams.
StreamCollectionInterface* local_streams() const { return local_streams_;}
// Returns all current remote MediaStreams.
StreamCollectionInterface* remote_streams() const {
return remote_streams_.get();
}
void OnDataTransportCreatedForSctp();
void OnDtlsRoleReadyForSctp(rtc::SSLRole role);
void OnRemoteSctpDataChannelClosed(uint32_t sid);
const SctpDataChannels& sctp_data_channels() const {
return sctp_data_channels_;
}
private:
struct RemotePeerInfo {
RemotePeerInfo()
: msid_supported(false),
default_audio_track_needed(false),
default_video_track_needed(false) {
}
// True if it has been discovered that the remote peer support MSID.
bool msid_supported;
// The remote peer indicates in the session description that audio will be
// sent but no MSID is given.
bool default_audio_track_needed;
// The remote peer indicates in the session description that video will be
// sent but no MSID is given.
bool default_video_track_needed;
bool IsDefaultMediaStreamNeeded() {
return !msid_supported && (default_audio_track_needed ||
default_video_track_needed);
}
};
struct TrackInfo {
TrackInfo() : ssrc(0) {}
TrackInfo(const std::string& stream_label,
const std::string track_id,
uint32_t ssrc)
: stream_label(stream_label), track_id(track_id), ssrc(ssrc) {}
std::string stream_label;
std::string track_id;
uint32_t ssrc;
};
typedef std::vector<TrackInfo> TrackInfos;
// Makes sure a MediaStream Track is created for each StreamParam in
// |streams|. |media_type| is the type of the |streams| and can be either
// audio or video.
// If a new MediaStream is created it is added to |new_streams|.
void UpdateRemoteStreamsList(
const std::vector<cricket::StreamParams>& streams,
cricket::MediaType media_type,
StreamCollection* new_streams);
// Triggered when a remote track has been seen for the first time in a remote
// session description. It creates a remote MediaStreamTrackInterface
// implementation and triggers MediaStreamSignaling::OnAddRemoteAudioTrack or
// MediaStreamSignaling::OnAddRemoteVideoTrack.
void OnRemoteTrackSeen(const std::string& stream_label,
const std::string& track_id,
uint32_t ssrc,
cricket::MediaType media_type);
// Triggered when a remote track has been removed from a remote session
// description. It removes the remote track with id |track_id| from a remote
// MediaStream and triggers MediaStreamSignaling::OnRemoveRemoteAudioTrack or
// MediaStreamSignaling::OnRemoveRemoteVideoTrack.
void OnRemoteTrackRemoved(const std::string& stream_label,
const std::string& track_id,
cricket::MediaType media_type);
// Set the MediaStreamTrackInterface::TrackState to |kEnded| on all remote
// tracks of type |media_type|.
void RejectRemoteTracks(cricket::MediaType media_type);
// Finds remote MediaStreams without any tracks and removes them from
// |remote_streams_| and notifies the observer that the MediaStream no longer
// exist.
void UpdateEndedRemoteMediaStreams();
void MaybeCreateDefaultStream();
TrackInfos* GetRemoteTracks(cricket::MediaType type);
// Returns a map of currently negotiated LocalTrackInfo of type |type|.
TrackInfos* GetLocalTracks(cricket::MediaType type);
bool FindLocalTrack(const std::string& track_id, cricket::MediaType type);
// Loops through the vector of |streams| and finds added and removed
// StreamParams since last time this method was called.
// For each new or removed StreamParam NotifyLocalTrackAdded or
// NotifyLocalTrackRemoved in invoked.
void UpdateLocalTracks(const std::vector<cricket::StreamParams>& streams,
cricket::MediaType media_type);
// Triggered when a local track has been seen for the first time in a local
// session description.
// This method triggers MediaStreamSignaling::OnAddLocalAudioTrack or
// MediaStreamSignaling::OnAddLocalVideoTrack if the rtp streams in the local
// SessionDescription can be mapped to a MediaStreamTrack in a MediaStream in
// |local_streams_|
void OnLocalTrackSeen(const std::string& stream_label,
const std::string& track_id,
uint32_t ssrc,
cricket::MediaType media_type);
// Triggered when a local track has been removed from a local session
// description.
// This method triggers MediaStreamSignaling::OnRemoveLocalAudioTrack or
// MediaStreamSignaling::OnRemoveLocalVideoTrack if a stream has been removed
// from the local SessionDescription and the stream can be mapped to a
// MediaStreamTrack in a MediaStream in |local_streams_|.
void OnLocalTrackRemoved(const std::string& stream_label,
const std::string& track_id,
uint32_t ssrc,
cricket::MediaType media_type);
void UpdateLocalRtpDataChannels(const cricket::StreamParamsVec& streams);
void UpdateRemoteRtpDataChannels(const cricket::StreamParamsVec& streams);
void UpdateClosingDataChannels(
const std::vector<std::string>& active_channels, bool is_local_update);
void CreateRemoteDataChannel(const std::string& label, uint32_t remote_ssrc);
const TrackInfo* FindTrackInfo(const TrackInfos& infos,
const std::string& stream_label,
const std::string track_id) const;
// Returns the index of the specified SCTP DataChannel in sctp_data_channels_,
// or -1 if not found.
int FindDataChannelBySid(int sid) const;
RemotePeerInfo remote_info_;
rtc::Thread* signaling_thread_;
DataChannelFactory* data_channel_factory_;
MediaStreamSignalingObserver* stream_observer_;
rtc::scoped_refptr<StreamCollection> local_streams_;
rtc::scoped_refptr<StreamCollection> remote_streams_;
rtc::scoped_ptr<RemoteMediaStreamFactory> remote_stream_factory_;
TrackInfos remote_audio_tracks_;
TrackInfos remote_video_tracks_;
TrackInfos local_audio_tracks_;
TrackInfos local_video_tracks_;
int last_allocated_sctp_even_sid_;
int last_allocated_sctp_odd_sid_;
RtpDataChannels rtp_data_channels_;
SctpDataChannels sctp_data_channels_;
};
} // namespace webrtc
#endif // TALK_APP_WEBRTC_MEDIASTREAMSIGNALING_H_

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -31,6 +31,7 @@
#include <string>
#include "talk/app/webrtc/dtlsidentitystore.h"
#include "talk/app/webrtc/mediastreamsignaling.h"
#include "talk/app/webrtc/peerconnectionfactory.h"
#include "talk/app/webrtc/peerconnectioninterface.h"
#include "talk/app/webrtc/rtpreceiverinterface.h"
@ -42,26 +43,11 @@
namespace webrtc {
class RemoteMediaStreamFactory;
typedef std::vector<PortAllocatorFactoryInterface::StunConfiguration>
StunConfigurations;
typedef std::vector<PortAllocatorFactoryInterface::TurnConfiguration>
TurnConfigurations;
// Populates |session_options| from |rtc_options|, and returns true if options
// are valid.
// Send streams should already be added to |session_options| before this method
// is called, as this affects the values of recv_audio and recv_video.
bool ConvertRtcOptionsForOffer(
const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
cricket::MediaSessionOptions* session_options);
// Populates |session_options| from |constraints|, and returns true if all
// mandatory constraints are satisfied.
bool ParseConstraintsForAnswer(const MediaConstraintsInterface* constraints,
cricket::MediaSessionOptions* session_options);
// Parses the URLs for each server in |servers| to build |stun_config| and
// |turn_config|.
bool ParseIceServers(const PeerConnectionInterface::IceServers& servers,
@ -69,8 +55,10 @@ bool ParseIceServers(const PeerConnectionInterface::IceServers& servers,
TurnConfigurations* turn_config);
// PeerConnection implements the PeerConnectionInterface interface.
// It uses WebRtcSession to implement the PeerConnection functionality.
// It uses MediaStreamSignaling and WebRtcSession to implement
// the PeerConnection functionality.
class PeerConnection : public PeerConnectionInterface,
public MediaStreamSignalingObserver,
public IceObserver,
public rtc::MessageHandler,
public sigslot::has_slots<> {
@ -88,8 +76,6 @@ class PeerConnection : public PeerConnectionInterface,
bool AddStream(MediaStreamInterface* local_stream) override;
void RemoveStream(MediaStreamInterface* local_stream) override;
virtual WebRtcSession* session() { return session_.get(); }
rtc::scoped_refptr<DtmfSenderInterface> CreateDtmfSender(
AudioTrackInterface* track) override;
@ -134,72 +120,39 @@ class PeerConnection : public PeerConnectionInterface,
void Close() override;
// Virtual for unit tests.
virtual const std::vector<rtc::scoped_refptr<DataChannel>>&
sctp_data_channels() const {
return sctp_data_channels_;
};
protected:
~PeerConnection() override;
private:
struct TrackInfo {
TrackInfo() : ssrc(0) {}
TrackInfo(const std::string& stream_label,
const std::string track_id,
uint32_t ssrc)
: stream_label(stream_label), track_id(track_id), ssrc(ssrc) {}
std::string stream_label;
std::string track_id;
uint32_t ssrc;
};
typedef std::vector<TrackInfo> TrackInfos;
struct RemotePeerInfo {
RemotePeerInfo()
: msid_supported(false),
default_audio_track_needed(false),
default_video_track_needed(false) {}
// True if it has been discovered that the remote peer support MSID.
bool msid_supported;
// The remote peer indicates in the session description that audio will be
// sent but no MSID is given.
bool default_audio_track_needed;
// The remote peer indicates in the session description that video will be
// sent but no MSID is given.
bool default_video_track_needed;
bool IsDefaultMediaStreamNeeded() {
return !msid_supported &&
(default_audio_track_needed || default_video_track_needed);
}
};
// Implements MessageHandler.
void OnMessage(rtc::Message* msg) override;
void CreateAudioReceiver(MediaStreamInterface* stream,
AudioTrackInterface* audio_track,
uint32_t ssrc);
void CreateVideoReceiver(MediaStreamInterface* stream,
VideoTrackInterface* video_track,
uint32_t ssrc);
void DestroyAudioReceiver(MediaStreamInterface* stream,
AudioTrackInterface* audio_track);
void DestroyVideoReceiver(MediaStreamInterface* stream,
VideoTrackInterface* video_track);
void CreateAudioSender(MediaStreamInterface* stream,
AudioTrackInterface* audio_track,
uint32_t ssrc);
void CreateVideoSender(MediaStreamInterface* stream,
VideoTrackInterface* video_track,
uint32_t ssrc);
void DestroyAudioSender(MediaStreamInterface* stream,
AudioTrackInterface* audio_track,
uint32_t ssrc);
void DestroyVideoSender(MediaStreamInterface* stream,
VideoTrackInterface* video_track);
// Implements MediaStreamSignalingObserver.
void OnAddRemoteStream(MediaStreamInterface* stream) override;
void OnRemoveRemoteStream(MediaStreamInterface* stream) override;
void OnAddDataChannel(DataChannelInterface* data_channel) override;
void OnAddRemoteAudioTrack(MediaStreamInterface* stream,
AudioTrackInterface* audio_track,
uint32_t ssrc) override;
void OnAddRemoteVideoTrack(MediaStreamInterface* stream,
VideoTrackInterface* video_track,
uint32_t ssrc) override;
void OnRemoveRemoteAudioTrack(MediaStreamInterface* stream,
AudioTrackInterface* audio_track) override;
void OnRemoveRemoteVideoTrack(MediaStreamInterface* stream,
VideoTrackInterface* video_track) override;
void OnAddLocalAudioTrack(MediaStreamInterface* stream,
AudioTrackInterface* audio_track,
uint32_t ssrc) override;
void OnAddLocalVideoTrack(MediaStreamInterface* stream,
VideoTrackInterface* video_track,
uint32_t ssrc) override;
void OnRemoveLocalAudioTrack(MediaStreamInterface* stream,
AudioTrackInterface* audio_track,
uint32_t ssrc) override;
void OnRemoveLocalVideoTrack(MediaStreamInterface* stream,
VideoTrackInterface* video_track) override;
void OnRemoveLocalStream(MediaStreamInterface* stream) override;
// Implements IceObserver
void OnIceConnectionChange(IceConnectionState new_state) override;
@ -219,138 +172,21 @@ class PeerConnection : public PeerConnectionInterface,
void PostSetSessionDescriptionFailure(SetSessionDescriptionObserver* observer,
const std::string& error);
void PostCreateSessionDescriptionFailure(
CreateSessionDescriptionObserver* observer,
const std::string& error);
bool IsClosed() const {
return signaling_state_ == PeerConnectionInterface::kClosed;
}
// Returns a MediaSessionOptions struct with options decided by |options|,
// the local MediaStreams and DataChannels.
virtual bool GetOptionsForOffer(
const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
cricket::MediaSessionOptions* session_options);
// Returns a MediaSessionOptions struct with options decided by
// |constraints|, the local MediaStreams and DataChannels.
virtual bool GetOptionsForAnswer(
const MediaConstraintsInterface* constraints,
cricket::MediaSessionOptions* session_options);
// Makes sure a MediaStream Track is created for each StreamParam in
// |streams|. |media_type| is the type of the |streams| and can be either
// audio or video.
// If a new MediaStream is created it is added to |new_streams|.
void UpdateRemoteStreamsList(
const std::vector<cricket::StreamParams>& streams,
cricket::MediaType media_type,
StreamCollection* new_streams);
// Triggered when a remote track has been seen for the first time in a remote
// session description. It creates a remote MediaStreamTrackInterface
// implementation and triggers CreateAudioReceiver or CreateVideoReceiver.
void OnRemoteTrackSeen(const std::string& stream_label,
const std::string& track_id,
uint32_t ssrc,
cricket::MediaType media_type);
// Triggered when a remote track has been removed from a remote session
// description. It removes the remote track with id |track_id| from a remote
// MediaStream and triggers DestroyAudioReceiver or DestroyVideoReceiver.
void OnRemoteTrackRemoved(const std::string& stream_label,
const std::string& track_id,
cricket::MediaType media_type);
// Finds remote MediaStreams without any tracks and removes them from
// |remote_streams_| and notifies the observer that the MediaStreams no longer
// exist.
void UpdateEndedRemoteMediaStreams();
void MaybeCreateDefaultStream();
// Set the MediaStreamTrackInterface::TrackState to |kEnded| on all remote
// tracks of type |media_type|.
void EndRemoteTracks(cricket::MediaType media_type);
// Loops through the vector of |streams| and finds added and removed
// StreamParams since last time this method was called.
// For each new or removed StreamParam, OnLocalTrackSeen or
// OnLocalTrackRemoved is invoked.
void UpdateLocalTracks(const std::vector<cricket::StreamParams>& streams,
cricket::MediaType media_type);
// Triggered when a local track has been seen for the first time in a local
// session description.
// This method triggers CreateAudioSender or CreateVideoSender if the rtp
// streams in the local SessionDescription can be mapped to a MediaStreamTrack
// in a MediaStream in |local_streams_|
void OnLocalTrackSeen(const std::string& stream_label,
const std::string& track_id,
uint32_t ssrc,
cricket::MediaType media_type);
// Triggered when a local track has been removed from a local session
// description.
// This method triggers DestroyAudioSender or DestroyVideoSender if a stream
// has been removed from the local SessionDescription and the stream can be
// mapped to a MediaStreamTrack in a MediaStream in |local_streams_|.
void OnLocalTrackRemoved(const std::string& stream_label,
const std::string& track_id,
uint32_t ssrc,
cricket::MediaType media_type);
void UpdateLocalRtpDataChannels(const cricket::StreamParamsVec& streams);
void UpdateRemoteRtpDataChannels(const cricket::StreamParamsVec& streams);
void UpdateClosingRtpDataChannels(
const std::vector<std::string>& active_channels,
bool is_local_update);
void CreateRemoteRtpDataChannel(const std::string& label,
uint32_t remote_ssrc);
// Creates channel and adds it to the collection of DataChannels that will
// be offered in a SessionDescription.
rtc::scoped_refptr<DataChannel> InternalCreateDataChannel(
const std::string& label,
const InternalDataChannelInit* config);
// Checks if any data channel has been added.
bool HasDataChannels() const;
void AllocateSctpSids(rtc::SSLRole role);
void OnSctpDataChannelClosed(DataChannel* channel);
// Notifications from WebRtcSession relating to BaseChannels.
void OnVoiceChannelDestroyed();
void OnVideoChannelDestroyed();
void OnDataChannelCreated();
void OnDataChannelDestroyed();
// Called when the cricket::DataChannel receives a message indicating that a
// webrtc::DataChannel should be opened.
void OnDataChannelOpenMessage(const std::string& label,
const InternalDataChannelInit& config);
std::vector<rtc::scoped_refptr<RtpSenderInterface>>::iterator
FindSenderForTrack(MediaStreamTrackInterface* track);
std::vector<rtc::scoped_refptr<RtpReceiverInterface>>::iterator
FindReceiverForTrack(MediaStreamTrackInterface* track);
TrackInfos* GetRemoteTracks(cricket::MediaType media_type);
TrackInfos* GetLocalTracks(cricket::MediaType media_type);
const TrackInfo* FindTrackInfo(const TrackInfos& infos,
const std::string& stream_label,
const std::string track_id) const;
// Returns the specified SCTP DataChannel in sctp_data_channels_,
// or nullptr if not found.
DataChannel* FindDataChannelBySid(int sid) const;
// Storing the factory as a scoped reference pointer ensures that the memory
// in the PeerConnectionFactoryImpl remains available as long as the
// PeerConnection is running. It is passed to PeerConnection as a raw pointer.
// However, since the reference counting is done in the
// PeerConnectionFactoryInterface all instances created using the raw pointer
// PeerConnectionFactoryInteface all instances created using the raw pointer
// will refer to the same reference count.
rtc::scoped_refptr<PeerConnectionFactory> factory_;
PeerConnectionObserver* observer_;
@ -362,35 +198,12 @@ class PeerConnection : public PeerConnectionInterface,
IceGatheringState ice_gathering_state_;
rtc::scoped_ptr<cricket::PortAllocator> port_allocator_;
// Streams added via AddStream.
rtc::scoped_refptr<StreamCollection> local_streams_;
// Streams created as a result of SetRemoteDescription.
rtc::scoped_refptr<StreamCollection> remote_streams_;
// These lists store track info seen in local/remote descriptions.
TrackInfos remote_audio_tracks_;
TrackInfos remote_video_tracks_;
TrackInfos local_audio_tracks_;
TrackInfos local_video_tracks_;
SctpSidAllocator sid_allocator_;
// label -> DataChannel
std::map<std::string, rtc::scoped_refptr<DataChannel>> rtp_data_channels_;
std::vector<rtc::scoped_refptr<DataChannel>> sctp_data_channels_;
RemotePeerInfo remote_info_;
rtc::scoped_ptr<RemoteMediaStreamFactory> remote_stream_factory_;
rtc::scoped_ptr<WebRtcSession> session_;
rtc::scoped_ptr<MediaStreamSignaling> mediastream_signaling_;
rtc::scoped_ptr<StatsCollector> stats_;
std::vector<rtc::scoped_refptr<RtpSenderInterface>> senders_;
std::vector<rtc::scoped_refptr<RtpReceiverInterface>> receivers_;
// The session_ scoped_ptr is declared at the bottom of PeerConnection
// because its destruction fires signals (such as VoiceChannelDestroyed)
// which will trigger some final actions in PeerConnection...
rtc::scoped_ptr<WebRtcSession> session_;
// ... But stats_ depends on session_ so it should be destroyed even earlier.
rtc::scoped_ptr<StatsCollector> stats_;
};
} // namespace webrtc

View File

@ -364,35 +364,3 @@ TEST_F(PeerConnectionEndToEndTest,
EXPECT_EQ(1U, dc_1_observer->received_message_count());
EXPECT_EQ(1U, dc_2_observer->received_message_count());
}
// Verifies that a DataChannel added from an OPEN message functions after
// a channel has been previously closed (webrtc issue 3778).
// This previously failed because the new channel re-uses the ID of the closed
// channel, and the closed channel was incorrectly still assigned to the id.
// TODO(deadbeef): This is disabled because there's currently a race condition
// caused by the fact that a data channel signals that it's closed before it
// really is. Re-enable this test once that's fixed.
TEST_F(PeerConnectionEndToEndTest,
DISABLED_DataChannelFromOpenWorksAfterClose) {
MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
CreatePcs();
webrtc::DataChannelInit init;
rtc::scoped_refptr<DataChannelInterface> caller_dc(
caller_->CreateDataChannel("data", init));
Negotiate();
WaitForConnection();
WaitForDataChannelsToOpen(caller_dc, callee_signaled_data_channels_, 0);
CloseDataChannels(caller_dc, callee_signaled_data_channels_, 0);
// Create a new channel and ensure it works after closing the previous one.
caller_dc = caller_->CreateDataChannel("data2", init);
WaitForDataChannelsToOpen(caller_dc, callee_signaled_data_channels_, 1);
TestDataChannelSendAndReceive(caller_dc, callee_signaled_data_channels_[1]);
CloseDataChannels(caller_dc, callee_signaled_data_channels_, 1);
}

View File

@ -29,7 +29,6 @@
#include "talk/app/webrtc/audiotrack.h"
#include "talk/app/webrtc/localaudiosource.h"
#include "talk/app/webrtc/mediastream.h"
#include "talk/app/webrtc/mediastreamproxy.h"
#include "talk/app/webrtc/mediastreamtrackproxy.h"
#include "talk/app/webrtc/peerconnection.h"

File diff suppressed because it is too large Load Diff

View File

@ -48,19 +48,6 @@ enum DataChannelOpenMessageChannelType {
DCOMCT_UNORDERED_PARTIAL_TIME = 0x82,
};
bool IsOpenMessage(const rtc::Buffer& payload) {
// Format defined at
// http://tools.ietf.org/html/draft-jesup-rtcweb-data-protocol-04
rtc::ByteBuffer buffer(payload);
uint8_t message_type;
if (!buffer.ReadUInt8(&message_type)) {
LOG(LS_WARNING) << "Could not read OPEN message type.";
return false;
}
return message_type == DATA_CHANNEL_OPEN_MESSAGE_TYPE;
}
bool ParseDataChannelOpenMessage(const rtc::Buffer& payload,
std::string* label,
DataChannelInit* config) {

View File

@ -39,9 +39,6 @@ class Buffer;
namespace webrtc {
struct DataChannelInit;
// Read the message type and return true if it's an OPEN message.
bool IsOpenMessage(const rtc::Buffer& payload);
bool ParseDataChannelOpenMessage(const rtc::Buffer& payload,
std::string* label,
DataChannelInit* config);

View File

@ -1,6 +1,6 @@
/*
* libjingle
* Copyright 2013 Google Inc.
* Copyright 2013 Google Inc
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@ -159,20 +159,3 @@ TEST_F(SctpUtilsTest, WriteParseAckMessage) {
EXPECT_TRUE(webrtc::ParseDataChannelOpenAckMessage(packet));
}
TEST_F(SctpUtilsTest, TestIsOpenMessage) {
rtc::ByteBuffer open;
open.WriteUInt8(0x03);
EXPECT_TRUE(webrtc::IsOpenMessage(open));
rtc::ByteBuffer openAck;
openAck.WriteUInt8(0x02);
EXPECT_FALSE(webrtc::IsOpenMessage(open));
rtc::ByteBuffer invalid;
openAck.WriteUInt8(0x01);
EXPECT_FALSE(webrtc::IsOpenMessage(invalid));
rtc::ByteBuffer empty;
EXPECT_FALSE(webrtc::IsOpenMessage(empty));
}

View File

@ -30,7 +30,6 @@
#include <utility>
#include <vector>
#include "talk/app/webrtc/peerconnection.h"
#include "talk/session/media/channel.h"
#include "webrtc/base/base64.h"
#include "webrtc/base/checks.h"
@ -357,13 +356,14 @@ const char* AdapterTypeToStatsType(rtc::AdapterType type) {
}
}
StatsCollector::StatsCollector(PeerConnection* pc)
: pc_(pc), stats_gathering_started_(0) {
RTC_DCHECK(pc_);
StatsCollector::StatsCollector(WebRtcSession* session)
: session_(session),
stats_gathering_started_(0) {
RTC_DCHECK(session_);
}
StatsCollector::~StatsCollector() {
RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent());
RTC_DCHECK(session_->signaling_thread()->IsCurrent());
}
double StatsCollector::GetTimeNow() {
@ -373,7 +373,7 @@ double StatsCollector::GetTimeNow() {
// Adds a MediaStream with tracks that can be used as a |selector| in a call
// to GetStats.
void StatsCollector::AddStream(MediaStreamInterface* stream) {
RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent());
RTC_DCHECK(session_->signaling_thread()->IsCurrent());
RTC_DCHECK(stream != NULL);
CreateTrackReports<AudioTrackVector>(stream->GetAudioTracks(),
@ -384,7 +384,7 @@ void StatsCollector::AddStream(MediaStreamInterface* stream) {
void StatsCollector::AddLocalAudioTrack(AudioTrackInterface* audio_track,
uint32_t ssrc) {
RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent());
RTC_DCHECK(session_->signaling_thread()->IsCurrent());
RTC_DCHECK(audio_track != NULL);
#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON))
for (const auto& track : local_audio_tracks_)
@ -416,7 +416,7 @@ void StatsCollector::RemoveLocalAudioTrack(AudioTrackInterface* audio_track,
void StatsCollector::GetStats(MediaStreamTrackInterface* track,
StatsReports* reports) {
RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent());
RTC_DCHECK(session_->signaling_thread()->IsCurrent());
RTC_DCHECK(reports != NULL);
RTC_DCHECK(reports->empty());
@ -430,7 +430,7 @@ void StatsCollector::GetStats(MediaStreamTrackInterface* track,
}
StatsReport* report = reports_.Find(StatsReport::NewTypedId(
StatsReport::kStatsReportTypeSession, pc_->session()->id()));
StatsReport::kStatsReportTypeSession, session_->id()));
if (report)
reports->push_back(report);
@ -456,7 +456,7 @@ void StatsCollector::GetStats(MediaStreamTrackInterface* track,
void
StatsCollector::UpdateStats(PeerConnectionInterface::StatsOutputLevel level) {
RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent());
RTC_DCHECK(session_->signaling_thread()->IsCurrent());
double time_now = GetTimeNow();
// Calls to UpdateStats() that occur less than kMinGatherStatsPeriod number of
// ms apart will be ignored.
@ -467,7 +467,7 @@ StatsCollector::UpdateStats(PeerConnectionInterface::StatsOutputLevel level) {
}
stats_gathering_started_ = time_now;
if (pc_->session()) {
if (session_) {
// TODO(tommi): All of these hop over to the worker thread to fetch
// information. We could use an AsyncInvoker to run all of these and post
// the information back to the signaling thread where we can create and
@ -482,12 +482,11 @@ StatsCollector::UpdateStats(PeerConnectionInterface::StatsOutputLevel level) {
}
}
StatsReport* StatsCollector::PrepareReport(
bool local,
uint32_t ssrc,
const StatsReport::Id& transport_id,
StatsReport::Direction direction) {
RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent());
StatsReport* StatsCollector::PrepareReport(bool local,
uint32_t ssrc,
const StatsReport::Id& transport_id,
StatsReport::Direction direction) {
RTC_DCHECK(session_->signaling_thread()->IsCurrent());
StatsReport::Id id(StatsReport::NewIdWithDirection(
local ? StatsReport::kStatsReportTypeSsrc
: StatsReport::kStatsReportTypeRemoteSsrc,
@ -526,7 +525,7 @@ StatsReport* StatsCollector::PrepareReport(
StatsReport* StatsCollector::AddOneCertificateReport(
const rtc::SSLCertificate* cert, const StatsReport* issuer) {
RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent());
RTC_DCHECK(session_->signaling_thread()->IsCurrent());
// TODO(bemasc): Move this computation to a helper class that caches these
// values to reduce CPU use in GetStats. This will require adding a fast
@ -569,7 +568,7 @@ StatsReport* StatsCollector::AddOneCertificateReport(
StatsReport* StatsCollector::AddCertificateReports(
const rtc::SSLCertificate* cert) {
RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent());
RTC_DCHECK(session_->signaling_thread()->IsCurrent());
// Produces a chain of StatsReports representing this certificate and the rest
// of its chain, and adds those reports to |reports_|. The return value is
// the id of the leaf report. The provided cert must be non-null, so at least
@ -669,18 +668,18 @@ StatsReport* StatsCollector::AddCandidateReport(
}
void StatsCollector::ExtractSessionInfo() {
RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent());
RTC_DCHECK(session_->signaling_thread()->IsCurrent());
// Extract information from the base session.
StatsReport::Id id(StatsReport::NewTypedId(
StatsReport::kStatsReportTypeSession, pc_->session()->id()));
StatsReport::kStatsReportTypeSession, session_->id()));
StatsReport* report = reports_.ReplaceOrAddNew(id);
report->set_timestamp(stats_gathering_started_);
report->AddBoolean(StatsReport::kStatsValueNameInitiator,
pc_->session()->initiator());
session_->initiator());
cricket::SessionStats stats;
if (!pc_->session()->GetTransportStats(&stats)) {
if (!session_->GetTransportStats(&stats)) {
return;
}
@ -699,16 +698,16 @@ void StatsCollector::ExtractSessionInfo() {
//
StatsReport::Id local_cert_report_id, remote_cert_report_id;
rtc::scoped_refptr<rtc::RTCCertificate> certificate;
if (pc_->session()->GetLocalCertificate(
transport_iter.second.transport_name, &certificate)) {
if (session_->GetLocalCertificate(transport_iter.second.transport_name,
&certificate)) {
StatsReport* r = AddCertificateReports(&(certificate->ssl_certificate()));
if (r)
local_cert_report_id = r->id();
}
rtc::scoped_ptr<rtc::SSLCertificate> cert;
if (pc_->session()->GetRemoteSSLCertificate(
transport_iter.second.transport_name, cert.accept())) {
if (session_->GetRemoteSSLCertificate(transport_iter.second.transport_name,
cert.accept())) {
StatsReport* r = AddCertificateReports(cert.get());
if (r)
remote_cert_report_id = r->id();
@ -759,13 +758,13 @@ void StatsCollector::ExtractSessionInfo() {
}
void StatsCollector::ExtractVoiceInfo() {
RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent());
RTC_DCHECK(session_->signaling_thread()->IsCurrent());
if (!pc_->session()->voice_channel()) {
if (!session_->voice_channel()) {
return;
}
cricket::VoiceMediaInfo voice_info;
if (!pc_->session()->voice_channel()->GetStats(&voice_info)) {
if (!session_->voice_channel()->GetStats(&voice_info)) {
LOG(LS_ERROR) << "Failed to get voice channel stats.";
return;
}
@ -774,11 +773,11 @@ void StatsCollector::ExtractVoiceInfo() {
// results back to the signaling thread, where we can add data to the reports.
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
StatsReport::Id transport_id(GetTransportIdFromProxy(
proxy_to_transport_, pc_->session()->voice_channel()->content_name()));
StatsReport::Id transport_id(GetTransportIdFromProxy(proxy_to_transport_,
session_->voice_channel()->content_name()));
if (!transport_id.get()) {
LOG(LS_ERROR) << "Failed to get transport name for proxy "
<< pc_->session()->voice_channel()->content_name();
<< session_->voice_channel()->content_name();
return;
}
@ -792,13 +791,13 @@ void StatsCollector::ExtractVoiceInfo() {
void StatsCollector::ExtractVideoInfo(
PeerConnectionInterface::StatsOutputLevel level) {
RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent());
RTC_DCHECK(session_->signaling_thread()->IsCurrent());
if (!pc_->session()->video_channel())
if (!session_->video_channel())
return;
cricket::VideoMediaInfo video_info;
if (!pc_->session()->video_channel()->GetStats(&video_info)) {
if (!session_->video_channel()->GetStats(&video_info)) {
LOG(LS_ERROR) << "Failed to get video channel stats.";
return;
}
@ -807,11 +806,11 @@ void StatsCollector::ExtractVideoInfo(
// results back to the signaling thread, where we can add data to the reports.
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
StatsReport::Id transport_id(GetTransportIdFromProxy(
proxy_to_transport_, pc_->session()->video_channel()->content_name()));
StatsReport::Id transport_id(GetTransportIdFromProxy(proxy_to_transport_,
session_->video_channel()->content_name()));
if (!transport_id.get()) {
LOG(LS_ERROR) << "Failed to get transport name for proxy "
<< pc_->session()->video_channel()->content_name();
<< session_->video_channel()->content_name();
return;
}
ExtractStatsFromList(video_info.receivers, transport_id, this,
@ -829,11 +828,12 @@ void StatsCollector::ExtractVideoInfo(
}
void StatsCollector::ExtractDataInfo() {
RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent());
RTC_DCHECK(session_->signaling_thread()->IsCurrent());
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
for (const auto& dc : pc_->sctp_data_channels()) {
for (const auto& dc :
session_->mediastream_signaling()->sctp_data_channels()) {
StatsReport::Id id(StatsReport::NewTypedIntId(
StatsReport::kStatsReportTypeDataChannel, dc->id()));
StatsReport* report = reports_.ReplaceOrAddNew(id);
@ -849,14 +849,14 @@ void StatsCollector::ExtractDataInfo() {
StatsReport* StatsCollector::GetReport(const StatsReport::StatsType& type,
const std::string& id,
StatsReport::Direction direction) {
RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent());
RTC_DCHECK(session_->signaling_thread()->IsCurrent());
RTC_DCHECK(type == StatsReport::kStatsReportTypeSsrc ||
type == StatsReport::kStatsReportTypeRemoteSsrc);
return reports_.Find(StatsReport::NewIdWithDirection(type, id, direction));
}
void StatsCollector::UpdateStatsFromExistingLocalAudioTracks() {
RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent());
RTC_DCHECK(session_->signaling_thread()->IsCurrent());
// Loop through the existing local audio tracks.
for (const auto& it : local_audio_tracks_) {
AudioTrackInterface* track = it.first;
@ -884,7 +884,7 @@ void StatsCollector::UpdateStatsFromExistingLocalAudioTracks() {
void StatsCollector::UpdateReportFromAudioTrack(AudioTrackInterface* track,
StatsReport* report) {
RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent());
RTC_DCHECK(session_->signaling_thread()->IsCurrent());
RTC_DCHECK(track != NULL);
int signal_level = 0;
@ -907,16 +907,16 @@ void StatsCollector::UpdateReportFromAudioTrack(AudioTrackInterface* track,
bool StatsCollector::GetTrackIdBySsrc(uint32_t ssrc,
std::string* track_id,
StatsReport::Direction direction) {
RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent());
RTC_DCHECK(session_->signaling_thread()->IsCurrent());
if (direction == StatsReport::kSend) {
if (!pc_->session()->GetLocalTrackIdBySsrc(ssrc, track_id)) {
if (!session_->GetLocalTrackIdBySsrc(ssrc, track_id)) {
LOG(LS_WARNING) << "The SSRC " << ssrc
<< " is not associated with a sending track";
return false;
}
} else {
RTC_DCHECK(direction == StatsReport::kReceive);
if (!pc_->session()->GetRemoteTrackIdBySsrc(ssrc, track_id)) {
if (!session_->GetRemoteTrackIdBySsrc(ssrc, track_id)) {
LOG(LS_WARNING) << "The SSRC " << ssrc
<< " is not associated with a receiving track";
return false;
@ -927,7 +927,7 @@ bool StatsCollector::GetTrackIdBySsrc(uint32_t ssrc,
}
void StatsCollector::UpdateTrackReports() {
RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent());
RTC_DCHECK(session_->signaling_thread()->IsCurrent());
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;

View File

@ -43,8 +43,6 @@
namespace webrtc {
class PeerConnection;
// Conversion function to convert candidate type string to the corresponding one
// from enum RTCStatsIceCandidateType.
const char* IceCandidateTypeToStatsType(const std::string& candidate_type);
@ -59,9 +57,9 @@ typedef std::map<std::string, StatsReport*> TrackIdMap;
class StatsCollector {
public:
// The caller is responsible for ensuring that the pc outlives the
// The caller is responsible for ensuring that the session outlives the
// StatsCollector instance.
explicit StatsCollector(PeerConnection* pc);
explicit StatsCollector(WebRtcSession* session);
virtual ~StatsCollector();
// Adds a MediaStream with tracks that can be used as a |selector| in a call
@ -153,8 +151,8 @@ class StatsCollector {
// A collection for all of our stats reports.
StatsCollection reports_;
TrackIdMap track_ids_;
// Raw pointer to the peer connection the statistics are gathered from.
PeerConnection* const pc_;
// Raw pointer to the session the statistics are gathered from.
WebRtcSession* const session_;
double stats_gathering_started_;
cricket::ProxyTransportMap proxy_to_transport_;

View File

@ -31,13 +31,12 @@
#include "talk/app/webrtc/statscollector.h"
#include "talk/app/webrtc/peerconnection.h"
#include "talk/app/webrtc/peerconnectionfactory.h"
#include "talk/app/webrtc/mediastream.h"
#include "talk/app/webrtc/mediastreaminterface.h"
#include "talk/app/webrtc/mediastreamsignaling.h"
#include "talk/app/webrtc/mediastreamtrack.h"
#include "talk/app/webrtc/test/fakedatachannelprovider.h"
#include "talk/app/webrtc/test/fakemediastreamsignaling.h"
#include "talk/app/webrtc/videotrack.h"
#include "talk/media/base/fakemediaengine.h"
#include "talk/session/media/channelmanager.h"
@ -55,7 +54,6 @@ using testing::DoAll;
using testing::Field;
using testing::Return;
using testing::ReturnNull;
using testing::ReturnRef;
using testing::SetArgPointee;
using webrtc::PeerConnectionInterface;
using webrtc::StatsReport;
@ -85,12 +83,12 @@ const uint32_t kSsrcOfTrack = 1234;
class MockWebRtcSession : public webrtc::WebRtcSession {
public:
explicit MockWebRtcSession(cricket::ChannelManager* channel_manager)
: WebRtcSession(channel_manager,
rtc::Thread::Current(),
rtc::Thread::Current(),
nullptr) {}
: WebRtcSession(channel_manager, rtc::Thread::Current(),
rtc::Thread::Current(), NULL, NULL) {
}
MOCK_METHOD0(voice_channel, cricket::VoiceChannel*());
MOCK_METHOD0(video_channel, cricket::VideoChannel*());
MOCK_CONST_METHOD0(mediastream_signaling, const MediaStreamSignaling*());
// Libjingle uses "local" for a outgoing track, and "remote" for a incoming
// track.
MOCK_METHOD2(GetLocalTrackIdBySsrc, bool(uint32_t, std::string*));
@ -104,21 +102,6 @@ class MockWebRtcSession : public webrtc::WebRtcSession {
rtc::SSLCertificate** cert));
};
// The factory isn't really used; it just satisfies the base PeerConnection.
class FakePeerConnectionFactory
: public rtc::RefCountedObject<PeerConnectionFactory> {};
class MockPeerConnection
: public rtc::RefCountedObject<webrtc::PeerConnection> {
public:
MockPeerConnection()
: rtc::RefCountedObject<webrtc::PeerConnection>(
new FakePeerConnectionFactory()) {}
MOCK_METHOD0(session, WebRtcSession*());
MOCK_CONST_METHOD0(sctp_data_channels,
const std::vector<rtc::scoped_refptr<DataChannel>>&());
};
class MockVideoMediaChannel : public cricket::FakeVideoMediaChannel {
public:
MockVideoMediaChannel() :
@ -489,8 +472,9 @@ void InitVoiceReceiverInfo(cricket::VoiceReceiverInfo* voice_receiver_info) {
class StatsCollectorForTest : public webrtc::StatsCollector {
public:
explicit StatsCollectorForTest(PeerConnection* pc)
: StatsCollector(pc), time_now_(19477) {}
explicit StatsCollectorForTest(WebRtcSession* session) :
StatsCollector(session), time_now_(19477) {
}
double GetTimeNow() override {
return time_now_;
@ -503,18 +487,15 @@ class StatsCollectorForTest : public webrtc::StatsCollector {
class StatsCollectorTest : public testing::Test {
protected:
StatsCollectorTest()
: media_engine_(new cricket::FakeMediaEngine()),
channel_manager_(
new cricket::ChannelManager(media_engine_, rtc::Thread::Current())),
session_(channel_manager_.get()) {
: media_engine_(new cricket::FakeMediaEngine()),
channel_manager_(
new cricket::ChannelManager(media_engine_, rtc::Thread::Current())),
session_(channel_manager_.get()),
signaling_(channel_manager_.get()) {
// By default, we ignore session GetStats calls.
EXPECT_CALL(session_, GetTransportStats(_)).WillRepeatedly(Return(false));
// Add default returns for mock classes.
EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
EXPECT_CALL(pc_, session()).WillRepeatedly(Return(&session_));
EXPECT_CALL(pc_, sctp_data_channels())
.WillRepeatedly(ReturnRef(data_channels_));
EXPECT_CALL(session_, mediastream_signaling()).WillRepeatedly(
Return(&signaling_));
}
~StatsCollectorTest() {}
@ -576,16 +557,6 @@ class StatsCollectorTest : public testing::Test {
.WillOnce(DoAll(SetArgPointee<1>(kRemoteTrackId), Return(true)));
}
void AddDataChannel(cricket::DataChannelType type,
const std::string& label,
int id) {
InternalDataChannelInit config;
config.id = id;
data_channels_.push_back(DataChannel::Create(
&data_channel_provider_, cricket::DCT_SCTP, label, config));
}
StatsReport* AddCandidateReport(StatsCollector* collector,
const cricket::Candidate& candidate,
bool local) {
@ -673,7 +644,7 @@ class StatsCollectorTest : public testing::Test {
const std::vector<std::string>& local_ders,
const rtc::FakeSSLCertificate& remote_cert,
const std::vector<std::string>& remote_ders) {
StatsCollectorForTest stats(&pc_);
StatsCollectorForTest stats(&session_);
StatsReports reports; // returned values.
@ -708,6 +679,8 @@ class StatsCollectorTest : public testing::Test {
EXPECT_CALL(session_, GetTransportStats(_))
.WillOnce(DoAll(SetArgPointee<0>(session_stats),
Return(true)));
EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
@ -761,13 +734,12 @@ class StatsCollectorTest : public testing::Test {
cricket::FakeMediaEngine* media_engine_;
rtc::scoped_ptr<cricket::ChannelManager> channel_manager_;
MockWebRtcSession session_;
MockPeerConnection pc_;
FakeMediaStreamSignaling signaling_;
FakeDataChannelProvider data_channel_provider_;
cricket::SessionStats session_stats_;
rtc::scoped_refptr<webrtc::MediaStream> stream_;
rtc::scoped_refptr<webrtc::VideoTrack> track_;
rtc::scoped_refptr<FakeAudioTrack> audio_track_;
std::vector<rtc::scoped_refptr<DataChannel>> data_channels_;
};
// Verify that ExtractDataInfo populates reports.
@ -777,8 +749,14 @@ TEST_F(StatsCollectorTest, ExtractDataInfo) {
const std::string state = DataChannelInterface::DataStateString(
DataChannelInterface::DataState::kConnecting);
AddDataChannel(cricket::DCT_SCTP, label, id);
StatsCollectorForTest stats(&pc_);
EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
InternalDataChannelInit config;
config.id = id;
signaling_.AddDataChannel(DataChannel::Create(
&data_channel_provider_, cricket::DCT_SCTP, label, config));
StatsCollectorForTest stats(&session_);
stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
@ -810,7 +788,7 @@ TEST_F(StatsCollectorTest, ExtractDataInfo) {
// This test verifies that 64-bit counters are passed successfully.
TEST_F(StatsCollectorTest, BytesCounterHandles64Bits) {
StatsCollectorForTest stats(&pc_);
StatsCollectorForTest stats(&session_);
EXPECT_CALL(session_, GetLocalCertificate(_, _))
.WillRepeatedly(Return(false));
@ -856,7 +834,7 @@ TEST_F(StatsCollectorTest, BytesCounterHandles64Bits) {
// Test that BWE information is reported via stats.
TEST_F(StatsCollectorTest, BandwidthEstimationInfoIsReported) {
StatsCollectorForTest stats(&pc_);
StatsCollectorForTest stats(&session_);
EXPECT_CALL(session_, GetLocalCertificate(_, _))
.WillRepeatedly(Return(false));
@ -913,9 +891,11 @@ TEST_F(StatsCollectorTest, BandwidthEstimationInfoIsReported) {
// This test verifies that an object of type "googSession" always
// exists in the returned stats.
TEST_F(StatsCollectorTest, SessionObjectExists) {
StatsCollectorForTest stats(&pc_);
StatsCollectorForTest stats(&session_);
StatsReports reports; // returned values.
EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
stats.GetStats(NULL, &reports);
const StatsReport* session_report = FindNthReportByType(
@ -926,9 +906,11 @@ TEST_F(StatsCollectorTest, SessionObjectExists) {
// This test verifies that only one object of type "googSession" exists
// in the returned stats.
TEST_F(StatsCollectorTest, OnlyOneSessionObjectExists) {
StatsCollectorForTest stats(&pc_);
StatsCollectorForTest stats(&session_);
StatsReports reports; // returned values.
EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
stats.GetStats(NULL, &reports);
@ -943,7 +925,7 @@ TEST_F(StatsCollectorTest, OnlyOneSessionObjectExists) {
// This test verifies that the empty track report exists in the returned stats
// without calling StatsCollector::UpdateStats.
TEST_F(StatsCollectorTest, TrackObjectExistsWithoutUpdateStats) {
StatsCollectorForTest stats(&pc_);
StatsCollectorForTest stats(&session_);
MockVideoMediaChannel* media_channel = new MockVideoMediaChannel();
cricket::VideoChannel video_channel(rtc::Thread::Current(),
@ -968,7 +950,7 @@ TEST_F(StatsCollectorTest, TrackObjectExistsWithoutUpdateStats) {
// This test verifies that the empty track report exists in the returned stats
// when StatsCollector::UpdateStats is called with ssrc stats.
TEST_F(StatsCollectorTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) {
StatsCollectorForTest stats(&pc_);
StatsCollectorForTest stats(&session_);
EXPECT_CALL(session_, GetLocalCertificate(_, _))
.WillRepeatedly(Return(false));
@ -1036,7 +1018,7 @@ TEST_F(StatsCollectorTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) {
// This test verifies that an SSRC object has the identifier of a Transport
// stats object, and that this transport stats object exists in stats.
TEST_F(StatsCollectorTest, TransportObjectLinkedFromSsrcObject) {
StatsCollectorForTest stats(&pc_);
StatsCollectorForTest stats(&session_);
EXPECT_CALL(session_, GetLocalCertificate(_, _))
.WillRepeatedly(Return(false));
@ -1099,7 +1081,7 @@ TEST_F(StatsCollectorTest, TransportObjectLinkedFromSsrcObject) {
// This test verifies that a remote stats object will not be created for
// an outgoing SSRC where remote stats are not returned.
TEST_F(StatsCollectorTest, RemoteSsrcInfoIsAbsent) {
StatsCollectorForTest stats(&pc_);
StatsCollectorForTest stats(&session_);
MockVideoMediaChannel* media_channel = new MockVideoMediaChannel();
// The transport_name known by the video channel.
@ -1109,6 +1091,9 @@ TEST_F(StatsCollectorTest, RemoteSsrcInfoIsAbsent) {
AddOutgoingVideoTrackStats();
stats.AddStream(stream_);
EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
StatsReports reports;
stats.GetStats(NULL, &reports);
@ -1120,7 +1105,7 @@ TEST_F(StatsCollectorTest, RemoteSsrcInfoIsAbsent) {
// This test verifies that a remote stats object will be created for
// an outgoing SSRC where stats are returned.
TEST_F(StatsCollectorTest, RemoteSsrcInfoIsPresent) {
StatsCollectorForTest stats(&pc_);
StatsCollectorForTest stats(&session_);
EXPECT_CALL(session_, GetLocalCertificate(_, _))
.WillRepeatedly(Return(false));
@ -1171,7 +1156,7 @@ TEST_F(StatsCollectorTest, RemoteSsrcInfoIsPresent) {
// This test verifies that the empty track report exists in the returned stats
// when StatsCollector::UpdateStats is called with ssrc stats.
TEST_F(StatsCollectorTest, ReportsFromRemoteTrack) {
StatsCollectorForTest stats(&pc_);
StatsCollectorForTest stats(&session_);
EXPECT_CALL(session_, GetLocalCertificate(_, _))
.WillRepeatedly(Return(false));
@ -1229,7 +1214,7 @@ TEST_F(StatsCollectorTest, ReportsFromRemoteTrack) {
// This test verifies the Ice Candidate report should contain the correct
// information from local/remote candidates.
TEST_F(StatsCollectorTest, IceCandidateReport) {
StatsCollectorForTest stats(&pc_);
StatsCollectorForTest stats(&session_);
StatsReports reports; // returned values.
@ -1359,7 +1344,7 @@ TEST_F(StatsCollectorTest, ChainlessCertificateReportsCreated) {
// This test verifies that the stats are generated correctly when no
// transport is present.
TEST_F(StatsCollectorTest, NoTransport) {
StatsCollectorForTest stats(&pc_);
StatsCollectorForTest stats(&session_);
EXPECT_CALL(session_, GetLocalCertificate(_, _))
.WillRepeatedly(Return(false));
@ -1385,6 +1370,9 @@ TEST_F(StatsCollectorTest, NoTransport) {
.WillOnce(DoAll(SetArgPointee<0>(session_stats),
Return(true)));
EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
stats.GetStats(NULL, &reports);
@ -1418,7 +1406,7 @@ TEST_F(StatsCollectorTest, NoTransport) {
// This test verifies that the stats are generated correctly when the transport
// does not have any certificates.
TEST_F(StatsCollectorTest, NoCertificates) {
StatsCollectorForTest stats(&pc_);
StatsCollectorForTest stats(&session_);
EXPECT_CALL(session_, GetLocalCertificate(_, _))
.WillRepeatedly(Return(false));
@ -1447,6 +1435,9 @@ TEST_F(StatsCollectorTest, NoCertificates) {
EXPECT_CALL(session_, GetTransportStats(_))
.WillOnce(DoAll(SetArgPointee<0>(session_stats),
Return(true)));
EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
stats.GetStats(NULL, &reports);
@ -1484,7 +1475,7 @@ TEST_F(StatsCollectorTest, UnsupportedDigestIgnored) {
// This test verifies that a local stats object can get statistics via
// AudioTrackInterface::GetStats() method.
TEST_F(StatsCollectorTest, GetStatsFromLocalAudioTrack) {
StatsCollectorForTest stats(&pc_);
StatsCollectorForTest stats(&session_);
EXPECT_CALL(session_, GetLocalCertificate(_, _))
.WillRepeatedly(Return(false));
@ -1519,7 +1510,7 @@ TEST_F(StatsCollectorTest, GetStatsFromLocalAudioTrack) {
// This test verifies that audio receive streams populate stats reports
// correctly.
TEST_F(StatsCollectorTest, GetStatsFromRemoteStream) {
StatsCollectorForTest stats(&pc_);
StatsCollectorForTest stats(&session_);
EXPECT_CALL(session_, GetLocalCertificate(_, _))
.WillRepeatedly(Return(false));
@ -1548,7 +1539,7 @@ TEST_F(StatsCollectorTest, GetStatsFromRemoteStream) {
// This test verifies that a local stats object won't update its statistics
// after a RemoveLocalAudioTrack() call.
TEST_F(StatsCollectorTest, GetStatsAfterRemoveAudioStream) {
StatsCollectorForTest stats(&pc_);
StatsCollectorForTest stats(&session_);
EXPECT_CALL(session_, GetLocalCertificate(_, _))
.WillRepeatedly(Return(false));
@ -1609,7 +1600,7 @@ TEST_F(StatsCollectorTest, GetStatsAfterRemoveAudioStream) {
// This test verifies that when ongoing and incoming audio tracks are using
// the same ssrc, they populate stats reports correctly.
TEST_F(StatsCollectorTest, LocalAndRemoteTracksWithSameSsrc) {
StatsCollectorForTest stats(&pc_);
StatsCollectorForTest stats(&session_);
EXPECT_CALL(session_, GetLocalCertificate(_, _))
.WillRepeatedly(Return(false));
@ -1696,7 +1687,7 @@ TEST_F(StatsCollectorTest, LocalAndRemoteTracksWithSameSsrc) {
// TODO(xians): Figure out if it is possible to encapsulate the setup and
// avoid duplication of code in test cases.
TEST_F(StatsCollectorTest, TwoLocalTracksWithSameSsrc) {
StatsCollectorForTest stats(&pc_);
StatsCollectorForTest stats(&session_);
EXPECT_CALL(session_, GetLocalCertificate(_, _))
.WillRepeatedly(Return(false));

View File

@ -38,7 +38,6 @@
#include "talk/app/webrtc/mediaconstraintsinterface.h"
#include "talk/app/webrtc/mediastreamsignaling.h"
#include "talk/app/webrtc/peerconnectioninterface.h"
#include "talk/app/webrtc/sctputils.h"
#include "talk/app/webrtc/webrtcsessiondescriptionfactory.h"
#include "talk/media/base/constants.h"
#include "talk/media/base/videocapturer.h"
@ -537,10 +536,12 @@ class IceRestartAnswerLatch {
bool ice_restart_;
};
WebRtcSession::WebRtcSession(cricket::ChannelManager* channel_manager,
rtc::Thread* signaling_thread,
rtc::Thread* worker_thread,
cricket::PortAllocator* port_allocator)
WebRtcSession::WebRtcSession(
cricket::ChannelManager* channel_manager,
rtc::Thread* signaling_thread,
rtc::Thread* worker_thread,
cricket::PortAllocator* port_allocator,
MediaStreamSignaling* mediastream_signaling)
: cricket::BaseSession(signaling_thread,
worker_thread,
port_allocator,
@ -550,6 +551,7 @@ WebRtcSession::WebRtcSession(cricket::ChannelManager* channel_manager,
// o line MUST be representable with a "64 bit signed integer".
// Due to this constraint session id |sid_| is max limited to LLONG_MAX.
channel_manager_(channel_manager),
mediastream_signaling_(mediastream_signaling),
ice_observer_(NULL),
ice_connection_state_(PeerConnectionInterface::kIceConnectionNew),
ice_connection_receiving_(true),
@ -641,6 +643,9 @@ bool WebRtcSession::Initialize(
data_channel_type_ = cricket::DCT_SCTP;
}
}
if (data_channel_type_ != cricket::DCT_NONE) {
mediastream_signaling_->SetDataChannelFactory(this);
}
// Find DSCP constraint.
if (FindConstraint(
@ -738,19 +743,21 @@ bool WebRtcSession::Initialize(
if (!dtls_enabled_) {
// Construct with DTLS disabled.
webrtc_session_desc_factory_.reset(new WebRtcSessionDescriptionFactory(
signaling_thread(), channel_manager_, this, id()));
signaling_thread(), channel_manager_, mediastream_signaling_, this,
id(), data_channel_type_));
} else {
// Construct with DTLS enabled.
if (!certificate) {
// Use the |dtls_identity_store| to generate a certificate.
RTC_DCHECK(dtls_identity_store);
webrtc_session_desc_factory_.reset(new WebRtcSessionDescriptionFactory(
signaling_thread(), channel_manager_, dtls_identity_store.Pass(),
this, id()));
signaling_thread(), channel_manager_, mediastream_signaling_,
dtls_identity_store.Pass(), this, id(), data_channel_type_));
} else {
// Use the already generated certificate.
webrtc_session_desc_factory_.reset(new WebRtcSessionDescriptionFactory(
signaling_thread(), channel_manager_, certificate, this, id()));
signaling_thread(), channel_manager_, mediastream_signaling_,
certificate, this, id(), data_channel_type_));
}
}
@ -812,17 +819,13 @@ bool WebRtcSession::GetSslRole(rtc::SSLRole* role) {
void WebRtcSession::CreateOffer(
CreateSessionDescriptionObserver* observer,
const PeerConnectionInterface::RTCOfferAnswerOptions& options,
const cricket::MediaSessionOptions& session_options) {
webrtc_session_desc_factory_->CreateOffer(observer, options, session_options);
const PeerConnectionInterface::RTCOfferAnswerOptions& options) {
webrtc_session_desc_factory_->CreateOffer(observer, options);
}
void WebRtcSession::CreateAnswer(
CreateSessionDescriptionObserver* observer,
const MediaConstraintsInterface* constraints,
const cricket::MediaSessionOptions& session_options) {
webrtc_session_desc_factory_->CreateAnswer(observer, constraints,
session_options);
void WebRtcSession::CreateAnswer(CreateSessionDescriptionObserver* observer,
const MediaConstraintsInterface* constraints) {
webrtc_session_desc_factory_->CreateAnswer(observer, constraints);
}
bool WebRtcSession::SetLocalDescription(SessionDescriptionInterface* desc,
@ -880,6 +883,14 @@ bool WebRtcSession::SetLocalDescription(SessionDescriptionInterface* desc,
UseCandidatesInSessionDescription(remote_desc_.get());
}
// Update state and SSRC of local MediaStreams and DataChannels based on the
// local session description.
mediastream_signaling_->OnLocalDescriptionChanged(local_desc_.get());
rtc::SSLRole role;
if (data_channel_type_ == cricket::DCT_SCTP && GetSslRole(&role)) {
mediastream_signaling_->OnDtlsRoleReadyForSctp(role);
}
if (error() != cricket::BaseSession::ERROR_NONE) {
return BadLocalSdp(desc->type(), GetSessionErrorMsg(), err_desc);
}
@ -916,6 +927,8 @@ bool WebRtcSession::SetRemoteDescription(SessionDescriptionInterface* desc,
return false;
}
// Update remote MediaStreams.
mediastream_signaling_->OnRemoteDescriptionChanged(desc);
if (local_description() && !UseCandidatesInSessionDescription(desc)) {
return BadRemoteSdp(desc->type(), kInvalidCandidates, err_desc);
}
@ -937,6 +950,11 @@ bool WebRtcSession::SetRemoteDescription(SessionDescriptionInterface* desc,
remote_desc_.reset(desc_temp.release());
rtc::SSLRole role;
if (data_channel_type_ == cricket::DCT_SCTP && GetSslRole(&role)) {
mediastream_signaling_->OnDtlsRoleReadyForSctp(role);
}
if (error() != cricket::BaseSession::ERROR_NONE) {
return BadRemoteSdp(desc->type(), GetSessionErrorMsg(), err_desc);
}
@ -1369,8 +1387,6 @@ bool WebRtcSession::ConnectDataChannel(DataChannel* webrtc_data_channel) {
&DataChannel::OnChannelReady);
data_channel_->SignalDataReceived.connect(webrtc_data_channel,
&DataChannel::OnDataReceived);
data_channel_->SignalStreamClosedRemotely.connect(
webrtc_data_channel, &DataChannel::OnStreamClosedRemotely);
return true;
}
@ -1381,7 +1397,6 @@ void WebRtcSession::DisconnectDataChannel(DataChannel* webrtc_data_channel) {
}
data_channel_->SignalReadyToSendData.disconnect(webrtc_data_channel);
data_channel_->SignalDataReceived.disconnect(webrtc_data_channel);
data_channel_->SignalStreamClosedRemotely.disconnect(webrtc_data_channel);
}
void WebRtcSession::AddSctpDataStream(int sid) {
@ -1394,6 +1409,8 @@ void WebRtcSession::AddSctpDataStream(int sid) {
}
void WebRtcSession::RemoveSctpDataStream(int sid) {
mediastream_signaling_->RemoveSctpDataChannel(sid);
if (!data_channel_) {
LOG(LS_ERROR) << "RemoveDataChannelStreams called when data_channel_ is "
<< "NULL.";
@ -1407,6 +1424,41 @@ bool WebRtcSession::ReadyToSendData() const {
return data_channel_ && data_channel_->ready_to_send_data();
}
rtc::scoped_refptr<DataChannel> WebRtcSession::CreateDataChannel(
const std::string& label,
const InternalDataChannelInit* config) {
if (state() == STATE_RECEIVEDTERMINATE) {
return NULL;
}
if (data_channel_type_ == cricket::DCT_NONE) {
LOG(LS_ERROR) << "CreateDataChannel: Data is not supported in this call.";
return NULL;
}
InternalDataChannelInit new_config =
config ? (*config) : InternalDataChannelInit();
if (data_channel_type_ == cricket::DCT_SCTP) {
if (new_config.id < 0) {
rtc::SSLRole role;
if (GetSslRole(&role) &&
!mediastream_signaling_->AllocateSctpSid(role, &new_config.id)) {
LOG(LS_ERROR) << "No id can be allocated for the SCTP data channel.";
return NULL;
}
} else if (!mediastream_signaling_->IsSctpSidAvailable(new_config.id)) {
LOG(LS_ERROR) << "Failed to create a SCTP data channel "
<< "because the id is already in use or out of range.";
return NULL;
}
}
rtc::scoped_refptr<DataChannel> channel(DataChannel::Create(
this, data_channel_type_, label, new_config));
if (channel && !mediastream_signaling_->AddDataChannel(channel))
return NULL;
return channel;
}
cricket::DataChannelType WebRtcSession::data_channel_type() const {
return data_channel_type_;
}
@ -1675,6 +1727,7 @@ void WebRtcSession::RemoveUnusedChannels(const SessionDescription* desc) {
const cricket::ContentInfo* video_info =
cricket::GetFirstVideoContent(desc);
if ((!video_info || video_info->rejected) && video_channel_) {
mediastream_signaling_->OnVideoChannelClose();
SignalVideoChannelDestroyed();
const std::string content_name = video_channel_->content_name();
channel_manager_->DestroyVideoChannel(video_channel_.release());
@ -1683,6 +1736,7 @@ void WebRtcSession::RemoveUnusedChannels(const SessionDescription* desc) {
const cricket::ContentInfo* voice_info =
cricket::GetFirstAudioContent(desc);
if ((!voice_info || voice_info->rejected) && voice_channel_) {
mediastream_signaling_->OnAudioChannelClose();
SignalVoiceChannelDestroyed();
const std::string content_name = voice_channel_->content_name();
channel_manager_->DestroyVoiceChannel(voice_channel_.release());
@ -1691,6 +1745,7 @@ void WebRtcSession::RemoveUnusedChannels(const SessionDescription* desc) {
const cricket::ContentInfo* data_info =
cricket::GetFirstDataContent(desc);
if ((!data_info || data_info->rejected) && data_channel_) {
mediastream_signaling_->OnDataChannelClose();
SignalDataChannelDestroyed();
const std::string content_name = data_channel_->content_name();
channel_manager_->DestroyDataChannel(data_channel_.release());
@ -1765,8 +1820,6 @@ bool WebRtcSession::CreateVoiceChannel(const cricket::ContentInfo* content) {
voice_channel_->SignalDtlsSetupFailure.connect(
this, &WebRtcSession::OnDtlsSetupFailure);
SignalVoiceChannelCreated();
return true;
}
@ -1780,8 +1833,6 @@ bool WebRtcSession::CreateVideoChannel(const cricket::ContentInfo* content) {
video_channel_->SignalDtlsSetupFailure.connect(
this, &WebRtcSession::OnDtlsSetupFailure);
SignalVideoChannelCreated();
return true;
}
@ -1794,14 +1845,16 @@ bool WebRtcSession::CreateDataChannel(const cricket::ContentInfo* content) {
}
if (sctp) {
mediastream_signaling_->OnDataTransportCreatedForSctp();
data_channel_->SignalDataReceived.connect(
this, &WebRtcSession::OnDataChannelMessageReceived);
data_channel_->SignalStreamClosedRemotely.connect(
mediastream_signaling_,
&MediaStreamSignaling::OnRemoteSctpDataChannelClosed);
}
data_channel_->SignalDtlsSetupFailure.connect(
this, &WebRtcSession::OnDtlsSetupFailure);
SignalDataChannelCreated();
return true;
}
@ -1827,22 +1880,13 @@ void WebRtcSession::OnDataChannelMessageReceived(
cricket::DataChannel* channel,
const cricket::ReceiveDataParams& params,
const rtc::Buffer& payload) {
RTC_DCHECK(data_channel_type_ == cricket::DCT_SCTP);
if (params.type == cricket::DMT_CONTROL && IsOpenMessage(payload)) {
// Received OPEN message; parse and signal that a new data channel should
// be created.
std::string label;
InternalDataChannelInit config;
config.id = params.ssrc;
if (!ParseDataChannelOpenMessage(payload, &label, &config)) {
LOG(LS_WARNING) << "Failed to parse the OPEN message for sid "
<< params.ssrc;
return;
}
config.open_handshake_role = InternalDataChannelInit::kAcker;
SignalDataChannelOpenMessage(label, config);
ASSERT(data_channel_type_ == cricket::DCT_SCTP);
if (params.type == cricket::DMT_CONTROL &&
mediastream_signaling_->IsSctpSidAvailable(params.ssrc)) {
// Received CONTROL on unused sid, process as an OPEN message.
mediastream_signaling_->AddDataChannelFromOpenMessage(params, payload);
}
// Otherwise ignore the message.
// otherwise ignore the message.
}
// Returns false if bundle is enabled and rtcp_mux is disabled.

View File

@ -114,6 +114,7 @@ class IceObserver {
class WebRtcSession : public cricket::BaseSession,
public AudioProviderInterface,
public DataChannelFactory,
public VideoProviderInterface,
public DtmfProviderInterface,
public DataChannelProviderInterface {
@ -121,7 +122,8 @@ class WebRtcSession : public cricket::BaseSession,
WebRtcSession(cricket::ChannelManager* channel_manager,
rtc::Thread* signaling_thread,
rtc::Thread* worker_thread,
cricket::PortAllocator* port_allocator);
cricket::PortAllocator* port_allocator,
MediaStreamSignaling* mediastream_signaling);
virtual ~WebRtcSession();
bool Initialize(
@ -147,6 +149,10 @@ class WebRtcSession : public cricket::BaseSession,
return data_channel_.get();
}
virtual const MediaStreamSignaling* mediastream_signaling() const {
return mediastream_signaling_;
}
void SetSdesPolicy(cricket::SecurePolicy secure_policy);
cricket::SecurePolicy SdesPolicy() const;
@ -159,11 +165,9 @@ class WebRtcSession : public cricket::BaseSession,
void CreateOffer(
CreateSessionDescriptionObserver* observer,
const PeerConnectionInterface::RTCOfferAnswerOptions& options,
const cricket::MediaSessionOptions& session_options);
const PeerConnectionInterface::RTCOfferAnswerOptions& options);
void CreateAnswer(CreateSessionDescriptionObserver* observer,
const MediaConstraintsInterface* constraints,
const cricket::MediaSessionOptions& session_options);
const MediaConstraintsInterface* constraints);
// The ownership of |desc| will be transferred after this call.
bool SetLocalDescription(SessionDescriptionInterface* desc,
std::string* err_desc);
@ -247,6 +251,11 @@ class WebRtcSession : public cricket::BaseSession,
virtual bool GetRemoteSSLCertificate(const std::string& transport_name,
rtc::SSLCertificate** cert);
// Implements DataChannelFactory.
rtc::scoped_refptr<DataChannel> CreateDataChannel(
const std::string& label,
const InternalDataChannelInit* config) override;
cricket::DataChannelType data_channel_type() const;
bool IceRestartPending() const;
@ -268,20 +277,6 @@ class WebRtcSession : public cricket::BaseSession,
metrics_observer_ = metrics_observer;
}
// Called when voice_channel_, video_channel_ and data_channel_ are created
// and destroyed. As a result of, for example, setting a new description.
sigslot::signal0<> SignalVoiceChannelCreated;
sigslot::signal0<> SignalVoiceChannelDestroyed;
sigslot::signal0<> SignalVideoChannelCreated;
sigslot::signal0<> SignalVideoChannelDestroyed;
sigslot::signal0<> SignalDataChannelCreated;
sigslot::signal0<> SignalDataChannelDestroyed;
// Called when a valid data channel OPEN message is received.
// std::string represents the data channel label.
sigslot::signal2<const std::string&, const InternalDataChannelInit&>
SignalDataChannelOpenMessage;
private:
// Indicates the type of SessionDescription in a call to SetLocalDescription
// and SetRemoteDescription.
@ -391,6 +386,7 @@ class WebRtcSession : public cricket::BaseSession,
rtc::scoped_ptr<cricket::VideoChannel> video_channel_;
rtc::scoped_ptr<cricket::DataChannel> data_channel_;
cricket::ChannelManager* channel_manager_;
MediaStreamSignaling* mediastream_signaling_;
IceObserver* ice_observer_;
PeerConnectionInterface::IceConnectionState ice_connection_state_;
bool ice_connection_receiving_;
@ -414,6 +410,10 @@ class WebRtcSession : public cricket::BaseSession,
rtc::scoped_ptr<WebRtcSessionDescriptionFactory>
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_;

File diff suppressed because it is too large Load Diff

View File

@ -31,6 +31,7 @@
#include "talk/app/webrtc/jsep.h"
#include "talk/app/webrtc/jsepsessiondescription.h"
#include "talk/app/webrtc/mediaconstraintsinterface.h"
#include "talk/app/webrtc/mediastreamsignaling.h"
#include "talk/app/webrtc/webrtcsession.h"
#include "webrtc/base/sslidentity.h"
@ -130,13 +131,16 @@ void WebRtcSessionDescriptionFactory::CopyCandidatesFromSessionDescription(
WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory(
rtc::Thread* signaling_thread,
cricket::ChannelManager* channel_manager,
MediaStreamSignaling* mediastream_signaling,
rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store,
const rtc::scoped_refptr<WebRtcIdentityRequestObserver>&
identity_request_observer,
WebRtcSession* session,
const std::string& session_id,
cricket::DataChannelType dct,
bool dtls_enabled)
: signaling_thread_(signaling_thread),
mediastream_signaling_(mediastream_signaling),
session_desc_factory_(channel_manager, &transport_desc_factory_),
// RFC 4566 suggested a Network Time Protocol (NTP) format timestamp
// as the session id and session version. To simplify, it should be fine
@ -147,6 +151,7 @@ WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory(
identity_request_observer_(identity_request_observer),
session_(session),
session_id_(session_id),
data_channel_type_(dct),
certificate_request_state_(CERTIFICATE_NOT_NEEDED) {
session_desc_factory_.set_add_legacy_streams(false);
// SRTP-SDES is disabled if DTLS is on.
@ -156,14 +161,18 @@ WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory(
WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory(
rtc::Thread* signaling_thread,
cricket::ChannelManager* channel_manager,
MediaStreamSignaling* mediastream_signaling,
WebRtcSession* session,
const std::string& session_id)
const std::string& session_id,
cricket::DataChannelType dct)
: WebRtcSessionDescriptionFactory(signaling_thread,
channel_manager,
mediastream_signaling,
nullptr,
nullptr,
session,
session_id,
dct,
false) {
LOG(LS_VERBOSE) << "DTLS-SRTP disabled.";
}
@ -171,17 +180,21 @@ WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory(
WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory(
rtc::Thread* signaling_thread,
cricket::ChannelManager* channel_manager,
MediaStreamSignaling* mediastream_signaling,
rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store,
WebRtcSession* session,
const std::string& session_id)
const std::string& session_id,
cricket::DataChannelType dct)
: WebRtcSessionDescriptionFactory(
signaling_thread,
channel_manager,
dtls_identity_store.Pass(),
new rtc::RefCountedObject<WebRtcIdentityRequestObserver>(),
session,
session_id,
true) {
signaling_thread,
channel_manager,
mediastream_signaling,
dtls_identity_store.Pass(),
new rtc::RefCountedObject<WebRtcIdentityRequestObserver>(),
session,
session_id,
dct,
true) {
RTC_DCHECK(dtls_identity_store_);
certificate_request_state_ = CERTIFICATE_WAITING;
@ -203,16 +216,14 @@ WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory(
WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory(
rtc::Thread* signaling_thread,
cricket::ChannelManager* channel_manager,
MediaStreamSignaling* mediastream_signaling,
const rtc::scoped_refptr<rtc::RTCCertificate>& certificate,
WebRtcSession* session,
const std::string& session_id)
: WebRtcSessionDescriptionFactory(signaling_thread,
channel_manager,
nullptr,
nullptr,
session,
session_id,
true) {
const std::string& session_id,
cricket::DataChannelType dct)
: WebRtcSessionDescriptionFactory(
signaling_thread, channel_manager, mediastream_signaling, nullptr,
nullptr, session, session_id, dct, true) {
RTC_DCHECK(certificate);
certificate_request_state_ = CERTIFICATE_WAITING;
@ -253,8 +264,9 @@ WebRtcSessionDescriptionFactory::~WebRtcSessionDescriptionFactory() {
void WebRtcSessionDescriptionFactory::CreateOffer(
CreateSessionDescriptionObserver* observer,
const PeerConnectionInterface::RTCOfferAnswerOptions& options,
const cricket::MediaSessionOptions& session_options) {
const PeerConnectionInterface::RTCOfferAnswerOptions& options) {
cricket::MediaSessionOptions session_options;
std::string error = "CreateOffer";
if (certificate_request_state_ == CERTIFICATE_FAILED) {
error += kFailedDueToIdentityFailed;
@ -263,6 +275,14 @@ void WebRtcSessionDescriptionFactory::CreateOffer(
return;
}
if (!mediastream_signaling_->GetOptionsForOffer(options,
&session_options)) {
error += " called with invalid options.";
LOG(LS_ERROR) << error;
PostCreateSessionDescriptionFailed(observer, error);
return;
}
if (!ValidStreams(session_options.streams)) {
error += " called with invalid media streams.";
LOG(LS_ERROR) << error;
@ -270,6 +290,11 @@ void WebRtcSessionDescriptionFactory::CreateOffer(
return;
}
if (data_channel_type_ == cricket::DCT_SCTP &&
mediastream_signaling_->HasDataChannels()) {
session_options.data_channel_type = cricket::DCT_SCTP;
}
CreateSessionDescriptionRequest request(
CreateSessionDescriptionRequest::kOffer, observer, session_options);
if (certificate_request_state_ == CERTIFICATE_WAITING) {
@ -283,8 +308,7 @@ void WebRtcSessionDescriptionFactory::CreateOffer(
void WebRtcSessionDescriptionFactory::CreateAnswer(
CreateSessionDescriptionObserver* observer,
const MediaConstraintsInterface* constraints,
const cricket::MediaSessionOptions& session_options) {
const MediaConstraintsInterface* constraints) {
std::string error = "CreateAnswer";
if (certificate_request_state_ == CERTIFICATE_FAILED) {
error += kFailedDueToIdentityFailed;
@ -306,15 +330,28 @@ void WebRtcSessionDescriptionFactory::CreateAnswer(
return;
}
if (!ValidStreams(session_options.streams)) {
cricket::MediaSessionOptions options;
if (!mediastream_signaling_->GetOptionsForAnswer(constraints, &options)) {
error += " called with invalid constraints.";
LOG(LS_ERROR) << error;
PostCreateSessionDescriptionFailed(observer, error);
return;
}
if (!ValidStreams(options.streams)) {
error += " called with invalid media streams.";
LOG(LS_ERROR) << error;
PostCreateSessionDescriptionFailed(observer, error);
return;
}
// RTP data channel is handled in MediaSessionOptions::AddStream. SCTP streams
// are not signaled in the SDP so does not go through that path and must be
// handled here.
if (data_channel_type_ == cricket::DCT_SCTP) {
options.data_channel_type = cricket::DCT_SCTP;
}
CreateSessionDescriptionRequest request(
CreateSessionDescriptionRequest::kAnswer, observer, session_options);
CreateSessionDescriptionRequest::kAnswer, observer, options);
if (certificate_request_state_ == CERTIFICATE_WAITING) {
create_session_description_requests_.push(request);
} else {

View File

@ -43,6 +43,7 @@ class TransportDescriptionFactory;
namespace webrtc {
class CreateSessionDescriptionObserver;
class MediaConstraintsInterface;
class MediaStreamSignaling;
class SessionDescriptionInterface;
class WebRtcSession;
@ -91,26 +92,32 @@ class WebRtcSessionDescriptionFactory : public rtc::MessageHandler,
// Construct with DTLS disabled.
WebRtcSessionDescriptionFactory(rtc::Thread* signaling_thread,
cricket::ChannelManager* channel_manager,
MediaStreamSignaling* mediastream_signaling,
WebRtcSession* session,
const std::string& session_id);
const std::string& session_id,
cricket::DataChannelType dct);
// Construct with DTLS enabled using the specified |dtls_identity_store| to
// generate a certificate.
WebRtcSessionDescriptionFactory(
rtc::Thread* signaling_thread,
cricket::ChannelManager* channel_manager,
MediaStreamSignaling* mediastream_signaling,
rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store,
WebRtcSession* session,
const std::string& session_id);
const std::string& session_id,
cricket::DataChannelType dct);
// Construct with DTLS enabled using the specified (already generated)
// |certificate|.
WebRtcSessionDescriptionFactory(
rtc::Thread* signaling_thread,
cricket::ChannelManager* channel_manager,
MediaStreamSignaling* mediastream_signaling,
const rtc::scoped_refptr<rtc::RTCCertificate>& certificate,
WebRtcSession* session,
const std::string& session_id);
const std::string& session_id,
cricket::DataChannelType dct);
virtual ~WebRtcSessionDescriptionFactory();
static void CopyCandidatesFromSessionDescription(
@ -119,11 +126,10 @@ class WebRtcSessionDescriptionFactory : public rtc::MessageHandler,
void CreateOffer(
CreateSessionDescriptionObserver* observer,
const PeerConnectionInterface::RTCOfferAnswerOptions& options,
const cricket::MediaSessionOptions& session_options);
void CreateAnswer(CreateSessionDescriptionObserver* observer,
const MediaConstraintsInterface* constraints,
const cricket::MediaSessionOptions& session_options);
const PeerConnectionInterface::RTCOfferAnswerOptions& options);
void CreateAnswer(
CreateSessionDescriptionObserver* observer,
const MediaConstraintsInterface* constraints);
void SetSdesPolicy(cricket::SecurePolicy secure_policy);
cricket::SecurePolicy SdesPolicy() const;
@ -147,11 +153,13 @@ class WebRtcSessionDescriptionFactory : public rtc::MessageHandler,
WebRtcSessionDescriptionFactory(
rtc::Thread* signaling_thread,
cricket::ChannelManager* channel_manager,
MediaStreamSignaling* mediastream_signaling,
rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store,
const rtc::scoped_refptr<WebRtcIdentityRequestObserver>&
identity_request_observer,
WebRtcSession* session,
const std::string& session_id,
cricket::DataChannelType dct,
bool dtls_enabled);
// MessageHandler implementation.
@ -175,6 +183,7 @@ class WebRtcSessionDescriptionFactory : public rtc::MessageHandler,
std::queue<CreateSessionDescriptionRequest>
create_session_description_requests_;
rtc::Thread* const signaling_thread_;
MediaStreamSignaling* const mediastream_signaling_;
cricket::TransportDescriptionFactory transport_desc_factory_;
cricket::MediaSessionDescriptionFactory session_desc_factory_;
uint64_t session_version_;
@ -184,6 +193,7 @@ class WebRtcSessionDescriptionFactory : public rtc::MessageHandler,
// TODO(jiayl): remove the dependency on session once bug 2264 is fixed.
WebRtcSession* const session_;
const std::string session_id_;
const cricket::DataChannelType data_channel_type_;
CertificateRequestState certificate_request_state_;
RTC_DISALLOW_COPY_AND_ASSIGN(WebRtcSessionDescriptionFactory);

View File

@ -200,6 +200,7 @@
'app/webrtc/jsepsessiondescription_unittest.cc',
'app/webrtc/localaudiosource_unittest.cc',
'app/webrtc/mediastream_unittest.cc',
'app/webrtc/mediastreamsignaling_unittest.cc',
'app/webrtc/peerconnection_unittest.cc',
'app/webrtc/peerconnectionendtoend_unittest.cc',
'app/webrtc/peerconnectionfactory_unittest.cc',