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:
parent
97c3929354
commit
fc648b6d93
@ -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() {
|
||||
|
||||
@ -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*)
|
||||
|
||||
@ -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
@ -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_
|
||||
|
||||
1341
talk/app/webrtc/mediastreamsignaling_unittest.cc
Normal file
1341
talk/app/webrtc/mediastreamsignaling_unittest.cc
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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
@ -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) {
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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_;
|
||||
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
@ -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 {
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user