Update talk to 56698267.

TBR=sergeyu@chromium.org

Review URL: https://webrtc-codereview.appspot.com/4119004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5143 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
wu@webrtc.org
2013-11-20 21:49:41 +00:00
parent dc50aaeaa8
commit 364f204d16
18 changed files with 777 additions and 116 deletions

View File

@@ -0,0 +1,218 @@
/*
* libjingle
* 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:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "talk/app/webrtc/test/peerconnectiontestwrapper.h"
#include "talk/base/gunit.h"
#include "talk/base/logging.h"
#include "talk/base/ssladapter.h"
#include "talk/base/sslstreamadapter.h"
#include "talk/base/stringencode.h"
#include "talk/base/stringutils.h"
using webrtc::FakeConstraints;
using webrtc::MediaConstraintsInterface;
using webrtc::MediaStreamInterface;
using webrtc::PeerConnectionInterface;
namespace {
const char kExternalGiceUfrag[] = "1234567890123456";
const char kExternalGicePwd[] = "123456789012345678901234";
void RemoveLinesFromSdp(const std::string& line_start,
std::string* sdp) {
const char kSdpLineEnd[] = "\r\n";
size_t ssrc_pos = 0;
while ((ssrc_pos = sdp->find(line_start, ssrc_pos)) !=
std::string::npos) {
size_t end_ssrc = sdp->find(kSdpLineEnd, ssrc_pos);
sdp->erase(ssrc_pos, end_ssrc - ssrc_pos + strlen(kSdpLineEnd));
}
}
// Add |newlines| to the |message| after |line|.
void InjectAfter(const std::string& line,
const std::string& newlines,
std::string* message) {
const std::string tmp = line + newlines;
talk_base::replace_substrs(line.c_str(), line.length(),
tmp.c_str(), tmp.length(), message);
}
void Replace(const std::string& line,
const std::string& newlines,
std::string* message) {
talk_base::replace_substrs(line.c_str(), line.length(),
newlines.c_str(), newlines.length(), message);
}
void UseExternalSdes(std::string* sdp) {
// Remove current crypto specification.
RemoveLinesFromSdp("a=crypto", sdp);
RemoveLinesFromSdp("a=fingerprint", sdp);
// Add external crypto.
const char kAudioSdes[] =
"a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
"inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR\r\n";
const char kVideoSdes[] =
"a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
"inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj\r\n";
const char kDataSdes[] =
"a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
"inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj\r\n";
InjectAfter("a=mid:audio\r\n", kAudioSdes, sdp);
InjectAfter("a=mid:video\r\n", kVideoSdes, sdp);
InjectAfter("a=mid:data\r\n", kDataSdes, sdp);
}
void UseGice(std::string* sdp) {
InjectAfter("t=0 0\r\n", "a=ice-options:google-ice\r\n", sdp);
std::string ufragline = "a=ice-ufrag:";
std::string pwdline = "a=ice-pwd:";
RemoveLinesFromSdp(ufragline, sdp);
RemoveLinesFromSdp(pwdline, sdp);
ufragline.append(kExternalGiceUfrag);
ufragline.append("\r\n");
pwdline.append(kExternalGicePwd);
pwdline.append("\r\n");
const std::string ufrag_pwd = ufragline + pwdline;
InjectAfter("a=mid:audio\r\n", ufrag_pwd, sdp);
InjectAfter("a=mid:video\r\n", ufrag_pwd, sdp);
InjectAfter("a=mid:data\r\n", ufrag_pwd, sdp);
}
void RemoveBundle(std::string* sdp) {
RemoveLinesFromSdp("a=group:BUNDLE", sdp);
}
} // namespace
class PeerConnectionEndToEndTest
: public sigslot::has_slots<>,
public testing::Test {
public:
PeerConnectionEndToEndTest()
: caller_(new talk_base::RefCountedObject<PeerConnectionTestWrapper>(
"caller")),
callee_(new talk_base::RefCountedObject<PeerConnectionTestWrapper>(
"callee")) {
talk_base::InitializeSSL(NULL);
}
void CreatePcs() {
CreatePcs(NULL);
}
void CreatePcs(const MediaConstraintsInterface* pc_constraints) {
EXPECT_TRUE(caller_->CreatePc(pc_constraints));
EXPECT_TRUE(callee_->CreatePc(pc_constraints));
PeerConnectionTestWrapper::Connect(caller_.get(), callee_.get());
}
void GetAndAddUserMedia() {
FakeConstraints audio_constraints;
FakeConstraints video_constraints;
GetAndAddUserMedia(true, audio_constraints, true, video_constraints);
}
void GetAndAddUserMedia(bool audio, FakeConstraints audio_constraints,
bool video, FakeConstraints video_constraints) {
caller_->GetAndAddUserMedia(audio, audio_constraints,
video, video_constraints);
callee_->GetAndAddUserMedia(audio, audio_constraints,
video, video_constraints);
}
void Negotiate() {
caller_->CreateOffer(NULL);
}
void WaitForCallEstablished() {
caller_->WaitForCallEstablished();
callee_->WaitForCallEstablished();
}
void SetupLegacySdpConverter() {
caller_->SignalOnSdpCreated.connect(
this, &PeerConnectionEndToEndTest::ConvertToLegacySdp);
callee_->SignalOnSdpCreated.connect(
this, &PeerConnectionEndToEndTest::ConvertToLegacySdp);
}
void ConvertToLegacySdp(std::string* sdp) {
UseExternalSdes(sdp);
UseGice(sdp);
RemoveBundle(sdp);
LOG(LS_INFO) << "ConvertToLegacySdp: " << *sdp;
}
void SetupGiceConverter() {
caller_->SignalOnIceCandidateCreated.connect(
this, &PeerConnectionEndToEndTest::AddGiceCredsToCandidate);
callee_->SignalOnIceCandidateCreated.connect(
this, &PeerConnectionEndToEndTest::AddGiceCredsToCandidate);
}
void AddGiceCredsToCandidate(std::string* sdp) {
std::string gice_creds = " username ";
gice_creds.append(kExternalGiceUfrag);
gice_creds.append(" password ");
gice_creds.append(kExternalGicePwd);
gice_creds.append("\r\n");
Replace("\r\n", gice_creds, sdp);
LOG(LS_INFO) << "AddGiceCredsToCandidate: " << *sdp;
}
~PeerConnectionEndToEndTest() {
talk_base::CleanupSSL();
}
protected:
talk_base::scoped_refptr<PeerConnectionTestWrapper> caller_;
talk_base::scoped_refptr<PeerConnectionTestWrapper> callee_;
};
TEST_F(PeerConnectionEndToEndTest, Call) {
CreatePcs();
GetAndAddUserMedia();
Negotiate();
WaitForCallEstablished();
}
TEST_F(PeerConnectionEndToEndTest, CallWithLegacySdp) {
FakeConstraints pc_constraints;
pc_constraints.AddMandatory(MediaConstraintsInterface::kEnableDtlsSrtp,
false);
CreatePcs(&pc_constraints);
SetupLegacySdpConverter();
SetupGiceConverter();
GetAndAddUserMedia();
Negotiate();
WaitForCallEstablished();
}

View File

@@ -100,6 +100,8 @@ const char StatsReport::kStatsValueNameInitiator[] = "googInitiator";
const char StatsReport::kStatsValueNameIssuerId[] = "googIssuerId"; const char StatsReport::kStatsValueNameIssuerId[] = "googIssuerId";
const char StatsReport::kStatsValueNameJitterReceived[] = "googJitterReceived"; const char StatsReport::kStatsValueNameJitterReceived[] = "googJitterReceived";
const char StatsReport::kStatsValueNameLocalAddress[] = "googLocalAddress"; const char StatsReport::kStatsValueNameLocalAddress[] = "googLocalAddress";
const char StatsReport::kStatsValueNameLocalCandidateType[] =
"googLocalCandidateType";
const char StatsReport::kStatsValueNameLocalCertificateId[] = const char StatsReport::kStatsValueNameLocalCertificateId[] =
"googLocalCertificateId"; "googLocalCertificateId";
const char StatsReport::kStatsValueNameNacksReceived[] = "googNacksReceived"; const char StatsReport::kStatsValueNameNacksReceived[] = "googNacksReceived";
@@ -109,6 +111,8 @@ const char StatsReport::kStatsValueNamePacketsSent[] = "packetsSent";
const char StatsReport::kStatsValueNamePacketsLost[] = "packetsLost"; const char StatsReport::kStatsValueNamePacketsLost[] = "packetsLost";
const char StatsReport::kStatsValueNameReadable[] = "googReadable"; const char StatsReport::kStatsValueNameReadable[] = "googReadable";
const char StatsReport::kStatsValueNameRemoteAddress[] = "googRemoteAddress"; const char StatsReport::kStatsValueNameRemoteAddress[] = "googRemoteAddress";
const char StatsReport::kStatsValueNameRemoteCandidateType[] =
"googRemoteCandidateType";
const char StatsReport::kStatsValueNameRemoteCertificateId[] = const char StatsReport::kStatsValueNameRemoteCertificateId[] =
"googRemoteCertificateId"; "googRemoteCertificateId";
const char StatsReport::kStatsValueNameRetransmitBitrate[] = const char StatsReport::kStatsValueNameRetransmitBitrate[] =
@@ -678,6 +682,10 @@ void StatsCollector::ExtractSessionInfo() {
report.AddValue(StatsReport::kStatsValueNameRtt, info.rtt); report.AddValue(StatsReport::kStatsValueNameRtt, info.rtt);
report.AddValue(StatsReport::kStatsValueNameTransportType, report.AddValue(StatsReport::kStatsValueNameTransportType,
info.local_candidate.protocol()); info.local_candidate.protocol());
report.AddValue(StatsReport::kStatsValueNameLocalCandidateType,
info.local_candidate.type());
report.AddValue(StatsReport::kStatsValueNameRemoteCandidateType,
info.remote_candidate.type());
reports_[report.id] = report; reports_[report.id] = report;
} }
} }

View File

@@ -177,6 +177,8 @@ class StatsReport {
static const char kStatsValueNameIssuerId[]; static const char kStatsValueNameIssuerId[];
static const char kStatsValueNameLocalCertificateId[]; static const char kStatsValueNameLocalCertificateId[];
static const char kStatsValueNameRemoteCertificateId[]; static const char kStatsValueNameRemoteCertificateId[];
static const char kStatsValueNameLocalCandidateType[];
static const char kStatsValueNameRemoteCandidateType[];
}; };
typedef std::vector<StatsReport> StatsReports; typedef std::vector<StatsReport> StatsReports;

View File

@@ -0,0 +1,278 @@
/*
* libjingle
* 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:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "talk/app/webrtc/fakeportallocatorfactory.h"
#include "talk/app/webrtc/test/fakeperiodicvideocapturer.h"
#include "talk/app/webrtc/test/mockpeerconnectionobservers.h"
#include "talk/app/webrtc/test/peerconnectiontestwrapper.h"
#include "talk/app/webrtc/videosourceinterface.h"
#include "talk/base/gunit.h"
static const char kStreamLabelBase[] = "stream_label";
static const char kVideoTrackLabelBase[] = "video_track";
static const char kAudioTrackLabelBase[] = "audio_track";
static const int kMaxWait = 5000;
static const int kTestAudioFrameCount = 3;
static const int kTestVideoFrameCount = 3;
using webrtc::FakeConstraints;
using webrtc::FakeVideoTrackRenderer;
using webrtc::IceCandidateInterface;
using webrtc::MediaConstraintsInterface;
using webrtc::MediaStreamInterface;
using webrtc::MockSetSessionDescriptionObserver;
using webrtc::PeerConnectionInterface;
using webrtc::SessionDescriptionInterface;
using webrtc::VideoTrackInterface;
void PeerConnectionTestWrapper::Connect(PeerConnectionTestWrapper* caller,
PeerConnectionTestWrapper* callee) {
caller->SignalOnIceCandidateReady.connect(
callee, &PeerConnectionTestWrapper::AddIceCandidate);
callee->SignalOnIceCandidateReady.connect(
caller, &PeerConnectionTestWrapper::AddIceCandidate);
caller->SignalOnSdpReady.connect(
callee, &PeerConnectionTestWrapper::ReceiveOfferSdp);
callee->SignalOnSdpReady.connect(
caller, &PeerConnectionTestWrapper::ReceiveAnswerSdp);
}
PeerConnectionTestWrapper::PeerConnectionTestWrapper(const std::string& name)
: name_(name) {}
PeerConnectionTestWrapper::~PeerConnectionTestWrapper() {}
bool PeerConnectionTestWrapper::CreatePc(
const MediaConstraintsInterface* constraints) {
allocator_factory_ = webrtc::FakePortAllocatorFactory::Create();
if (!allocator_factory_) {
return false;
}
audio_thread_.Start();
fake_audio_capture_module_ = FakeAudioCaptureModule::Create(
&audio_thread_);
if (fake_audio_capture_module_ == NULL) {
return false;
}
peer_connection_factory_ = webrtc::CreatePeerConnectionFactory(
talk_base::Thread::Current(), talk_base::Thread::Current(),
fake_audio_capture_module_, NULL, NULL);
if (!peer_connection_factory_) {
return false;
}
// CreatePeerConnection with IceServers.
webrtc::PeerConnectionInterface::IceServers ice_servers;
webrtc::PeerConnectionInterface::IceServer ice_server;
ice_server.uri = "stun:stun.l.google.com:19302";
ice_servers.push_back(ice_server);
peer_connection_ = peer_connection_factory_->CreatePeerConnection(
ice_servers, constraints, allocator_factory_.get(), NULL, this);
return peer_connection_.get() != NULL;
}
void PeerConnectionTestWrapper::OnAddStream(MediaStreamInterface* stream) {
LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_
<< ": OnAddStream";
// TODO(ronghuawu): support multiple streams.
if (stream->GetVideoTracks().size() > 0) {
renderer_.reset(new FakeVideoTrackRenderer(stream->GetVideoTracks()[0]));
}
}
void PeerConnectionTestWrapper::OnIceCandidate(
const IceCandidateInterface* candidate) {
std::string sdp;
EXPECT_TRUE(candidate->ToString(&sdp));
// Give the user a chance to modify sdp for testing.
SignalOnIceCandidateCreated(&sdp);
SignalOnIceCandidateReady(candidate->sdp_mid(), candidate->sdp_mline_index(),
sdp);
}
void PeerConnectionTestWrapper::OnSuccess(SessionDescriptionInterface* desc) {
std::string sdp;
EXPECT_TRUE(desc->ToString(&sdp));
LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_
<< ": " << desc->type() << " sdp created: " << sdp;
// Give the user a chance to modify sdp for testing.
SignalOnSdpCreated(&sdp);
SetLocalDescription(desc->type(), sdp);
SignalOnSdpReady(sdp);
}
void PeerConnectionTestWrapper::CreateOffer(
const MediaConstraintsInterface* constraints) {
LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_
<< ": CreateOffer.";
peer_connection_->CreateOffer(this, constraints);
}
void PeerConnectionTestWrapper::CreateAnswer(
const MediaConstraintsInterface* constraints) {
LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_
<< ": CreateAnswer.";
peer_connection_->CreateAnswer(this, constraints);
}
void PeerConnectionTestWrapper::ReceiveOfferSdp(const std::string& sdp) {
SetRemoteDescription(SessionDescriptionInterface::kOffer, sdp);
CreateAnswer(NULL);
}
void PeerConnectionTestWrapper::ReceiveAnswerSdp(const std::string& sdp) {
SetRemoteDescription(SessionDescriptionInterface::kAnswer, sdp);
}
void PeerConnectionTestWrapper::SetLocalDescription(const std::string& type,
const std::string& sdp) {
LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_
<< ": SetLocalDescription " << type << " " << sdp;
talk_base::scoped_refptr<MockSetSessionDescriptionObserver>
observer(new talk_base::RefCountedObject<
MockSetSessionDescriptionObserver>());
peer_connection_->SetLocalDescription(
observer, webrtc::CreateSessionDescription(type, sdp, NULL));
}
void PeerConnectionTestWrapper::SetRemoteDescription(const std::string& type,
const std::string& sdp) {
LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_
<< ": SetRemoteDescription " << type << " " << sdp;
talk_base::scoped_refptr<MockSetSessionDescriptionObserver>
observer(new talk_base::RefCountedObject<
MockSetSessionDescriptionObserver>());
peer_connection_->SetRemoteDescription(
observer, webrtc::CreateSessionDescription(type, sdp, NULL));
}
void PeerConnectionTestWrapper::AddIceCandidate(const std::string& sdp_mid,
int sdp_mline_index,
const std::string& candidate) {
EXPECT_TRUE(peer_connection_->AddIceCandidate(
webrtc::CreateIceCandidate(sdp_mid, sdp_mline_index,
candidate, NULL)));
}
void PeerConnectionTestWrapper::WaitForCallEstablished() {
WaitForConnection();
WaitForAudio();
WaitForVideo();
}
void PeerConnectionTestWrapper::WaitForConnection() {
EXPECT_TRUE_WAIT(CheckForConnection(), kMaxWait);
LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_
<< ": Connected.";
}
bool PeerConnectionTestWrapper::CheckForConnection() {
return (peer_connection_->ice_connection_state() ==
PeerConnectionInterface::kIceConnectionConnected);
}
void PeerConnectionTestWrapper::WaitForAudio() {
EXPECT_TRUE_WAIT(CheckForAudio(), kMaxWait);
LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_
<< ": Got enough audio frames.";
}
bool PeerConnectionTestWrapper::CheckForAudio() {
return (fake_audio_capture_module_->frames_received() >=
kTestAudioFrameCount);
}
void PeerConnectionTestWrapper::WaitForVideo() {
EXPECT_TRUE_WAIT(CheckForVideo(), kMaxWait);
LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_
<< ": Got enough video frames.";
}
bool PeerConnectionTestWrapper::CheckForVideo() {
if (!renderer_) {
return false;
}
return (renderer_->num_rendered_frames() >= kTestVideoFrameCount);
}
void PeerConnectionTestWrapper::GetAndAddUserMedia(
bool audio, const webrtc::FakeConstraints& audio_constraints,
bool video, const webrtc::FakeConstraints& video_constraints) {
talk_base::scoped_refptr<webrtc::MediaStreamInterface> stream =
GetUserMedia(audio, audio_constraints, video, video_constraints);
EXPECT_TRUE(peer_connection_->AddStream(stream, NULL));
}
talk_base::scoped_refptr<webrtc::MediaStreamInterface>
PeerConnectionTestWrapper::GetUserMedia(
bool audio, const webrtc::FakeConstraints& audio_constraints,
bool video, const webrtc::FakeConstraints& video_constraints) {
std::string label = kStreamLabelBase +
talk_base::ToString<int>(
static_cast<int>(peer_connection_->local_streams()->count()));
talk_base::scoped_refptr<webrtc::MediaStreamInterface> stream =
peer_connection_factory_->CreateLocalMediaStream(label);
if (audio) {
FakeConstraints constraints = audio_constraints;
// Disable highpass filter so that we can get all the test audio frames.
constraints.AddMandatory(
MediaConstraintsInterface::kHighpassFilter, false);
talk_base::scoped_refptr<webrtc::AudioSourceInterface> source =
peer_connection_factory_->CreateAudioSource(&constraints);
talk_base::scoped_refptr<webrtc::AudioTrackInterface> audio_track(
peer_connection_factory_->CreateAudioTrack(kAudioTrackLabelBase,
source));
stream->AddTrack(audio_track);
}
if (video) {
// Set max frame rate to 10fps to reduce the risk of the tests to be flaky.
FakeConstraints constraints = video_constraints;
constraints.SetMandatoryMaxFrameRate(10);
talk_base::scoped_refptr<webrtc::VideoSourceInterface> source =
peer_connection_factory_->CreateVideoSource(
new webrtc::FakePeriodicVideoCapturer(), &constraints);
std::string videotrack_label = label + kVideoTrackLabelBase;
talk_base::scoped_refptr<webrtc::VideoTrackInterface> video_track(
peer_connection_factory_->CreateVideoTrack(videotrack_label, source));
stream->AddTrack(video_track);
}
return stream;
}

View File

@@ -0,0 +1,119 @@
/*
* libjingle
* 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:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TALK_APP_WEBRTC_TEST_PEERCONNECTIONTESTWRAPPER_H_
#define TALK_APP_WEBRTC_TEST_PEERCONNECTIONTESTWRAPPER_H_
#include "talk/app/webrtc/peerconnectioninterface.h"
#include "talk/app/webrtc/test/fakeaudiocapturemodule.h"
#include "talk/app/webrtc/test/fakeconstraints.h"
#include "talk/app/webrtc/test/fakevideotrackrenderer.h"
#include "talk/base/sigslot.h"
#include "talk/base/thread.h"
namespace webrtc {
class PortAllocatorFactoryInterface;
}
class PeerConnectionTestWrapper
: public webrtc::PeerConnectionObserver,
public webrtc::CreateSessionDescriptionObserver,
public sigslot::has_slots<> {
public:
static void Connect(PeerConnectionTestWrapper* caller,
PeerConnectionTestWrapper* callee);
explicit PeerConnectionTestWrapper(const std::string& name);
virtual ~PeerConnectionTestWrapper();
bool CreatePc(const webrtc::MediaConstraintsInterface* constraints);
// Implements PeerConnectionObserver.
virtual void OnError() {}
virtual void OnSignalingChange(
webrtc::PeerConnectionInterface::SignalingState new_state) {}
virtual void OnStateChange(
webrtc::PeerConnectionObserver::StateType state_changed) {}
virtual void OnAddStream(webrtc::MediaStreamInterface* stream);
virtual void OnRemoveStream(webrtc::MediaStreamInterface* stream) {}
virtual void OnDataChannel(webrtc::DataChannelInterface* data_channel) {}
virtual void OnRenegotiationNeeded() {}
virtual void OnIceConnectionChange(
webrtc::PeerConnectionInterface::IceConnectionState new_state) {}
virtual void OnIceGatheringChange(
webrtc::PeerConnectionInterface::IceGatheringState new_state) {}
virtual void OnIceCandidate(const webrtc::IceCandidateInterface* candidate);
virtual void OnIceComplete() {}
// Implements CreateSessionDescriptionObserver.
virtual void OnSuccess(webrtc::SessionDescriptionInterface* desc);
virtual void OnFailure(const std::string& error) {}
void CreateOffer(const webrtc::MediaConstraintsInterface* constraints);
void CreateAnswer(const webrtc::MediaConstraintsInterface* constraints);
void ReceiveOfferSdp(const std::string& sdp);
void ReceiveAnswerSdp(const std::string& sdp);
void AddIceCandidate(const std::string& sdp_mid, int sdp_mline_index,
const std::string& candidate);
void WaitForCallEstablished();
void WaitForConnection();
void WaitForAudio();
void WaitForVideo();
void GetAndAddUserMedia(
bool audio, const webrtc::FakeConstraints& audio_constraints,
bool video, const webrtc::FakeConstraints& video_constraints);
// sigslots
sigslot::signal1<std::string*> SignalOnIceCandidateCreated;
sigslot::signal3<const std::string&,
int,
const std::string&> SignalOnIceCandidateReady;
sigslot::signal1<std::string*> SignalOnSdpCreated;
sigslot::signal1<const std::string&> SignalOnSdpReady;
private:
void SetLocalDescription(const std::string& type, const std::string& sdp);
void SetRemoteDescription(const std::string& type, const std::string& sdp);
bool CheckForConnection();
bool CheckForAudio();
bool CheckForVideo();
talk_base::scoped_refptr<webrtc::MediaStreamInterface> GetUserMedia(
bool audio, const webrtc::FakeConstraints& audio_constraints,
bool video, const webrtc::FakeConstraints& video_constraints);
std::string name_;
talk_base::Thread audio_thread_;
talk_base::scoped_refptr<webrtc::PortAllocatorFactoryInterface>
allocator_factory_;
talk_base::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection_;
talk_base::scoped_refptr<webrtc::PeerConnectionFactoryInterface>
peer_connection_factory_;
talk_base::scoped_refptr<FakeAudioCaptureModule> fake_audio_capture_module_;
talk_base::scoped_ptr<webrtc::FakeVideoTrackRenderer> renderer_;
};
#endif // TALK_APP_WEBRTC_TEST_PEERCONNECTIONTESTWRAPPER_H_

View File

@@ -526,7 +526,7 @@ bool WebRtcSession::Initialize(
this, &WebRtcSession::OnIdentityReady); this, &WebRtcSession::OnIdentityReady);
if (options.disable_encryption) { if (options.disable_encryption) {
webrtc_session_desc_factory_->set_secure(cricket::SEC_DISABLED); webrtc_session_desc_factory_->SetSecure(cricket::SEC_DISABLED);
} }
return true; return true;
@@ -554,13 +554,13 @@ bool WebRtcSession::StartCandidatesAllocation() {
return true; return true;
} }
void WebRtcSession::set_secure_policy( void WebRtcSession::SetSecurePolicy(
cricket::SecureMediaPolicy secure_policy) { cricket::SecureMediaPolicy secure_policy) {
webrtc_session_desc_factory_->set_secure(secure_policy); webrtc_session_desc_factory_->SetSecure(secure_policy);
} }
cricket::SecureMediaPolicy WebRtcSession::secure_policy() const { cricket::SecureMediaPolicy WebRtcSession::SecurePolicy() const {
return webrtc_session_desc_factory_->secure(); return webrtc_session_desc_factory_->Secure();
} }
bool WebRtcSession::GetSslRole(talk_base::SSLRole* role) { bool WebRtcSession::GetSslRole(talk_base::SSLRole* role) {
@@ -610,7 +610,7 @@ bool WebRtcSession::SetLocalDescription(SessionDescriptionInterface* desc,
} }
cricket::SecureMediaPolicy secure_policy = cricket::SecureMediaPolicy secure_policy =
webrtc_session_desc_factory_->secure(); webrtc_session_desc_factory_->Secure();
// Update the MediaContentDescription crypto settings as per the policy set. // Update the MediaContentDescription crypto settings as per the policy set.
UpdateSessionDescriptionSecurePolicy(secure_policy, desc->description()); UpdateSessionDescriptionSecurePolicy(secure_policy, desc->description());
@@ -1483,7 +1483,7 @@ bool WebRtcSession::ValidateSessionDescription(
// Verify crypto settings. // Verify crypto settings.
std::string crypto_error; std::string crypto_error;
if (webrtc_session_desc_factory_->secure() == cricket::SEC_REQUIRED && if (webrtc_session_desc_factory_->Secure() == cricket::SEC_REQUIRED &&
!VerifyCrypto(sdesc->description(), dtls_enabled_, &crypto_error)) { !VerifyCrypto(sdesc->description(), dtls_enabled_, &crypto_error)) {
return BadSdp(source, crypto_error, error_desc); return BadSdp(source, crypto_error, error_desc);
} }

View File

@@ -42,20 +42,17 @@
#include "talk/session/media/mediasession.h" #include "talk/session/media/mediasession.h"
namespace cricket { namespace cricket {
class BaseChannel;
class ChannelManager; class ChannelManager;
class DataChannel; class DataChannel;
class StatsReport; class StatsReport;
class Transport; class Transport;
class VideoCapturer; class VideoCapturer;
class BaseChannel;
class VideoChannel; class VideoChannel;
class VoiceChannel; class VoiceChannel;
} // namespace cricket } // namespace cricket
namespace webrtc { namespace webrtc {
class IceRestartAnswerLatch; class IceRestartAnswerLatch;
class MediaStreamSignaling; class MediaStreamSignaling;
class WebRtcSessionDescriptionFactory; class WebRtcSessionDescriptionFactory;
@@ -79,6 +76,7 @@ extern const char kPushDownAnswerTDFailed[];
// ICE state callback interface. // ICE state callback interface.
class IceObserver { class IceObserver {
public: public:
IceObserver() {}
// Called any time the IceConnectionState changes // Called any time the IceConnectionState changes
virtual void OnIceConnectionChange( virtual void OnIceConnectionChange(
PeerConnectionInterface::IceConnectionState new_state) {} PeerConnectionInterface::IceConnectionState new_state) {}
@@ -94,6 +92,9 @@ class IceObserver {
protected: protected:
~IceObserver() {} ~IceObserver() {}
private:
DISALLOW_COPY_AND_ASSIGN(IceObserver);
}; };
class WebRtcSession : public cricket::BaseSession, class WebRtcSession : public cricket::BaseSession,
@@ -131,8 +132,8 @@ class WebRtcSession : public cricket::BaseSession,
return data_channel_.get(); return data_channel_.get();
} }
void set_secure_policy(cricket::SecureMediaPolicy secure_policy); void SetSecurePolicy(cricket::SecureMediaPolicy secure_policy);
cricket::SecureMediaPolicy secure_policy() const; cricket::SecureMediaPolicy SecurePolicy() const;
// Get current ssl role from transport. // Get current ssl role from transport.
bool GetSslRole(talk_base::SSLRole* role); bool GetSslRole(talk_base::SSLRole* role);
@@ -330,8 +331,9 @@ class WebRtcSession : public cricket::BaseSession,
sigslot::signal0<> SignalVoiceChannelDestroyed; sigslot::signal0<> SignalVoiceChannelDestroyed;
sigslot::signal0<> SignalVideoChannelDestroyed; sigslot::signal0<> SignalVideoChannelDestroyed;
sigslot::signal0<> SignalDataChannelDestroyed; sigslot::signal0<> SignalDataChannelDestroyed;
};
DISALLOW_COPY_AND_ASSIGN(WebRtcSession);
};
} // namespace webrtc } // namespace webrtc
#endif // TALK_APP_WEBRTC_WEBRTCSESSION_H_ #endif // TALK_APP_WEBRTC_WEBRTCSESSION_H_

View File

@@ -86,20 +86,21 @@ using webrtc::PeerConnectionInterface;
using webrtc::SessionDescriptionInterface; using webrtc::SessionDescriptionInterface;
using webrtc::StreamCollection; using webrtc::StreamCollection;
using webrtc::WebRtcSession; using webrtc::WebRtcSession;
using webrtc::kBundleWithoutRtcpMux;
using webrtc::kMlineMismatch; using webrtc::kMlineMismatch;
using webrtc::kPushDownAnswerTDFailed;
using webrtc::kPushDownPranswerTDFailed;
using webrtc::kSdpWithoutCrypto; using webrtc::kSdpWithoutCrypto;
using webrtc::kSdpWithoutSdesAndDtlsDisabled;
using webrtc::kSdpWithoutIceUfragPwd; using webrtc::kSdpWithoutIceUfragPwd;
using webrtc::kSdpWithoutSdesAndDtlsDisabled;
using webrtc::kSessionError; using webrtc::kSessionError;
using webrtc::kSetLocalSdpFailed; using webrtc::kSetLocalSdpFailed;
using webrtc::kSetRemoteSdpFailed; using webrtc::kSetRemoteSdpFailed;
using webrtc::kPushDownAnswerTDFailed;
using webrtc::kPushDownPranswerTDFailed;
using webrtc::kBundleWithoutRtcpMux;
static const SocketAddress kClientAddr1("11.11.11.11", 0); static const int kClientAddrPort = 0;
static const SocketAddress kClientAddr2("22.22.22.22", 0); static const char kClientAddrHost1[] = "11.11.11.11";
static const SocketAddress kStunAddr("99.99.99.1", cricket::STUN_SERVER_PORT); static const char kClientAddrHost2[] = "22.22.22.22";
static const char kStunAddrHost[] = "99.99.99.1";
static const char kSessionVersion[] = "1"; static const char kSessionVersion[] = "1";
@@ -113,11 +114,6 @@ static const char kMediaContentName1[] = "video";
static const int kIceCandidatesTimeout = 10000; static const int kIceCandidatesTimeout = 10000;
static const cricket::AudioCodec
kTelephoneEventCodec(106, "telephone-event", 8000, 0, 1, 0);
static const cricket::AudioCodec kCNCodec1(102, "CN", 8000, 0, 1, 0);
static const cricket::AudioCodec kCNCodec2(103, "CN", 16000, 0, 1, 0);
static const char kFakeDtlsFingerprint[] = static const char kFakeDtlsFingerprint[] =
"BB:CD:72:F7:2F:D0:BA:43:F3:68:B1:0C:23:72:B6:4A:" "BB:CD:72:F7:2F:D0:BA:43:F3:68:B1:0C:23:72:B6:4A:"
"0F:DE:34:06:BC:E0:FE:01:BC:73:C8:6D:F4:65:D5:24"; "0F:DE:34:06:BC:E0:FE:01:BC:73:C8:6D:F4:65:D5:24";
@@ -159,11 +155,17 @@ class MockIceObserver : public webrtc::IceObserver {
// Found a new candidate. // Found a new candidate.
virtual void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) { virtual void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) {
if (candidate->sdp_mline_index() == kMediaContentIndex0) { switch (candidate->sdp_mline_index()) {
mline_0_candidates_.push_back(candidate->candidate()); case kMediaContentIndex0:
} else if (candidate->sdp_mline_index() == kMediaContentIndex1) { mline_0_candidates_.push_back(candidate->candidate());
mline_1_candidates_.push_back(candidate->candidate()); break;
case kMediaContentIndex1:
mline_1_candidates_.push_back(candidate->candidate());
break;
default:
ASSERT(false);
} }
// The ICE gathering state should always be Gathering when a candidate is // The ICE gathering state should always be Gathering when a candidate is
// received (or possibly Completed in the case of the final candidate). // received (or possibly Completed in the case of the final candidate).
EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, ice_gathering_state_); EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, ice_gathering_state_);
@@ -281,8 +283,10 @@ class WebRtcSessionTest : public testing::Test {
vss_(new talk_base::VirtualSocketServer(pss_.get())), vss_(new talk_base::VirtualSocketServer(pss_.get())),
fss_(new talk_base::FirewallSocketServer(vss_.get())), fss_(new talk_base::FirewallSocketServer(vss_.get())),
ss_scope_(fss_.get()), ss_scope_(fss_.get()),
stun_server_(talk_base::Thread::Current(), kStunAddr), stun_socket_addr_(talk_base::SocketAddress(kStunAddrHost,
allocator_(&network_manager_, kStunAddr, cricket::STUN_SERVER_PORT)),
stun_server_(talk_base::Thread::Current(), stun_socket_addr_),
allocator_(&network_manager_, stun_socket_addr_,
SocketAddress(), SocketAddress(), SocketAddress()), SocketAddress(), SocketAddress(), SocketAddress()),
mediastream_signaling_(channel_manager_.get()) { mediastream_signaling_(channel_manager_.get()) {
tdesc_factory_->set_protocol(cricket::ICEPROTO_HYBRID); tdesc_factory_->set_protocol(cricket::ICEPROTO_HYBRID);
@@ -324,6 +328,8 @@ class WebRtcSessionTest : public testing::Test {
void InitWithDtmfCodec() { void InitWithDtmfCodec() {
// Add kTelephoneEventCodec for dtmf test. // Add kTelephoneEventCodec for dtmf test.
const cricket::AudioCodec kTelephoneEventCodec(
106, "telephone-event", 8000, 0, 1, 0);
std::vector<cricket::AudioCodec> codecs; std::vector<cricket::AudioCodec> codecs;
codecs.push_back(kTelephoneEventCodec); codecs.push_back(kTelephoneEventCodec);
media_engine_->SetAudioCodecs(codecs); media_engine_->SetAudioCodecs(codecs);
@@ -370,12 +376,12 @@ class WebRtcSessionTest : public testing::Test {
return observer->ReleaseDescription(); return observer->ReleaseDescription();
} }
bool ChannelsExist() { bool ChannelsExist() const {
return (session_->voice_channel() != NULL && return (session_->voice_channel() != NULL &&
session_->video_channel() != NULL); session_->video_channel() != NULL);
} }
void CheckTransportChannels() { void CheckTransportChannels() const {
EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 1) != NULL); EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 1) != NULL);
EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 2) != NULL); EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 2) != NULL);
EXPECT_TRUE(session_->GetChannel(cricket::CN_VIDEO, 1) != NULL); EXPECT_TRUE(session_->GetChannel(cricket::CN_VIDEO, 1) != NULL);
@@ -710,7 +716,7 @@ class WebRtcSessionTest : public testing::Test {
} }
void TestSessionCandidatesWithBundleRtcpMux(bool bundle, bool rtcp_mux) { void TestSessionCandidatesWithBundleRtcpMux(bool bundle, bool rtcp_mux) {
AddInterface(kClientAddr1); AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
Init(NULL); Init(NULL);
mediastream_signaling_.SendAudioVideoStream1(); mediastream_signaling_.SendAudioVideoStream1();
FakeConstraints constraints; FakeConstraints constraints;
@@ -780,7 +786,7 @@ class WebRtcSessionTest : public testing::Test {
// New -> Checking -> Connected -> Disconnected -> Connected. // New -> Checking -> Connected -> Disconnected -> Connected.
// The Gathering state should go: New -> Gathering -> Completed. // The Gathering state should go: New -> Gathering -> Completed.
void TestLoopbackCall() { void TestLoopbackCall() {
AddInterface(kClientAddr1); AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
Init(NULL); Init(NULL);
mediastream_signaling_.SendAudioVideoStream1(); mediastream_signaling_.SendAudioVideoStream1();
SessionDescriptionInterface* offer = CreateOffer(NULL); SessionDescriptionInterface* offer = CreateOffer(NULL);
@@ -815,7 +821,10 @@ class WebRtcSessionTest : public testing::Test {
// Adding firewall rule to block ping requests, which should cause // Adding firewall rule to block ping requests, which should cause
// transport channel failure. // transport channel failure.
fss_->AddRule(false, talk_base::FP_ANY, talk_base::FD_ANY, kClientAddr1); fss_->AddRule(false,
talk_base::FP_ANY,
talk_base::FD_ANY,
talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionDisconnected, EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionDisconnected,
observer_.ice_connection_state_, observer_.ice_connection_state_,
kIceCandidatesTimeout); kIceCandidatesTimeout);
@@ -840,7 +849,10 @@ class WebRtcSessionTest : public testing::Test {
// Adds CN codecs to FakeMediaEngine and MediaDescriptionFactory. // Adds CN codecs to FakeMediaEngine and MediaDescriptionFactory.
void AddCNCodecs() { void AddCNCodecs() {
// Add kTelephoneEventCodec for dtmf test. const cricket::AudioCodec kCNCodec1(102, "CN", 8000, 0, 1, 0);
const cricket::AudioCodec kCNCodec2(103, "CN", 16000, 0, 1, 0);
// Add kCNCodec for dtmf test.
std::vector<cricket::AudioCodec> codecs = media_engine_->audio_codecs();; std::vector<cricket::AudioCodec> codecs = media_engine_->audio_codecs();;
codecs.push_back(kCNCodec1); codecs.push_back(kCNCodec1);
codecs.push_back(kCNCodec2); codecs.push_back(kCNCodec2);
@@ -918,6 +930,7 @@ class WebRtcSessionTest : public testing::Test {
talk_base::scoped_ptr<talk_base::VirtualSocketServer> vss_; talk_base::scoped_ptr<talk_base::VirtualSocketServer> vss_;
talk_base::scoped_ptr<talk_base::FirewallSocketServer> fss_; talk_base::scoped_ptr<talk_base::FirewallSocketServer> fss_;
talk_base::SocketServerScope ss_scope_; talk_base::SocketServerScope ss_scope_;
talk_base::SocketAddress stun_socket_addr_;
cricket::TestStunServer stun_server_; cricket::TestStunServer stun_server_;
talk_base::FakeNetworkManager network_manager_; talk_base::FakeNetworkManager network_manager_;
cricket::BasicPortAllocator allocator_; cricket::BasicPortAllocator allocator_;
@@ -941,7 +954,7 @@ TEST_F(WebRtcSessionTest, TestInitializeWithDtls) {
// Verifies that WebRtcSession uses SEC_REQUIRED by default. // Verifies that WebRtcSession uses SEC_REQUIRED by default.
TEST_F(WebRtcSessionTest, TestDefaultSetSecurePolicy) { TEST_F(WebRtcSessionTest, TestDefaultSetSecurePolicy) {
Init(NULL); Init(NULL);
EXPECT_EQ(cricket::SEC_REQUIRED, session_->secure_policy()); EXPECT_EQ(cricket::SEC_REQUIRED, session_->SecurePolicy());
} }
TEST_F(WebRtcSessionTest, TestSessionCandidates) { TEST_F(WebRtcSessionTest, TestSessionCandidates) {
@@ -959,8 +972,8 @@ TEST_F(WebRtcSessionTest, TestSessionCandidatesWithBundleRtcpMux) {
} }
TEST_F(WebRtcSessionTest, TestMultihomeCandidates) { TEST_F(WebRtcSessionTest, TestMultihomeCandidates) {
AddInterface(kClientAddr1); AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
AddInterface(kClientAddr2); AddInterface(talk_base::SocketAddress(kClientAddrHost2, kClientAddrPort));
Init(NULL); Init(NULL);
mediastream_signaling_.SendAudioVideoStream1(); mediastream_signaling_.SendAudioVideoStream1();
InitiateCall(); InitiateCall();
@@ -970,13 +983,16 @@ TEST_F(WebRtcSessionTest, TestMultihomeCandidates) {
} }
TEST_F(WebRtcSessionTest, TestStunError) { TEST_F(WebRtcSessionTest, TestStunError) {
AddInterface(kClientAddr1); AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
AddInterface(kClientAddr2); AddInterface(talk_base::SocketAddress(kClientAddrHost2, kClientAddrPort));
fss_->AddRule(false, talk_base::FP_UDP, talk_base::FD_ANY, kClientAddr1); fss_->AddRule(false,
talk_base::FP_UDP,
talk_base::FD_ANY,
talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
Init(NULL); Init(NULL);
mediastream_signaling_.SendAudioVideoStream1(); mediastream_signaling_.SendAudioVideoStream1();
InitiateCall(); InitiateCall();
// Since kClientAddr1 is blocked, not expecting stun candidates for it. // Since kClientAddrHost1 is blocked, not expecting stun candidates for it.
EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout); EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
EXPECT_EQ(6u, observer_.mline_0_candidates_.size()); EXPECT_EQ(6u, observer_.mline_0_candidates_.size());
EXPECT_EQ(6u, observer_.mline_1_candidates_.size()); EXPECT_EQ(6u, observer_.mline_1_candidates_.size());
@@ -1420,7 +1436,7 @@ TEST_F(WebRtcSessionTest, TestRemoteCandidatesAddedToSessionDescription) {
// Test that local candidates are added to the local session description and // Test that local candidates are added to the local session description and
// that they are retained if the local session description is changed. // that they are retained if the local session description is changed.
TEST_F(WebRtcSessionTest, TestLocalCandidatesAddedToSessionDescription) { TEST_F(WebRtcSessionTest, TestLocalCandidatesAddedToSessionDescription) {
AddInterface(kClientAddr1); AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
Init(NULL); Init(NULL);
mediastream_signaling_.SendAudioVideoStream1(); mediastream_signaling_.SendAudioVideoStream1();
CreateAndSetRemoteOfferAndLocalAnswer(); CreateAndSetRemoteOfferAndLocalAnswer();
@@ -1484,7 +1500,7 @@ TEST_F(WebRtcSessionTest, TestSetRemoteSessionDescriptionWithCandidates) {
// Test that offers and answers contains ice candidates when Ice candidates have // Test that offers and answers contains ice candidates when Ice candidates have
// been gathered. // been gathered.
TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteDescriptionWithCandidates) { TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteDescriptionWithCandidates) {
AddInterface(kClientAddr1); AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
Init(NULL); Init(NULL);
mediastream_signaling_.SendAudioVideoStream1(); mediastream_signaling_.SendAudioVideoStream1();
// Ice is started but candidates are not provided until SetLocalDescription // Ice is started but candidates are not provided until SetLocalDescription

View File

@@ -33,10 +33,10 @@
#include "talk/app/webrtc/mediastreamsignaling.h" #include "talk/app/webrtc/mediastreamsignaling.h"
#include "talk/app/webrtc/webrtcsession.h" #include "talk/app/webrtc/webrtcsession.h"
using cricket::MediaSessionOptions;
namespace webrtc { namespace webrtc {
namespace { namespace {
static const char kFailedDueToIdentityFailed[] = static const char kFailedDueToIdentityFailed[] =
" failed because DTLS identity request failed"; " failed because DTLS identity request failed";
@@ -46,25 +46,24 @@ static const char kWebRTCIdentityName[] = "WebRTC";
static const uint64 kInitSessionVersion = 2; static const uint64 kInitSessionVersion = 2;
typedef cricket::MediaSessionOptions::Stream Stream; static bool CompareStream(const MediaSessionOptions::Stream& stream1,
typedef cricket::MediaSessionOptions::Streams Streams; const MediaSessionOptions::Stream& stream2) {
return stream1.id < stream2.id;
static bool CompareStream(const Stream& stream1, const Stream& stream2) {
return (stream1.id < stream2.id);
} }
static bool SameId(const Stream& stream1, const Stream& stream2) { static bool SameId(const MediaSessionOptions::Stream& stream1,
return (stream1.id == stream2.id); const MediaSessionOptions::Stream& stream2) {
return stream1.id == stream2.id;
} }
// Checks if each Stream within the |streams| has unique id. // Checks if each Stream within the |streams| has unique id.
static bool ValidStreams(const Streams& streams) { static bool ValidStreams(const MediaSessionOptions::Streams& streams) {
Streams sorted_streams = streams; MediaSessionOptions::Streams sorted_streams = streams;
std::sort(sorted_streams.begin(), sorted_streams.end(), CompareStream); std::sort(sorted_streams.begin(), sorted_streams.end(), CompareStream);
Streams::iterator it = MediaSessionOptions::Streams::iterator it =
std::adjacent_find(sorted_streams.begin(), sorted_streams.end(), std::adjacent_find(sorted_streams.begin(), sorted_streams.end(),
SameId); SameId);
return (it == sorted_streams.end()); return it == sorted_streams.end();
} }
enum { enum {
@@ -83,7 +82,6 @@ struct CreateSessionDescriptionMsg : public talk_base::MessageData {
std::string error; std::string error;
talk_base::scoped_ptr<webrtc::SessionDescriptionInterface> description; talk_base::scoped_ptr<webrtc::SessionDescriptionInterface> description;
}; };
} // namespace } // namespace
// static // static
@@ -130,33 +128,35 @@ WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory(
transport_desc_factory_.set_protocol(cricket::ICEPROTO_HYBRID); transport_desc_factory_.set_protocol(cricket::ICEPROTO_HYBRID);
session_desc_factory_.set_add_legacy_streams(false); session_desc_factory_.set_add_legacy_streams(false);
// By default SRTP-SDES is enabled in WebRtc. // By default SRTP-SDES is enabled in WebRtc.
set_secure(cricket::SEC_REQUIRED); SetSecure(cricket::SEC_REQUIRED);
if (dtls_enabled) { if (!dtls_enabled) {
if (identity_service_.get()) { return;
identity_request_observer_ = }
new talk_base::RefCountedObject<WebRtcIdentityRequestObserver>();
identity_request_observer_->SignalRequestFailed.connect( if (identity_service_.get()) {
this, &WebRtcSessionDescriptionFactory::OnIdentityRequestFailed); identity_request_observer_ =
identity_request_observer_->SignalIdentityReady.connect( new talk_base::RefCountedObject<WebRtcIdentityRequestObserver>();
this, &WebRtcSessionDescriptionFactory::OnIdentityReady);
if (identity_service_->RequestIdentity(kWebRTCIdentityName, identity_request_observer_->SignalRequestFailed.connect(
kWebRTCIdentityName, this, &WebRtcSessionDescriptionFactory::OnIdentityRequestFailed);
identity_request_observer_)) { identity_request_observer_->SignalIdentityReady.connect(
LOG(LS_VERBOSE) << "DTLS-SRTP enabled; sent DTLS identity request."; this, &WebRtcSessionDescriptionFactory::OnIdentityReady);
identity_request_state_ = IDENTITY_WAITING;
} else { if (identity_service_->RequestIdentity(kWebRTCIdentityName,
LOG(LS_ERROR) << "Failed to send DTLS identity request."; kWebRTCIdentityName,
identity_request_state_ = IDENTITY_FAILED; identity_request_observer_)) {
} LOG(LS_VERBOSE) << "DTLS-SRTP enabled; sent DTLS identity request.";
} else {
identity_request_state_ = IDENTITY_WAITING; identity_request_state_ = IDENTITY_WAITING;
// Do not generate the identity in the constructor since the caller has } else {
// not got a chance to connect to SignalIdentityReady. LOG(LS_ERROR) << "Failed to send DTLS identity request.";
signaling_thread_->Post(this, MSG_GENERATE_IDENTITY, NULL); identity_request_state_ = IDENTITY_FAILED;
} }
} else {
identity_request_state_ = IDENTITY_WAITING;
// Do not generate the identity in the constructor since the caller has
// not got a chance to connect to SignalIdentityReady.
signaling_thread_->Post(this, MSG_GENERATE_IDENTITY, NULL);
} }
} }
@@ -261,19 +261,15 @@ void WebRtcSessionDescriptionFactory::CreateAnswer(
} }
} }
void WebRtcSessionDescriptionFactory::set_secure( void WebRtcSessionDescriptionFactory::SetSecure(
cricket::SecureMediaPolicy secure_policy) { cricket::SecureMediaPolicy secure_policy) {
session_desc_factory_.set_secure(secure_policy); session_desc_factory_.set_secure(secure_policy);
} }
cricket::SecureMediaPolicy WebRtcSessionDescriptionFactory::secure() const { cricket::SecureMediaPolicy WebRtcSessionDescriptionFactory::Secure() const {
return session_desc_factory_.secure(); return session_desc_factory_.secure();
} }
bool WebRtcSessionDescriptionFactory::waiting_for_identity() const {
return identity_request_state_ == IDENTITY_WAITING;
}
void WebRtcSessionDescriptionFactory::OnMessage(talk_base::Message* msg) { void WebRtcSessionDescriptionFactory::OnMessage(talk_base::Message* msg) {
switch (msg->message_id) { switch (msg->message_id) {
case MSG_CREATE_SESSIONDESCRIPTION_SUCCESS: { case MSG_CREATE_SESSIONDESCRIPTION_SUCCESS: {
@@ -450,5 +446,4 @@ void WebRtcSessionDescriptionFactory::SetIdentity(
create_session_description_requests_.pop(); create_session_description_requests_.pop();
} }
} }
} // namespace webrtc } // namespace webrtc

View File

@@ -34,21 +34,17 @@
#include "talk/session/media/mediasession.h" #include "talk/session/media/mediasession.h"
namespace cricket { namespace cricket {
class ChannelManager; class ChannelManager;
class TransportDescriptionFactory; class TransportDescriptionFactory;
} // namespace cricket } // namespace cricket
namespace webrtc { namespace webrtc {
class CreateSessionDescriptionObserver; class CreateSessionDescriptionObserver;
class MediaConstraintsInterface; class MediaConstraintsInterface;
class MediaStreamSignaling; class MediaStreamSignaling;
class SessionDescriptionInterface; class SessionDescriptionInterface;
class WebRtcSession; class WebRtcSession;
// DTLS identity request callback class. // DTLS identity request callback class.
class WebRtcIdentityRequestObserver : public DTLSIdentityRequestObserver, class WebRtcIdentityRequestObserver : public DTLSIdentityRequestObserver,
public sigslot::has_slots<> { public sigslot::has_slots<> {
@@ -116,13 +112,15 @@ class WebRtcSessionDescriptionFactory : public talk_base::MessageHandler,
CreateSessionDescriptionObserver* observer, CreateSessionDescriptionObserver* observer,
const MediaConstraintsInterface* constraints); const MediaConstraintsInterface* constraints);
void set_secure(cricket::SecureMediaPolicy secure_policy); void SetSecure(cricket::SecureMediaPolicy secure_policy);
cricket::SecureMediaPolicy secure() const; cricket::SecureMediaPolicy Secure() const;
sigslot::signal1<talk_base::SSLIdentity*> SignalIdentityReady; sigslot::signal1<talk_base::SSLIdentity*> SignalIdentityReady;
// For testing. // For testing.
bool waiting_for_identity() const; bool waiting_for_identity() const {
return identity_request_state_ == IDENTITY_WAITING;
}
private: private:
enum IdentityRequestState { enum IdentityRequestState {
@@ -166,7 +164,6 @@ class WebRtcSessionDescriptionFactory : public talk_base::MessageHandler,
DISALLOW_COPY_AND_ASSIGN(WebRtcSessionDescriptionFactory); DISALLOW_COPY_AND_ASSIGN(WebRtcSessionDescriptionFactory);
}; };
} // namespace webrtc } // namespace webrtc
#endif // TALK_APP_WEBRTC_WEBRTCSESSIONDESCRIPTIONFACTORY_H_ #endif // TALK_APP_WEBRTC_WEBRTCSESSIONDESCRIPTIONFACTORY_H_

View File

@@ -383,6 +383,7 @@
# 'app/webrtc/mediastreamhandler_unittest.cc', # 'app/webrtc/mediastreamhandler_unittest.cc',
'app/webrtc/mediastreamsignaling_unittest.cc', 'app/webrtc/mediastreamsignaling_unittest.cc',
'app/webrtc/peerconnection_unittest.cc', 'app/webrtc/peerconnection_unittest.cc',
'app/webrtc/peerconnectionendtoend_unittest.cc',
'app/webrtc/peerconnectionfactory_unittest.cc', 'app/webrtc/peerconnectionfactory_unittest.cc',
'app/webrtc/peerconnectioninterface_unittest.cc', 'app/webrtc/peerconnectioninterface_unittest.cc',
# 'app/webrtc/peerconnectionproxy_unittest.cc', # 'app/webrtc/peerconnectionproxy_unittest.cc',
@@ -397,6 +398,8 @@
'app/webrtc/test/fakeperiodicvideocapturer.h', 'app/webrtc/test/fakeperiodicvideocapturer.h',
'app/webrtc/test/fakevideotrackrenderer.h', 'app/webrtc/test/fakevideotrackrenderer.h',
'app/webrtc/test/mockpeerconnectionobservers.h', 'app/webrtc/test/mockpeerconnectionobservers.h',
'app/webrtc/test/peerconnectiontestwrapper.h',
'app/webrtc/test/peerconnectiontestwrapper.cc',
'app/webrtc/test/testsdpstrings.h', 'app/webrtc/test/testsdpstrings.h',
'app/webrtc/videosource_unittest.cc', 'app/webrtc/videosource_unittest.cc',
'app/webrtc/videotrack_unittest.cc', 'app/webrtc/videotrack_unittest.cc',

View File

@@ -109,7 +109,7 @@ class CoordinatedVideoAdapter
: public VideoAdapter, public sigslot::has_slots<> { : public VideoAdapter, public sigslot::has_slots<> {
public: public:
enum AdaptRequest { UPGRADE, KEEP, DOWNGRADE }; enum AdaptRequest { UPGRADE, KEEP, DOWNGRADE };
enum { enum AdaptReasonEnum {
ADAPTREASON_CPU = 1, ADAPTREASON_CPU = 1,
ADAPTREASON_BANDWIDTH = 2, ADAPTREASON_BANDWIDTH = 2,
ADAPTREASON_VIEW = 4 ADAPTREASON_VIEW = 4

View File

@@ -252,6 +252,19 @@ class FakeWebRtcVoiceEngine
true); true);
} }
} }
int AddChannel() {
if (fail_create_channel_) {
return -1;
}
Channel* ch = new Channel();
for (int i = 0; i < NumOfCodecs(); ++i) {
webrtc::CodecInst codec;
GetCodec(i, codec);
ch->recv_codecs.push_back(codec);
}
channels_[++last_channel_] = ch;
return last_channel_;
}
WEBRTC_STUB(Release, ()); WEBRTC_STUB(Release, ());
@@ -275,18 +288,13 @@ class FakeWebRtcVoiceEngine
return NULL; return NULL;
} }
WEBRTC_FUNC(CreateChannel, ()) { WEBRTC_FUNC(CreateChannel, ()) {
if (fail_create_channel_) { return AddChannel();
return -1;
}
Channel* ch = new Channel();
for (int i = 0; i < NumOfCodecs(); ++i) {
webrtc::CodecInst codec;
GetCodec(i, codec);
ch->recv_codecs.push_back(codec);
}
channels_[++last_channel_] = ch;
return last_channel_;
} }
#ifdef USE_WEBRTC_DEV_BRANCH
WEBRTC_FUNC(CreateChannel, (const webrtc::Config& /*config*/)) {
return AddChannel();
}
#endif
WEBRTC_FUNC(DeleteChannel, (int channel)) { WEBRTC_FUNC(DeleteChannel, (int channel)) {
WEBRTC_CHECK_CHANNEL(channel); WEBRTC_CHECK_CHANNEL(channel);
delete channels_[channel]; delete channels_[channel];

View File

@@ -998,10 +998,11 @@ bool Session::TerminateWithReason(const std::string& reason) {
return true; return true;
} }
bool Session::SendInfoMessage(const XmlElements& elems) { bool Session::SendInfoMessage(const XmlElements& elems,
const std::string& remote_name) {
ASSERT(signaling_thread()->IsCurrent()); ASSERT(signaling_thread()->IsCurrent());
SessionError error; SessionError error;
if (!SendMessage(ACTION_SESSION_INFO, elems, &error)) { if (!SendMessage(ACTION_SESSION_INFO, elems, remote_name, &error)) {
LOG(LS_ERROR) << "Could not send info message " << error.text; LOG(LS_ERROR) << "Could not send info message " << error.text;
return false; return false;
} }
@@ -1644,11 +1645,16 @@ bool Session::SendAllUnsentTransportInfoMessages(SessionError* error) {
bool Session::SendMessage(ActionType type, const XmlElements& action_elems, bool Session::SendMessage(ActionType type, const XmlElements& action_elems,
SessionError* error) { SessionError* error) {
return SendMessage(type, action_elems, remote_name(), error);
}
bool Session::SendMessage(ActionType type, const XmlElements& action_elems,
const std::string& remote_name, SessionError* error) {
talk_base::scoped_ptr<buzz::XmlElement> stanza( talk_base::scoped_ptr<buzz::XmlElement> stanza(
new buzz::XmlElement(buzz::QN_IQ)); new buzz::XmlElement(buzz::QN_IQ));
SessionMessage msg(current_protocol_, type, id(), initiator_name()); SessionMessage msg(current_protocol_, type, id(), initiator_name());
msg.to = remote_name(); msg.to = remote_name;
WriteSessionMessage(msg, action_elems, stanza.get()); WriteSessionMessage(msg, action_elems, stanza.get());
SignalOutgoingMessage(this, stanza.get()); SignalOutgoingMessage(this, stanza.get());

View File

@@ -584,7 +584,8 @@ class Session : public BaseSession {
// arbitrary XML messages, which are called "info" messages. Sending // arbitrary XML messages, which are called "info" messages. Sending
// takes ownership of the given elements. The signal does not; the // takes ownership of the given elements. The signal does not; the
// parent element will be deleted after the signal. // parent element will be deleted after the signal.
bool SendInfoMessage(const XmlElements& elems); bool SendInfoMessage(const XmlElements& elems,
const std::string& remote_name);
bool SendDescriptionInfoMessage(const ContentInfos& contents); bool SendDescriptionInfoMessage(const ContentInfos& contents);
sigslot::signal2<Session*, const buzz::XmlElement*> SignalInfoMessage; sigslot::signal2<Session*, const buzz::XmlElement*> SignalInfoMessage;
@@ -638,7 +639,7 @@ class Session : public BaseSession {
bool ResendAllTransportInfoMessages(SessionError* error); bool ResendAllTransportInfoMessages(SessionError* error);
bool SendAllUnsentTransportInfoMessages(SessionError* error); bool SendAllUnsentTransportInfoMessages(SessionError* error);
// Both versions of SendMessage send a message of the given type to // All versions of SendMessage send a message of the given type to
// the other client. Can pass either a set of elements or an // the other client. Can pass either a set of elements or an
// "action", which must have a WriteSessionAction method to go along // "action", which must have a WriteSessionAction method to go along
// with it. Sending with an action supports sending a "hybrid" // with it. Sending with an action supports sending a "hybrid"
@@ -648,6 +649,10 @@ class Session : public BaseSession {
// Takes ownership of action_elems. // Takes ownership of action_elems.
bool SendMessage(ActionType type, const XmlElements& action_elems, bool SendMessage(ActionType type, const XmlElements& action_elems,
SessionError* error); SessionError* error);
// Sends a messge, but overrides the remote name.
bool SendMessage(ActionType type, const XmlElements& action_elems,
const std::string& remote_name,
SessionError* error);
// When passing an action, may be Hybrid protocol. // When passing an action, may be Hybrid protocol.
template <typename Action> template <typename Action>
bool SendMessage(ActionType type, const Action& action, bool SendMessage(ActionType type, const Action& action,

View File

@@ -186,7 +186,7 @@ bool Call::SendViewRequest(Session* session,
return false; return false;
} }
return session->SendInfoMessage(elems); return session->SendInfoMessage(elems, session->remote_name());
} }
void Call::SetLocalRenderer(VideoRenderer* renderer) { void Call::SetLocalRenderer(VideoRenderer* renderer) {

View File

@@ -22,6 +22,8 @@ JsepPeerConnectionP2PTestClient.LocalP2PTestWithoutMsid
JsepPeerConnectionP2PTestClient.LocalP2PTestWithVideoDecoderFactory JsepPeerConnectionP2PTestClient.LocalP2PTestWithVideoDecoderFactory
JsepPeerConnectionP2PTestClient.RegisterDataChannelObserver JsepPeerConnectionP2PTestClient.RegisterDataChannelObserver
JsepPeerConnectionP2PTestClient.UpdateOfferWithRejectedContent JsepPeerConnectionP2PTestClient.UpdateOfferWithRejectedContent
PeerConnectionEndToEndTest.Call
PeerConnectionEndToEndTest.CallWithLegacySdp
PeerConnectionInterfaceTest.DataChannelCloseWhenPeerConnectionClose PeerConnectionInterfaceTest.DataChannelCloseWhenPeerConnectionClose
PeerConnectionInterfaceTest.TestDataChannel PeerConnectionInterfaceTest.TestDataChannel
PeerConnectionInterfaceTest.TestSendBinaryOnRtpDataChannel PeerConnectionInterfaceTest.TestSendBinaryOnRtpDataChannel

View File

@@ -21,6 +21,8 @@ JsepPeerConnectionP2PTestClient.LocalP2PTestWithVideoDecoderFactory
JsepPeerConnectionP2PTestClient.RegisterDataChannelObserver JsepPeerConnectionP2PTestClient.RegisterDataChannelObserver
JsepPeerConnectionP2PTestClient.UpdateOfferWithRejectedContent JsepPeerConnectionP2PTestClient.UpdateOfferWithRejectedContent
PeerConnectionInterfaceTest.DataChannelCloseWhenPeerConnectionClose PeerConnectionInterfaceTest.DataChannelCloseWhenPeerConnectionClose
PeerConnectionEndToEndTest.Call
PeerConnectionEndToEndTest.CallWithLegacySdp
PeerConnectionInterfaceTest.ReceiveFireFoxOffer PeerConnectionInterfaceTest.ReceiveFireFoxOffer
PeerConnectionInterfaceTest.TestDataChannel PeerConnectionInterfaceTest.TestDataChannel
PeerConnectionInterfaceTest.TestSendBinaryOnRtpDataChannel PeerConnectionInterfaceTest.TestSendBinaryOnRtpDataChannel