blob: 674d54fa5397619ad8c98653ad44c6c9d8b4d724 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
kjellanderb24317b2016-02-10 07:54:43 -08002 * Copyright 2012 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
kjellanderb24317b2016-02-10 07:54:43 -08004 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00009 */
10
jbauch555604a2016-04-26 03:13:22 -070011#include <memory>
kwiberg0eb15ed2015-12-17 03:04:15 -080012#include <utility>
deadbeefcbecd352015-09-23 11:50:27 -070013#include <vector>
14
Henrik Kjellander15583c12016-02-10 10:53:12 +010015#include "webrtc/api/audiotrack.h"
16#include "webrtc/api/fakemediacontroller.h"
17#include "webrtc/api/fakemetricsobserver.h"
18#include "webrtc/api/jsepicecandidate.h"
19#include "webrtc/api/jsepsessiondescription.h"
20#include "webrtc/api/peerconnection.h"
21#include "webrtc/api/sctputils.h"
Henrik Boströmd79599d2016-06-01 13:58:50 +020022#include "webrtc/api/test/fakertccertificategenerator.h"
Henrik Kjellander15583c12016-02-10 10:53:12 +010023#include "webrtc/api/videotrack.h"
24#include "webrtc/api/webrtcsession.h"
25#include "webrtc/api/webrtcsessiondescriptionfactory.h"
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000026#include "webrtc/base/fakenetwork.h"
27#include "webrtc/base/firewallsocketserver.h"
28#include "webrtc/base/gunit.h"
29#include "webrtc/base/logging.h"
30#include "webrtc/base/network.h"
31#include "webrtc/base/physicalsocketserver.h"
32#include "webrtc/base/ssladapter.h"
Henrik Boström5e56c592015-08-11 10:33:13 +020033#include "webrtc/base/sslidentity.h"
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000034#include "webrtc/base/sslstreamadapter.h"
35#include "webrtc/base/stringutils.h"
36#include "webrtc/base/thread.h"
37#include "webrtc/base/virtualsocketserver.h"
kjellandera96e2d72016-02-04 23:52:28 -080038#include "webrtc/media/base/fakemediaengine.h"
39#include "webrtc/media/base/fakevideorenderer.h"
40#include "webrtc/media/base/mediachannel.h"
kjellander@webrtc.org5ad12972016-02-12 06:39:40 +010041#include "webrtc/media/engine/fakewebrtccall.h"
kjellandera96e2d72016-02-04 23:52:28 -080042#include "webrtc/p2p/base/stunserver.h"
43#include "webrtc/p2p/base/teststunserver.h"
44#include "webrtc/p2p/base/testturnserver.h"
45#include "webrtc/p2p/base/transportchannel.h"
46#include "webrtc/p2p/client/basicportallocator.h"
kjellander@webrtc.org9b8df252016-02-12 06:47:59 +010047#include "webrtc/pc/channelmanager.h"
48#include "webrtc/pc/mediasession.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000049
50#define MAYBE_SKIP_TEST(feature) \
51 if (!(feature())) { \
52 LOG(LS_INFO) << "Feature disabled... skipping"; \
53 return; \
54 }
55
henrike@webrtc.org28e20752013-07-10 00:45:36 +000056using cricket::FakeVoiceMediaChannel;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000057using cricket::TransportInfo;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000058using rtc::SocketAddress;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000059using rtc::Thread;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000060using webrtc::CreateSessionDescription;
wu@webrtc.org91053e72013-08-10 07:18:04 +000061using webrtc::CreateSessionDescriptionObserver;
62using webrtc::CreateSessionDescriptionRequest;
deadbeefab9b2d12015-10-14 11:33:11 -070063using webrtc::DataChannel;
Henrik Boström5e56c592015-08-11 10:33:13 +020064using webrtc::DtlsIdentityStoreInterface;
jbauchac8869e2015-07-03 01:36:14 -070065using webrtc::FakeMetricsObserver;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000066using webrtc::IceCandidateCollection;
deadbeefab9b2d12015-10-14 11:33:11 -070067using webrtc::InternalDataChannelInit;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000068using webrtc::JsepIceCandidate;
69using webrtc::JsepSessionDescription;
wu@webrtc.org97077a32013-10-25 21:18:33 +000070using webrtc::PeerConnectionFactoryInterface;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000071using webrtc::PeerConnectionInterface;
72using webrtc::SessionDescriptionInterface;
deadbeefd59daf82015-10-14 15:02:44 -070073using webrtc::SessionStats;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000074using webrtc::StreamCollection;
wu@webrtc.org91053e72013-08-10 07:18:04 +000075using webrtc::WebRtcSession;
wu@webrtc.org364f2042013-11-20 21:49:41 +000076using webrtc::kBundleWithoutRtcpMux;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +000077using webrtc::kCreateChannelFailed;
78using webrtc::kInvalidSdp;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000079using webrtc::kMlineMismatch;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +000080using webrtc::kPushDownTDFailed;
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +000081using webrtc::kSdpWithoutIceUfragPwd;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +000082using webrtc::kSdpWithoutDtlsFingerprint;
83using webrtc::kSdpWithoutSdesCrypto;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000084using webrtc::kSessionError;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +000085using webrtc::kSessionErrorDesc;
buildbot@webrtc.org53df88c2014-08-07 22:46:01 +000086using webrtc::kMaxUnsignalledRecvStreams;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000087
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +000088typedef PeerConnectionInterface::RTCOfferAnswerOptions RTCOfferAnswerOptions;
89
wu@webrtc.org364f2042013-11-20 21:49:41 +000090static const int kClientAddrPort = 0;
91static const char kClientAddrHost1[] = "11.11.11.11";
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +000092static const char kClientIPv6AddrHost1[] =
93 "2620:0:aaaa:bbbb:cccc:dddd:eeee:ffff";
wu@webrtc.org364f2042013-11-20 21:49:41 +000094static const char kClientAddrHost2[] = "22.22.22.22";
95static const char kStunAddrHost[] = "99.99.99.1";
buildbot@webrtc.org41451d42014-05-03 05:39:45 +000096static const SocketAddress kTurnUdpIntAddr("99.99.99.4", 3478);
97static const SocketAddress kTurnUdpExtAddr("99.99.99.6", 0);
mallinath@webrtc.org3d81b1b2014-09-09 14:38:10 +000098static const char kTurnUsername[] = "test";
99static const char kTurnPassword[] = "test";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000100
101static const char kSessionVersion[] = "1";
102
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000103// Media index of candidates belonging to the first media content.
104static const int kMediaContentIndex0 = 0;
105static const char kMediaContentName0[] = "audio";
106
107// Media index of candidates belonging to the second media content.
108static const int kMediaContentIndex1 = 1;
109static const char kMediaContentName1[] = "video";
110
111static const int kIceCandidatesTimeout = 10000;
deadbeeff5f03e82016-06-06 11:16:06 -0700112// STUN timeout with all retransmissions is a total of 9500ms.
113static const int kStunTimeout = 9500;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000114
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +0000115static const char kFakeDtlsFingerprint[] =
116 "BB:CD:72:F7:2F:D0:BA:43:F3:68:B1:0C:23:72:B6:4A:"
117 "0F:DE:34:06:BC:E0:FE:01:BC:73:C8:6D:F4:65:D5:24";
118
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +0000119static const char kTooLongIceUfragPwd[] =
120 "IceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfrag"
121 "IceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfrag"
122 "IceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfrag"
123 "IceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfrag";
124
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +0000125static const char kSdpWithRtx[] =
126 "v=0\r\n"
127 "o=- 4104004319237231850 2 IN IP4 127.0.0.1\r\n"
128 "s=-\r\n"
129 "t=0 0\r\n"
130 "a=msid-semantic: WMS stream1\r\n"
131 "m=video 9 RTP/SAVPF 0 96\r\n"
132 "c=IN IP4 0.0.0.0\r\n"
133 "a=rtcp:9 IN IP4 0.0.0.0\r\n"
134 "a=ice-ufrag:CerjGp19G7wpXwl7\r\n"
135 "a=ice-pwd:cMvOlFvQ6ochez1ZOoC2uBEC\r\n"
136 "a=mid:video\r\n"
137 "a=sendrecv\r\n"
138 "a=rtcp-mux\r\n"
139 "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
140 "inline:5/4N5CDvMiyDArHtBByUM71VIkguH17ZNoX60GrA\r\n"
141 "a=rtpmap:0 fake_video_codec/90000\r\n"
142 "a=rtpmap:96 rtx/90000\r\n"
143 "a=fmtp:96 apt=0\r\n";
144
deadbeefab9b2d12015-10-14 11:33:11 -0700145static const char kStream1[] = "stream1";
146static const char kVideoTrack1[] = "video1";
147static const char kAudioTrack1[] = "audio1";
148
149static const char kStream2[] = "stream2";
150static const char kVideoTrack2[] = "video2";
151static const char kAudioTrack2[] = "audio2";
152
Henrik Boström87713d02015-08-25 09:53:21 +0200153enum RTCCertificateGenerationMethod { ALREADY_GENERATED, DTLS_IDENTITY_STORE };
154
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000155class MockIceObserver : public webrtc::IceObserver {
156 public:
157 MockIceObserver()
158 : oncandidatesready_(false),
159 ice_connection_state_(PeerConnectionInterface::kIceConnectionNew),
160 ice_gathering_state_(PeerConnectionInterface::kIceGatheringNew) {
161 }
162
Henrik Kjellander3fe372d2016-05-12 08:10:52 +0200163 virtual ~MockIceObserver() = default;
164
perkjdfb769d2016-02-09 03:09:43 -0800165 void OnIceConnectionChange(
166 PeerConnectionInterface::IceConnectionState new_state) override {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000167 ice_connection_state_ = new_state;
skvlad6c87a672016-05-17 17:49:52 -0700168 ice_connection_state_history_.push_back(new_state);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000169 }
perkjdfb769d2016-02-09 03:09:43 -0800170 void OnIceGatheringChange(
171 PeerConnectionInterface::IceGatheringState new_state) override {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000172 // We can never transition back to "new".
173 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, new_state);
174 ice_gathering_state_ = new_state;
perkjdfb769d2016-02-09 03:09:43 -0800175 oncandidatesready_ =
176 new_state == PeerConnectionInterface::kIceGatheringComplete;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000177 }
178
179 // Found a new candidate.
perkjdfb769d2016-02-09 03:09:43 -0800180 void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) override {
wu@webrtc.org364f2042013-11-20 21:49:41 +0000181 switch (candidate->sdp_mline_index()) {
182 case kMediaContentIndex0:
183 mline_0_candidates_.push_back(candidate->candidate());
184 break;
185 case kMediaContentIndex1:
186 mline_1_candidates_.push_back(candidate->candidate());
187 break;
188 default:
189 ASSERT(false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000190 }
wu@webrtc.org364f2042013-11-20 21:49:41 +0000191
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000192 // The ICE gathering state should always be Gathering when a candidate is
193 // received (or possibly Completed in the case of the final candidate).
194 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, ice_gathering_state_);
195 }
196
Honghai Zhang7fb69db2016-03-14 11:59:18 -0700197 // Some local candidates are removed.
198 void OnIceCandidatesRemoved(
nisseef8b61e2016-04-29 06:09:15 -0700199 const std::vector<cricket::Candidate>& candidates) override {
Honghai Zhang7fb69db2016-03-14 11:59:18 -0700200 num_candidates_removed_ += candidates.size();
201 }
202
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000203 bool oncandidatesready_;
204 std::vector<cricket::Candidate> mline_0_candidates_;
205 std::vector<cricket::Candidate> mline_1_candidates_;
206 PeerConnectionInterface::IceConnectionState ice_connection_state_;
207 PeerConnectionInterface::IceGatheringState ice_gathering_state_;
skvlad6c87a672016-05-17 17:49:52 -0700208 std::vector<PeerConnectionInterface::IceConnectionState>
209 ice_connection_state_history_;
Honghai Zhang7fb69db2016-03-14 11:59:18 -0700210 size_t num_candidates_removed_ = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000211};
212
213class WebRtcSessionForTest : public webrtc::WebRtcSession {
214 public:
stefanc1aeaf02015-10-15 07:26:07 -0700215 WebRtcSessionForTest(webrtc::MediaControllerInterface* media_controller,
danilchape9021a32016-05-17 01:52:02 -0700216 rtc::Thread* network_thread,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000217 rtc::Thread* worker_thread,
danilchape9021a32016-05-17 01:52:02 -0700218 rtc::Thread* signaling_thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000219 cricket::PortAllocator* port_allocator,
deadbeefab9b2d12015-10-14 11:33:11 -0700220 webrtc::IceObserver* ice_observer)
stefanc1aeaf02015-10-15 07:26:07 -0700221 : WebRtcSession(media_controller,
danilchape9021a32016-05-17 01:52:02 -0700222 network_thread,
stefanc1aeaf02015-10-15 07:26:07 -0700223 worker_thread,
danilchape9021a32016-05-17 01:52:02 -0700224 signaling_thread,
stefanc1aeaf02015-10-15 07:26:07 -0700225 port_allocator) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000226 RegisterIceObserver(ice_observer);
227 }
228 virtual ~WebRtcSessionForTest() {}
229
deadbeefcbecd352015-09-23 11:50:27 -0700230 // Note that these methods are only safe to use if the signaling thread
231 // is the same as the worker thread
232 cricket::TransportChannel* voice_rtp_transport_channel() {
233 return rtp_transport_channel(voice_channel());
234 }
235
236 cricket::TransportChannel* voice_rtcp_transport_channel() {
237 return rtcp_transport_channel(voice_channel());
238 }
239
240 cricket::TransportChannel* video_rtp_transport_channel() {
241 return rtp_transport_channel(video_channel());
242 }
243
244 cricket::TransportChannel* video_rtcp_transport_channel() {
245 return rtcp_transport_channel(video_channel());
246 }
247
248 cricket::TransportChannel* data_rtp_transport_channel() {
249 return rtp_transport_channel(data_channel());
250 }
251
252 cricket::TransportChannel* data_rtcp_transport_channel() {
253 return rtcp_transport_channel(data_channel());
254 }
255
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000256 using webrtc::WebRtcSession::SetAudioPlayout;
257 using webrtc::WebRtcSession::SetAudioSend;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000258 using webrtc::WebRtcSession::SetVideoPlayout;
259 using webrtc::WebRtcSession::SetVideoSend;
deadbeefcbecd352015-09-23 11:50:27 -0700260
261 private:
262 cricket::TransportChannel* rtp_transport_channel(cricket::BaseChannel* ch) {
263 if (!ch) {
264 return nullptr;
265 }
266 return ch->transport_channel();
267 }
268
269 cricket::TransportChannel* rtcp_transport_channel(cricket::BaseChannel* ch) {
270 if (!ch) {
271 return nullptr;
272 }
273 return ch->rtcp_transport_channel();
274 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000275};
276
wu@webrtc.org91053e72013-08-10 07:18:04 +0000277class WebRtcSessionCreateSDPObserverForTest
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000278 : public rtc::RefCountedObject<CreateSessionDescriptionObserver> {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000279 public:
wu@webrtc.org91053e72013-08-10 07:18:04 +0000280 enum State {
281 kInit,
282 kFailed,
283 kSucceeded,
284 };
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000285 WebRtcSessionCreateSDPObserverForTest() : state_(kInit) {}
wu@webrtc.org91053e72013-08-10 07:18:04 +0000286
287 // CreateSessionDescriptionObserver implementation.
288 virtual void OnSuccess(SessionDescriptionInterface* desc) {
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000289 description_.reset(desc);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000290 state_ = kSucceeded;
291 }
292 virtual void OnFailure(const std::string& error) {
293 state_ = kFailed;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000294 }
295
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000296 SessionDescriptionInterface* description() { return description_.get(); }
297
298 SessionDescriptionInterface* ReleaseDescription() {
299 return description_.release();
300 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000301
wu@webrtc.org91053e72013-08-10 07:18:04 +0000302 State state() const { return state_; }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000303
wu@webrtc.org91053e72013-08-10 07:18:04 +0000304 protected:
305 ~WebRtcSessionCreateSDPObserverForTest() {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000306
307 private:
kwibergd1fe2812016-04-27 06:47:29 -0700308 std::unique_ptr<SessionDescriptionInterface> description_;
wu@webrtc.org91053e72013-08-10 07:18:04 +0000309 State state_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000310};
311
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800312class FakeAudioSource : public cricket::AudioSource {
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000313 public:
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800314 FakeAudioSource() : sink_(NULL) {}
315 virtual ~FakeAudioSource() {
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000316 if (sink_)
317 sink_->OnClose();
318 }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000319
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000320 void SetSink(Sink* sink) override { sink_ = sink; }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000321
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800322 const cricket::AudioSource::Sink* sink() const { return sink_; }
323
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000324 private:
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800325 cricket::AudioSource::Sink* sink_;
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000326};
327
Henrik Boström87713d02015-08-25 09:53:21 +0200328class WebRtcSessionTest
deadbeefab9b2d12015-10-14 11:33:11 -0700329 : public testing::TestWithParam<RTCCertificateGenerationMethod>,
330 public sigslot::has_slots<> {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000331 protected:
332 // TODO Investigate why ChannelManager crashes, if it's created
333 // after stun_server.
334 WebRtcSessionTest()
stefanc1aeaf02015-10-15 07:26:07 -0700335 : media_engine_(new cricket::FakeMediaEngine()),
336 data_engine_(new cricket::FakeDataEngine()),
337 channel_manager_(
338 new cricket::ChannelManager(media_engine_,
339 data_engine_,
stefanc1aeaf02015-10-15 07:26:07 -0700340 rtc::Thread::Current())),
341 fake_call_(webrtc::Call::Config()),
342 media_controller_(
nisse51542be2016-02-12 02:27:06 -0800343 webrtc::MediaControllerInterface::Create(cricket::MediaConfig(),
344 rtc::Thread::Current(),
stefanc1aeaf02015-10-15 07:26:07 -0700345 channel_manager_.get())),
346 tdesc_factory_(new cricket::TransportDescriptionFactory()),
347 desc_factory_(
348 new cricket::MediaSessionDescriptionFactory(channel_manager_.get(),
349 tdesc_factory_.get())),
350 pss_(new rtc::PhysicalSocketServer),
351 vss_(new rtc::VirtualSocketServer(pss_.get())),
352 fss_(new rtc::FirewallSocketServer(vss_.get())),
353 ss_scope_(fss_.get()),
354 stun_socket_addr_(
355 rtc::SocketAddress(kStunAddrHost, cricket::STUN_SERVER_PORT)),
356 stun_server_(cricket::TestStunServer::Create(Thread::Current(),
357 stun_socket_addr_)),
358 turn_server_(Thread::Current(), kTurnUdpIntAddr, kTurnUdpExtAddr),
359 metrics_observer_(new rtc::RefCountedObject<FakeMetricsObserver>()) {
buildbot@webrtc.org51c55082014-07-28 22:26:15 +0000360 cricket::ServerAddresses stun_servers;
361 stun_servers.insert(stun_socket_addr_);
362 allocator_.reset(new cricket::BasicPortAllocator(
363 &network_manager_,
364 stun_servers,
365 SocketAddress(), SocketAddress(), SocketAddress()));
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000366 allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700367 cricket::PORTALLOCATOR_DISABLE_RELAY);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000368 EXPECT_TRUE(channel_manager_->Init());
369 desc_factory_->set_add_legacy_streams(false);
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000370 allocator_->set_step_delay(cricket::kMinimumStepDelay);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000371 }
372
373 void AddInterface(const SocketAddress& addr) {
374 network_manager_.AddInterface(addr);
375 }
Honghai Zhang7fb69db2016-03-14 11:59:18 -0700376 void RemoveInterface(const SocketAddress& addr) {
377 network_manager_.RemoveInterface(addr);
378 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000379
Henrik Boströmd79599d2016-06-01 13:58:50 +0200380 // If |cert_generator| != null or |rtc_configuration| contains |certificates|
381 // then DTLS will be enabled unless explicitly disabled by |rtc_configuration|
382 // options. When DTLS is enabled a certificate will be used if provided,
383 // otherwise one will be generated using the |cert_generator|.
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +0000384 void Init(
Henrik Boströmd79599d2016-06-01 13:58:50 +0200385 std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000386 ASSERT_TRUE(session_.get() == NULL);
387 session_.reset(new WebRtcSessionForTest(
stefanc1aeaf02015-10-15 07:26:07 -0700388 media_controller_.get(), rtc::Thread::Current(), rtc::Thread::Current(),
danilchape9021a32016-05-17 01:52:02 -0700389 rtc::Thread::Current(), allocator_.get(), &observer_));
deadbeefab9b2d12015-10-14 11:33:11 -0700390 session_->SignalDataChannelOpenMessage.connect(
391 this, &WebRtcSessionTest::OnDataChannelOpenMessage);
deadbeef057ecf02016-01-20 14:30:43 -0800392 session_->GetOnDestroyedSignal()->connect(
393 this, &WebRtcSessionTest::OnSessionDestroyed);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000394
395 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
396 observer_.ice_connection_state_);
397 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
398 observer_.ice_gathering_state_);
399
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200400 EXPECT_TRUE(session_->Initialize(options_, std::move(cert_generator),
htaa2a49d92016-03-04 02:51:39 -0800401 configuration_));
jbauchac8869e2015-07-03 01:36:14 -0700402 session_->set_metrics_observer(metrics_observer_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000403 }
404
deadbeefab9b2d12015-10-14 11:33:11 -0700405 void OnDataChannelOpenMessage(const std::string& label,
406 const InternalDataChannelInit& config) {
407 last_data_channel_label_ = label;
408 last_data_channel_config_ = config;
409 }
410
deadbeef057ecf02016-01-20 14:30:43 -0800411 void OnSessionDestroyed() { session_destroyed_ = true; }
412
htaa2a49d92016-03-04 02:51:39 -0800413 void Init() { Init(nullptr); }
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +0000414
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +0000415 void InitWithBundlePolicy(
416 PeerConnectionInterface::BundlePolicy bundle_policy) {
htaa2a49d92016-03-04 02:51:39 -0800417 configuration_.bundle_policy = bundle_policy;
418 Init();
Peter Thatcheraf55ccc2015-05-21 07:48:41 -0700419 }
420
421 void InitWithRtcpMuxPolicy(
422 PeerConnectionInterface::RtcpMuxPolicy rtcp_mux_policy) {
423 PeerConnectionInterface::RTCConfiguration configuration;
htaa2a49d92016-03-04 02:51:39 -0800424 configuration_.rtcp_mux_policy = rtcp_mux_policy;
425 Init();
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +0000426 }
427
Henrik Boström87713d02015-08-25 09:53:21 +0200428 // Successfully init with DTLS; with a certificate generated and supplied or
429 // with a store that generates it for us.
430 void InitWithDtls(RTCCertificateGenerationMethod cert_gen_method) {
Henrik Boströmd79599d2016-06-01 13:58:50 +0200431 std::unique_ptr<FakeRTCCertificateGenerator> cert_generator;
Henrik Boström87713d02015-08-25 09:53:21 +0200432 if (cert_gen_method == ALREADY_GENERATED) {
htaa2a49d92016-03-04 02:51:39 -0800433 configuration_.certificates.push_back(
Henrik Boströmd79599d2016-06-01 13:58:50 +0200434 FakeRTCCertificateGenerator::GenerateCertificate());
Henrik Boström87713d02015-08-25 09:53:21 +0200435 } else if (cert_gen_method == DTLS_IDENTITY_STORE) {
Henrik Boströmd79599d2016-06-01 13:58:50 +0200436 cert_generator.reset(new FakeRTCCertificateGenerator());
437 cert_generator->set_should_fail(false);
Henrik Boström87713d02015-08-25 09:53:21 +0200438 } else {
henrikg91d6ede2015-09-17 00:24:34 -0700439 RTC_CHECK(false);
Henrik Boström87713d02015-08-25 09:53:21 +0200440 }
Henrik Boströmd79599d2016-06-01 13:58:50 +0200441 Init(std::move(cert_generator));
Henrik Boström87713d02015-08-25 09:53:21 +0200442 }
443
444 // Init with DTLS with a store that will fail to generate a certificate.
445 void InitWithDtlsIdentityGenFail() {
Henrik Boströmd79599d2016-06-01 13:58:50 +0200446 std::unique_ptr<FakeRTCCertificateGenerator> cert_generator(
447 new FakeRTCCertificateGenerator());
448 cert_generator->set_should_fail(true);
449 Init(std::move(cert_generator));
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +0000450 }
451
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000452 void InitWithDtmfCodec() {
453 // Add kTelephoneEventCodec for dtmf test.
deadbeef67cf2c12016-04-13 10:07:16 -0700454 const cricket::AudioCodec kTelephoneEventCodec(106, "telephone-event", 8000,
455 0, 1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000456 std::vector<cricket::AudioCodec> codecs;
457 codecs.push_back(kTelephoneEventCodec);
458 media_engine_->SetAudioCodecs(codecs);
ossu075af922016-06-14 03:29:38 -0700459 desc_factory_->set_audio_codecs(codecs, codecs);
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +0000460 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000461 }
462
deadbeefab9b2d12015-10-14 11:33:11 -0700463 void SendAudioVideoStream1() {
464 send_stream_1_ = true;
465 send_stream_2_ = false;
466 send_audio_ = true;
467 send_video_ = true;
468 }
469
470 void SendAudioVideoStream2() {
471 send_stream_1_ = false;
472 send_stream_2_ = true;
473 send_audio_ = true;
474 send_video_ = true;
475 }
476
477 void SendAudioVideoStream1And2() {
478 send_stream_1_ = true;
479 send_stream_2_ = true;
480 send_audio_ = true;
481 send_video_ = true;
482 }
483
484 void SendNothing() {
485 send_stream_1_ = false;
486 send_stream_2_ = false;
487 send_audio_ = false;
488 send_video_ = false;
489 }
490
491 void SendAudioOnlyStream2() {
492 send_stream_1_ = false;
493 send_stream_2_ = true;
494 send_audio_ = true;
495 send_video_ = false;
496 }
497
498 void SendVideoOnlyStream2() {
499 send_stream_1_ = false;
500 send_stream_2_ = true;
501 send_audio_ = false;
502 send_video_ = true;
503 }
504
505 void AddStreamsToOptions(cricket::MediaSessionOptions* session_options) {
506 if (send_stream_1_ && send_audio_) {
507 session_options->AddSendStream(cricket::MEDIA_TYPE_AUDIO, kAudioTrack1,
508 kStream1);
509 }
510 if (send_stream_1_ && send_video_) {
511 session_options->AddSendStream(cricket::MEDIA_TYPE_VIDEO, kVideoTrack1,
512 kStream1);
513 }
514 if (send_stream_2_ && send_audio_) {
515 session_options->AddSendStream(cricket::MEDIA_TYPE_AUDIO, kAudioTrack2,
516 kStream2);
517 }
518 if (send_stream_2_ && send_video_) {
519 session_options->AddSendStream(cricket::MEDIA_TYPE_VIDEO, kVideoTrack2,
520 kStream2);
521 }
522 if (data_channel_ && session_->data_channel_type() == cricket::DCT_RTP) {
523 session_options->AddSendStream(cricket::MEDIA_TYPE_DATA,
524 data_channel_->label(),
525 data_channel_->label());
526 }
527 }
528
529 void GetOptionsForOffer(
530 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
531 cricket::MediaSessionOptions* session_options) {
htaaac2dea2016-03-10 13:35:55 -0800532 ASSERT_TRUE(ExtractMediaSessionOptions(rtc_options, true, session_options));
deadbeefab9b2d12015-10-14 11:33:11 -0700533
deadbeefc80741f2015-10-22 13:14:45 -0700534 AddStreamsToOptions(session_options);
535 if (rtc_options.offer_to_receive_audio ==
536 RTCOfferAnswerOptions::kUndefined) {
537 session_options->recv_audio =
538 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_AUDIO);
539 }
540 if (rtc_options.offer_to_receive_video ==
541 RTCOfferAnswerOptions::kUndefined) {
542 session_options->recv_video =
543 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_VIDEO);
544 }
545 session_options->bundle_enabled =
546 session_options->bundle_enabled &&
547 (session_options->has_audio() || session_options->has_video() ||
548 session_options->has_data());
549
deadbeefab9b2d12015-10-14 11:33:11 -0700550 if (session_->data_channel_type() == cricket::DCT_SCTP && data_channel_) {
551 session_options->data_channel_type = cricket::DCT_SCTP;
552 }
553 }
554
htaa2a49d92016-03-04 02:51:39 -0800555 void GetOptionsForAnswer(cricket::MediaSessionOptions* session_options) {
556 // ParseConstraintsForAnswer is used to set some defaults.
557 ASSERT_TRUE(webrtc::ParseConstraintsForAnswer(nullptr, session_options));
deadbeefab9b2d12015-10-14 11:33:11 -0700558
deadbeefc80741f2015-10-22 13:14:45 -0700559 AddStreamsToOptions(session_options);
560 session_options->bundle_enabled =
561 session_options->bundle_enabled &&
562 (session_options->has_audio() || session_options->has_video() ||
563 session_options->has_data());
564
deadbeefab9b2d12015-10-14 11:33:11 -0700565 if (session_->data_channel_type() == cricket::DCT_SCTP) {
566 session_options->data_channel_type = cricket::DCT_SCTP;
567 }
568 }
569
570 // Creates a local offer and applies it. Starts ICE.
571 // Call SendAudioVideoStreamX() before this function
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000572 // to decide which streams to create.
573 void InitiateCall() {
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000574 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000575 SetLocalDescriptionWithoutError(offer);
576 EXPECT_TRUE_WAIT(PeerConnectionInterface::kIceGatheringNew !=
577 observer_.ice_gathering_state_,
578 kIceCandidatesTimeout);
579 }
580
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000581 SessionDescriptionInterface* CreateOffer() {
582 PeerConnectionInterface::RTCOfferAnswerOptions options;
583 options.offer_to_receive_audio =
584 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
585
586 return CreateOffer(options);
587 }
588
wu@webrtc.org91053e72013-08-10 07:18:04 +0000589 SessionDescriptionInterface* CreateOffer(
htaa2a49d92016-03-04 02:51:39 -0800590 const PeerConnectionInterface::RTCOfferAnswerOptions options) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000591 rtc::scoped_refptr<WebRtcSessionCreateSDPObserverForTest>
wu@webrtc.org91053e72013-08-10 07:18:04 +0000592 observer = new WebRtcSessionCreateSDPObserverForTest();
deadbeefab9b2d12015-10-14 11:33:11 -0700593 cricket::MediaSessionOptions session_options;
594 GetOptionsForOffer(options, &session_options);
595 session_->CreateOffer(observer, options, session_options);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000596 EXPECT_TRUE_WAIT(
597 observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit,
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000598 2000);
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000599 return observer->ReleaseDescription();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000600 }
601
602 SessionDescriptionInterface* CreateAnswer(
htaa2a49d92016-03-04 02:51:39 -0800603 const cricket::MediaSessionOptions& options) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000604 rtc::scoped_refptr<WebRtcSessionCreateSDPObserverForTest> observer
wu@webrtc.org91053e72013-08-10 07:18:04 +0000605 = new WebRtcSessionCreateSDPObserverForTest();
htaa2a49d92016-03-04 02:51:39 -0800606 cricket::MediaSessionOptions session_options = options;
607 GetOptionsForAnswer(&session_options);
608 // Overwrite recv_audio and recv_video with passed-in values.
609 session_options.recv_video = options.recv_video;
610 session_options.recv_audio = options.recv_audio;
611 session_->CreateAnswer(observer, session_options);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000612 EXPECT_TRUE_WAIT(
613 observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit,
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000614 2000);
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000615 return observer->ReleaseDescription();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000616 }
617
htaa2a49d92016-03-04 02:51:39 -0800618 SessionDescriptionInterface* CreateAnswer() {
619 cricket::MediaSessionOptions options;
620 options.recv_video = true;
621 options.recv_audio = true;
622 return CreateAnswer(options);
623 }
624
wu@webrtc.org364f2042013-11-20 21:49:41 +0000625 bool ChannelsExist() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000626 return (session_->voice_channel() != NULL &&
627 session_->video_channel() != NULL);
628 }
629
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000630 void VerifyCryptoParams(const cricket::SessionDescription* sdp) {
631 ASSERT_TRUE(session_.get() != NULL);
632 const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp);
633 ASSERT_TRUE(content != NULL);
634 const cricket::AudioContentDescription* audio_content =
635 static_cast<const cricket::AudioContentDescription*>(
636 content->description);
637 ASSERT_TRUE(audio_content != NULL);
638 ASSERT_EQ(1U, audio_content->cryptos().size());
639 ASSERT_EQ(47U, audio_content->cryptos()[0].key_params.size());
640 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80",
641 audio_content->cryptos()[0].cipher_suite);
642 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
643 audio_content->protocol());
644
645 content = cricket::GetFirstVideoContent(sdp);
646 ASSERT_TRUE(content != NULL);
647 const cricket::VideoContentDescription* video_content =
648 static_cast<const cricket::VideoContentDescription*>(
649 content->description);
650 ASSERT_TRUE(video_content != NULL);
651 ASSERT_EQ(1U, video_content->cryptos().size());
652 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80",
653 video_content->cryptos()[0].cipher_suite);
654 ASSERT_EQ(47U, video_content->cryptos()[0].key_params.size());
655 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
656 video_content->protocol());
657 }
658
659 void VerifyNoCryptoParams(const cricket::SessionDescription* sdp, bool dtls) {
660 const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp);
661 ASSERT_TRUE(content != NULL);
662 const cricket::AudioContentDescription* audio_content =
663 static_cast<const cricket::AudioContentDescription*>(
664 content->description);
665 ASSERT_TRUE(audio_content != NULL);
666 ASSERT_EQ(0U, audio_content->cryptos().size());
667
668 content = cricket::GetFirstVideoContent(sdp);
669 ASSERT_TRUE(content != NULL);
670 const cricket::VideoContentDescription* video_content =
671 static_cast<const cricket::VideoContentDescription*>(
672 content->description);
673 ASSERT_TRUE(video_content != NULL);
674 ASSERT_EQ(0U, video_content->cryptos().size());
675
676 if (dtls) {
deadbeeff3938292015-07-15 12:20:53 -0700677 EXPECT_EQ(std::string(cricket::kMediaProtocolDtlsSavpf),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000678 audio_content->protocol());
deadbeeff3938292015-07-15 12:20:53 -0700679 EXPECT_EQ(std::string(cricket::kMediaProtocolDtlsSavpf),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000680 video_content->protocol());
681 } else {
682 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf),
683 audio_content->protocol());
684 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf),
685 video_content->protocol());
686 }
687 }
688
689 // Set the internal fake description factories to do DTLS-SRTP.
690 void SetFactoryDtlsSrtp() {
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000691 desc_factory_->set_secure(cricket::SEC_DISABLED);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000692 std::string identity_name = "WebRTC" +
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000693 rtc::ToString(rtc::CreateRandomId());
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200694 // Confirmed to work with KT_RSA and KT_ECDSA.
kwiberg0eb15ed2015-12-17 03:04:15 -0800695 tdesc_factory_->set_certificate(
jbauch555604a2016-04-26 03:13:22 -0700696 rtc::RTCCertificate::Create(std::unique_ptr<rtc::SSLIdentity>(
kwiberg0eb15ed2015-12-17 03:04:15 -0800697 rtc::SSLIdentity::Generate(identity_name, rtc::KT_DEFAULT))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000698 tdesc_factory_->set_secure(cricket::SEC_REQUIRED);
699 }
700
701 void VerifyFingerprintStatus(const cricket::SessionDescription* sdp,
702 bool expected) {
703 const TransportInfo* audio = sdp->GetTransportInfoByName("audio");
704 ASSERT_TRUE(audio != NULL);
705 ASSERT_EQ(expected, audio->description.identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000706 const TransportInfo* video = sdp->GetTransportInfoByName("video");
707 ASSERT_TRUE(video != NULL);
708 ASSERT_EQ(expected, video->description.identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000709 }
710
711 void VerifyAnswerFromNonCryptoOffer() {
jiayl@webrtc.org7d4891d2014-09-09 21:43:15 +0000712 // Create an SDP without Crypto.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000713 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000714 options.recv_video = true;
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000715 JsepSessionDescription* offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000716 CreateRemoteOffer(options, cricket::SEC_DISABLED));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000717 ASSERT_TRUE(offer != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000718 VerifyNoCryptoParams(offer->description(), false);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000719 SetRemoteDescriptionOfferExpectError(kSdpWithoutSdesCrypto,
720 offer);
htaa2a49d92016-03-04 02:51:39 -0800721 const webrtc::SessionDescriptionInterface* answer = CreateAnswer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000722 // Answer should be NULL as no crypto params in offer.
723 ASSERT_TRUE(answer == NULL);
724 }
725
726 void VerifyAnswerFromCryptoOffer() {
727 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000728 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000729 options.bundle_enabled = true;
kwibergd1fe2812016-04-27 06:47:29 -0700730 std::unique_ptr<JsepSessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000731 CreateRemoteOffer(options, cricket::SEC_REQUIRED));
732 ASSERT_TRUE(offer.get() != NULL);
733 VerifyCryptoParams(offer->description());
734 SetRemoteDescriptionWithoutError(offer.release());
kwibergd1fe2812016-04-27 06:47:29 -0700735 std::unique_ptr<SessionDescriptionInterface> answer(CreateAnswer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000736 ASSERT_TRUE(answer.get() != NULL);
737 VerifyCryptoParams(answer->description());
738 }
739
deadbeef0ed85b22016-02-23 17:24:52 -0800740 bool IceUfragPwdEqual(const cricket::SessionDescription* desc1,
741 const cricket::SessionDescription* desc2) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000742 if (desc1->contents().size() != desc2->contents().size()) {
deadbeef0ed85b22016-02-23 17:24:52 -0800743 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000744 }
745
746 const cricket::ContentInfos& contents = desc1->contents();
747 cricket::ContentInfos::const_iterator it = contents.begin();
748
749 for (; it != contents.end(); ++it) {
750 const cricket::TransportDescription* transport_desc1 =
751 desc1->GetTransportDescriptionByName(it->name);
752 const cricket::TransportDescription* transport_desc2 =
753 desc2->GetTransportDescriptionByName(it->name);
754 if (!transport_desc1 || !transport_desc2) {
deadbeef0ed85b22016-02-23 17:24:52 -0800755 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000756 }
757 if (transport_desc1->ice_pwd != transport_desc2->ice_pwd ||
758 transport_desc1->ice_ufrag != transport_desc2->ice_ufrag) {
deadbeef0ed85b22016-02-23 17:24:52 -0800759 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000760 }
761 }
deadbeef0ed85b22016-02-23 17:24:52 -0800762 return true;
763 }
764
765 // Compares ufrag/password only for the specified |media_type|.
766 bool IceUfragPwdEqual(const cricket::SessionDescription* desc1,
767 const cricket::SessionDescription* desc2,
768 cricket::MediaType media_type) {
769 if (desc1->contents().size() != desc2->contents().size()) {
770 return false;
771 }
772
773 const cricket::ContentInfo* cinfo =
774 cricket::GetFirstMediaContent(desc1->contents(), media_type);
775 const cricket::TransportDescription* transport_desc1 =
776 desc1->GetTransportDescriptionByName(cinfo->name);
777 const cricket::TransportDescription* transport_desc2 =
778 desc2->GetTransportDescriptionByName(cinfo->name);
779 if (!transport_desc1 || !transport_desc2) {
780 return false;
781 }
782 if (transport_desc1->ice_pwd != transport_desc2->ice_pwd ||
783 transport_desc1->ice_ufrag != transport_desc2->ice_ufrag) {
784 return false;
785 }
786 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000787 }
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000788
789 void RemoveIceUfragPwdLines(const SessionDescriptionInterface* current_desc,
790 std::string *sdp) {
791 const cricket::SessionDescription* desc = current_desc->description();
792 EXPECT_TRUE(current_desc->ToString(sdp));
793
794 const cricket::ContentInfos& contents = desc->contents();
795 cricket::ContentInfos::const_iterator it = contents.begin();
796 // Replace ufrag and pwd lines with empty strings.
797 for (; it != contents.end(); ++it) {
798 const cricket::TransportDescription* transport_desc =
799 desc->GetTransportDescriptionByName(it->name);
800 std::string ufrag_line = "a=ice-ufrag:" + transport_desc->ice_ufrag
801 + "\r\n";
802 std::string pwd_line = "a=ice-pwd:" + transport_desc->ice_pwd
803 + "\r\n";
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000804 rtc::replace_substrs(ufrag_line.c_str(), ufrag_line.length(),
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000805 "", 0,
806 sdp);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000807 rtc::replace_substrs(pwd_line.c_str(), pwd_line.length(),
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000808 "", 0,
809 sdp);
810 }
811 }
812
deadbeef0ed85b22016-02-23 17:24:52 -0800813 void SetIceUfragPwd(SessionDescriptionInterface* current_desc,
814 const std::string& ufrag,
815 const std::string& pwd) {
816 cricket::SessionDescription* desc = current_desc->description();
817 for (TransportInfo& transport_info : desc->transport_infos()) {
818 cricket::TransportDescription& transport_desc =
819 transport_info.description;
820 transport_desc.ice_ufrag = ufrag;
821 transport_desc.ice_pwd = pwd;
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +0000822 }
823 }
824
deadbeef0ed85b22016-02-23 17:24:52 -0800825 // Sets ufrag/pwd for specified |media_type|.
826 void SetIceUfragPwd(SessionDescriptionInterface* current_desc,
827 cricket::MediaType media_type,
828 const std::string& ufrag,
829 const std::string& pwd) {
830 cricket::SessionDescription* desc = current_desc->description();
831 const cricket::ContentInfo* cinfo =
832 cricket::GetFirstMediaContent(desc->contents(), media_type);
833 TransportInfo* transport_info = desc->GetTransportInfoByName(cinfo->name);
834 cricket::TransportDescription* transport_desc =
835 &transport_info->description;
836 transport_desc->ice_ufrag = ufrag;
837 transport_desc->ice_pwd = pwd;
838 }
839
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000840 // Creates a remote offer and and applies it as a remote description,
841 // creates a local answer and applies is as a local description.
deadbeefab9b2d12015-10-14 11:33:11 -0700842 // Call SendAudioVideoStreamX() before this function
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000843 // to decide which local and remote streams to create.
844 void CreateAndSetRemoteOfferAndLocalAnswer() {
845 SessionDescriptionInterface* offer = CreateRemoteOffer();
846 SetRemoteDescriptionWithoutError(offer);
htaa2a49d92016-03-04 02:51:39 -0800847 SessionDescriptionInterface* answer = CreateAnswer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000848 SetLocalDescriptionWithoutError(answer);
849 }
850 void SetLocalDescriptionWithoutError(SessionDescriptionInterface* desc) {
851 EXPECT_TRUE(session_->SetLocalDescription(desc, NULL));
deadbeefcbecd352015-09-23 11:50:27 -0700852 session_->MaybeStartGathering();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000853 }
854 void SetLocalDescriptionExpectState(SessionDescriptionInterface* desc,
deadbeefd59daf82015-10-14 15:02:44 -0700855 WebRtcSession::State expected_state) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000856 SetLocalDescriptionWithoutError(desc);
857 EXPECT_EQ(expected_state, session_->state());
858 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000859 void SetLocalDescriptionExpectError(const std::string& action,
860 const std::string& expected_error,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000861 SessionDescriptionInterface* desc) {
862 std::string error;
863 EXPECT_FALSE(session_->SetLocalDescription(desc, &error));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000864 std::string sdp_type = "local ";
865 sdp_type.append(action);
866 EXPECT_NE(std::string::npos, error.find(sdp_type));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000867 EXPECT_NE(std::string::npos, error.find(expected_error));
868 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000869 void SetLocalDescriptionOfferExpectError(const std::string& expected_error,
870 SessionDescriptionInterface* desc) {
871 SetLocalDescriptionExpectError(SessionDescriptionInterface::kOffer,
872 expected_error, desc);
873 }
874 void SetLocalDescriptionAnswerExpectError(const std::string& expected_error,
875 SessionDescriptionInterface* desc) {
876 SetLocalDescriptionExpectError(SessionDescriptionInterface::kAnswer,
877 expected_error, desc);
878 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000879 void SetRemoteDescriptionWithoutError(SessionDescriptionInterface* desc) {
880 EXPECT_TRUE(session_->SetRemoteDescription(desc, NULL));
881 }
882 void SetRemoteDescriptionExpectState(SessionDescriptionInterface* desc,
deadbeefd59daf82015-10-14 15:02:44 -0700883 WebRtcSession::State expected_state) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000884 SetRemoteDescriptionWithoutError(desc);
885 EXPECT_EQ(expected_state, session_->state());
886 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000887 void SetRemoteDescriptionExpectError(const std::string& action,
888 const std::string& expected_error,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000889 SessionDescriptionInterface* desc) {
890 std::string error;
891 EXPECT_FALSE(session_->SetRemoteDescription(desc, &error));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000892 std::string sdp_type = "remote ";
893 sdp_type.append(action);
894 EXPECT_NE(std::string::npos, error.find(sdp_type));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000895 EXPECT_NE(std::string::npos, error.find(expected_error));
896 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000897 void SetRemoteDescriptionOfferExpectError(
898 const std::string& expected_error, SessionDescriptionInterface* desc) {
899 SetRemoteDescriptionExpectError(SessionDescriptionInterface::kOffer,
900 expected_error, desc);
901 }
902 void SetRemoteDescriptionPranswerExpectError(
903 const std::string& expected_error, SessionDescriptionInterface* desc) {
904 SetRemoteDescriptionExpectError(SessionDescriptionInterface::kPrAnswer,
905 expected_error, desc);
906 }
907 void SetRemoteDescriptionAnswerExpectError(
908 const std::string& expected_error, SessionDescriptionInterface* desc) {
909 SetRemoteDescriptionExpectError(SessionDescriptionInterface::kAnswer,
910 expected_error, desc);
911 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000912
913 void CreateCryptoOfferAndNonCryptoAnswer(SessionDescriptionInterface** offer,
914 SessionDescriptionInterface** nocrypto_answer) {
915 // Create a SDP without Crypto.
916 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000917 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000918 options.bundle_enabled = true;
919 *offer = CreateRemoteOffer(options, cricket::SEC_ENABLED);
920 ASSERT_TRUE(*offer != NULL);
921 VerifyCryptoParams((*offer)->description());
922
923 *nocrypto_answer = CreateRemoteAnswer(*offer, options,
924 cricket::SEC_DISABLED);
925 EXPECT_TRUE(*nocrypto_answer != NULL);
926 }
927
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000928 void CreateDtlsOfferAndNonDtlsAnswer(SessionDescriptionInterface** offer,
929 SessionDescriptionInterface** nodtls_answer) {
930 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000931 options.recv_video = true;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000932 options.bundle_enabled = true;
933
kwibergd1fe2812016-04-27 06:47:29 -0700934 std::unique_ptr<SessionDescriptionInterface> temp_offer(
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000935 CreateRemoteOffer(options, cricket::SEC_ENABLED));
936
937 *nodtls_answer =
938 CreateRemoteAnswer(temp_offer.get(), options, cricket::SEC_ENABLED);
939 EXPECT_TRUE(*nodtls_answer != NULL);
940 VerifyFingerprintStatus((*nodtls_answer)->description(), false);
941 VerifyCryptoParams((*nodtls_answer)->description());
942
943 SetFactoryDtlsSrtp();
944 *offer = CreateRemoteOffer(options, cricket::SEC_ENABLED);
945 ASSERT_TRUE(*offer != NULL);
946 VerifyFingerprintStatus((*offer)->description(), true);
947 VerifyCryptoParams((*offer)->description());
948 }
949
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000950 JsepSessionDescription* CreateRemoteOfferWithVersion(
951 cricket::MediaSessionOptions options,
952 cricket::SecurePolicy secure_policy,
953 const std::string& session_version,
954 const SessionDescriptionInterface* current_desc) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000955 std::string session_id = rtc::ToString(rtc::CreateRandomId64());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000956 const cricket::SessionDescription* cricket_desc = NULL;
957 if (current_desc) {
958 cricket_desc = current_desc->description();
959 session_id = current_desc->session_id();
960 }
961
962 desc_factory_->set_secure(secure_policy);
963 JsepSessionDescription* offer(
964 new JsepSessionDescription(JsepSessionDescription::kOffer));
965 if (!offer->Initialize(desc_factory_->CreateOffer(options, cricket_desc),
966 session_id, session_version)) {
967 delete offer;
968 offer = NULL;
969 }
970 return offer;
971 }
972 JsepSessionDescription* CreateRemoteOffer(
973 cricket::MediaSessionOptions options) {
974 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED,
975 kSessionVersion, NULL);
976 }
977 JsepSessionDescription* CreateRemoteOffer(
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000978 cricket::MediaSessionOptions options, cricket::SecurePolicy sdes_policy) {
979 return CreateRemoteOfferWithVersion(
980 options, sdes_policy, kSessionVersion, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000981 }
982 JsepSessionDescription* CreateRemoteOffer(
983 cricket::MediaSessionOptions options,
984 const SessionDescriptionInterface* current_desc) {
985 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED,
986 kSessionVersion, current_desc);
987 }
988
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000989 JsepSessionDescription* CreateRemoteOfferWithSctpPort(
990 const char* sctp_stream_name, int new_port,
991 cricket::MediaSessionOptions options) {
992 options.data_channel_type = cricket::DCT_SCTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000993 options.AddSendStream(cricket::MEDIA_TYPE_DATA, "datachannel",
994 sctp_stream_name);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000995 return ChangeSDPSctpPort(new_port, CreateRemoteOffer(options));
996 }
997
998 // Takes ownership of offer_basis (and deletes it).
999 JsepSessionDescription* ChangeSDPSctpPort(
1000 int new_port, webrtc::SessionDescriptionInterface *offer_basis) {
1001 // Stringify the input SDP, swap the 5000 for 'new_port' and create a new
1002 // SessionDescription from the mutated string.
1003 const char* default_port_str = "5000";
1004 char new_port_str[16];
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001005 rtc::sprintfn(new_port_str, sizeof(new_port_str), "%d", new_port);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001006 std::string offer_str;
1007 offer_basis->ToString(&offer_str);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001008 rtc::replace_substrs(default_port_str, strlen(default_port_str),
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001009 new_port_str, strlen(new_port_str),
1010 &offer_str);
1011 JsepSessionDescription* offer = new JsepSessionDescription(
1012 offer_basis->type());
1013 delete offer_basis;
1014 offer->Initialize(offer_str, NULL);
1015 return offer;
1016 }
1017
deadbeefab9b2d12015-10-14 11:33:11 -07001018 // Create a remote offer. Call SendAudioVideoStreamX()
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001019 // before this function to decide which streams to create.
1020 JsepSessionDescription* CreateRemoteOffer() {
1021 cricket::MediaSessionOptions options;
htaa2a49d92016-03-04 02:51:39 -08001022 GetOptionsForAnswer(&options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001023 return CreateRemoteOffer(options, session_->remote_description());
1024 }
1025
1026 JsepSessionDescription* CreateRemoteAnswer(
1027 const SessionDescriptionInterface* offer,
1028 cricket::MediaSessionOptions options,
1029 cricket::SecurePolicy policy) {
1030 desc_factory_->set_secure(policy);
1031 const std::string session_id =
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001032 rtc::ToString(rtc::CreateRandomId64());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001033 JsepSessionDescription* answer(
1034 new JsepSessionDescription(JsepSessionDescription::kAnswer));
1035 if (!answer->Initialize(desc_factory_->CreateAnswer(offer->description(),
1036 options, NULL),
1037 session_id, kSessionVersion)) {
1038 delete answer;
1039 answer = NULL;
1040 }
1041 return answer;
1042 }
1043
1044 JsepSessionDescription* CreateRemoteAnswer(
1045 const SessionDescriptionInterface* offer,
1046 cricket::MediaSessionOptions options) {
1047 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED);
1048 }
1049
deadbeefab9b2d12015-10-14 11:33:11 -07001050 // Creates an answer session description.
1051 // Call SendAudioVideoStreamX() before this function
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001052 // to decide which streams to create.
1053 JsepSessionDescription* CreateRemoteAnswer(
1054 const SessionDescriptionInterface* offer) {
1055 cricket::MediaSessionOptions options;
htaa2a49d92016-03-04 02:51:39 -08001056 GetOptionsForAnswer(&options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001057 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED);
1058 }
1059
1060 void TestSessionCandidatesWithBundleRtcpMux(bool bundle, bool rtcp_mux) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001061 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001062 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001063 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001064
1065 PeerConnectionInterface::RTCOfferAnswerOptions options;
1066 options.use_rtp_mux = bundle;
1067
1068 SessionDescriptionInterface* offer = CreateOffer(options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001069 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
1070 // and answer.
1071 SetLocalDescriptionWithoutError(offer);
1072
kwibergd1fe2812016-04-27 06:47:29 -07001073 std::unique_ptr<SessionDescriptionInterface> answer(
henrike@webrtc.org723d6832013-07-12 16:04:50 +00001074 CreateRemoteAnswer(session_->local_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001075 std::string sdp;
1076 EXPECT_TRUE(answer->ToString(&sdp));
1077
1078 size_t expected_candidate_num = 2;
1079 if (!rtcp_mux) {
1080 // If rtcp_mux is enabled we should expect 4 candidates - host and srflex
1081 // for rtp and rtcp.
1082 expected_candidate_num = 4;
1083 // Disable rtcp-mux from the answer
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001084 const std::string kRtcpMux = "a=rtcp-mux";
1085 const std::string kXRtcpMux = "a=xrtcp-mux";
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001086 rtc::replace_substrs(kRtcpMux.c_str(), kRtcpMux.length(),
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001087 kXRtcpMux.c_str(), kXRtcpMux.length(),
1088 &sdp);
1089 }
1090
1091 SessionDescriptionInterface* new_answer = CreateSessionDescription(
1092 JsepSessionDescription::kAnswer, sdp, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001093
1094 // SetRemoteDescription to enable rtcp mux.
henrike@webrtc.org723d6832013-07-12 16:04:50 +00001095 SetRemoteDescriptionWithoutError(new_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001096 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1097 EXPECT_EQ(expected_candidate_num, observer_.mline_0_candidates_.size());
deadbeefcbecd352015-09-23 11:50:27 -07001098 if (bundle) {
1099 EXPECT_EQ(0, observer_.mline_1_candidates_.size());
1100 } else {
1101 EXPECT_EQ(expected_candidate_num, observer_.mline_1_candidates_.size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001102 }
1103 }
1104 // Tests that we can only send DTMF when the dtmf codec is supported.
1105 void TestCanInsertDtmf(bool can) {
1106 if (can) {
1107 InitWithDtmfCodec();
1108 } else {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001109 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001110 }
deadbeefab9b2d12015-10-14 11:33:11 -07001111 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001112 CreateAndSetRemoteOfferAndLocalAnswer();
1113 EXPECT_FALSE(session_->CanInsertDtmf(""));
1114 EXPECT_EQ(can, session_->CanInsertDtmf(kAudioTrack1));
1115 }
1116
zhihuang3a334652016-05-05 18:37:49 -07001117 bool ContainsVideoCodecWithName(const SessionDescriptionInterface* desc,
1118 const std::string& codec_name) {
1119 for (const auto& content : desc->description()->contents()) {
1120 if (static_cast<cricket::MediaContentDescription*>(content.description)
1121 ->type() == cricket::MEDIA_TYPE_VIDEO) {
1122 const auto* mdesc =
1123 static_cast<cricket::VideoContentDescription*>(content.description);
1124 for (const auto& codec : mdesc->codecs()) {
1125 if (codec.name == codec_name) {
1126 return true;
1127 }
1128 }
1129 }
1130 }
1131 return false;
1132 }
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001133 // Helper class to configure loopback network and verify Best
1134 // Connection using right IP protocol for TestLoopbackCall
1135 // method. LoopbackNetworkManager applies firewall rules to block
1136 // all ping traffic once ICE completed, and remove them to observe
1137 // ICE reconnected again. This LoopbackNetworkConfiguration struct
1138 // verifies the best connection is using the right IP protocol after
1139 // initial ICE convergences.
1140
1141 class LoopbackNetworkConfiguration {
deadbeefcbecd352015-09-23 11:50:27 -07001142 public:
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001143 LoopbackNetworkConfiguration()
1144 : test_ipv6_network_(false),
1145 test_extra_ipv4_network_(false),
1146 best_connection_after_initial_ice_converged_(1, 0) {}
1147
1148 // Used to track the expected best connection count in each IP protocol.
1149 struct ExpectedBestConnection {
1150 ExpectedBestConnection(int ipv4_count, int ipv6_count)
1151 : ipv4_count_(ipv4_count),
1152 ipv6_count_(ipv6_count) {}
1153
1154 int ipv4_count_;
1155 int ipv6_count_;
1156 };
1157
1158 bool test_ipv6_network_;
1159 bool test_extra_ipv4_network_;
1160 ExpectedBestConnection best_connection_after_initial_ice_converged_;
1161
1162 void VerifyBestConnectionAfterIceConverge(
jbauchac8869e2015-07-03 01:36:14 -07001163 const rtc::scoped_refptr<FakeMetricsObserver> metrics_observer) const {
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001164 Verify(metrics_observer, best_connection_after_initial_ice_converged_);
1165 }
1166
1167 private:
jbauchac8869e2015-07-03 01:36:14 -07001168 void Verify(const rtc::scoped_refptr<FakeMetricsObserver> metrics_observer,
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001169 const ExpectedBestConnection& expected) const {
1170 EXPECT_EQ(
Guo-wei Shieh3d564c12015-08-19 16:51:15 -07001171 metrics_observer->GetEnumCounter(webrtc::kEnumCounterAddressFamily,
1172 webrtc::kBestConnections_IPv4),
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001173 expected.ipv4_count_);
1174 EXPECT_EQ(
Guo-wei Shieh3d564c12015-08-19 16:51:15 -07001175 metrics_observer->GetEnumCounter(webrtc::kEnumCounterAddressFamily,
1176 webrtc::kBestConnections_IPv6),
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001177 expected.ipv6_count_);
Guo-wei Shieh3d564c12015-08-19 16:51:15 -07001178 // This is used in the loopback call so there is only single host to host
1179 // candidate pair.
1180 EXPECT_EQ(metrics_observer->GetEnumCounter(
1181 webrtc::kEnumCounterIceCandidatePairTypeUdp,
1182 webrtc::kIceCandidatePairHostHost),
Guo-wei Shieh3cc834a2015-09-04 15:52:14 -07001183 0);
1184 EXPECT_EQ(metrics_observer->GetEnumCounter(
1185 webrtc::kEnumCounterIceCandidatePairTypeUdp,
1186 webrtc::kIceCandidatePairHostPublicHostPublic),
Guo-wei Shieh3d564c12015-08-19 16:51:15 -07001187 1);
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001188 }
1189 };
1190
1191 class LoopbackNetworkManager {
1192 public:
1193 LoopbackNetworkManager(WebRtcSessionTest* session,
1194 const LoopbackNetworkConfiguration& config)
1195 : config_(config) {
1196 session->AddInterface(
1197 rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
1198 if (config_.test_extra_ipv4_network_) {
1199 session->AddInterface(
1200 rtc::SocketAddress(kClientAddrHost2, kClientAddrPort));
1201 }
1202 if (config_.test_ipv6_network_) {
1203 session->AddInterface(
1204 rtc::SocketAddress(kClientIPv6AddrHost1, kClientAddrPort));
1205 }
1206 }
1207
1208 void ApplyFirewallRules(rtc::FirewallSocketServer* fss) {
1209 fss->AddRule(false, rtc::FP_ANY, rtc::FD_ANY,
1210 rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
1211 if (config_.test_extra_ipv4_network_) {
1212 fss->AddRule(false, rtc::FP_ANY, rtc::FD_ANY,
1213 rtc::SocketAddress(kClientAddrHost2, kClientAddrPort));
1214 }
1215 if (config_.test_ipv6_network_) {
1216 fss->AddRule(false, rtc::FP_ANY, rtc::FD_ANY,
1217 rtc::SocketAddress(kClientIPv6AddrHost1, kClientAddrPort));
1218 }
1219 }
1220
1221 void ClearRules(rtc::FirewallSocketServer* fss) { fss->ClearRules(); }
1222
1223 private:
1224 LoopbackNetworkConfiguration config_;
1225 };
1226
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001227 // The method sets up a call from the session to itself, in a loopback
1228 // arrangement. It also uses a firewall rule to create a temporary
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00001229 // disconnection, and then a permanent disconnection.
1230 // This code is placed in a method so that it can be invoked
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001231 // by multiple tests with different allocators (e.g. with and without BUNDLE).
1232 // While running the call, this method also checks if the session goes through
1233 // the correct sequence of ICE states when a connection is established,
1234 // broken, and re-established.
1235 // The Connection state should go:
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00001236 // New -> Checking -> (Connected) -> Completed -> Disconnected -> Completed
1237 // -> Failed.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001238 // The Gathering state should go: New -> Gathering -> Completed.
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001239
stefanc1aeaf02015-10-15 07:26:07 -07001240 void SetupLoopbackCall() {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001241 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001242 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001243 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001244
1245 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
1246 observer_.ice_gathering_state_);
1247 SetLocalDescriptionWithoutError(offer);
1248 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
1249 observer_.ice_connection_state_);
1250 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringGathering,
stefanc1aeaf02015-10-15 07:26:07 -07001251 observer_.ice_gathering_state_, kIceCandidatesTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001252 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1253 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringComplete,
stefanc1aeaf02015-10-15 07:26:07 -07001254 observer_.ice_gathering_state_, kIceCandidatesTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001255
1256 std::string sdp;
1257 offer->ToString(&sdp);
stefanc1aeaf02015-10-15 07:26:07 -07001258 SessionDescriptionInterface* desc = webrtc::CreateSessionDescription(
1259 JsepSessionDescription::kAnswer, sdp, nullptr);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001260 ASSERT_TRUE(desc != NULL);
1261 SetRemoteDescriptionWithoutError(desc);
1262
1263 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionChecking,
stefanc1aeaf02015-10-15 07:26:07 -07001264 observer_.ice_connection_state_, kIceCandidatesTimeout);
mallinath@webrtc.orgd3dc4242014-03-01 00:05:52 +00001265
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00001266 // The ice connection state is "Connected" too briefly to catch in a test.
1267 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
stefanc1aeaf02015-10-15 07:26:07 -07001268 observer_.ice_connection_state_, kIceCandidatesTimeout);
1269 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001270
stefanc1aeaf02015-10-15 07:26:07 -07001271 void TestLoopbackCall(const LoopbackNetworkConfiguration& config) {
1272 LoopbackNetworkManager loopback_network_manager(this, config);
1273 SetupLoopbackCall();
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001274 config.VerifyBestConnectionAfterIceConverge(metrics_observer_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001275 // Adding firewall rule to block ping requests, which should cause
1276 // transport channel failure.
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001277
1278 loopback_network_manager.ApplyFirewallRules(fss_.get());
1279
1280 LOG(LS_INFO) << "Firewall Rules applied";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001281 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionDisconnected,
1282 observer_.ice_connection_state_,
1283 kIceCandidatesTimeout);
1284
jbauchac8869e2015-07-03 01:36:14 -07001285 metrics_observer_->Reset();
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001286
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001287 // Clearing the rules, session should move back to completed state.
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001288 loopback_network_manager.ClearRules(fss_.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001289
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001290 LOG(LS_INFO) << "Firewall Rules cleared";
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00001291 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001292 observer_.ice_connection_state_,
1293 kIceCandidatesTimeout);
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00001294
1295 // Now we block ping requests and wait until the ICE connection transitions
1296 // to the Failed state. This will take at least 30 seconds because it must
1297 // wait for the Port to timeout.
1298 int port_timeout = 30000;
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001299
1300 loopback_network_manager.ApplyFirewallRules(fss_.get());
1301 LOG(LS_INFO) << "Firewall Rules applied again";
jlmiller@webrtc.org804eb462015-02-20 02:20:03 +00001302 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionDisconnected,
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00001303 observer_.ice_connection_state_,
1304 kIceCandidatesTimeout + port_timeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001305 }
1306
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001307 void TestLoopbackCall() {
1308 LoopbackNetworkConfiguration config;
1309 TestLoopbackCall(config);
1310 }
1311
stefanc1aeaf02015-10-15 07:26:07 -07001312 void TestPacketOptions() {
1313 media_controller_.reset(
1314 new cricket::FakeMediaController(channel_manager_.get(), &fake_call_));
1315 LoopbackNetworkConfiguration config;
1316 LoopbackNetworkManager loopback_network_manager(this, config);
1317
1318 SetupLoopbackCall();
1319
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001320 // Wait for channel to be ready for sending.
1321 EXPECT_TRUE_WAIT(media_engine_->GetVideoChannel(0)->sending(), 100);
stefanc1aeaf02015-10-15 07:26:07 -07001322 uint8_t test_packet[15] = {0};
1323 rtc::PacketOptions options;
1324 options.packet_id = 10;
1325 media_engine_->GetVideoChannel(0)
1326 ->SendRtp(test_packet, sizeof(test_packet), options);
1327
1328 const int kPacketTimeout = 2000;
1329 EXPECT_EQ_WAIT(fake_call_.last_sent_packet().packet_id, 10, kPacketTimeout);
1330 EXPECT_GT(fake_call_.last_sent_packet().send_time_ms, -1);
1331 }
1332
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001333 // Adds CN codecs to FakeMediaEngine and MediaDescriptionFactory.
1334 void AddCNCodecs() {
deadbeef67cf2c12016-04-13 10:07:16 -07001335 const cricket::AudioCodec kCNCodec1(102, "CN", 8000, 0, 1);
1336 const cricket::AudioCodec kCNCodec2(103, "CN", 16000, 0, 1);
wu@webrtc.org364f2042013-11-20 21:49:41 +00001337
1338 // Add kCNCodec for dtmf test.
ossudedfd282016-06-14 07:12:39 -07001339 std::vector<cricket::AudioCodec> codecs =
1340 media_engine_->audio_send_codecs();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001341 codecs.push_back(kCNCodec1);
1342 codecs.push_back(kCNCodec2);
1343 media_engine_->SetAudioCodecs(codecs);
ossu075af922016-06-14 03:29:38 -07001344 desc_factory_->set_audio_codecs(codecs, codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001345 }
1346
1347 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
1348 const cricket::ContentDescription* description = content->description;
1349 ASSERT(description != NULL);
1350 const cricket::AudioContentDescription* audio_content_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00001351 static_cast<const cricket::AudioContentDescription*>(description);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001352 ASSERT(audio_content_desc != NULL);
1353 for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
1354 if (audio_content_desc->codecs()[i].name == "CN")
1355 return false;
1356 }
1357 return true;
1358 }
1359
deadbeefab9b2d12015-10-14 11:33:11 -07001360 void CreateDataChannel() {
deadbeeffc648b62015-10-13 16:42:33 -07001361 webrtc::InternalDataChannelInit dci;
htaa2a49d92016-03-04 02:51:39 -08001362 ASSERT(session_.get());
deadbeefab9b2d12015-10-14 11:33:11 -07001363 dci.reliable = session_->data_channel_type() == cricket::DCT_SCTP;
1364 data_channel_ = DataChannel::Create(
1365 session_.get(), session_->data_channel_type(), "datachannel", dci);
1366 }
1367
1368 void SetLocalDescriptionWithDataChannel() {
1369 CreateDataChannel();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001370 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001371 SetLocalDescriptionWithoutError(offer);
1372 }
1373
wu@webrtc.org91053e72013-08-10 07:18:04 +00001374 void VerifyMultipleAsyncCreateDescription(
Henrik Boström87713d02015-08-25 09:53:21 +02001375 RTCCertificateGenerationMethod cert_gen_method,
1376 CreateSessionDescriptionRequest::Type type) {
1377 InitWithDtls(cert_gen_method);
1378 VerifyMultipleAsyncCreateDescriptionAfterInit(true, type);
1379 }
1380
1381 void VerifyMultipleAsyncCreateDescriptionIdentityGenFailure(
1382 CreateSessionDescriptionRequest::Type type) {
1383 InitWithDtlsIdentityGenFail();
1384 VerifyMultipleAsyncCreateDescriptionAfterInit(false, type);
1385 }
1386
1387 void VerifyMultipleAsyncCreateDescriptionAfterInit(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001388 bool success, CreateSessionDescriptionRequest::Type type) {
henrikg91d6ede2015-09-17 00:24:34 -07001389 RTC_CHECK(session_);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001390 SetFactoryDtlsSrtp();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001391 if (type == CreateSessionDescriptionRequest::kAnswer) {
1392 cricket::MediaSessionOptions options;
kwibergd1fe2812016-04-27 06:47:29 -07001393 std::unique_ptr<JsepSessionDescription> offer(
1394 CreateRemoteOffer(options, cricket::SEC_DISABLED));
wu@webrtc.org91053e72013-08-10 07:18:04 +00001395 ASSERT_TRUE(offer.get() != NULL);
1396 SetRemoteDescriptionWithoutError(offer.release());
1397 }
1398
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001399 PeerConnectionInterface::RTCOfferAnswerOptions options;
deadbeefab9b2d12015-10-14 11:33:11 -07001400 cricket::MediaSessionOptions session_options;
wu@webrtc.org91053e72013-08-10 07:18:04 +00001401 const int kNumber = 3;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001402 rtc::scoped_refptr<WebRtcSessionCreateSDPObserverForTest>
wu@webrtc.org91053e72013-08-10 07:18:04 +00001403 observers[kNumber];
1404 for (int i = 0; i < kNumber; ++i) {
1405 observers[i] = new WebRtcSessionCreateSDPObserverForTest();
1406 if (type == CreateSessionDescriptionRequest::kOffer) {
deadbeefab9b2d12015-10-14 11:33:11 -07001407 session_->CreateOffer(observers[i], options, session_options);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001408 } else {
htaa2a49d92016-03-04 02:51:39 -08001409 session_->CreateAnswer(observers[i], session_options);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001410 }
1411 }
1412
1413 WebRtcSessionCreateSDPObserverForTest::State expected_state =
1414 success ? WebRtcSessionCreateSDPObserverForTest::kSucceeded :
1415 WebRtcSessionCreateSDPObserverForTest::kFailed;
1416
1417 for (int i = 0; i < kNumber; ++i) {
1418 EXPECT_EQ_WAIT(expected_state, observers[i]->state(), 1000);
1419 if (success) {
1420 EXPECT_TRUE(observers[i]->description() != NULL);
1421 } else {
1422 EXPECT_TRUE(observers[i]->description() == NULL);
1423 }
1424 }
1425 }
1426
mallinath@webrtc.org3d81b1b2014-09-09 14:38:10 +00001427 void ConfigureAllocatorWithTurn() {
deadbeef653b8e02015-11-11 12:55:10 -08001428 cricket::RelayServerConfig turn_server(cricket::RELAY_TURN);
mallinath@webrtc.org3d81b1b2014-09-09 14:38:10 +00001429 cricket::RelayCredentials credentials(kTurnUsername, kTurnPassword);
deadbeef653b8e02015-11-11 12:55:10 -08001430 turn_server.credentials = credentials;
1431 turn_server.ports.push_back(
1432 cricket::ProtocolAddress(kTurnUdpIntAddr, cricket::PROTO_UDP, false));
1433 allocator_->AddTurnServer(turn_server);
mallinath@webrtc.org3d81b1b2014-09-09 14:38:10 +00001434 allocator_->set_step_delay(cricket::kMinimumStepDelay);
Peter Thatcher7cbd1882015-09-17 18:54:52 -07001435 allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP);
mallinath@webrtc.org3d81b1b2014-09-09 14:38:10 +00001436 }
1437
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001438 cricket::FakeMediaEngine* media_engine_;
1439 cricket::FakeDataEngine* data_engine_;
kwibergd1fe2812016-04-27 06:47:29 -07001440 std::unique_ptr<cricket::ChannelManager> channel_manager_;
stefanc1aeaf02015-10-15 07:26:07 -07001441 cricket::FakeCall fake_call_;
kwibergd1fe2812016-04-27 06:47:29 -07001442 std::unique_ptr<webrtc::MediaControllerInterface> media_controller_;
1443 std::unique_ptr<cricket::TransportDescriptionFactory> tdesc_factory_;
1444 std::unique_ptr<cricket::MediaSessionDescriptionFactory> desc_factory_;
1445 std::unique_ptr<rtc::PhysicalSocketServer> pss_;
1446 std::unique_ptr<rtc::VirtualSocketServer> vss_;
1447 std::unique_ptr<rtc::FirewallSocketServer> fss_;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001448 rtc::SocketServerScope ss_scope_;
1449 rtc::SocketAddress stun_socket_addr_;
kwibergd1fe2812016-04-27 06:47:29 -07001450 std::unique_ptr<cricket::TestStunServer> stun_server_;
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00001451 cricket::TestTurnServer turn_server_;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001452 rtc::FakeNetworkManager network_manager_;
kwibergd1fe2812016-04-27 06:47:29 -07001453 std::unique_ptr<cricket::BasicPortAllocator> allocator_;
wu@webrtc.org97077a32013-10-25 21:18:33 +00001454 PeerConnectionFactoryInterface::Options options_;
htaa2a49d92016-03-04 02:51:39 -08001455 PeerConnectionInterface::RTCConfiguration configuration_;
kwibergd1fe2812016-04-27 06:47:29 -07001456 std::unique_ptr<WebRtcSessionForTest> session_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001457 MockIceObserver observer_;
1458 cricket::FakeVideoMediaChannel* video_channel_;
1459 cricket::FakeVoiceMediaChannel* voice_channel_;
jbauchac8869e2015-07-03 01:36:14 -07001460 rtc::scoped_refptr<FakeMetricsObserver> metrics_observer_;
deadbeefab9b2d12015-10-14 11:33:11 -07001461 // The following flags affect options created for CreateOffer/CreateAnswer.
1462 bool send_stream_1_ = false;
1463 bool send_stream_2_ = false;
1464 bool send_audio_ = false;
1465 bool send_video_ = false;
1466 rtc::scoped_refptr<DataChannel> data_channel_;
1467 // Last values received from data channel creation signal.
1468 std::string last_data_channel_label_;
1469 InternalDataChannelInit last_data_channel_config_;
deadbeef8947a012016-01-21 10:26:38 -08001470 bool session_destroyed_ = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001471};
1472
Henrik Boström87713d02015-08-25 09:53:21 +02001473TEST_P(WebRtcSessionTest, TestInitializeWithDtls) {
1474 InitWithDtls(GetParam());
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001475 // SDES is disabled when DTLS is on.
1476 EXPECT_EQ(cricket::SEC_DISABLED, session_->SdesPolicy());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001477}
1478
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001479TEST_F(WebRtcSessionTest, TestInitializeWithoutDtls) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001480 Init();
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001481 // SDES is required if DTLS is off.
1482 EXPECT_EQ(cricket::SEC_REQUIRED, session_->SdesPolicy());
wu@webrtc.org91053e72013-08-10 07:18:04 +00001483}
1484
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001485TEST_F(WebRtcSessionTest, TestSessionCandidates) {
1486 TestSessionCandidatesWithBundleRtcpMux(false, false);
1487}
1488
1489// Below test cases (TestSessionCandidatesWith*) verify the candidates gathered
1490// with rtcp-mux and/or bundle.
1491TEST_F(WebRtcSessionTest, TestSessionCandidatesWithRtcpMux) {
1492 TestSessionCandidatesWithBundleRtcpMux(false, true);
1493}
1494
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001495TEST_F(WebRtcSessionTest, TestSessionCandidatesWithBundleRtcpMux) {
1496 TestSessionCandidatesWithBundleRtcpMux(true, true);
1497}
1498
1499TEST_F(WebRtcSessionTest, TestMultihomeCandidates) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001500 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
1501 AddInterface(rtc::SocketAddress(kClientAddrHost2, kClientAddrPort));
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001502 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001503 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001504 InitiateCall();
1505 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1506 EXPECT_EQ(8u, observer_.mline_0_candidates_.size());
1507 EXPECT_EQ(8u, observer_.mline_1_candidates_.size());
1508}
1509
deadbeeff5f03e82016-06-06 11:16:06 -07001510TEST_F(WebRtcSessionTest, TestStunError) {
1511 rtc::ScopedFakeClock clock;
1512
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001513 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
1514 AddInterface(rtc::SocketAddress(kClientAddrHost2, kClientAddrPort));
wu@webrtc.org364f2042013-11-20 21:49:41 +00001515 fss_->AddRule(false,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001516 rtc::FP_UDP,
1517 rtc::FD_ANY,
1518 rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001519 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001520 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001521 InitiateCall();
wu@webrtc.org364f2042013-11-20 21:49:41 +00001522 // Since kClientAddrHost1 is blocked, not expecting stun candidates for it.
deadbeeff5f03e82016-06-06 11:16:06 -07001523 EXPECT_TRUE_SIMULATED_WAIT(observer_.oncandidatesready_, kStunTimeout, clock);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001524 EXPECT_EQ(6u, observer_.mline_0_candidates_.size());
1525 EXPECT_EQ(6u, observer_.mline_1_candidates_.size());
deadbeeff5f03e82016-06-06 11:16:06 -07001526 // Destroy session before scoped fake clock goes out of scope to avoid TSan
1527 // warning.
1528 session_->Close();
1529 session_.reset(nullptr);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001530}
1531
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001532TEST_F(WebRtcSessionTest, SetSdpFailedOnInvalidSdp) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001533 Init();
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001534 SessionDescriptionInterface* offer = NULL;
1535 // Since |offer| is NULL, there's no way to tell if it's an offer or answer.
1536 std::string unknown_action;
1537 SetLocalDescriptionExpectError(unknown_action, kInvalidSdp, offer);
1538 SetRemoteDescriptionExpectError(unknown_action, kInvalidSdp, offer);
1539}
1540
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001541// Test creating offers and receive answers and make sure the
1542// media engine creates the expected send and receive streams.
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001543TEST_F(WebRtcSessionTest, TestCreateSdesOfferReceiveSdesAnswer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001544 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001545 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001546 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001547 const std::string session_id_orig = offer->session_id();
1548 const std::string session_version_orig = offer->session_version();
1549 SetLocalDescriptionWithoutError(offer);
1550
deadbeefab9b2d12015-10-14 11:33:11 -07001551 SendAudioVideoStream2();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001552 SessionDescriptionInterface* answer =
1553 CreateRemoteAnswer(session_->local_description());
1554 SetRemoteDescriptionWithoutError(answer);
1555
1556 video_channel_ = media_engine_->GetVideoChannel(0);
1557 voice_channel_ = media_engine_->GetVoiceChannel(0);
1558
1559 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1560 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1561
1562 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1563 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1564
1565 ASSERT_EQ(1u, video_channel_->send_streams().size());
1566 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
1567 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1568 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
1569
1570 // Create new offer without send streams.
deadbeefab9b2d12015-10-14 11:33:11 -07001571 SendNothing();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001572 offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001573
1574 // Verify the session id is the same and the session version is
1575 // increased.
1576 EXPECT_EQ(session_id_orig, offer->session_id());
Peter Boström0c4e06b2015-10-07 12:23:21 +02001577 EXPECT_LT(rtc::FromString<uint64_t>(session_version_orig),
1578 rtc::FromString<uint64_t>(offer->session_version()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001579
1580 SetLocalDescriptionWithoutError(offer);
jiayl@webrtc.org7d4891d2014-09-09 21:43:15 +00001581 EXPECT_EQ(0u, video_channel_->send_streams().size());
1582 EXPECT_EQ(0u, voice_channel_->send_streams().size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001583
deadbeefab9b2d12015-10-14 11:33:11 -07001584 SendAudioVideoStream2();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001585 answer = CreateRemoteAnswer(session_->local_description());
1586 SetRemoteDescriptionWithoutError(answer);
1587
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001588 // Make sure the receive streams have not changed.
1589 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1590 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1591 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1592 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1593}
1594
1595// Test receiving offers and creating answers and make sure the
1596// media engine creates the expected send and receive streams.
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001597TEST_F(WebRtcSessionTest, TestReceiveSdesOfferCreateSdesAnswer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001598 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001599 SendAudioVideoStream2();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001600 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001601 VerifyCryptoParams(offer->description());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001602 SetRemoteDescriptionWithoutError(offer);
1603
deadbeefab9b2d12015-10-14 11:33:11 -07001604 SendAudioVideoStream1();
htaa2a49d92016-03-04 02:51:39 -08001605 SessionDescriptionInterface* answer = CreateAnswer();
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001606 VerifyCryptoParams(answer->description());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001607 SetLocalDescriptionWithoutError(answer);
1608
1609 const std::string session_id_orig = answer->session_id();
1610 const std::string session_version_orig = answer->session_version();
1611
1612 video_channel_ = media_engine_->GetVideoChannel(0);
1613 voice_channel_ = media_engine_->GetVoiceChannel(0);
1614
htaa2a49d92016-03-04 02:51:39 -08001615 ASSERT_TRUE(video_channel_);
1616 ASSERT_TRUE(voice_channel_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001617 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1618 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1619
1620 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1621 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1622
1623 ASSERT_EQ(1u, video_channel_->send_streams().size());
1624 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
1625 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1626 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
1627
deadbeefab9b2d12015-10-14 11:33:11 -07001628 SendAudioVideoStream1And2();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001629 offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001630 SetRemoteDescriptionWithoutError(offer);
1631
1632 // Answer by turning off all send streams.
deadbeefab9b2d12015-10-14 11:33:11 -07001633 SendNothing();
htaa2a49d92016-03-04 02:51:39 -08001634 answer = CreateAnswer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001635
1636 // Verify the session id is the same and the session version is
1637 // increased.
1638 EXPECT_EQ(session_id_orig, answer->session_id());
Peter Boström0c4e06b2015-10-07 12:23:21 +02001639 EXPECT_LT(rtc::FromString<uint64_t>(session_version_orig),
1640 rtc::FromString<uint64_t>(answer->session_version()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001641 SetLocalDescriptionWithoutError(answer);
1642
1643 ASSERT_EQ(2u, video_channel_->recv_streams().size());
1644 EXPECT_TRUE(kVideoTrack1 == video_channel_->recv_streams()[0].id);
1645 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[1].id);
1646 ASSERT_EQ(2u, voice_channel_->recv_streams().size());
1647 EXPECT_TRUE(kAudioTrack1 == voice_channel_->recv_streams()[0].id);
1648 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[1].id);
1649
1650 // Make sure we have no send streams.
1651 EXPECT_EQ(0u, video_channel_->send_streams().size());
1652 EXPECT_EQ(0u, voice_channel_->send_streams().size());
1653}
1654
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001655TEST_F(WebRtcSessionTest, SetLocalSdpFailedOnCreateChannel) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001656 Init();
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001657 media_engine_->set_fail_create_channel(true);
1658
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001659 SessionDescriptionInterface* offer = CreateOffer();
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001660 ASSERT_TRUE(offer != NULL);
1661 // SetRemoteDescription and SetLocalDescription will take the ownership of
1662 // the offer.
1663 SetRemoteDescriptionOfferExpectError(kCreateChannelFailed, offer);
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001664 offer = CreateOffer();
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001665 ASSERT_TRUE(offer != NULL);
1666 SetLocalDescriptionOfferExpectError(kCreateChannelFailed, offer);
1667}
1668
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001669//
1670// Tests for creating/setting SDP under different SDES/DTLS polices:
1671//
1672// --DTLS off and SDES on
1673// TestCreateSdesOfferReceiveSdesAnswer/TestReceiveSdesOfferCreateSdesAnswer:
1674// set local/remote offer/answer with crypto --> success
1675// TestSetNonSdesOfferWhenSdesOn: set local/remote offer without crypto --->
1676// failure
1677// TestSetLocalNonSdesAnswerWhenSdesOn: set local answer without crypto -->
1678// failure
1679// TestSetRemoteNonSdesAnswerWhenSdesOn: set remote answer without crypto -->
1680// failure
1681//
1682// --DTLS on and SDES off
1683// TestCreateDtlsOfferReceiveDtlsAnswer/TestReceiveDtlsOfferCreateDtlsAnswer:
1684// set local/remote offer/answer with DTLS fingerprint --> success
1685// TestReceiveNonDtlsOfferWhenDtlsOn: set local/remote offer without DTLS
1686// fingerprint --> failure
1687// TestSetLocalNonDtlsAnswerWhenDtlsOn: set local answer without fingerprint
1688// --> failure
1689// TestSetRemoteNonDtlsAnswerWhenDtlsOn: set remote answer without fingerprint
1690// --> failure
1691//
1692// --Encryption disabled: DTLS off and SDES off
1693// TestCreateOfferReceiveAnswerWithoutEncryption: set local offer and remote
1694// answer without SDES or DTLS --> success
1695// TestCreateAnswerReceiveOfferWithoutEncryption: set remote offer and local
1696// answer without SDES or DTLS --> success
1697//
1698
1699// Test that we return a failure when applying a remote/local offer that doesn't
1700// have cryptos enabled when DTLS is off.
1701TEST_F(WebRtcSessionTest, TestSetNonSdesOfferWhenSdesOn) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001702 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001703 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001704 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001705 JsepSessionDescription* offer = CreateRemoteOffer(
1706 options, cricket::SEC_DISABLED);
1707 ASSERT_TRUE(offer != NULL);
1708 VerifyNoCryptoParams(offer->description(), false);
1709 // SetRemoteDescription and SetLocalDescription will take the ownership of
1710 // the offer.
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001711 SetRemoteDescriptionOfferExpectError(kSdpWithoutSdesCrypto, offer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001712 offer = CreateRemoteOffer(options, cricket::SEC_DISABLED);
1713 ASSERT_TRUE(offer != NULL);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001714 SetLocalDescriptionOfferExpectError(kSdpWithoutSdesCrypto, offer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001715}
1716
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001717// Test that we return a failure when applying a local answer that doesn't have
1718// cryptos enabled when DTLS is off.
1719TEST_F(WebRtcSessionTest, TestSetLocalNonSdesAnswerWhenSdesOn) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001720 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001721 SessionDescriptionInterface* offer = NULL;
1722 SessionDescriptionInterface* answer = NULL;
1723 CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer);
1724 // SetRemoteDescription and SetLocalDescription will take the ownership of
1725 // the offer.
1726 SetRemoteDescriptionWithoutError(offer);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001727 SetLocalDescriptionAnswerExpectError(kSdpWithoutSdesCrypto, answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001728}
1729
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001730// Test we will return fail when apply an remote answer that doesn't have
1731// crypto enabled when DTLS is off.
1732TEST_F(WebRtcSessionTest, TestSetRemoteNonSdesAnswerWhenSdesOn) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001733 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001734 SessionDescriptionInterface* offer = NULL;
1735 SessionDescriptionInterface* answer = NULL;
1736 CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer);
1737 // SetRemoteDescription and SetLocalDescription will take the ownership of
1738 // the offer.
1739 SetLocalDescriptionWithoutError(offer);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001740 SetRemoteDescriptionAnswerExpectError(kSdpWithoutSdesCrypto, answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001741}
1742
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001743// Test that we accept an offer with a DTLS fingerprint when DTLS is on
1744// and that we return an answer with a DTLS fingerprint.
Henrik Boström87713d02015-08-25 09:53:21 +02001745TEST_P(WebRtcSessionTest, TestReceiveDtlsOfferCreateDtlsAnswer) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001746 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
deadbeefab9b2d12015-10-14 11:33:11 -07001747 SendAudioVideoStream1();
Henrik Boström87713d02015-08-25 09:53:21 +02001748 InitWithDtls(GetParam());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001749 SetFactoryDtlsSrtp();
1750 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001751 options.recv_video = true;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001752 JsepSessionDescription* offer =
1753 CreateRemoteOffer(options, cricket::SEC_DISABLED);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001754 ASSERT_TRUE(offer != NULL);
1755 VerifyFingerprintStatus(offer->description(), true);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001756 VerifyNoCryptoParams(offer->description(), true);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001757
1758 // SetRemoteDescription will take the ownership of the offer.
1759 SetRemoteDescriptionWithoutError(offer);
1760
1761 // Verify that we get a crypto fingerprint in the answer.
htaa2a49d92016-03-04 02:51:39 -08001762 SessionDescriptionInterface* answer = CreateAnswer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001763 ASSERT_TRUE(answer != NULL);
1764 VerifyFingerprintStatus(answer->description(), true);
1765 // Check that we don't have an a=crypto line in the answer.
1766 VerifyNoCryptoParams(answer->description(), true);
1767
1768 // Now set the local description, which should work, even without a=crypto.
1769 SetLocalDescriptionWithoutError(answer);
1770}
1771
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001772// Test that we set a local offer with a DTLS fingerprint when DTLS is on
1773// and then we accept a remote answer with a DTLS fingerprint successfully.
Henrik Boström87713d02015-08-25 09:53:21 +02001774TEST_P(WebRtcSessionTest, TestCreateDtlsOfferReceiveDtlsAnswer) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001775 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
deadbeefab9b2d12015-10-14 11:33:11 -07001776 SendAudioVideoStream1();
Henrik Boström87713d02015-08-25 09:53:21 +02001777 InitWithDtls(GetParam());
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001778 SetFactoryDtlsSrtp();
1779
1780 // Verify that we get a crypto fingerprint in the answer.
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001781 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001782 ASSERT_TRUE(offer != NULL);
1783 VerifyFingerprintStatus(offer->description(), true);
1784 // Check that we don't have an a=crypto line in the offer.
1785 VerifyNoCryptoParams(offer->description(), true);
1786
1787 // Now set the local description, which should work, even without a=crypto.
1788 SetLocalDescriptionWithoutError(offer);
1789
1790 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001791 options.recv_video = true;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001792 JsepSessionDescription* answer =
1793 CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED);
1794 ASSERT_TRUE(answer != NULL);
1795 VerifyFingerprintStatus(answer->description(), true);
1796 VerifyNoCryptoParams(answer->description(), true);
1797
1798 // SetRemoteDescription will take the ownership of the answer.
1799 SetRemoteDescriptionWithoutError(answer);
1800}
1801
1802// Test that if we support DTLS and the other side didn't offer a fingerprint,
1803// we will fail to set the remote description.
Henrik Boström87713d02015-08-25 09:53:21 +02001804TEST_P(WebRtcSessionTest, TestReceiveNonDtlsOfferWhenDtlsOn) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001805 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
Henrik Boström87713d02015-08-25 09:53:21 +02001806 InitWithDtls(GetParam());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001807 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001808 options.recv_video = true;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001809 options.bundle_enabled = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001810 JsepSessionDescription* offer = CreateRemoteOffer(
1811 options, cricket::SEC_REQUIRED);
1812 ASSERT_TRUE(offer != NULL);
1813 VerifyFingerprintStatus(offer->description(), false);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001814 VerifyCryptoParams(offer->description());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001815
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001816 // SetRemoteDescription will take the ownership of the offer.
1817 SetRemoteDescriptionOfferExpectError(
1818 kSdpWithoutDtlsFingerprint, offer);
1819
1820 offer = CreateRemoteOffer(options, cricket::SEC_REQUIRED);
1821 // SetLocalDescription will take the ownership of the offer.
1822 SetLocalDescriptionOfferExpectError(
1823 kSdpWithoutDtlsFingerprint, offer);
1824}
1825
1826// Test that we return a failure when applying a local answer that doesn't have
1827// a DTLS fingerprint when DTLS is required.
Henrik Boström87713d02015-08-25 09:53:21 +02001828TEST_P(WebRtcSessionTest, TestSetLocalNonDtlsAnswerWhenDtlsOn) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001829 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
Henrik Boström87713d02015-08-25 09:53:21 +02001830 InitWithDtls(GetParam());
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001831 SessionDescriptionInterface* offer = NULL;
1832 SessionDescriptionInterface* answer = NULL;
1833 CreateDtlsOfferAndNonDtlsAnswer(&offer, &answer);
1834
1835 // SetRemoteDescription and SetLocalDescription will take the ownership of
1836 // the offer and answer.
1837 SetRemoteDescriptionWithoutError(offer);
1838 SetLocalDescriptionAnswerExpectError(
1839 kSdpWithoutDtlsFingerprint, answer);
1840}
1841
1842// Test that we return a failure when applying a remote answer that doesn't have
1843// a DTLS fingerprint when DTLS is required.
Henrik Boström87713d02015-08-25 09:53:21 +02001844TEST_P(WebRtcSessionTest, TestSetRemoteNonDtlsAnswerWhenDtlsOn) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001845 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
Henrik Boström87713d02015-08-25 09:53:21 +02001846 InitWithDtls(GetParam());
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001847 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001848 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001849 options.recv_video = true;
kwibergd1fe2812016-04-27 06:47:29 -07001850 std::unique_ptr<SessionDescriptionInterface> temp_offer(
deadbeefcbecd352015-09-23 11:50:27 -07001851 CreateRemoteOffer(options, cricket::SEC_ENABLED));
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001852 JsepSessionDescription* answer =
deadbeefcbecd352015-09-23 11:50:27 -07001853 CreateRemoteAnswer(temp_offer.get(), options, cricket::SEC_ENABLED);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001854
1855 // SetRemoteDescription and SetLocalDescription will take the ownership of
1856 // the offer and answer.
1857 SetLocalDescriptionWithoutError(offer);
1858 SetRemoteDescriptionAnswerExpectError(
1859 kSdpWithoutDtlsFingerprint, answer);
1860}
1861
1862// Test that we create a local offer without SDES or DTLS and accept a remote
1863// answer without SDES or DTLS when encryption is disabled.
Henrik Boström87713d02015-08-25 09:53:21 +02001864TEST_P(WebRtcSessionTest, TestCreateOfferReceiveAnswerWithoutEncryption) {
deadbeefab9b2d12015-10-14 11:33:11 -07001865 SendAudioVideoStream1();
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001866 options_.disable_encryption = true;
Henrik Boström87713d02015-08-25 09:53:21 +02001867 InitWithDtls(GetParam());
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001868
1869 // Verify that we get a crypto fingerprint in the answer.
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001870 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001871 ASSERT_TRUE(offer != NULL);
1872 VerifyFingerprintStatus(offer->description(), false);
1873 // Check that we don't have an a=crypto line in the offer.
1874 VerifyNoCryptoParams(offer->description(), false);
1875
1876 // Now set the local description, which should work, even without a=crypto.
1877 SetLocalDescriptionWithoutError(offer);
1878
1879 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001880 options.recv_video = true;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001881 JsepSessionDescription* answer =
1882 CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED);
1883 ASSERT_TRUE(answer != NULL);
1884 VerifyFingerprintStatus(answer->description(), false);
1885 VerifyNoCryptoParams(answer->description(), false);
1886
1887 // SetRemoteDescription will take the ownership of the answer.
1888 SetRemoteDescriptionWithoutError(answer);
1889}
1890
1891// Test that we create a local answer without SDES or DTLS and accept a remote
1892// offer without SDES or DTLS when encryption is disabled.
Henrik Boström87713d02015-08-25 09:53:21 +02001893TEST_P(WebRtcSessionTest, TestCreateAnswerReceiveOfferWithoutEncryption) {
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001894 options_.disable_encryption = true;
Henrik Boström87713d02015-08-25 09:53:21 +02001895 InitWithDtls(GetParam());
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001896
1897 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001898 options.recv_video = true;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001899 JsepSessionDescription* offer =
1900 CreateRemoteOffer(options, cricket::SEC_DISABLED);
1901 ASSERT_TRUE(offer != NULL);
1902 VerifyFingerprintStatus(offer->description(), false);
1903 VerifyNoCryptoParams(offer->description(), false);
1904
1905 // SetRemoteDescription will take the ownership of the offer.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001906 SetRemoteDescriptionWithoutError(offer);
1907
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001908 // Verify that we get a crypto fingerprint in the answer.
htaa2a49d92016-03-04 02:51:39 -08001909 SessionDescriptionInterface* answer = CreateAnswer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001910 ASSERT_TRUE(answer != NULL);
1911 VerifyFingerprintStatus(answer->description(), false);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001912 // Check that we don't have an a=crypto line in the answer.
1913 VerifyNoCryptoParams(answer->description(), false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001914
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001915 // Now set the local description, which should work, even without a=crypto.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001916 SetLocalDescriptionWithoutError(answer);
1917}
1918
Taylor Brandstetterf475d362016-01-08 15:35:57 -08001919// Test that we can create and set an answer correctly when different
1920// SSL roles have been negotiated for different transports.
1921// See: https://bugs.chromium.org/p/webrtc/issues/detail?id=4525
1922TEST_P(WebRtcSessionTest, TestCreateAnswerWithDifferentSslRoles) {
1923 SendAudioVideoStream1();
1924 InitWithDtls(GetParam());
1925 SetFactoryDtlsSrtp();
1926
1927 SessionDescriptionInterface* offer = CreateOffer();
1928 SetLocalDescriptionWithoutError(offer);
1929
1930 cricket::MediaSessionOptions options;
1931 options.recv_video = true;
1932
1933 // First, negotiate different SSL roles.
1934 SessionDescriptionInterface* answer =
1935 CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED);
1936 TransportInfo* audio_transport_info =
1937 answer->description()->GetTransportInfoByName("audio");
1938 audio_transport_info->description.connection_role =
1939 cricket::CONNECTIONROLE_ACTIVE;
1940 TransportInfo* video_transport_info =
1941 answer->description()->GetTransportInfoByName("video");
1942 video_transport_info->description.connection_role =
1943 cricket::CONNECTIONROLE_PASSIVE;
1944 SetRemoteDescriptionWithoutError(answer);
1945
1946 // Now create an offer in the reverse direction, and ensure the initial
1947 // offerer responds with an answer with correct SSL roles.
1948 offer = CreateRemoteOfferWithVersion(options, cricket::SEC_DISABLED,
1949 kSessionVersion,
1950 session_->remote_description());
1951 SetRemoteDescriptionWithoutError(offer);
1952
htaa2a49d92016-03-04 02:51:39 -08001953 answer = CreateAnswer();
Taylor Brandstetterf475d362016-01-08 15:35:57 -08001954 audio_transport_info = answer->description()->GetTransportInfoByName("audio");
1955 EXPECT_EQ(cricket::CONNECTIONROLE_PASSIVE,
1956 audio_transport_info->description.connection_role);
1957 video_transport_info = answer->description()->GetTransportInfoByName("video");
1958 EXPECT_EQ(cricket::CONNECTIONROLE_ACTIVE,
1959 video_transport_info->description.connection_role);
1960 SetLocalDescriptionWithoutError(answer);
1961
1962 // Lastly, start BUNDLE-ing on "audio", expecting that the "passive" role of
1963 // audio is transferred over to video in the answer that completes the BUNDLE
1964 // negotiation.
1965 options.bundle_enabled = true;
1966 offer = CreateRemoteOfferWithVersion(options, cricket::SEC_DISABLED,
1967 kSessionVersion,
1968 session_->remote_description());
1969 SetRemoteDescriptionWithoutError(offer);
htaa2a49d92016-03-04 02:51:39 -08001970 answer = CreateAnswer();
Taylor Brandstetterf475d362016-01-08 15:35:57 -08001971 audio_transport_info = answer->description()->GetTransportInfoByName("audio");
1972 EXPECT_EQ(cricket::CONNECTIONROLE_PASSIVE,
1973 audio_transport_info->description.connection_role);
1974 video_transport_info = answer->description()->GetTransportInfoByName("video");
1975 EXPECT_EQ(cricket::CONNECTIONROLE_PASSIVE,
1976 video_transport_info->description.connection_role);
1977 SetLocalDescriptionWithoutError(answer);
1978}
1979
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001980TEST_F(WebRtcSessionTest, TestSetLocalOfferTwice) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001981 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001982 SendNothing();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001983 // SetLocalDescription take ownership of offer.
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001984 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001985 SetLocalDescriptionWithoutError(offer);
1986
1987 // SetLocalDescription take ownership of offer.
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001988 SessionDescriptionInterface* offer2 = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001989 SetLocalDescriptionWithoutError(offer2);
1990}
1991
1992TEST_F(WebRtcSessionTest, TestSetRemoteOfferTwice) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001993 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001994 SendNothing();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001995 // SetLocalDescription take ownership of offer.
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001996 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001997 SetRemoteDescriptionWithoutError(offer);
1998
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001999 SessionDescriptionInterface* offer2 = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002000 SetRemoteDescriptionWithoutError(offer2);
2001}
2002
2003TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteOffer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002004 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07002005 SendNothing();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002006 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002007 SetLocalDescriptionWithoutError(offer);
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002008 offer = CreateOffer();
deadbeefd59daf82015-10-14 15:02:44 -07002009 SetRemoteDescriptionOfferExpectError("Called in wrong state: STATE_SENTOFFER",
2010 offer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002011}
2012
2013TEST_F(WebRtcSessionTest, TestSetRemoteAndLocalOffer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002014 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07002015 SendNothing();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002016 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002017 SetRemoteDescriptionWithoutError(offer);
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002018 offer = CreateOffer();
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002019 SetLocalDescriptionOfferExpectError(
deadbeefd59daf82015-10-14 15:02:44 -07002020 "Called in wrong state: STATE_RECEIVEDOFFER", offer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002021}
2022
2023TEST_F(WebRtcSessionTest, TestSetLocalPrAnswer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002024 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07002025 SendNothing();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002026 SessionDescriptionInterface* offer = CreateRemoteOffer();
deadbeefd59daf82015-10-14 15:02:44 -07002027 SetRemoteDescriptionExpectState(offer, WebRtcSession::STATE_RECEIVEDOFFER);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002028
htaa2a49d92016-03-04 02:51:39 -08002029 JsepSessionDescription* pranswer =
2030 static_cast<JsepSessionDescription*>(CreateAnswer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002031 pranswer->set_type(SessionDescriptionInterface::kPrAnswer);
deadbeefd59daf82015-10-14 15:02:44 -07002032 SetLocalDescriptionExpectState(pranswer, WebRtcSession::STATE_SENTPRANSWER);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002033
deadbeefab9b2d12015-10-14 11:33:11 -07002034 SendAudioVideoStream1();
htaa2a49d92016-03-04 02:51:39 -08002035 JsepSessionDescription* pranswer2 =
2036 static_cast<JsepSessionDescription*>(CreateAnswer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002037 pranswer2->set_type(SessionDescriptionInterface::kPrAnswer);
2038
deadbeefd59daf82015-10-14 15:02:44 -07002039 SetLocalDescriptionExpectState(pranswer2, WebRtcSession::STATE_SENTPRANSWER);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002040
deadbeefab9b2d12015-10-14 11:33:11 -07002041 SendAudioVideoStream2();
htaa2a49d92016-03-04 02:51:39 -08002042 SessionDescriptionInterface* answer = CreateAnswer();
deadbeefd59daf82015-10-14 15:02:44 -07002043 SetLocalDescriptionExpectState(answer, WebRtcSession::STATE_INPROGRESS);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002044}
2045
2046TEST_F(WebRtcSessionTest, TestSetRemotePrAnswer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002047 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07002048 SendNothing();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002049 SessionDescriptionInterface* offer = CreateOffer();
deadbeefd59daf82015-10-14 15:02:44 -07002050 SetLocalDescriptionExpectState(offer, WebRtcSession::STATE_SENTOFFER);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002051
2052 JsepSessionDescription* pranswer =
2053 CreateRemoteAnswer(session_->local_description());
2054 pranswer->set_type(SessionDescriptionInterface::kPrAnswer);
2055
2056 SetRemoteDescriptionExpectState(pranswer,
deadbeefd59daf82015-10-14 15:02:44 -07002057 WebRtcSession::STATE_RECEIVEDPRANSWER);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002058
deadbeefab9b2d12015-10-14 11:33:11 -07002059 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002060 JsepSessionDescription* pranswer2 =
2061 CreateRemoteAnswer(session_->local_description());
2062 pranswer2->set_type(SessionDescriptionInterface::kPrAnswer);
2063
2064 SetRemoteDescriptionExpectState(pranswer2,
deadbeefd59daf82015-10-14 15:02:44 -07002065 WebRtcSession::STATE_RECEIVEDPRANSWER);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002066
deadbeefab9b2d12015-10-14 11:33:11 -07002067 SendAudioVideoStream2();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002068 SessionDescriptionInterface* answer =
2069 CreateRemoteAnswer(session_->local_description());
deadbeefd59daf82015-10-14 15:02:44 -07002070 SetRemoteDescriptionExpectState(answer, WebRtcSession::STATE_INPROGRESS);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002071}
2072
2073TEST_F(WebRtcSessionTest, TestSetLocalAnswerWithoutOffer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002074 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07002075 SendNothing();
kwibergd1fe2812016-04-27 06:47:29 -07002076 std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer());
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002077
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002078 SessionDescriptionInterface* answer =
2079 CreateRemoteAnswer(offer.get());
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002080 SetLocalDescriptionAnswerExpectError("Called in wrong state: STATE_INIT",
2081 answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002082}
2083
2084TEST_F(WebRtcSessionTest, TestSetRemoteAnswerWithoutOffer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002085 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07002086 SendNothing();
kwibergd1fe2812016-04-27 06:47:29 -07002087 std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer());
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002088
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002089 SessionDescriptionInterface* answer =
2090 CreateRemoteAnswer(offer.get());
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002091 SetRemoteDescriptionAnswerExpectError(
2092 "Called in wrong state: STATE_INIT", answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002093}
2094
Honghai Zhang7fb69db2016-03-14 11:59:18 -07002095// Tests that the remote candidates are added and removed successfully.
2096TEST_F(WebRtcSessionTest, TestAddAndRemoveRemoteCandidates) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002097 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07002098 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002099
Honghai Zhang7fb69db2016-03-14 11:59:18 -07002100 cricket::Candidate candidate(1, "udp", rtc::SocketAddress("1.1.1.1", 5000), 0,
2101 "", "", "host", 0, "");
2102 candidate.set_transport_name("audio");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002103 JsepIceCandidate ice_candidate1(kMediaContentName0, 0, candidate);
2104
deadbeefd59daf82015-10-14 15:02:44 -07002105 // Fail since we have not set a remote description.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002106 EXPECT_FALSE(session_->ProcessIceMessage(&ice_candidate1));
2107
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002108 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002109 SetLocalDescriptionWithoutError(offer);
deadbeefd59daf82015-10-14 15:02:44 -07002110
2111 // Fail since we have not set a remote description.
2112 EXPECT_FALSE(session_->ProcessIceMessage(&ice_candidate1));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002113
2114 SessionDescriptionInterface* answer = CreateRemoteAnswer(
2115 session_->local_description());
2116 SetRemoteDescriptionWithoutError(answer);
2117
deadbeefd59daf82015-10-14 15:02:44 -07002118 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
2119 candidate.set_component(2);
Honghai Zhang7fb69db2016-03-14 11:59:18 -07002120 candidate.set_address(rtc::SocketAddress("2.2.2.2", 6000));
deadbeefd59daf82015-10-14 15:02:44 -07002121 JsepIceCandidate ice_candidate2(kMediaContentName0, 0, candidate);
2122 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
2123
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002124 // Verifying the candidates are copied properly from internal vector.
2125 const SessionDescriptionInterface* remote_desc =
2126 session_->remote_description();
2127 ASSERT_TRUE(remote_desc != NULL);
2128 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
2129 const IceCandidateCollection* candidates =
2130 remote_desc->candidates(kMediaContentIndex0);
2131 ASSERT_EQ(2u, candidates->count());
2132 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
2133 EXPECT_EQ(kMediaContentName0, candidates->at(0)->sdp_mid());
2134 EXPECT_EQ(1, candidates->at(0)->candidate().component());
2135 EXPECT_EQ(2, candidates->at(1)->candidate().component());
2136
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00002137 // |ice_candidate3| is identical to |ice_candidate2|. It can be added
2138 // successfully, but the total count of candidates will not increase.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002139 candidate.set_component(2);
2140 JsepIceCandidate ice_candidate3(kMediaContentName0, 0, candidate);
2141 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate3));
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00002142 ASSERT_EQ(2u, candidates->count());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002143
2144 JsepIceCandidate bad_ice_candidate("bad content name", 99, candidate);
2145 EXPECT_FALSE(session_->ProcessIceMessage(&bad_ice_candidate));
Honghai Zhang7fb69db2016-03-14 11:59:18 -07002146
2147 // Remove candidate1 and candidate2
2148 std::vector<cricket::Candidate> remote_candidates;
2149 remote_candidates.push_back(ice_candidate1.candidate());
2150 remote_candidates.push_back(ice_candidate2.candidate());
2151 EXPECT_TRUE(session_->RemoveRemoteIceCandidates(remote_candidates));
2152 EXPECT_EQ(0u, candidates->count());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002153}
2154
Honghai Zhang7fb69db2016-03-14 11:59:18 -07002155// Tests that a remote candidate is added to the remote session description and
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002156// that it is retained if the remote session description is changed.
2157TEST_F(WebRtcSessionTest, TestRemoteCandidatesAddedToSessionDescription) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002158 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002159 cricket::Candidate candidate1;
2160 candidate1.set_component(1);
2161 JsepIceCandidate ice_candidate1(kMediaContentName0, kMediaContentIndex0,
2162 candidate1);
deadbeefab9b2d12015-10-14 11:33:11 -07002163 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002164 CreateAndSetRemoteOfferAndLocalAnswer();
2165
2166 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
2167 const SessionDescriptionInterface* remote_desc =
2168 session_->remote_description();
2169 ASSERT_TRUE(remote_desc != NULL);
2170 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
2171 const IceCandidateCollection* candidates =
2172 remote_desc->candidates(kMediaContentIndex0);
2173 ASSERT_EQ(1u, candidates->count());
2174 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
2175
2176 // Update the RemoteSessionDescription with a new session description and
2177 // a candidate and check that the new remote session description contains both
2178 // candidates.
2179 SessionDescriptionInterface* offer = CreateRemoteOffer();
2180 cricket::Candidate candidate2;
2181 JsepIceCandidate ice_candidate2(kMediaContentName0, kMediaContentIndex0,
2182 candidate2);
2183 EXPECT_TRUE(offer->AddCandidate(&ice_candidate2));
2184 SetRemoteDescriptionWithoutError(offer);
2185
2186 remote_desc = session_->remote_description();
2187 ASSERT_TRUE(remote_desc != NULL);
2188 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
2189 candidates = remote_desc->candidates(kMediaContentIndex0);
2190 ASSERT_EQ(2u, candidates->count());
2191 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
2192 // Username and password have be updated with the TransportInfo of the
2193 // SessionDescription, won't be equal to the original one.
2194 candidate2.set_username(candidates->at(0)->candidate().username());
2195 candidate2.set_password(candidates->at(0)->candidate().password());
2196 EXPECT_TRUE(candidate2.IsEquivalent(candidates->at(0)->candidate()));
2197 EXPECT_EQ(kMediaContentIndex0, candidates->at(1)->sdp_mline_index());
2198 // No need to verify the username and password.
2199 candidate1.set_username(candidates->at(1)->candidate().username());
2200 candidate1.set_password(candidates->at(1)->candidate().password());
2201 EXPECT_TRUE(candidate1.IsEquivalent(candidates->at(1)->candidate()));
2202
2203 // Test that the candidate is ignored if we can add the same candidate again.
2204 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
2205}
2206
2207// Test that local candidates are added to the local session description and
Honghai Zhang7fb69db2016-03-14 11:59:18 -07002208// that they are retained if the local session description is changed. And if
2209// continual gathering is enabled, they are removed from the local session
2210// description when the network is down.
2211TEST_F(WebRtcSessionTest,
2212 TestLocalCandidatesAddedAndRemovedIfGatherContinually) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002213 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002214 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07002215 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002216 CreateAndSetRemoteOfferAndLocalAnswer();
2217
2218 const SessionDescriptionInterface* local_desc = session_->local_description();
2219 const IceCandidateCollection* candidates =
2220 local_desc->candidates(kMediaContentIndex0);
2221 ASSERT_TRUE(candidates != NULL);
2222 EXPECT_EQ(0u, candidates->count());
2223
2224 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
2225
2226 local_desc = session_->local_description();
2227 candidates = local_desc->candidates(kMediaContentIndex0);
2228 ASSERT_TRUE(candidates != NULL);
2229 EXPECT_LT(0u, candidates->count());
2230 candidates = local_desc->candidates(1);
2231 ASSERT_TRUE(candidates != NULL);
deadbeefcbecd352015-09-23 11:50:27 -07002232 EXPECT_EQ(0u, candidates->count());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002233
2234 // Update the session descriptions.
deadbeefab9b2d12015-10-14 11:33:11 -07002235 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002236 CreateAndSetRemoteOfferAndLocalAnswer();
2237
2238 local_desc = session_->local_description();
2239 candidates = local_desc->candidates(kMediaContentIndex0);
2240 ASSERT_TRUE(candidates != NULL);
2241 EXPECT_LT(0u, candidates->count());
2242 candidates = local_desc->candidates(1);
2243 ASSERT_TRUE(candidates != NULL);
deadbeefcbecd352015-09-23 11:50:27 -07002244 EXPECT_EQ(0u, candidates->count());
Honghai Zhang7fb69db2016-03-14 11:59:18 -07002245
2246 candidates = local_desc->candidates(kMediaContentIndex0);
2247 size_t num_local_candidates = candidates->count();
2248 // Enable Continual Gathering
2249 session_->SetIceConfig(cricket::IceConfig(-1, -1, true, false, -1));
2250 // Bring down the network interface to trigger candidate removals.
2251 RemoveInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
2252 // Verify that all local candidates are removed.
2253 EXPECT_EQ(0, observer_.num_candidates_removed_);
2254 EXPECT_EQ_WAIT(num_local_candidates, observer_.num_candidates_removed_,
2255 kIceCandidatesTimeout);
2256 EXPECT_EQ_WAIT(0u, candidates->count(), kIceCandidatesTimeout);
2257}
2258
2259// Tests that if continual gathering is disabled, local candidates won't be
2260// removed when the interface is turned down.
2261TEST_F(WebRtcSessionTest, TestLocalCandidatesNotRemovedIfNotGatherContinually) {
2262 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
2263 Init();
2264 SendAudioVideoStream1();
2265 CreateAndSetRemoteOfferAndLocalAnswer();
2266
2267 const SessionDescriptionInterface* local_desc = session_->local_description();
2268 const IceCandidateCollection* candidates =
2269 local_desc->candidates(kMediaContentIndex0);
2270 ASSERT_TRUE(candidates != NULL);
2271 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
2272
2273 size_t num_local_candidates = candidates->count();
2274 EXPECT_LT(0u, num_local_candidates);
2275 // By default, Continual Gathering is disabled.
2276 // Bring down the network interface.
2277 RemoveInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
2278 // Verify that the local candidates are not removed.
2279 rtc::Thread::Current()->ProcessMessages(1000);
2280 EXPECT_EQ(0, observer_.num_candidates_removed_);
2281 EXPECT_EQ(num_local_candidates, candidates->count());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002282}
2283
2284// Test that we can set a remote session description with remote candidates.
2285TEST_F(WebRtcSessionTest, TestSetRemoteSessionDescriptionWithCandidates) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002286 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002287
2288 cricket::Candidate candidate1;
2289 candidate1.set_component(1);
2290 JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0,
2291 candidate1);
deadbeefab9b2d12015-10-14 11:33:11 -07002292 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002293 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002294
2295 EXPECT_TRUE(offer->AddCandidate(&ice_candidate));
2296 SetRemoteDescriptionWithoutError(offer);
2297
2298 const SessionDescriptionInterface* remote_desc =
2299 session_->remote_description();
2300 ASSERT_TRUE(remote_desc != NULL);
2301 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
2302 const IceCandidateCollection* candidates =
2303 remote_desc->candidates(kMediaContentIndex0);
2304 ASSERT_EQ(1u, candidates->count());
2305 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
2306
htaa2a49d92016-03-04 02:51:39 -08002307 SessionDescriptionInterface* answer = CreateAnswer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002308 SetLocalDescriptionWithoutError(answer);
2309}
2310
2311// Test that offers and answers contains ice candidates when Ice candidates have
2312// been gathered.
2313TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteDescriptionWithCandidates) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002314 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002315 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07002316 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002317 // Ice is started but candidates are not provided until SetLocalDescription
2318 // is called.
2319 EXPECT_EQ(0u, observer_.mline_0_candidates_.size());
2320 EXPECT_EQ(0u, observer_.mline_1_candidates_.size());
2321 CreateAndSetRemoteOfferAndLocalAnswer();
2322 // Wait until at least one local candidate has been collected.
2323 EXPECT_TRUE_WAIT(0u < observer_.mline_0_candidates_.size(),
2324 kIceCandidatesTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002325
kwibergd1fe2812016-04-27 06:47:29 -07002326 std::unique_ptr<SessionDescriptionInterface> local_offer(CreateOffer());
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002327
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002328 ASSERT_TRUE(local_offer->candidates(kMediaContentIndex0) != NULL);
2329 EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex0)->count());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002330
2331 SessionDescriptionInterface* remote_offer(CreateRemoteOffer());
2332 SetRemoteDescriptionWithoutError(remote_offer);
htaa2a49d92016-03-04 02:51:39 -08002333 SessionDescriptionInterface* answer = CreateAnswer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002334 ASSERT_TRUE(answer->candidates(kMediaContentIndex0) != NULL);
2335 EXPECT_LT(0u, answer->candidates(kMediaContentIndex0)->count());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002336 SetLocalDescriptionWithoutError(answer);
2337}
2338
2339// Verifies TransportProxy and media channels are created with content names
2340// present in the SessionDescription.
2341TEST_F(WebRtcSessionTest, TestChannelCreationsWithContentNames) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002342 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07002343 SendAudioVideoStream1();
kwibergd1fe2812016-04-27 06:47:29 -07002344 std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002345
2346 // CreateOffer creates session description with the content names "audio" and
deadbeefd59daf82015-10-14 15:02:44 -07002347 // "video". Goal is to modify these content names and verify transport
2348 // channels
2349 // in the WebRtcSession, as channels are created with the content names
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002350 // present in SDP.
2351 std::string sdp;
2352 EXPECT_TRUE(offer->ToString(&sdp));
2353 const std::string kAudioMid = "a=mid:audio";
2354 const std::string kAudioMidReplaceStr = "a=mid:audio_content_name";
2355 const std::string kVideoMid = "a=mid:video";
2356 const std::string kVideoMidReplaceStr = "a=mid:video_content_name";
2357
2358 // Replacing |audio| with |audio_content_name|.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002359 rtc::replace_substrs(kAudioMid.c_str(), kAudioMid.length(),
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002360 kAudioMidReplaceStr.c_str(),
2361 kAudioMidReplaceStr.length(),
2362 &sdp);
2363 // Replacing |video| with |video_content_name|.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002364 rtc::replace_substrs(kVideoMid.c_str(), kVideoMid.length(),
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002365 kVideoMidReplaceStr.c_str(),
2366 kVideoMidReplaceStr.length(),
2367 &sdp);
2368
2369 SessionDescriptionInterface* modified_offer =
2370 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
2371
2372 SetRemoteDescriptionWithoutError(modified_offer);
2373
htaa2a49d92016-03-04 02:51:39 -08002374 SessionDescriptionInterface* answer = CreateAnswer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002375 SetLocalDescriptionWithoutError(answer);
2376
deadbeefcbecd352015-09-23 11:50:27 -07002377 cricket::TransportChannel* voice_transport_channel =
2378 session_->voice_rtp_transport_channel();
2379 EXPECT_TRUE(voice_transport_channel != NULL);
2380 EXPECT_EQ(voice_transport_channel->transport_name(), "audio_content_name");
2381 cricket::TransportChannel* video_transport_channel =
2382 session_->video_rtp_transport_channel();
htaa2a49d92016-03-04 02:51:39 -08002383 ASSERT_TRUE(video_transport_channel != NULL);
deadbeefcbecd352015-09-23 11:50:27 -07002384 EXPECT_EQ(video_transport_channel->transport_name(), "video_content_name");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002385 EXPECT_TRUE((video_channel_ = media_engine_->GetVideoChannel(0)) != NULL);
2386 EXPECT_TRUE((voice_channel_ = media_engine_->GetVoiceChannel(0)) != NULL);
2387}
2388
2389// Test that an offer contains the correct media content descriptions based on
2390// the send streams when no constraints have been set.
2391TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraintsOrStreams) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002392 Init();
kwibergd1fe2812016-04-27 06:47:29 -07002393 std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer());
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002394
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002395 ASSERT_TRUE(offer != NULL);
2396 const cricket::ContentInfo* content =
2397 cricket::GetFirstAudioContent(offer->description());
2398 EXPECT_TRUE(content != NULL);
2399 content = cricket::GetFirstVideoContent(offer->description());
2400 EXPECT_TRUE(content == NULL);
2401}
2402
2403// Test that an offer contains the correct media content descriptions based on
2404// the send streams when no constraints have been set.
2405TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraints) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002406 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002407 // Test Audio only offer.
deadbeefab9b2d12015-10-14 11:33:11 -07002408 SendAudioOnlyStream2();
kwibergd1fe2812016-04-27 06:47:29 -07002409 std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer());
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002410
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002411 const cricket::ContentInfo* content =
2412 cricket::GetFirstAudioContent(offer->description());
2413 EXPECT_TRUE(content != NULL);
2414 content = cricket::GetFirstVideoContent(offer->description());
2415 EXPECT_TRUE(content == NULL);
2416
2417 // Test Audio / Video offer.
deadbeefab9b2d12015-10-14 11:33:11 -07002418 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002419 offer.reset(CreateOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002420 content = cricket::GetFirstAudioContent(offer->description());
2421 EXPECT_TRUE(content != NULL);
2422 content = cricket::GetFirstVideoContent(offer->description());
2423 EXPECT_TRUE(content != NULL);
2424}
2425
2426// Test that an offer contains no media content descriptions if
2427// kOfferToReceiveVideo and kOfferToReceiveAudio constraints are set to false.
2428TEST_F(WebRtcSessionTest, CreateOfferWithConstraintsWithoutStreams) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002429 Init();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002430 PeerConnectionInterface::RTCOfferAnswerOptions options;
2431 options.offer_to_receive_audio = 0;
2432 options.offer_to_receive_video = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002433
kwibergd1fe2812016-04-27 06:47:29 -07002434 std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer(options));
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002435
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002436 ASSERT_TRUE(offer != NULL);
2437 const cricket::ContentInfo* content =
2438 cricket::GetFirstAudioContent(offer->description());
2439 EXPECT_TRUE(content == NULL);
2440 content = cricket::GetFirstVideoContent(offer->description());
2441 EXPECT_TRUE(content == NULL);
2442}
2443
2444// Test that an offer contains only audio media content descriptions if
2445// kOfferToReceiveAudio constraints are set to true.
2446TEST_F(WebRtcSessionTest, CreateAudioOnlyOfferWithConstraints) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002447 Init();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002448 PeerConnectionInterface::RTCOfferAnswerOptions options;
2449 options.offer_to_receive_audio =
2450 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
2451
kwibergd1fe2812016-04-27 06:47:29 -07002452 std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer(options));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002453
2454 const cricket::ContentInfo* content =
2455 cricket::GetFirstAudioContent(offer->description());
2456 EXPECT_TRUE(content != NULL);
2457 content = cricket::GetFirstVideoContent(offer->description());
2458 EXPECT_TRUE(content == NULL);
2459}
2460
2461// Test that an offer contains audio and video media content descriptions if
2462// kOfferToReceiveAudio and kOfferToReceiveVideo constraints are set to true.
2463TEST_F(WebRtcSessionTest, CreateOfferWithConstraints) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002464 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002465 // Test Audio / Video offer.
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002466 PeerConnectionInterface::RTCOfferAnswerOptions options;
2467 options.offer_to_receive_audio =
2468 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
2469 options.offer_to_receive_video =
2470 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
2471
kwibergd1fe2812016-04-27 06:47:29 -07002472 std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer(options));
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002473
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002474 const cricket::ContentInfo* content =
2475 cricket::GetFirstAudioContent(offer->description());
jiayl@webrtc.orgc1723202014-09-08 20:44:36 +00002476 EXPECT_TRUE(content != NULL);
jiayl@webrtc.org7d4891d2014-09-09 21:43:15 +00002477
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002478 content = cricket::GetFirstVideoContent(offer->description());
2479 EXPECT_TRUE(content != NULL);
2480
jiayl@webrtc.org7d4891d2014-09-09 21:43:15 +00002481 // Sets constraints to false and verifies that audio/video contents are
2482 // removed.
2483 options.offer_to_receive_audio = 0;
2484 options.offer_to_receive_video = 0;
2485 offer.reset(CreateOffer(options));
2486
2487 content = cricket::GetFirstAudioContent(offer->description());
2488 EXPECT_TRUE(content == NULL);
2489 content = cricket::GetFirstVideoContent(offer->description());
2490 EXPECT_TRUE(content == NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002491}
2492
2493// Test that an answer can not be created if the last remote description is not
2494// an offer.
2495TEST_F(WebRtcSessionTest, CreateAnswerWithoutAnOffer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002496 Init();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002497 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002498 SetLocalDescriptionWithoutError(offer);
2499 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
2500 SetRemoteDescriptionWithoutError(answer);
htaa2a49d92016-03-04 02:51:39 -08002501 EXPECT_TRUE(CreateAnswer() == NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002502}
2503
2504// Test that an answer contains the correct media content descriptions when no
2505// constraints have been set.
2506TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraintsOrStreams) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002507 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002508 // Create a remote offer with audio and video content.
kwibergd1fe2812016-04-27 06:47:29 -07002509 std::unique_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002510 SetRemoteDescriptionWithoutError(offer.release());
kwibergd1fe2812016-04-27 06:47:29 -07002511 std::unique_ptr<SessionDescriptionInterface> answer(CreateAnswer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002512 const cricket::ContentInfo* content =
2513 cricket::GetFirstAudioContent(answer->description());
2514 ASSERT_TRUE(content != NULL);
2515 EXPECT_FALSE(content->rejected);
2516
2517 content = cricket::GetFirstVideoContent(answer->description());
2518 ASSERT_TRUE(content != NULL);
2519 EXPECT_FALSE(content->rejected);
2520}
2521
2522// Test that an answer contains the correct media content descriptions when no
2523// constraints have been set and the offer only contain audio.
2524TEST_F(WebRtcSessionTest, CreateAudioAnswerWithoutConstraintsOrStreams) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002525 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002526 // Create a remote offer with audio only.
2527 cricket::MediaSessionOptions options;
jiayl@webrtc.org7d4891d2014-09-09 21:43:15 +00002528
kwibergd1fe2812016-04-27 06:47:29 -07002529 std::unique_ptr<JsepSessionDescription> offer(CreateRemoteOffer(options));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002530 ASSERT_TRUE(cricket::GetFirstVideoContent(offer->description()) == NULL);
2531 ASSERT_TRUE(cricket::GetFirstAudioContent(offer->description()) != NULL);
2532
2533 SetRemoteDescriptionWithoutError(offer.release());
kwibergd1fe2812016-04-27 06:47:29 -07002534 std::unique_ptr<SessionDescriptionInterface> answer(CreateAnswer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002535 const cricket::ContentInfo* content =
2536 cricket::GetFirstAudioContent(answer->description());
2537 ASSERT_TRUE(content != NULL);
2538 EXPECT_FALSE(content->rejected);
2539
2540 EXPECT_TRUE(cricket::GetFirstVideoContent(answer->description()) == NULL);
2541}
2542
2543// Test that an answer contains the correct media content descriptions when no
2544// constraints have been set.
2545TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraints) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002546 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002547 // Create a remote offer with audio and video content.
kwibergd1fe2812016-04-27 06:47:29 -07002548 std::unique_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002549 SetRemoteDescriptionWithoutError(offer.release());
2550 // Test with a stream with tracks.
deadbeefab9b2d12015-10-14 11:33:11 -07002551 SendAudioVideoStream1();
kwibergd1fe2812016-04-27 06:47:29 -07002552 std::unique_ptr<SessionDescriptionInterface> answer(CreateAnswer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002553 const cricket::ContentInfo* content =
2554 cricket::GetFirstAudioContent(answer->description());
2555 ASSERT_TRUE(content != NULL);
2556 EXPECT_FALSE(content->rejected);
2557
2558 content = cricket::GetFirstVideoContent(answer->description());
2559 ASSERT_TRUE(content != NULL);
2560 EXPECT_FALSE(content->rejected);
2561}
2562
2563// Test that an answer contains the correct media content descriptions when
2564// constraints have been set but no stream is sent.
2565TEST_F(WebRtcSessionTest, CreateAnswerWithConstraintsWithoutStreams) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002566 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002567 // Create a remote offer with audio and video content.
kwibergd1fe2812016-04-27 06:47:29 -07002568 std::unique_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002569 SetRemoteDescriptionWithoutError(offer.release());
2570
htaa2a49d92016-03-04 02:51:39 -08002571 cricket::MediaSessionOptions session_options;
2572 session_options.recv_audio = false;
2573 session_options.recv_video = false;
kwibergd1fe2812016-04-27 06:47:29 -07002574 std::unique_ptr<SessionDescriptionInterface> answer(
htaa2a49d92016-03-04 02:51:39 -08002575 CreateAnswer(session_options));
2576
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002577 const cricket::ContentInfo* content =
2578 cricket::GetFirstAudioContent(answer->description());
2579 ASSERT_TRUE(content != NULL);
2580 EXPECT_TRUE(content->rejected);
2581
2582 content = cricket::GetFirstVideoContent(answer->description());
2583 ASSERT_TRUE(content != NULL);
2584 EXPECT_TRUE(content->rejected);
2585}
2586
2587// Test that an answer contains the correct media content descriptions when
2588// constraints have been set and streams are sent.
2589TEST_F(WebRtcSessionTest, CreateAnswerWithConstraints) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002590 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002591 // Create a remote offer with audio and video content.
kwibergd1fe2812016-04-27 06:47:29 -07002592 std::unique_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002593 SetRemoteDescriptionWithoutError(offer.release());
2594
htaa2a49d92016-03-04 02:51:39 -08002595 cricket::MediaSessionOptions options;
2596 options.recv_audio = false;
2597 options.recv_video = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002598
2599 // Test with a stream with tracks.
deadbeefab9b2d12015-10-14 11:33:11 -07002600 SendAudioVideoStream1();
kwibergd1fe2812016-04-27 06:47:29 -07002601 std::unique_ptr<SessionDescriptionInterface> answer(CreateAnswer(options));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002602
2603 // TODO(perkj): Should the direction be set to SEND_ONLY?
2604 const cricket::ContentInfo* content =
2605 cricket::GetFirstAudioContent(answer->description());
2606 ASSERT_TRUE(content != NULL);
2607 EXPECT_FALSE(content->rejected);
2608
2609 // TODO(perkj): Should the direction be set to SEND_ONLY?
2610 content = cricket::GetFirstVideoContent(answer->description());
2611 ASSERT_TRUE(content != NULL);
2612 EXPECT_FALSE(content->rejected);
2613}
2614
2615TEST_F(WebRtcSessionTest, CreateOfferWithoutCNCodecs) {
2616 AddCNCodecs();
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002617 Init();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002618 PeerConnectionInterface::RTCOfferAnswerOptions options;
2619 options.offer_to_receive_audio =
2620 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
2621 options.voice_activity_detection = false;
2622
kwibergd1fe2812016-04-27 06:47:29 -07002623 std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer(options));
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002624
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002625 const cricket::ContentInfo* content =
2626 cricket::GetFirstAudioContent(offer->description());
2627 EXPECT_TRUE(content != NULL);
2628 EXPECT_TRUE(VerifyNoCNCodecs(content));
2629}
2630
2631TEST_F(WebRtcSessionTest, CreateAnswerWithoutCNCodecs) {
2632 AddCNCodecs();
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002633 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002634 // Create a remote offer with audio and video content.
kwibergd1fe2812016-04-27 06:47:29 -07002635 std::unique_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002636 SetRemoteDescriptionWithoutError(offer.release());
2637
htaa2a49d92016-03-04 02:51:39 -08002638 cricket::MediaSessionOptions options;
2639 options.vad_enabled = false;
kwibergd1fe2812016-04-27 06:47:29 -07002640 std::unique_ptr<SessionDescriptionInterface> answer(CreateAnswer(options));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002641 const cricket::ContentInfo* content =
2642 cricket::GetFirstAudioContent(answer->description());
2643 ASSERT_TRUE(content != NULL);
2644 EXPECT_TRUE(VerifyNoCNCodecs(content));
2645}
2646
2647// This test verifies the call setup when remote answer with audio only and
2648// later updates with video.
2649TEST_F(WebRtcSessionTest, TestAVOfferWithAudioOnlyAnswer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002650 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002651 EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL);
2652 EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL);
2653
deadbeefab9b2d12015-10-14 11:33:11 -07002654 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002655 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002656
2657 cricket::MediaSessionOptions options;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002658 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer, options);
2659
2660 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
2661 // and answer;
2662 SetLocalDescriptionWithoutError(offer);
2663 SetRemoteDescriptionWithoutError(answer);
2664
2665 video_channel_ = media_engine_->GetVideoChannel(0);
2666 voice_channel_ = media_engine_->GetVoiceChannel(0);
2667
2668 ASSERT_TRUE(video_channel_ == NULL);
2669
2670 ASSERT_EQ(0u, voice_channel_->recv_streams().size());
2671 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2672 EXPECT_EQ(kAudioTrack1, voice_channel_->send_streams()[0].id);
2673
2674 // Let the remote end update the session descriptions, with Audio and Video.
deadbeefab9b2d12015-10-14 11:33:11 -07002675 SendAudioVideoStream2();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002676 CreateAndSetRemoteOfferAndLocalAnswer();
2677
2678 video_channel_ = media_engine_->GetVideoChannel(0);
2679 voice_channel_ = media_engine_->GetVoiceChannel(0);
2680
2681 ASSERT_TRUE(video_channel_ != NULL);
2682 ASSERT_TRUE(voice_channel_ != NULL);
2683
2684 ASSERT_EQ(1u, video_channel_->recv_streams().size());
2685 ASSERT_EQ(1u, video_channel_->send_streams().size());
2686 EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id);
2687 EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id);
2688 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
2689 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2690 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
2691 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
2692
2693 // Change session back to audio only.
deadbeefab9b2d12015-10-14 11:33:11 -07002694 SendAudioOnlyStream2();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002695 CreateAndSetRemoteOfferAndLocalAnswer();
2696
2697 EXPECT_EQ(0u, video_channel_->recv_streams().size());
2698 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
2699 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
2700 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2701 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
2702}
2703
2704// This test verifies the call setup when remote answer with video only and
2705// later updates with audio.
2706TEST_F(WebRtcSessionTest, TestAVOfferWithVideoOnlyAnswer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002707 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002708 EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL);
2709 EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL);
deadbeefab9b2d12015-10-14 11:33:11 -07002710 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002711 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002712
2713 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002714 options.recv_audio = false;
2715 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002716 SessionDescriptionInterface* answer = CreateRemoteAnswer(
2717 offer, options, cricket::SEC_ENABLED);
2718
2719 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
2720 // and answer.
2721 SetLocalDescriptionWithoutError(offer);
2722 SetRemoteDescriptionWithoutError(answer);
2723
2724 video_channel_ = media_engine_->GetVideoChannel(0);
2725 voice_channel_ = media_engine_->GetVoiceChannel(0);
2726
2727 ASSERT_TRUE(voice_channel_ == NULL);
2728 ASSERT_TRUE(video_channel_ != NULL);
2729
2730 EXPECT_EQ(0u, video_channel_->recv_streams().size());
2731 ASSERT_EQ(1u, video_channel_->send_streams().size());
2732 EXPECT_EQ(kVideoTrack1, video_channel_->send_streams()[0].id);
2733
2734 // Update the session descriptions, with Audio and Video.
deadbeefab9b2d12015-10-14 11:33:11 -07002735 SendAudioVideoStream2();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002736 CreateAndSetRemoteOfferAndLocalAnswer();
2737
2738 voice_channel_ = media_engine_->GetVoiceChannel(0);
2739 ASSERT_TRUE(voice_channel_ != NULL);
2740
2741 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
2742 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2743 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
2744 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
2745
2746 // Change session back to video only.
deadbeefab9b2d12015-10-14 11:33:11 -07002747 SendVideoOnlyStream2();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002748 CreateAndSetRemoteOfferAndLocalAnswer();
2749
2750 video_channel_ = media_engine_->GetVideoChannel(0);
2751 voice_channel_ = media_engine_->GetVoiceChannel(0);
2752
2753 ASSERT_EQ(1u, video_channel_->recv_streams().size());
2754 EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id);
2755 ASSERT_EQ(1u, video_channel_->send_streams().size());
2756 EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id);
2757}
2758
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002759TEST_F(WebRtcSessionTest, VerifyCryptoParamsInSDP) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002760 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07002761 SendAudioVideoStream1();
kwibergd1fe2812016-04-27 06:47:29 -07002762 std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002763 VerifyCryptoParams(offer->description());
2764 SetRemoteDescriptionWithoutError(offer.release());
kwibergd1fe2812016-04-27 06:47:29 -07002765 std::unique_ptr<SessionDescriptionInterface> answer(CreateAnswer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002766 VerifyCryptoParams(answer->description());
2767}
2768
2769TEST_F(WebRtcSessionTest, VerifyNoCryptoParamsInSDP) {
wu@webrtc.org97077a32013-10-25 21:18:33 +00002770 options_.disable_encryption = true;
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002771 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07002772 SendAudioVideoStream1();
kwibergd1fe2812016-04-27 06:47:29 -07002773 std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002774 VerifyNoCryptoParams(offer->description(), false);
2775}
2776
2777TEST_F(WebRtcSessionTest, VerifyAnswerFromNonCryptoOffer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002778 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002779 VerifyAnswerFromNonCryptoOffer();
2780}
2781
2782TEST_F(WebRtcSessionTest, VerifyAnswerFromCryptoOffer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002783 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002784 VerifyAnswerFromCryptoOffer();
2785}
2786
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002787// This test verifies that setLocalDescription fails if
2788// no a=ice-ufrag and a=ice-pwd lines are present in the SDP.
2789TEST_F(WebRtcSessionTest, TestSetLocalDescriptionWithoutIce) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002790 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07002791 SendAudioVideoStream1();
kwibergd1fe2812016-04-27 06:47:29 -07002792 std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer());
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002793
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002794 std::string sdp;
2795 RemoveIceUfragPwdLines(offer.get(), &sdp);
2796 SessionDescriptionInterface* modified_offer =
2797 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002798 SetLocalDescriptionOfferExpectError(kSdpWithoutIceUfragPwd, modified_offer);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002799}
2800
2801// This test verifies that setRemoteDescription fails if
2802// no a=ice-ufrag and a=ice-pwd lines are present in the SDP.
2803TEST_F(WebRtcSessionTest, TestSetRemoteDescriptionWithoutIce) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002804 Init();
kwibergd1fe2812016-04-27 06:47:29 -07002805 std::unique_ptr<SessionDescriptionInterface> offer(CreateRemoteOffer());
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002806 std::string sdp;
2807 RemoveIceUfragPwdLines(offer.get(), &sdp);
2808 SessionDescriptionInterface* modified_offer =
2809 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002810 SetRemoteDescriptionOfferExpectError(kSdpWithoutIceUfragPwd, modified_offer);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002811}
2812
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +00002813// This test verifies that setLocalDescription fails if local offer has
2814// too short ice ufrag and pwd strings.
2815TEST_F(WebRtcSessionTest, TestSetLocalDescriptionInvalidIceCredentials) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002816 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07002817 SendAudioVideoStream1();
kwibergd1fe2812016-04-27 06:47:29 -07002818 std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer());
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +00002819 // Modifying ice ufrag and pwd in local offer with strings smaller than the
2820 // recommended values of 4 and 22 bytes respectively.
deadbeef0ed85b22016-02-23 17:24:52 -08002821 SetIceUfragPwd(offer.get(), "ice", "icepwd");
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +00002822 std::string error;
deadbeef0ed85b22016-02-23 17:24:52 -08002823 EXPECT_FALSE(session_->SetLocalDescription(offer.release(), &error));
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +00002824
2825 // Test with string greater than 256.
deadbeef0ed85b22016-02-23 17:24:52 -08002826 offer.reset(CreateOffer());
2827 SetIceUfragPwd(offer.get(), kTooLongIceUfragPwd, kTooLongIceUfragPwd);
2828 EXPECT_FALSE(session_->SetLocalDescription(offer.release(), &error));
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +00002829}
2830
2831// This test verifies that setRemoteDescription fails if remote offer has
2832// too short ice ufrag and pwd strings.
2833TEST_F(WebRtcSessionTest, TestSetRemoteDescriptionInvalidIceCredentials) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002834 Init();
kwibergd1fe2812016-04-27 06:47:29 -07002835 std::unique_ptr<SessionDescriptionInterface> offer(CreateRemoteOffer());
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +00002836 // Modifying ice ufrag and pwd in remote offer with strings smaller than the
2837 // recommended values of 4 and 22 bytes respectively.
deadbeef0ed85b22016-02-23 17:24:52 -08002838 SetIceUfragPwd(offer.get(), "ice", "icepwd");
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +00002839 std::string error;
deadbeef0ed85b22016-02-23 17:24:52 -08002840 EXPECT_FALSE(session_->SetRemoteDescription(offer.release(), &error));
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +00002841
deadbeef0ed85b22016-02-23 17:24:52 -08002842 offer.reset(CreateRemoteOffer());
2843 SetIceUfragPwd(offer.get(), kTooLongIceUfragPwd, kTooLongIceUfragPwd);
2844 EXPECT_FALSE(session_->SetRemoteDescription(offer.release(), &error));
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +00002845}
2846
Honghai Zhang04e91462015-12-11 14:26:22 -08002847// Test that if the remote offer indicates the peer requested ICE restart (via
2848// a new ufrag or pwd), the old ICE candidates are not copied, and vice versa.
2849TEST_F(WebRtcSessionTest, TestSetRemoteOfferWithIceRestart) {
honghaiz503726c2015-07-31 12:37:38 -07002850 Init();
honghaiz503726c2015-07-31 12:37:38 -07002851
2852 // Create the first offer.
kwibergd1fe2812016-04-27 06:47:29 -07002853 std::unique_ptr<SessionDescriptionInterface> offer(CreateRemoteOffer());
deadbeef0ed85b22016-02-23 17:24:52 -08002854 SetIceUfragPwd(offer.get(), "0123456789012345", "abcdefghijklmnopqrstuvwx");
honghaiz503726c2015-07-31 12:37:38 -07002855 cricket::Candidate candidate1(1, "udp", rtc::SocketAddress("1.1.1.1", 5000),
2856 0, "", "", "relay", 0, "");
2857 JsepIceCandidate ice_candidate1(kMediaContentName0, kMediaContentIndex0,
2858 candidate1);
deadbeef0ed85b22016-02-23 17:24:52 -08002859 EXPECT_TRUE(offer->AddCandidate(&ice_candidate1));
2860 SetRemoteDescriptionWithoutError(offer.release());
honghaiz503726c2015-07-31 12:37:38 -07002861 EXPECT_EQ(1, session_->remote_description()->candidates(0)->count());
2862
2863 // The second offer has the same ufrag and pwd but different address.
deadbeef0ed85b22016-02-23 17:24:52 -08002864 offer.reset(CreateRemoteOffer());
2865 SetIceUfragPwd(offer.get(), "0123456789012345", "abcdefghijklmnopqrstuvwx");
honghaiz503726c2015-07-31 12:37:38 -07002866 candidate1.set_address(rtc::SocketAddress("1.1.1.1", 6000));
2867 JsepIceCandidate ice_candidate2(kMediaContentName0, kMediaContentIndex0,
2868 candidate1);
deadbeef0ed85b22016-02-23 17:24:52 -08002869 EXPECT_TRUE(offer->AddCandidate(&ice_candidate2));
2870 SetRemoteDescriptionWithoutError(offer.release());
honghaiz503726c2015-07-31 12:37:38 -07002871 EXPECT_EQ(2, session_->remote_description()->candidates(0)->count());
2872
2873 // The third offer has a different ufrag and different address.
deadbeef0ed85b22016-02-23 17:24:52 -08002874 offer.reset(CreateRemoteOffer());
2875 SetIceUfragPwd(offer.get(), "0123456789012333", "abcdefghijklmnopqrstuvwx");
honghaiz503726c2015-07-31 12:37:38 -07002876 candidate1.set_address(rtc::SocketAddress("1.1.1.1", 7000));
2877 JsepIceCandidate ice_candidate3(kMediaContentName0, kMediaContentIndex0,
2878 candidate1);
deadbeef0ed85b22016-02-23 17:24:52 -08002879 EXPECT_TRUE(offer->AddCandidate(&ice_candidate3));
2880 SetRemoteDescriptionWithoutError(offer.release());
honghaiz503726c2015-07-31 12:37:38 -07002881 EXPECT_EQ(1, session_->remote_description()->candidates(0)->count());
2882
2883 // The fourth offer has no candidate but a different ufrag/pwd.
deadbeef0ed85b22016-02-23 17:24:52 -08002884 offer.reset(CreateRemoteOffer());
2885 SetIceUfragPwd(offer.get(), "0123456789012444", "abcdefghijklmnopqrstuvyz");
2886 SetRemoteDescriptionWithoutError(offer.release());
honghaiz503726c2015-07-31 12:37:38 -07002887 EXPECT_EQ(0, session_->remote_description()->candidates(0)->count());
2888}
2889
Honghai Zhang04e91462015-12-11 14:26:22 -08002890// Test that if the remote answer indicates the peer requested ICE restart (via
2891// a new ufrag or pwd), the old ICE candidates are not copied, and vice versa.
2892TEST_F(WebRtcSessionTest, TestSetRemoteAnswerWithIceRestart) {
2893 Init();
2894 SessionDescriptionInterface* offer = CreateOffer();
2895 SetLocalDescriptionWithoutError(offer);
Honghai Zhang04e91462015-12-11 14:26:22 -08002896
2897 // Create the first answer.
kwibergd1fe2812016-04-27 06:47:29 -07002898 std::unique_ptr<JsepSessionDescription> answer(CreateRemoteAnswer(offer));
deadbeef0ed85b22016-02-23 17:24:52 -08002899 answer->set_type(JsepSessionDescription::kPrAnswer);
2900 SetIceUfragPwd(answer.get(), "0123456789012345", "abcdefghijklmnopqrstuvwx");
Honghai Zhang04e91462015-12-11 14:26:22 -08002901 cricket::Candidate candidate1(1, "udp", rtc::SocketAddress("1.1.1.1", 5000),
2902 0, "", "", "relay", 0, "");
2903 JsepIceCandidate ice_candidate1(kMediaContentName0, kMediaContentIndex0,
2904 candidate1);
deadbeef0ed85b22016-02-23 17:24:52 -08002905 EXPECT_TRUE(answer->AddCandidate(&ice_candidate1));
2906 SetRemoteDescriptionWithoutError(answer.release());
Honghai Zhang04e91462015-12-11 14:26:22 -08002907 EXPECT_EQ(1, session_->remote_description()->candidates(0)->count());
2908
2909 // The second answer has the same ufrag and pwd but different address.
deadbeef0ed85b22016-02-23 17:24:52 -08002910 answer.reset(CreateRemoteAnswer(offer));
2911 answer->set_type(JsepSessionDescription::kPrAnswer);
2912 SetIceUfragPwd(answer.get(), "0123456789012345", "abcdefghijklmnopqrstuvwx");
Honghai Zhang04e91462015-12-11 14:26:22 -08002913 candidate1.set_address(rtc::SocketAddress("1.1.1.1", 6000));
2914 JsepIceCandidate ice_candidate2(kMediaContentName0, kMediaContentIndex0,
2915 candidate1);
deadbeef0ed85b22016-02-23 17:24:52 -08002916 EXPECT_TRUE(answer->AddCandidate(&ice_candidate2));
2917 SetRemoteDescriptionWithoutError(answer.release());
Honghai Zhang04e91462015-12-11 14:26:22 -08002918 EXPECT_EQ(2, session_->remote_description()->candidates(0)->count());
2919
2920 // The third answer has a different ufrag and different address.
deadbeef0ed85b22016-02-23 17:24:52 -08002921 answer.reset(CreateRemoteAnswer(offer));
2922 answer->set_type(JsepSessionDescription::kPrAnswer);
2923 SetIceUfragPwd(answer.get(), "0123456789012333", "abcdefghijklmnopqrstuvwx");
Honghai Zhang04e91462015-12-11 14:26:22 -08002924 candidate1.set_address(rtc::SocketAddress("1.1.1.1", 7000));
2925 JsepIceCandidate ice_candidate3(kMediaContentName0, kMediaContentIndex0,
2926 candidate1);
deadbeef0ed85b22016-02-23 17:24:52 -08002927 EXPECT_TRUE(answer->AddCandidate(&ice_candidate3));
2928 SetRemoteDescriptionWithoutError(answer.release());
Honghai Zhang04e91462015-12-11 14:26:22 -08002929 EXPECT_EQ(1, session_->remote_description()->candidates(0)->count());
2930
2931 // The fourth answer has no candidate but a different ufrag/pwd.
deadbeef0ed85b22016-02-23 17:24:52 -08002932 answer.reset(CreateRemoteAnswer(offer));
2933 answer->set_type(JsepSessionDescription::kPrAnswer);
2934 SetIceUfragPwd(answer.get(), "0123456789012444", "abcdefghijklmnopqrstuvyz");
2935 SetRemoteDescriptionWithoutError(answer.release());
Honghai Zhang04e91462015-12-11 14:26:22 -08002936 EXPECT_EQ(0, session_->remote_description()->candidates(0)->count());
2937}
2938
Donald Curtisd4f769d2015-05-28 09:48:21 -07002939// Test that candidates sent to the "video" transport do not get pushed down to
deadbeefd59daf82015-10-14 15:02:44 -07002940// the "audio" transport channel when bundling.
Donald Curtisd4f769d2015-05-28 09:48:21 -07002941TEST_F(WebRtcSessionTest, TestIgnoreCandidatesForUnusedTransportWhenBundling) {
2942 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
2943
2944 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyBalanced);
deadbeefab9b2d12015-10-14 11:33:11 -07002945 SendAudioVideoStream1();
Donald Curtisd4f769d2015-05-28 09:48:21 -07002946
2947 PeerConnectionInterface::RTCOfferAnswerOptions options;
2948 options.use_rtp_mux = true;
2949
2950 SessionDescriptionInterface* offer = CreateRemoteOffer();
2951 SetRemoteDescriptionWithoutError(offer);
2952
htaa2a49d92016-03-04 02:51:39 -08002953 SessionDescriptionInterface* answer = CreateAnswer();
Donald Curtisd4f769d2015-05-28 09:48:21 -07002954 SetLocalDescriptionWithoutError(answer);
2955
deadbeefcbecd352015-09-23 11:50:27 -07002956 EXPECT_EQ(session_->voice_rtp_transport_channel(),
2957 session_->video_rtp_transport_channel());
Donald Curtisd4f769d2015-05-28 09:48:21 -07002958
deadbeefcbecd352015-09-23 11:50:27 -07002959 cricket::BaseChannel* voice_channel = session_->voice_channel();
2960 ASSERT(voice_channel != NULL);
Donald Curtisd4f769d2015-05-28 09:48:21 -07002961
2962 // Checks if one of the transport channels contains a connection using a given
2963 // port.
deadbeefcbecd352015-09-23 11:50:27 -07002964 auto connection_with_remote_port = [this, voice_channel](int port) {
deadbeefd59daf82015-10-14 15:02:44 -07002965 SessionStats stats;
deadbeefcbecd352015-09-23 11:50:27 -07002966 session_->GetChannelTransportStats(voice_channel, &stats);
2967 for (auto& kv : stats.transport_stats) {
2968 for (auto& chan_stat : kv.second.channel_stats) {
2969 for (auto& conn_info : chan_stat.connection_infos) {
2970 if (conn_info.remote_candidate.address().port() == port) {
2971 return true;
2972 }
Donald Curtisd4f769d2015-05-28 09:48:21 -07002973 }
2974 }
2975 }
2976 return false;
2977 };
2978
2979 EXPECT_FALSE(connection_with_remote_port(5000));
2980 EXPECT_FALSE(connection_with_remote_port(5001));
2981 EXPECT_FALSE(connection_with_remote_port(6000));
2982
2983 // The way the *_WAIT checks work is they only wait if the condition fails,
2984 // which does not help in the case where state is not changing. This is
2985 // problematic in this test since we want to verify that adding a video
2986 // candidate does _not_ change state. So we interleave candidates and assume
2987 // that messages are executed in the order they were posted.
2988
2989 // First audio candidate.
2990 cricket::Candidate candidate0;
2991 candidate0.set_address(rtc::SocketAddress("1.1.1.1", 5000));
2992 candidate0.set_component(1);
2993 candidate0.set_protocol("udp");
2994 JsepIceCandidate ice_candidate0(kMediaContentName0, kMediaContentIndex0,
2995 candidate0);
2996 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate0));
2997
2998 // Video candidate.
2999 cricket::Candidate candidate1;
3000 candidate1.set_address(rtc::SocketAddress("1.1.1.1", 6000));
3001 candidate1.set_component(1);
3002 candidate1.set_protocol("udp");
3003 JsepIceCandidate ice_candidate1(kMediaContentName1, kMediaContentIndex1,
3004 candidate1);
3005 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
3006
3007 // Second audio candidate.
3008 cricket::Candidate candidate2;
3009 candidate2.set_address(rtc::SocketAddress("1.1.1.1", 5001));
3010 candidate2.set_component(1);
3011 candidate2.set_protocol("udp");
3012 JsepIceCandidate ice_candidate2(kMediaContentName0, kMediaContentIndex0,
3013 candidate2);
3014 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
3015
3016 EXPECT_TRUE_WAIT(connection_with_remote_port(5000), 1000);
3017 EXPECT_TRUE_WAIT(connection_with_remote_port(5001), 1000);
3018
3019 // No need here for a _WAIT check since we are checking that state hasn't
3020 // changed: if this is false we would be doing waits for nothing and if this
3021 // is true then there will be no messages processed anyways.
3022 EXPECT_FALSE(connection_with_remote_port(6000));
3023}
3024
deadbeefcbecd352015-09-23 11:50:27 -07003025// kBundlePolicyBalanced BUNDLE policy and answer contains BUNDLE.
Donald Curtis0e209b02015-03-24 09:29:54 -07003026TEST_F(WebRtcSessionTest, TestBalancedBundleInAnswer) {
3027 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyBalanced);
deadbeefab9b2d12015-10-14 11:33:11 -07003028 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00003029
3030 PeerConnectionInterface::RTCOfferAnswerOptions options;
3031 options.use_rtp_mux = true;
3032
3033 SessionDescriptionInterface* offer = CreateOffer(options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003034 SetLocalDescriptionWithoutError(offer);
Donald Curtis0e209b02015-03-24 09:29:54 -07003035
deadbeefcbecd352015-09-23 11:50:27 -07003036 EXPECT_NE(session_->voice_rtp_transport_channel(),
3037 session_->video_rtp_transport_channel());
Donald Curtis0e209b02015-03-24 09:29:54 -07003038
deadbeefab9b2d12015-10-14 11:33:11 -07003039 SendAudioVideoStream2();
Donald Curtis0e209b02015-03-24 09:29:54 -07003040 SessionDescriptionInterface* answer =
3041 CreateRemoteAnswer(session_->local_description());
3042 SetRemoteDescriptionWithoutError(answer);
3043
deadbeefcbecd352015-09-23 11:50:27 -07003044 EXPECT_EQ(session_->voice_rtp_transport_channel(),
3045 session_->video_rtp_transport_channel());
Donald Curtis0e209b02015-03-24 09:29:54 -07003046}
3047
deadbeefcbecd352015-09-23 11:50:27 -07003048// kBundlePolicyBalanced BUNDLE policy but no BUNDLE in the answer.
Donald Curtis0e209b02015-03-24 09:29:54 -07003049TEST_F(WebRtcSessionTest, TestBalancedNoBundleInAnswer) {
3050 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyBalanced);
deadbeefab9b2d12015-10-14 11:33:11 -07003051 SendAudioVideoStream1();
Peter Thatcher4eddf182015-04-30 10:55:59 -07003052
Donald Curtis0e209b02015-03-24 09:29:54 -07003053 PeerConnectionInterface::RTCOfferAnswerOptions options;
3054 options.use_rtp_mux = true;
3055
3056 SessionDescriptionInterface* offer = CreateOffer(options);
3057 SetLocalDescriptionWithoutError(offer);
3058
deadbeefcbecd352015-09-23 11:50:27 -07003059 EXPECT_NE(session_->voice_rtp_transport_channel(),
3060 session_->video_rtp_transport_channel());
Donald Curtis0e209b02015-03-24 09:29:54 -07003061
deadbeefab9b2d12015-10-14 11:33:11 -07003062 SendAudioVideoStream2();
Donald Curtis0e209b02015-03-24 09:29:54 -07003063
3064 // Remove BUNDLE from the answer.
kwibergd1fe2812016-04-27 06:47:29 -07003065 std::unique_ptr<SessionDescriptionInterface> answer(
Donald Curtis0e209b02015-03-24 09:29:54 -07003066 CreateRemoteAnswer(session_->local_description()));
3067 cricket::SessionDescription* answer_copy = answer->description()->Copy();
3068 answer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
3069 JsepSessionDescription* modified_answer =
3070 new JsepSessionDescription(JsepSessionDescription::kAnswer);
3071 modified_answer->Initialize(answer_copy, "1", "1");
3072 SetRemoteDescriptionWithoutError(modified_answer); //
3073
deadbeefcbecd352015-09-23 11:50:27 -07003074 EXPECT_NE(session_->voice_rtp_transport_channel(),
3075 session_->video_rtp_transport_channel());
Donald Curtis0e209b02015-03-24 09:29:54 -07003076}
3077
3078// kBundlePolicyMaxBundle policy with BUNDLE in the answer.
3079TEST_F(WebRtcSessionTest, TestMaxBundleBundleInAnswer) {
3080 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle);
deadbeefab9b2d12015-10-14 11:33:11 -07003081 SendAudioVideoStream1();
Donald Curtis0e209b02015-03-24 09:29:54 -07003082
3083 PeerConnectionInterface::RTCOfferAnswerOptions options;
3084 options.use_rtp_mux = true;
3085
3086 SessionDescriptionInterface* offer = CreateOffer(options);
3087 SetLocalDescriptionWithoutError(offer);
3088
deadbeefcbecd352015-09-23 11:50:27 -07003089 EXPECT_EQ(session_->voice_rtp_transport_channel(),
3090 session_->video_rtp_transport_channel());
Donald Curtis0e209b02015-03-24 09:29:54 -07003091
deadbeefab9b2d12015-10-14 11:33:11 -07003092 SendAudioVideoStream2();
Donald Curtis0e209b02015-03-24 09:29:54 -07003093 SessionDescriptionInterface* answer =
3094 CreateRemoteAnswer(session_->local_description());
3095 SetRemoteDescriptionWithoutError(answer);
3096
deadbeefcbecd352015-09-23 11:50:27 -07003097 EXPECT_EQ(session_->voice_rtp_transport_channel(),
3098 session_->video_rtp_transport_channel());
3099}
3100
3101// kBundlePolicyMaxBundle policy with BUNDLE in the answer, but no
3102// audio content in the answer.
3103TEST_F(WebRtcSessionTest, TestMaxBundleRejectAudio) {
3104 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle);
deadbeefab9b2d12015-10-14 11:33:11 -07003105 SendAudioVideoStream1();
deadbeefcbecd352015-09-23 11:50:27 -07003106
3107 PeerConnectionInterface::RTCOfferAnswerOptions options;
3108 options.use_rtp_mux = true;
3109
3110 SessionDescriptionInterface* offer = CreateOffer(options);
3111 SetLocalDescriptionWithoutError(offer);
3112
3113 EXPECT_EQ(session_->voice_rtp_transport_channel(),
3114 session_->video_rtp_transport_channel());
3115
deadbeefab9b2d12015-10-14 11:33:11 -07003116 SendAudioVideoStream2();
deadbeefcbecd352015-09-23 11:50:27 -07003117 cricket::MediaSessionOptions recv_options;
3118 recv_options.recv_audio = false;
3119 recv_options.recv_video = true;
3120 SessionDescriptionInterface* answer =
3121 CreateRemoteAnswer(session_->local_description(), recv_options);
3122 SetRemoteDescriptionWithoutError(answer);
3123
deadbeefd59daf82015-10-14 15:02:44 -07003124 EXPECT_TRUE(nullptr == session_->voice_channel());
3125 EXPECT_TRUE(nullptr != session_->video_rtp_transport_channel());
deadbeefcbecd352015-09-23 11:50:27 -07003126
deadbeefd59daf82015-10-14 15:02:44 -07003127 session_->Close();
3128 EXPECT_TRUE(nullptr == session_->voice_rtp_transport_channel());
3129 EXPECT_TRUE(nullptr == session_->voice_rtcp_transport_channel());
3130 EXPECT_TRUE(nullptr == session_->video_rtp_transport_channel());
3131 EXPECT_TRUE(nullptr == session_->video_rtcp_transport_channel());
Donald Curtis0e209b02015-03-24 09:29:54 -07003132}
3133
3134// kBundlePolicyMaxBundle policy but no BUNDLE in the answer.
3135TEST_F(WebRtcSessionTest, TestMaxBundleNoBundleInAnswer) {
3136 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle);
deadbeefab9b2d12015-10-14 11:33:11 -07003137 SendAudioVideoStream1();
Peter Thatcher4eddf182015-04-30 10:55:59 -07003138
Donald Curtis0e209b02015-03-24 09:29:54 -07003139 PeerConnectionInterface::RTCOfferAnswerOptions options;
3140 options.use_rtp_mux = true;
3141
3142 SessionDescriptionInterface* offer = CreateOffer(options);
3143 SetLocalDescriptionWithoutError(offer);
3144
deadbeefcbecd352015-09-23 11:50:27 -07003145 EXPECT_EQ(session_->voice_rtp_transport_channel(),
3146 session_->video_rtp_transport_channel());
Donald Curtis0e209b02015-03-24 09:29:54 -07003147
deadbeefab9b2d12015-10-14 11:33:11 -07003148 SendAudioVideoStream2();
Donald Curtis0e209b02015-03-24 09:29:54 -07003149
3150 // Remove BUNDLE from the answer.
kwibergd1fe2812016-04-27 06:47:29 -07003151 std::unique_ptr<SessionDescriptionInterface> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003152 CreateRemoteAnswer(session_->local_description()));
3153 cricket::SessionDescription* answer_copy = answer->description()->Copy();
3154 answer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
3155 JsepSessionDescription* modified_answer =
3156 new JsepSessionDescription(JsepSessionDescription::kAnswer);
3157 modified_answer->Initialize(answer_copy, "1", "1");
3158 SetRemoteDescriptionWithoutError(modified_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003159
deadbeefcbecd352015-09-23 11:50:27 -07003160 EXPECT_EQ(session_->voice_rtp_transport_channel(),
3161 session_->video_rtp_transport_channel());
3162}
3163
3164// kBundlePolicyMaxBundle policy with BUNDLE in the remote offer.
3165TEST_F(WebRtcSessionTest, TestMaxBundleBundleInRemoteOffer) {
3166 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle);
deadbeefab9b2d12015-10-14 11:33:11 -07003167 SendAudioVideoStream1();
deadbeefcbecd352015-09-23 11:50:27 -07003168
3169 SessionDescriptionInterface* offer = CreateRemoteOffer();
3170 SetRemoteDescriptionWithoutError(offer);
3171
3172 EXPECT_EQ(session_->voice_rtp_transport_channel(),
3173 session_->video_rtp_transport_channel());
3174
deadbeefab9b2d12015-10-14 11:33:11 -07003175 SendAudioVideoStream2();
htaa2a49d92016-03-04 02:51:39 -08003176 SessionDescriptionInterface* answer = CreateAnswer();
deadbeefcbecd352015-09-23 11:50:27 -07003177 SetLocalDescriptionWithoutError(answer);
3178
3179 EXPECT_EQ(session_->voice_rtp_transport_channel(),
3180 session_->video_rtp_transport_channel());
3181}
3182
3183// kBundlePolicyMaxBundle policy but no BUNDLE in the remote offer.
3184TEST_F(WebRtcSessionTest, TestMaxBundleNoBundleInRemoteOffer) {
3185 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle);
deadbeefab9b2d12015-10-14 11:33:11 -07003186 SendAudioVideoStream1();
deadbeefcbecd352015-09-23 11:50:27 -07003187
3188 // Remove BUNDLE from the offer.
kwibergd1fe2812016-04-27 06:47:29 -07003189 std::unique_ptr<SessionDescriptionInterface> offer(CreateRemoteOffer());
deadbeefcbecd352015-09-23 11:50:27 -07003190 cricket::SessionDescription* offer_copy = offer->description()->Copy();
3191 offer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
3192 JsepSessionDescription* modified_offer =
3193 new JsepSessionDescription(JsepSessionDescription::kOffer);
3194 modified_offer->Initialize(offer_copy, "1", "1");
3195
3196 // Expect an error when applying the remote description
3197 SetRemoteDescriptionExpectError(JsepSessionDescription::kOffer,
3198 kCreateChannelFailed, modified_offer);
Donald Curtis0e209b02015-03-24 09:29:54 -07003199}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003200
Peter Thatcher4eddf182015-04-30 10:55:59 -07003201// kBundlePolicyMaxCompat bundle policy and answer contains BUNDLE.
Donald Curtis0e209b02015-03-24 09:29:54 -07003202TEST_F(WebRtcSessionTest, TestMaxCompatBundleInAnswer) {
3203 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxCompat);
deadbeefab9b2d12015-10-14 11:33:11 -07003204 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003205
Donald Curtis0e209b02015-03-24 09:29:54 -07003206 PeerConnectionInterface::RTCOfferAnswerOptions options;
3207 options.use_rtp_mux = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003208
Donald Curtis0e209b02015-03-24 09:29:54 -07003209 SessionDescriptionInterface* offer = CreateOffer(options);
3210 SetLocalDescriptionWithoutError(offer);
3211
deadbeefcbecd352015-09-23 11:50:27 -07003212 EXPECT_NE(session_->voice_rtp_transport_channel(),
3213 session_->video_rtp_transport_channel());
Donald Curtis0e209b02015-03-24 09:29:54 -07003214
deadbeefab9b2d12015-10-14 11:33:11 -07003215 SendAudioVideoStream2();
Donald Curtis0e209b02015-03-24 09:29:54 -07003216 SessionDescriptionInterface* answer =
3217 CreateRemoteAnswer(session_->local_description());
3218 SetRemoteDescriptionWithoutError(answer);
3219
3220 // This should lead to an audio-only call but isn't implemented
3221 // correctly yet.
deadbeefcbecd352015-09-23 11:50:27 -07003222 EXPECT_EQ(session_->voice_rtp_transport_channel(),
3223 session_->video_rtp_transport_channel());
Donald Curtis0e209b02015-03-24 09:29:54 -07003224}
3225
deadbeefcbecd352015-09-23 11:50:27 -07003226// kBundlePolicyMaxCompat BUNDLE policy but no BUNDLE in the answer.
Donald Curtis0e209b02015-03-24 09:29:54 -07003227TEST_F(WebRtcSessionTest, TestMaxCompatNoBundleInAnswer) {
3228 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxCompat);
deadbeefab9b2d12015-10-14 11:33:11 -07003229 SendAudioVideoStream1();
Donald Curtis0e209b02015-03-24 09:29:54 -07003230 PeerConnectionInterface::RTCOfferAnswerOptions options;
3231 options.use_rtp_mux = true;
3232
3233 SessionDescriptionInterface* offer = CreateOffer(options);
3234 SetLocalDescriptionWithoutError(offer);
3235
deadbeefcbecd352015-09-23 11:50:27 -07003236 EXPECT_NE(session_->voice_rtp_transport_channel(),
3237 session_->video_rtp_transport_channel());
Donald Curtis0e209b02015-03-24 09:29:54 -07003238
deadbeefab9b2d12015-10-14 11:33:11 -07003239 SendAudioVideoStream2();
Donald Curtis0e209b02015-03-24 09:29:54 -07003240
3241 // Remove BUNDLE from the answer.
kwibergd1fe2812016-04-27 06:47:29 -07003242 std::unique_ptr<SessionDescriptionInterface> answer(
Donald Curtis0e209b02015-03-24 09:29:54 -07003243 CreateRemoteAnswer(session_->local_description()));
3244 cricket::SessionDescription* answer_copy = answer->description()->Copy();
3245 answer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
3246 JsepSessionDescription* modified_answer =
3247 new JsepSessionDescription(JsepSessionDescription::kAnswer);
3248 modified_answer->Initialize(answer_copy, "1", "1");
3249 SetRemoteDescriptionWithoutError(modified_answer); //
3250
deadbeefcbecd352015-09-23 11:50:27 -07003251 EXPECT_NE(session_->voice_rtp_transport_channel(),
3252 session_->video_rtp_transport_channel());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003253}
3254
Peter Thatcher4eddf182015-04-30 10:55:59 -07003255// kBundlePolicyMaxbundle and then we call SetRemoteDescription first.
3256TEST_F(WebRtcSessionTest, TestMaxBundleWithSetRemoteDescriptionFirst) {
3257 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle);
deadbeefab9b2d12015-10-14 11:33:11 -07003258 SendAudioVideoStream1();
Peter Thatcher4eddf182015-04-30 10:55:59 -07003259
3260 PeerConnectionInterface::RTCOfferAnswerOptions options;
3261 options.use_rtp_mux = true;
3262
3263 SessionDescriptionInterface* offer = CreateOffer(options);
3264 SetRemoteDescriptionWithoutError(offer);
3265
deadbeefcbecd352015-09-23 11:50:27 -07003266 EXPECT_EQ(session_->voice_rtp_transport_channel(),
3267 session_->video_rtp_transport_channel());
Peter Thatcher4eddf182015-04-30 10:55:59 -07003268}
3269
skvlad6c87a672016-05-17 17:49:52 -07003270// Adding a new channel to a BUNDLE which is already connected should directly
3271// assign the bundle transport to the channel, without first setting a
3272// disconnected non-bundle transport and then replacing it. The application
3273// should not receive any changes in the ICE state.
3274TEST_F(WebRtcSessionTest, TestAddChannelToConnectedBundle) {
3275 LoopbackNetworkConfiguration config;
3276 LoopbackNetworkManager loopback_network_manager(this, config);
3277 // Both BUNDLE and RTCP-mux need to be enabled for the ICE state to remain
3278 // connected. Disabling either of these two means that we need to wait for the
3279 // answer to find out if more transports are needed.
3280 configuration_.bundle_policy =
3281 PeerConnectionInterface::kBundlePolicyMaxBundle;
3282 configuration_.rtcp_mux_policy =
3283 PeerConnectionInterface::kRtcpMuxPolicyRequire;
3284 options_.disable_encryption = true;
3285 Init();
3286
3287 // Negotiate an audio channel with MAX_BUNDLE enabled.
3288 SendAudioOnlyStream2();
3289 SessionDescriptionInterface* offer = CreateOffer();
3290 SetLocalDescriptionWithoutError(offer);
3291 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringComplete,
3292 observer_.ice_gathering_state_, kIceCandidatesTimeout);
3293 std::string sdp;
3294 offer->ToString(&sdp);
3295 SessionDescriptionInterface* answer = webrtc::CreateSessionDescription(
3296 JsepSessionDescription::kAnswer, sdp, nullptr);
3297 ASSERT_TRUE(answer != NULL);
3298 SetRemoteDescriptionWithoutError(answer);
3299
3300 // Wait for the ICE state to stabilize.
3301 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
3302 observer_.ice_connection_state_, kIceCandidatesTimeout);
3303 observer_.ice_connection_state_history_.clear();
3304
3305 // Now add a video channel which should be using the same bundle transport.
3306 SendAudioVideoStream2();
3307 offer = CreateOffer();
3308 offer->ToString(&sdp);
3309 SetLocalDescriptionWithoutError(offer);
3310 answer = webrtc::CreateSessionDescription(JsepSessionDescription::kAnswer,
3311 sdp, nullptr);
3312 ASSERT_TRUE(answer != NULL);
3313 SetRemoteDescriptionWithoutError(answer);
3314
3315 // Wait for ICE state to stabilize
3316 rtc::Thread::Current()->ProcessMessages(0);
3317 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
3318 observer_.ice_connection_state_, kIceCandidatesTimeout);
3319
3320 // No ICE state changes are expected to happen.
3321 EXPECT_EQ(0, observer_.ice_connection_state_history_.size());
3322}
3323
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07003324TEST_F(WebRtcSessionTest, TestRequireRtcpMux) {
3325 InitWithRtcpMuxPolicy(PeerConnectionInterface::kRtcpMuxPolicyRequire);
deadbeefab9b2d12015-10-14 11:33:11 -07003326 SendAudioVideoStream1();
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07003327
3328 PeerConnectionInterface::RTCOfferAnswerOptions options;
3329 SessionDescriptionInterface* offer = CreateOffer(options);
3330 SetLocalDescriptionWithoutError(offer);
3331
deadbeefcbecd352015-09-23 11:50:27 -07003332 EXPECT_TRUE(session_->voice_rtcp_transport_channel() == NULL);
3333 EXPECT_TRUE(session_->video_rtcp_transport_channel() == NULL);
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07003334
deadbeefab9b2d12015-10-14 11:33:11 -07003335 SendAudioVideoStream2();
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07003336 SessionDescriptionInterface* answer =
3337 CreateRemoteAnswer(session_->local_description());
3338 SetRemoteDescriptionWithoutError(answer);
3339
deadbeefcbecd352015-09-23 11:50:27 -07003340 EXPECT_TRUE(session_->voice_rtcp_transport_channel() == NULL);
3341 EXPECT_TRUE(session_->video_rtcp_transport_channel() == NULL);
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07003342}
3343
3344TEST_F(WebRtcSessionTest, TestNegotiateRtcpMux) {
3345 InitWithRtcpMuxPolicy(PeerConnectionInterface::kRtcpMuxPolicyNegotiate);
deadbeefab9b2d12015-10-14 11:33:11 -07003346 SendAudioVideoStream1();
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07003347
3348 PeerConnectionInterface::RTCOfferAnswerOptions options;
3349 SessionDescriptionInterface* offer = CreateOffer(options);
3350 SetLocalDescriptionWithoutError(offer);
3351
deadbeefcbecd352015-09-23 11:50:27 -07003352 EXPECT_TRUE(session_->voice_rtcp_transport_channel() != NULL);
3353 EXPECT_TRUE(session_->video_rtcp_transport_channel() != NULL);
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07003354
deadbeefab9b2d12015-10-14 11:33:11 -07003355 SendAudioVideoStream2();
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07003356 SessionDescriptionInterface* answer =
3357 CreateRemoteAnswer(session_->local_description());
3358 SetRemoteDescriptionWithoutError(answer);
3359
deadbeefcbecd352015-09-23 11:50:27 -07003360 EXPECT_TRUE(session_->voice_rtcp_transport_channel() == NULL);
3361 EXPECT_TRUE(session_->video_rtcp_transport_channel() == NULL);
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07003362}
3363
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00003364// This test verifies that SetLocalDescription and SetRemoteDescription fails
3365// if BUNDLE is enabled but rtcp-mux is disabled in m-lines.
3366TEST_F(WebRtcSessionTest, TestDisabledRtcpMuxWithBundleEnabled) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003367 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07003368 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00003369
3370 PeerConnectionInterface::RTCOfferAnswerOptions options;
3371 options.use_rtp_mux = true;
3372
3373 SessionDescriptionInterface* offer = CreateOffer(options);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00003374 std::string offer_str;
3375 offer->ToString(&offer_str);
3376 // Disable rtcp-mux
3377 const std::string rtcp_mux = "rtcp-mux";
3378 const std::string xrtcp_mux = "xrtcp-mux";
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003379 rtc::replace_substrs(rtcp_mux.c_str(), rtcp_mux.length(),
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00003380 xrtcp_mux.c_str(), xrtcp_mux.length(),
3381 &offer_str);
deadbeefcbecd352015-09-23 11:50:27 -07003382 JsepSessionDescription* local_offer =
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00003383 new JsepSessionDescription(JsepSessionDescription::kOffer);
3384 EXPECT_TRUE((local_offer)->Initialize(offer_str, NULL));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00003385 SetLocalDescriptionOfferExpectError(kBundleWithoutRtcpMux, local_offer);
deadbeefcbecd352015-09-23 11:50:27 -07003386 JsepSessionDescription* remote_offer =
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00003387 new JsepSessionDescription(JsepSessionDescription::kOffer);
3388 EXPECT_TRUE((remote_offer)->Initialize(offer_str, NULL));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00003389 SetRemoteDescriptionOfferExpectError(kBundleWithoutRtcpMux, remote_offer);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00003390 // Trying unmodified SDP.
3391 SetLocalDescriptionWithoutError(offer);
3392}
3393
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003394TEST_F(WebRtcSessionTest, SetAudioPlayout) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003395 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07003396 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003397 CreateAndSetRemoteOfferAndLocalAnswer();
3398 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
3399 ASSERT_TRUE(channel != NULL);
3400 ASSERT_EQ(1u, channel->recv_streams().size());
Peter Boström0c4e06b2015-10-07 12:23:21 +02003401 uint32_t receive_ssrc = channel->recv_streams()[0].first_ssrc();
solenberg4bac9c52015-10-09 02:32:53 -07003402 double volume;
3403 EXPECT_TRUE(channel->GetOutputVolume(receive_ssrc, &volume));
3404 EXPECT_EQ(1, volume);
solenbergd4cec0d2015-10-09 08:55:48 -07003405 session_->SetAudioPlayout(receive_ssrc, false);
solenberg4bac9c52015-10-09 02:32:53 -07003406 EXPECT_TRUE(channel->GetOutputVolume(receive_ssrc, &volume));
3407 EXPECT_EQ(0, volume);
solenbergd4cec0d2015-10-09 08:55:48 -07003408 session_->SetAudioPlayout(receive_ssrc, true);
solenberg4bac9c52015-10-09 02:32:53 -07003409 EXPECT_TRUE(channel->GetOutputVolume(receive_ssrc, &volume));
3410 EXPECT_EQ(1, volume);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003411}
3412
skvlade0d46372016-04-07 22:59:22 -07003413TEST_F(WebRtcSessionTest, SetAudioMaxSendBitrate) {
skvladdc1c62c2016-03-16 19:07:43 -07003414 Init();
3415 SendAudioVideoStream1();
3416 CreateAndSetRemoteOfferAndLocalAnswer();
3417 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
3418 ASSERT_TRUE(channel != NULL);
3419 uint32_t send_ssrc = channel->send_streams()[0].first_ssrc();
skvlade0d46372016-04-07 22:59:22 -07003420 EXPECT_EQ(-1, channel->max_bps());
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07003421 webrtc::RtpParameters params = session_->GetAudioRtpSendParameters(send_ssrc);
skvlade0d46372016-04-07 22:59:22 -07003422 EXPECT_EQ(1, params.encodings.size());
3423 EXPECT_EQ(-1, params.encodings[0].max_bitrate_bps);
3424 params.encodings[0].max_bitrate_bps = 1000;
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07003425 EXPECT_TRUE(session_->SetAudioRtpSendParameters(send_ssrc, params));
skvladdc1c62c2016-03-16 19:07:43 -07003426
skvlade0d46372016-04-07 22:59:22 -07003427 // Read back the parameters and verify they have been changed.
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07003428 params = session_->GetAudioRtpSendParameters(send_ssrc);
skvlade0d46372016-04-07 22:59:22 -07003429 EXPECT_EQ(1, params.encodings.size());
3430 EXPECT_EQ(1000, params.encodings[0].max_bitrate_bps);
3431
3432 // Verify that the audio channel received the new parameters.
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07003433 params = channel->GetRtpSendParameters(send_ssrc);
skvlade0d46372016-04-07 22:59:22 -07003434 EXPECT_EQ(1, params.encodings.size());
3435 EXPECT_EQ(1000, params.encodings[0].max_bitrate_bps);
3436
3437 // Verify that the global bitrate limit has not been changed.
3438 EXPECT_EQ(-1, channel->max_bps());
skvladdc1c62c2016-03-16 19:07:43 -07003439}
3440
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003441TEST_F(WebRtcSessionTest, SetAudioSend) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003442 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07003443 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003444 CreateAndSetRemoteOfferAndLocalAnswer();
3445 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
3446 ASSERT_TRUE(channel != NULL);
3447 ASSERT_EQ(1u, channel->send_streams().size());
Peter Boström0c4e06b2015-10-07 12:23:21 +02003448 uint32_t send_ssrc = channel->send_streams()[0].first_ssrc();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003449 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
3450
3451 cricket::AudioOptions options;
Karl Wibergbe579832015-11-10 22:34:18 +01003452 options.echo_cancellation = rtc::Optional<bool>(true);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003453
kwibergd1fe2812016-04-27 06:47:29 -07003454 std::unique_ptr<FakeAudioSource> source(new FakeAudioSource());
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08003455 session_->SetAudioSend(send_ssrc, false, options, source.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003456 EXPECT_TRUE(channel->IsStreamMuted(send_ssrc));
Karl Wibergbe579832015-11-10 22:34:18 +01003457 EXPECT_EQ(rtc::Optional<bool>(), channel->options().echo_cancellation);
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08003458 EXPECT_TRUE(source->sink() != nullptr);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003459
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08003460 // This will trigger SetSink(nullptr) to the |source|.
3461 session_->SetAudioSend(send_ssrc, true, options, nullptr);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003462 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
Karl Wibergbe579832015-11-10 22:34:18 +01003463 EXPECT_EQ(rtc::Optional<bool>(true), channel->options().echo_cancellation);
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08003464 EXPECT_TRUE(source->sink() == nullptr);
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00003465}
3466
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08003467TEST_F(WebRtcSessionTest, AudioSourceForLocalStream) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003468 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07003469 SendAudioVideoStream1();
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00003470 CreateAndSetRemoteOfferAndLocalAnswer();
3471 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
3472 ASSERT_TRUE(channel != NULL);
3473 ASSERT_EQ(1u, channel->send_streams().size());
Peter Boström0c4e06b2015-10-07 12:23:21 +02003474 uint32_t send_ssrc = channel->send_streams()[0].first_ssrc();
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00003475
kwibergd1fe2812016-04-27 06:47:29 -07003476 std::unique_ptr<FakeAudioSource> source(new FakeAudioSource());
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00003477 cricket::AudioOptions options;
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08003478 session_->SetAudioSend(send_ssrc, true, options, source.get());
3479 EXPECT_TRUE(source->sink() != nullptr);
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00003480
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08003481 // Delete the |source| and it will trigger OnClose() to the sink, and this
3482 // will invalidate the |source_| pointer in the sink and prevent getting a
3483 // SetSink(nullptr) callback afterwards.
3484 source.reset();
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00003485
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08003486 // This will trigger SetSink(nullptr) if no OnClose() callback.
3487 session_->SetAudioSend(send_ssrc, true, options, nullptr);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003488}
3489
3490TEST_F(WebRtcSessionTest, SetVideoPlayout) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003491 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07003492 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003493 CreateAndSetRemoteOfferAndLocalAnswer();
3494 cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0);
3495 ASSERT_TRUE(channel != NULL);
nisse08582ff2016-02-04 01:24:52 -08003496 ASSERT_LT(0u, channel->sinks().size());
3497 EXPECT_TRUE(channel->sinks().begin()->second == NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003498 ASSERT_EQ(1u, channel->recv_streams().size());
Peter Boström0c4e06b2015-10-07 12:23:21 +02003499 uint32_t receive_ssrc = channel->recv_streams()[0].first_ssrc();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003500 cricket::FakeVideoRenderer renderer;
3501 session_->SetVideoPlayout(receive_ssrc, true, &renderer);
nisse08582ff2016-02-04 01:24:52 -08003502 EXPECT_TRUE(channel->sinks().begin()->second == &renderer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003503 session_->SetVideoPlayout(receive_ssrc, false, &renderer);
nisse08582ff2016-02-04 01:24:52 -08003504 EXPECT_TRUE(channel->sinks().begin()->second == NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003505}
3506
skvladdc1c62c2016-03-16 19:07:43 -07003507TEST_F(WebRtcSessionTest, SetVideoMaxSendBitrate) {
3508 Init();
3509 SendAudioVideoStream1();
3510 CreateAndSetRemoteOfferAndLocalAnswer();
3511 cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0);
3512 ASSERT_TRUE(channel != NULL);
3513 uint32_t send_ssrc = channel->send_streams()[0].first_ssrc();
3514 EXPECT_EQ(-1, channel->max_bps());
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07003515 webrtc::RtpParameters params = session_->GetVideoRtpSendParameters(send_ssrc);
skvladdc1c62c2016-03-16 19:07:43 -07003516 EXPECT_EQ(1, params.encodings.size());
3517 EXPECT_EQ(-1, params.encodings[0].max_bitrate_bps);
3518 params.encodings[0].max_bitrate_bps = 1000;
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07003519 EXPECT_TRUE(session_->SetVideoRtpSendParameters(send_ssrc, params));
skvladdc1c62c2016-03-16 19:07:43 -07003520
3521 // Read back the parameters and verify they have been changed.
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07003522 params = session_->GetVideoRtpSendParameters(send_ssrc);
skvladdc1c62c2016-03-16 19:07:43 -07003523 EXPECT_EQ(1, params.encodings.size());
3524 EXPECT_EQ(1000, params.encodings[0].max_bitrate_bps);
3525
3526 // Verify that the video channel received the new parameters.
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07003527 params = channel->GetRtpSendParameters(send_ssrc);
skvladdc1c62c2016-03-16 19:07:43 -07003528 EXPECT_EQ(1, params.encodings.size());
3529 EXPECT_EQ(1000, params.encodings[0].max_bitrate_bps);
3530
3531 // Verify that the global bitrate limit has not been changed.
3532 EXPECT_EQ(-1, channel->max_bps());
3533}
3534
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003535TEST_F(WebRtcSessionTest, SetVideoSend) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003536 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07003537 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003538 CreateAndSetRemoteOfferAndLocalAnswer();
3539 cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0);
3540 ASSERT_TRUE(channel != NULL);
3541 ASSERT_EQ(1u, channel->send_streams().size());
Peter Boström0c4e06b2015-10-07 12:23:21 +02003542 uint32_t send_ssrc = channel->send_streams()[0].first_ssrc();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003543 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
3544 cricket::VideoOptions* options = NULL;
deadbeef5a4a75a2016-06-02 16:23:38 -07003545 session_->SetVideoSend(send_ssrc, false, options, nullptr);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003546 EXPECT_TRUE(channel->IsStreamMuted(send_ssrc));
deadbeef5a4a75a2016-06-02 16:23:38 -07003547 session_->SetVideoSend(send_ssrc, true, options, nullptr);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003548 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
3549}
3550
3551TEST_F(WebRtcSessionTest, CanNotInsertDtmf) {
3552 TestCanInsertDtmf(false);
3553}
3554
3555TEST_F(WebRtcSessionTest, CanInsertDtmf) {
3556 TestCanInsertDtmf(true);
3557}
3558
3559TEST_F(WebRtcSessionTest, InsertDtmf) {
3560 // Setup
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003561 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07003562 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003563 CreateAndSetRemoteOfferAndLocalAnswer();
3564 FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
3565 EXPECT_EQ(0U, channel->dtmf_info_queue().size());
3566
3567 // Insert DTMF
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003568 const int expected_duration = 90;
3569 session_->InsertDtmf(kAudioTrack1, 0, expected_duration);
3570 session_->InsertDtmf(kAudioTrack1, 1, expected_duration);
3571 session_->InsertDtmf(kAudioTrack1, 2, expected_duration);
3572
3573 // Verify
3574 ASSERT_EQ(3U, channel->dtmf_info_queue().size());
Peter Boström0c4e06b2015-10-07 12:23:21 +02003575 const uint32_t send_ssrc = channel->send_streams()[0].first_ssrc();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003576 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[0], send_ssrc, 0,
solenberg1d63dd02015-12-02 12:35:09 -08003577 expected_duration));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003578 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[1], send_ssrc, 1,
solenberg1d63dd02015-12-02 12:35:09 -08003579 expected_duration));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003580 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[2], send_ssrc, 2,
solenberg1d63dd02015-12-02 12:35:09 -08003581 expected_duration));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003582}
3583
deadbeefd59daf82015-10-14 15:02:44 -07003584// This test verifies the |initial_offerer| flag when session initiates the
3585// call.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003586TEST_F(WebRtcSessionTest, TestInitiatorFlagAsOriginator) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003587 Init();
deadbeefd59daf82015-10-14 15:02:44 -07003588 EXPECT_FALSE(session_->initial_offerer());
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00003589 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003590 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
3591 SetLocalDescriptionWithoutError(offer);
deadbeefd59daf82015-10-14 15:02:44 -07003592 EXPECT_TRUE(session_->initial_offerer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003593 SetRemoteDescriptionWithoutError(answer);
deadbeefd59daf82015-10-14 15:02:44 -07003594 EXPECT_TRUE(session_->initial_offerer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003595}
3596
deadbeefd59daf82015-10-14 15:02:44 -07003597// This test verifies the |initial_offerer| flag when session receives the call.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003598TEST_F(WebRtcSessionTest, TestInitiatorFlagAsReceiver) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003599 Init();
deadbeefd59daf82015-10-14 15:02:44 -07003600 EXPECT_FALSE(session_->initial_offerer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003601 SessionDescriptionInterface* offer = CreateRemoteOffer();
3602 SetRemoteDescriptionWithoutError(offer);
htaa2a49d92016-03-04 02:51:39 -08003603 SessionDescriptionInterface* answer = CreateAnswer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003604
deadbeefd59daf82015-10-14 15:02:44 -07003605 EXPECT_FALSE(session_->initial_offerer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003606 SetLocalDescriptionWithoutError(answer);
deadbeefd59daf82015-10-14 15:02:44 -07003607 EXPECT_FALSE(session_->initial_offerer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003608}
3609
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003610// Verifing local offer and remote answer have matching m-lines as per RFC 3264.
3611TEST_F(WebRtcSessionTest, TestIncorrectMLinesInRemoteAnswer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003612 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07003613 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00003614 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003615 SetLocalDescriptionWithoutError(offer);
kwibergd1fe2812016-04-27 06:47:29 -07003616 std::unique_ptr<SessionDescriptionInterface> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003617 CreateRemoteAnswer(session_->local_description()));
3618
3619 cricket::SessionDescription* answer_copy = answer->description()->Copy();
3620 answer_copy->RemoveContentByName("video");
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00003621 JsepSessionDescription* modified_answer =
3622 new JsepSessionDescription(JsepSessionDescription::kAnswer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003623
3624 EXPECT_TRUE(modified_answer->Initialize(answer_copy,
3625 answer->session_id(),
3626 answer->session_version()));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00003627 SetRemoteDescriptionAnswerExpectError(kMlineMismatch, modified_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003628
wu@webrtc.org4e393072014-04-07 17:04:35 +00003629 // Different content names.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003630 std::string sdp;
3631 EXPECT_TRUE(answer->ToString(&sdp));
3632 const std::string kAudioMid = "a=mid:audio";
3633 const std::string kAudioMidReplaceStr = "a=mid:audio_content_name";
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003634 rtc::replace_substrs(kAudioMid.c_str(), kAudioMid.length(),
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003635 kAudioMidReplaceStr.c_str(),
3636 kAudioMidReplaceStr.length(),
3637 &sdp);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00003638 SessionDescriptionInterface* modified_answer1 =
3639 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00003640 SetRemoteDescriptionAnswerExpectError(kMlineMismatch, modified_answer1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003641
wu@webrtc.org4e393072014-04-07 17:04:35 +00003642 // Different media types.
3643 EXPECT_TRUE(answer->ToString(&sdp));
3644 const std::string kAudioMline = "m=audio";
3645 const std::string kAudioMlineReplaceStr = "m=video";
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003646 rtc::replace_substrs(kAudioMline.c_str(), kAudioMline.length(),
wu@webrtc.org4e393072014-04-07 17:04:35 +00003647 kAudioMlineReplaceStr.c_str(),
3648 kAudioMlineReplaceStr.length(),
3649 &sdp);
3650 SessionDescriptionInterface* modified_answer2 =
3651 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
3652 SetRemoteDescriptionAnswerExpectError(kMlineMismatch, modified_answer2);
3653
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003654 SetRemoteDescriptionWithoutError(answer.release());
3655}
3656
3657// Verifying remote offer and local answer have matching m-lines as per
3658// RFC 3264.
3659TEST_F(WebRtcSessionTest, TestIncorrectMLinesInLocalAnswer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003660 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07003661 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003662 SessionDescriptionInterface* offer = CreateRemoteOffer();
3663 SetRemoteDescriptionWithoutError(offer);
htaa2a49d92016-03-04 02:51:39 -08003664 SessionDescriptionInterface* answer = CreateAnswer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003665
3666 cricket::SessionDescription* answer_copy = answer->description()->Copy();
3667 answer_copy->RemoveContentByName("video");
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00003668 JsepSessionDescription* modified_answer =
3669 new JsepSessionDescription(JsepSessionDescription::kAnswer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003670
3671 EXPECT_TRUE(modified_answer->Initialize(answer_copy,
3672 answer->session_id(),
3673 answer->session_version()));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00003674 SetLocalDescriptionAnswerExpectError(kMlineMismatch, modified_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003675 SetLocalDescriptionWithoutError(answer);
3676}
3677
3678// This test verifies that WebRtcSession does not start candidate allocation
3679// before SetLocalDescription is called.
3680TEST_F(WebRtcSessionTest, TestIceStartAfterSetLocalDescriptionOnly) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003681 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07003682 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003683 SessionDescriptionInterface* offer = CreateRemoteOffer();
3684 cricket::Candidate candidate;
3685 candidate.set_component(1);
3686 JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0,
3687 candidate);
3688 EXPECT_TRUE(offer->AddCandidate(&ice_candidate));
3689 cricket::Candidate candidate1;
3690 candidate1.set_component(1);
3691 JsepIceCandidate ice_candidate1(kMediaContentName1, kMediaContentIndex1,
3692 candidate1);
3693 EXPECT_TRUE(offer->AddCandidate(&ice_candidate1));
3694 SetRemoteDescriptionWithoutError(offer);
deadbeefcbecd352015-09-23 11:50:27 -07003695 ASSERT_TRUE(session_->voice_rtp_transport_channel() != NULL);
3696 ASSERT_TRUE(session_->video_rtp_transport_channel() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003697
3698 // Pump for 1 second and verify that no candidates are generated.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003699 rtc::Thread::Current()->ProcessMessages(1000);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003700 EXPECT_TRUE(observer_.mline_0_candidates_.empty());
3701 EXPECT_TRUE(observer_.mline_1_candidates_.empty());
3702
htaa2a49d92016-03-04 02:51:39 -08003703 SessionDescriptionInterface* answer = CreateAnswer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003704 SetLocalDescriptionWithoutError(answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003705 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
3706}
3707
3708// This test verifies that crypto parameter is updated in local session
3709// description as per security policy set in MediaSessionDescriptionFactory.
3710TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescription) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003711 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07003712 SendAudioVideoStream1();
kwibergd1fe2812016-04-27 06:47:29 -07003713 std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003714
3715 // Making sure SetLocalDescription correctly sets crypto value in
3716 // SessionDescription object after de-serialization of sdp string. The value
3717 // will be set as per MediaSessionDescriptionFactory.
3718 std::string offer_str;
3719 offer->ToString(&offer_str);
3720 SessionDescriptionInterface* jsep_offer_str =
3721 CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL);
3722 SetLocalDescriptionWithoutError(jsep_offer_str);
3723 EXPECT_TRUE(session_->voice_channel()->secure_required());
3724 EXPECT_TRUE(session_->video_channel()->secure_required());
3725}
3726
3727// This test verifies the crypto parameter when security is disabled.
3728TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescriptionWithDisabled) {
wu@webrtc.org97077a32013-10-25 21:18:33 +00003729 options_.disable_encryption = true;
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003730 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07003731 SendAudioVideoStream1();
kwibergd1fe2812016-04-27 06:47:29 -07003732 std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003733
3734 // Making sure SetLocalDescription correctly sets crypto value in
3735 // SessionDescription object after de-serialization of sdp string. The value
3736 // will be set as per MediaSessionDescriptionFactory.
3737 std::string offer_str;
3738 offer->ToString(&offer_str);
deadbeefcbecd352015-09-23 11:50:27 -07003739 SessionDescriptionInterface* jsep_offer_str =
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003740 CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL);
3741 SetLocalDescriptionWithoutError(jsep_offer_str);
3742 EXPECT_FALSE(session_->voice_channel()->secure_required());
3743 EXPECT_FALSE(session_->video_channel()->secure_required());
3744}
3745
3746// This test verifies that an answer contains new ufrag and password if an offer
3747// with new ufrag and password is received.
3748TEST_F(WebRtcSessionTest, TestCreateAnswerWithNewUfragAndPassword) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003749 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003750 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00003751 options.recv_video = true;
kwibergd1fe2812016-04-27 06:47:29 -07003752 std::unique_ptr<JsepSessionDescription> offer(CreateRemoteOffer(options));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003753 SetRemoteDescriptionWithoutError(offer.release());
3754
deadbeefab9b2d12015-10-14 11:33:11 -07003755 SendAudioVideoStream1();
kwibergd1fe2812016-04-27 06:47:29 -07003756 std::unique_ptr<SessionDescriptionInterface> answer(CreateAnswer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003757 SetLocalDescriptionWithoutError(answer.release());
3758
3759 // Receive an offer with new ufrag and password.
deadbeef0ed85b22016-02-23 17:24:52 -08003760 for (const cricket::ContentInfo& content :
3761 session_->local_description()->description()->contents()) {
3762 options.transport_options[content.name].ice_restart = true;
3763 }
kwibergd1fe2812016-04-27 06:47:29 -07003764 std::unique_ptr<JsepSessionDescription> updated_offer1(
wu@webrtc.org91053e72013-08-10 07:18:04 +00003765 CreateRemoteOffer(options, session_->remote_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003766 SetRemoteDescriptionWithoutError(updated_offer1.release());
3767
kwibergd1fe2812016-04-27 06:47:29 -07003768 std::unique_ptr<SessionDescriptionInterface> updated_answer1(CreateAnswer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003769
deadbeef0ed85b22016-02-23 17:24:52 -08003770 EXPECT_FALSE(IceUfragPwdEqual(updated_answer1->description(),
3771 session_->local_description()->description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003772
deadbeef0ed85b22016-02-23 17:24:52 -08003773 // Even a second answer (created before the description is set) should have
3774 // a new ufrag/password.
kwibergd1fe2812016-04-27 06:47:29 -07003775 std::unique_ptr<SessionDescriptionInterface> updated_answer2(CreateAnswer());
deadbeef0ed85b22016-02-23 17:24:52 -08003776
3777 EXPECT_FALSE(IceUfragPwdEqual(updated_answer2->description(),
3778 session_->local_description()->description()));
3779
3780 SetLocalDescriptionWithoutError(updated_answer2.release());
3781}
3782
3783// This test verifies that an answer contains new ufrag and password if an offer
3784// that changes either the ufrag or password (but not both) is received.
3785// RFC 5245 says: "If the offer contained a change in the a=ice-ufrag or
3786// a=ice-pwd attributes compared to the previous SDP from the peer, it
3787// indicates that ICE is restarting for this media stream."
3788TEST_F(WebRtcSessionTest, TestOfferChangingOnlyUfragOrPassword) {
3789 Init();
3790 cricket::MediaSessionOptions options;
3791 options.recv_audio = true;
3792 options.recv_video = true;
3793 // Create an offer with audio and video.
kwibergd1fe2812016-04-27 06:47:29 -07003794 std::unique_ptr<JsepSessionDescription> offer(CreateRemoteOffer(options));
deadbeef0ed85b22016-02-23 17:24:52 -08003795 SetIceUfragPwd(offer.get(), "original_ufrag", "original_password12345");
3796 SetRemoteDescriptionWithoutError(offer.release());
3797
3798 SendAudioVideoStream1();
kwibergd1fe2812016-04-27 06:47:29 -07003799 std::unique_ptr<SessionDescriptionInterface> answer(CreateAnswer());
deadbeef0ed85b22016-02-23 17:24:52 -08003800 SetLocalDescriptionWithoutError(answer.release());
3801
3802 // Receive an offer with a new ufrag but stale password.
kwibergd1fe2812016-04-27 06:47:29 -07003803 std::unique_ptr<JsepSessionDescription> ufrag_changed_offer(
deadbeef0ed85b22016-02-23 17:24:52 -08003804 CreateRemoteOffer(options, session_->remote_description()));
3805 SetIceUfragPwd(ufrag_changed_offer.get(), "modified_ufrag",
3806 "original_password12345");
3807 SetRemoteDescriptionWithoutError(ufrag_changed_offer.release());
3808
kwibergd1fe2812016-04-27 06:47:29 -07003809 std::unique_ptr<SessionDescriptionInterface> updated_answer1(CreateAnswer());
deadbeef0ed85b22016-02-23 17:24:52 -08003810 EXPECT_FALSE(IceUfragPwdEqual(updated_answer1->description(),
3811 session_->local_description()->description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003812 SetLocalDescriptionWithoutError(updated_answer1.release());
deadbeef0ed85b22016-02-23 17:24:52 -08003813
3814 // Receive an offer with a new password but stale ufrag.
kwibergd1fe2812016-04-27 06:47:29 -07003815 std::unique_ptr<JsepSessionDescription> password_changed_offer(
deadbeef0ed85b22016-02-23 17:24:52 -08003816 CreateRemoteOffer(options, session_->remote_description()));
3817 SetIceUfragPwd(password_changed_offer.get(), "modified_ufrag",
3818 "modified_password12345");
3819 SetRemoteDescriptionWithoutError(password_changed_offer.release());
3820
kwibergd1fe2812016-04-27 06:47:29 -07003821 std::unique_ptr<SessionDescriptionInterface> updated_answer2(CreateAnswer());
deadbeef0ed85b22016-02-23 17:24:52 -08003822 EXPECT_FALSE(IceUfragPwdEqual(updated_answer2->description(),
3823 session_->local_description()->description()));
3824 SetLocalDescriptionWithoutError(updated_answer2.release());
wu@webrtc.org91053e72013-08-10 07:18:04 +00003825}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003826
wu@webrtc.org91053e72013-08-10 07:18:04 +00003827// This test verifies that an answer contains old ufrag and password if an offer
3828// with old ufrag and password is received.
3829TEST_F(WebRtcSessionTest, TestCreateAnswerWithOldUfragAndPassword) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003830 Init();
wu@webrtc.org91053e72013-08-10 07:18:04 +00003831 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00003832 options.recv_video = true;
kwibergd1fe2812016-04-27 06:47:29 -07003833 std::unique_ptr<JsepSessionDescription> offer(CreateRemoteOffer(options));
wu@webrtc.org91053e72013-08-10 07:18:04 +00003834 SetRemoteDescriptionWithoutError(offer.release());
3835
deadbeefab9b2d12015-10-14 11:33:11 -07003836 SendAudioVideoStream1();
kwibergd1fe2812016-04-27 06:47:29 -07003837 std::unique_ptr<SessionDescriptionInterface> answer(CreateAnswer());
wu@webrtc.org91053e72013-08-10 07:18:04 +00003838 SetLocalDescriptionWithoutError(answer.release());
3839
3840 // Receive an offer without changed ufrag or password.
kwibergd1fe2812016-04-27 06:47:29 -07003841 std::unique_ptr<JsepSessionDescription> updated_offer2(
wu@webrtc.org91053e72013-08-10 07:18:04 +00003842 CreateRemoteOffer(options, session_->remote_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003843 SetRemoteDescriptionWithoutError(updated_offer2.release());
3844
kwibergd1fe2812016-04-27 06:47:29 -07003845 std::unique_ptr<SessionDescriptionInterface> updated_answer2(CreateAnswer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003846
deadbeef0ed85b22016-02-23 17:24:52 -08003847 EXPECT_TRUE(IceUfragPwdEqual(updated_answer2->description(),
3848 session_->local_description()->description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003849
3850 SetLocalDescriptionWithoutError(updated_answer2.release());
3851}
3852
deadbeef0ed85b22016-02-23 17:24:52 -08003853// This test verifies that if an offer does an ICE restart on some, but not all
3854// media sections, the answer will change the ufrag/password in the correct
3855// media sections.
3856TEST_F(WebRtcSessionTest, TestCreateAnswerWithNewAndOldUfragAndPassword) {
3857 Init();
3858 cricket::MediaSessionOptions options;
3859 options.recv_video = true;
3860 options.recv_audio = true;
3861 options.bundle_enabled = false;
kwibergd1fe2812016-04-27 06:47:29 -07003862 std::unique_ptr<JsepSessionDescription> offer(CreateRemoteOffer(options));
deadbeef0ed85b22016-02-23 17:24:52 -08003863
3864 SetIceUfragPwd(offer.get(), cricket::MEDIA_TYPE_AUDIO, "aaaa",
3865 "aaaaaaaaaaaaaaaaaaaaaa");
3866 SetIceUfragPwd(offer.get(), cricket::MEDIA_TYPE_VIDEO, "bbbb",
3867 "bbbbbbbbbbbbbbbbbbbbbb");
3868 SetRemoteDescriptionWithoutError(offer.release());
3869
3870 SendAudioVideoStream1();
kwibergd1fe2812016-04-27 06:47:29 -07003871 std::unique_ptr<SessionDescriptionInterface> answer(CreateAnswer());
deadbeef0ed85b22016-02-23 17:24:52 -08003872 SetLocalDescriptionWithoutError(answer.release());
3873
3874 // Receive an offer with new ufrag and password, but only for the video media
3875 // section.
kwibergd1fe2812016-04-27 06:47:29 -07003876 std::unique_ptr<JsepSessionDescription> updated_offer(
deadbeef0ed85b22016-02-23 17:24:52 -08003877 CreateRemoteOffer(options, session_->remote_description()));
3878 SetIceUfragPwd(updated_offer.get(), cricket::MEDIA_TYPE_VIDEO, "cccc",
3879 "cccccccccccccccccccccc");
3880 SetRemoteDescriptionWithoutError(updated_offer.release());
3881
kwibergd1fe2812016-04-27 06:47:29 -07003882 std::unique_ptr<SessionDescriptionInterface> updated_answer(CreateAnswer());
deadbeef0ed85b22016-02-23 17:24:52 -08003883
3884 EXPECT_TRUE(IceUfragPwdEqual(updated_answer->description(),
3885 session_->local_description()->description(),
3886 cricket::MEDIA_TYPE_AUDIO));
3887
3888 EXPECT_FALSE(IceUfragPwdEqual(updated_answer->description(),
3889 session_->local_description()->description(),
3890 cricket::MEDIA_TYPE_VIDEO));
3891
3892 SetLocalDescriptionWithoutError(updated_answer.release());
3893}
3894
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003895TEST_F(WebRtcSessionTest, TestSessionContentError) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003896 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07003897 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00003898 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003899 const std::string session_id_orig = offer->session_id();
3900 const std::string session_version_orig = offer->session_version();
3901 SetLocalDescriptionWithoutError(offer);
3902
3903 video_channel_ = media_engine_->GetVideoChannel(0);
3904 video_channel_->set_fail_set_send_codecs(true);
3905
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00003906 SessionDescriptionInterface* answer =
3907 CreateRemoteAnswer(session_->local_description());
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00003908 SetRemoteDescriptionAnswerExpectError("ERROR_CONTENT", answer);
deadbeefd59daf82015-10-14 15:02:44 -07003909
3910 // Test that after a content error, setting any description will
3911 // result in an error.
3912 video_channel_->set_fail_set_send_codecs(false);
3913 answer = CreateRemoteAnswer(session_->local_description());
3914 SetRemoteDescriptionExpectError("", "ERROR_CONTENT", answer);
3915 offer = CreateRemoteOffer();
3916 SetLocalDescriptionExpectError("", "ERROR_CONTENT", offer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003917}
3918
3919// Runs the loopback call test with BUNDLE and STUN disabled.
3920TEST_F(WebRtcSessionTest, TestIceStatesBasic) {
3921 // Lets try with only UDP ports.
Peter Thatcher7cbd1882015-09-17 18:54:52 -07003922 allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00003923 cricket::PORTALLOCATOR_DISABLE_STUN |
3924 cricket::PORTALLOCATOR_DISABLE_RELAY);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003925 TestLoopbackCall();
3926}
3927
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00003928TEST_F(WebRtcSessionTest, TestIceStatesBasicIPv6) {
Peter Thatcher7cbd1882015-09-17 18:54:52 -07003929 allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00003930 cricket::PORTALLOCATOR_DISABLE_STUN |
3931 cricket::PORTALLOCATOR_ENABLE_IPV6 |
3932 cricket::PORTALLOCATOR_DISABLE_RELAY);
3933
3934 // best connection is IPv6 since it has higher network preference.
3935 LoopbackNetworkConfiguration config;
3936 config.test_ipv6_network_ = true;
3937 config.best_connection_after_initial_ice_converged_ =
3938 LoopbackNetworkConfiguration::ExpectedBestConnection(0, 1);
3939
3940 TestLoopbackCall(config);
3941}
3942
mallinath@webrtc.orgd3dc4242014-03-01 00:05:52 +00003943// Runs the loopback call test with BUNDLE and STUN enabled.
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00003944TEST_F(WebRtcSessionTest, TestIceStatesBundle) {
Peter Thatcher7cbd1882015-09-17 18:54:52 -07003945 allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
3946 cricket::PORTALLOCATOR_DISABLE_RELAY);
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00003947 TestLoopbackCall();
3948}
3949
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003950TEST_F(WebRtcSessionTest, TestRtpDataChannel) {
htaa2a49d92016-03-04 02:51:39 -08003951 configuration_.enable_rtp_data_channel = true;
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003952 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003953 SetLocalDescriptionWithDataChannel();
htaa2a49d92016-03-04 02:51:39 -08003954 ASSERT_TRUE(data_engine_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003955 EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type());
3956}
3957
Henrik Boström87713d02015-08-25 09:53:21 +02003958TEST_P(WebRtcSessionTest, TestRtpDataChannelConstraintTakesPrecedence) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003959 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003960
htaa2a49d92016-03-04 02:51:39 -08003961 configuration_.enable_rtp_data_channel = true;
wu@webrtc.org97077a32013-10-25 21:18:33 +00003962 options_.disable_sctp_data_channels = false;
3963
Henrik Boström87713d02015-08-25 09:53:21 +02003964 InitWithDtls(GetParam());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003965
3966 SetLocalDescriptionWithDataChannel();
3967 EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type());
3968}
3969
Henrik Boström87713d02015-08-25 09:53:21 +02003970TEST_P(WebRtcSessionTest, TestCreateOfferWithSctpEnabledWithoutStreams) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003971 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
wu@webrtc.org967bfff2013-09-19 05:49:50 +00003972
Henrik Boström87713d02015-08-25 09:53:21 +02003973 InitWithDtls(GetParam());
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00003974
kwibergd1fe2812016-04-27 06:47:29 -07003975 std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer());
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00003976 EXPECT_TRUE(offer->description()->GetContentByName("data") == NULL);
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00003977 EXPECT_TRUE(offer->description()->GetTransportInfoByName("data") == NULL);
3978}
3979
Henrik Boström87713d02015-08-25 09:53:21 +02003980TEST_P(WebRtcSessionTest, TestCreateAnswerWithSctpInOfferAndNoStreams) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003981 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00003982 SetFactoryDtlsSrtp();
Henrik Boström87713d02015-08-25 09:53:21 +02003983 InitWithDtls(GetParam());
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00003984
3985 // Create remote offer with SCTP.
3986 cricket::MediaSessionOptions options;
3987 options.data_channel_type = cricket::DCT_SCTP;
3988 JsepSessionDescription* offer =
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003989 CreateRemoteOffer(options, cricket::SEC_DISABLED);
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00003990 SetRemoteDescriptionWithoutError(offer);
3991
3992 // Verifies the answer contains SCTP.
kwibergd1fe2812016-04-27 06:47:29 -07003993 std::unique_ptr<SessionDescriptionInterface> answer(CreateAnswer());
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00003994 EXPECT_TRUE(answer != NULL);
3995 EXPECT_TRUE(answer->description()->GetContentByName("data") != NULL);
3996 EXPECT_TRUE(answer->description()->GetTransportInfoByName("data") != NULL);
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00003997}
3998
Henrik Boström87713d02015-08-25 09:53:21 +02003999TEST_P(WebRtcSessionTest, TestSctpDataChannelWithoutDtls) {
htaa2a49d92016-03-04 02:51:39 -08004000 configuration_.enable_dtls_srtp = rtc::Optional<bool>(false);
Henrik Boström87713d02015-08-25 09:53:21 +02004001 InitWithDtls(GetParam());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00004002
4003 SetLocalDescriptionWithDataChannel();
4004 EXPECT_EQ(cricket::DCT_NONE, data_engine_->last_channel_type());
4005}
4006
Henrik Boström87713d02015-08-25 09:53:21 +02004007TEST_P(WebRtcSessionTest, TestSctpDataChannelWithDtls) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00004008 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00004009
Henrik Boström87713d02015-08-25 09:53:21 +02004010 InitWithDtls(GetParam());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00004011
4012 SetLocalDescriptionWithDataChannel();
4013 EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type());
4014}
wu@webrtc.org91053e72013-08-10 07:18:04 +00004015
Henrik Boström87713d02015-08-25 09:53:21 +02004016TEST_P(WebRtcSessionTest, TestDisableSctpDataChannels) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00004017 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
wu@webrtc.org97077a32013-10-25 21:18:33 +00004018 options_.disable_sctp_data_channels = true;
Henrik Boström87713d02015-08-25 09:53:21 +02004019 InitWithDtls(GetParam());
wu@webrtc.org97077a32013-10-25 21:18:33 +00004020
4021 SetLocalDescriptionWithDataChannel();
4022 EXPECT_EQ(cricket::DCT_NONE, data_engine_->last_channel_type());
4023}
4024
Henrik Boström87713d02015-08-25 09:53:21 +02004025TEST_P(WebRtcSessionTest, TestSctpDataChannelSendPortParsing) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00004026 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00004027 const int new_send_port = 9998;
4028 const int new_recv_port = 7775;
4029
Henrik Boström87713d02015-08-25 09:53:21 +02004030 InitWithDtls(GetParam());
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00004031 SetFactoryDtlsSrtp();
4032
4033 // By default, don't actually add the codecs to desc_factory_; they don't
4034 // actually get serialized for SCTP in BuildMediaDescription(). Instead,
4035 // let the session description get parsed. That'll get the proper codecs
4036 // into the stream.
4037 cricket::MediaSessionOptions options;
4038 JsepSessionDescription* offer = CreateRemoteOfferWithSctpPort(
4039 "stream1", new_send_port, options);
4040
4041 // SetRemoteDescription will take the ownership of the offer.
4042 SetRemoteDescriptionWithoutError(offer);
4043
htaa2a49d92016-03-04 02:51:39 -08004044 SessionDescriptionInterface* answer =
4045 ChangeSDPSctpPort(new_recv_port, CreateAnswer());
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00004046 ASSERT_TRUE(answer != NULL);
4047
4048 // Now set the local description, which'll take ownership of the answer.
4049 SetLocalDescriptionWithoutError(answer);
4050
4051 // TEST PLAN: Set the port number to something new, set it in the SDP,
4052 // and pass it all the way down.
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00004053 EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type());
deadbeefab9b2d12015-10-14 11:33:11 -07004054 CreateDataChannel();
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00004055
4056 cricket::FakeDataMediaChannel* ch = data_engine_->GetChannel(0);
4057 int portnum = -1;
4058 ASSERT_TRUE(ch != NULL);
4059 ASSERT_EQ(1UL, ch->send_codecs().size());
4060 EXPECT_EQ(cricket::kGoogleSctpDataCodecId, ch->send_codecs()[0].id);
Donald Curtisd4f769d2015-05-28 09:48:21 -07004061 EXPECT_EQ(0, strcmp(cricket::kGoogleSctpDataCodecName,
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00004062 ch->send_codecs()[0].name.c_str()));
4063 EXPECT_TRUE(ch->send_codecs()[0].GetParam(cricket::kCodecParamPort,
4064 &portnum));
4065 EXPECT_EQ(new_send_port, portnum);
4066
4067 ASSERT_EQ(1UL, ch->recv_codecs().size());
4068 EXPECT_EQ(cricket::kGoogleSctpDataCodecId, ch->recv_codecs()[0].id);
Donald Curtisd4f769d2015-05-28 09:48:21 -07004069 EXPECT_EQ(0, strcmp(cricket::kGoogleSctpDataCodecName,
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00004070 ch->recv_codecs()[0].name.c_str()));
4071 EXPECT_TRUE(ch->recv_codecs()[0].GetParam(cricket::kCodecParamPort,
4072 &portnum));
4073 EXPECT_EQ(new_recv_port, portnum);
4074}
4075
deadbeefab9b2d12015-10-14 11:33:11 -07004076// Verifies that when a session's DataChannel receives an OPEN message,
4077// WebRtcSession signals the DataChannel creation request with the expected
4078// config.
4079TEST_P(WebRtcSessionTest, TestSctpDataChannelOpenMessage) {
4080 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
4081
4082 InitWithDtls(GetParam());
4083
4084 SetLocalDescriptionWithDataChannel();
4085 EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type());
4086
4087 webrtc::DataChannelInit config;
4088 config.id = 1;
jbaucheec21bd2016-03-20 06:15:43 -07004089 rtc::CopyOnWriteBuffer payload;
deadbeefab9b2d12015-10-14 11:33:11 -07004090 webrtc::WriteDataChannelOpenMessage("a", config, &payload);
4091 cricket::ReceiveDataParams params;
4092 params.ssrc = config.id;
4093 params.type = cricket::DMT_CONTROL;
4094
4095 cricket::DataChannel* data_channel = session_->data_channel();
4096 data_channel->SignalDataReceived(data_channel, params, payload);
4097
4098 EXPECT_EQ("a", last_data_channel_label_);
4099 EXPECT_EQ(config.id, last_data_channel_config_.id);
4100 EXPECT_FALSE(last_data_channel_config_.negotiated);
4101 EXPECT_EQ(webrtc::InternalDataChannelInit::kAcker,
4102 last_data_channel_config_.open_handshake_role);
4103}
4104
4105TEST_P(WebRtcSessionTest, TestUsesProvidedCertificate) {
Henrik Boströmd8281982015-08-27 10:12:24 +02004106 rtc::scoped_refptr<rtc::RTCCertificate> certificate =
Henrik Boströmd79599d2016-06-01 13:58:50 +02004107 FakeRTCCertificateGenerator::GenerateCertificate();
Henrik Boströmd8281982015-08-27 10:12:24 +02004108
htaa2a49d92016-03-04 02:51:39 -08004109 configuration_.certificates.push_back(certificate);
4110 Init();
Henrik Boströmd8281982015-08-27 10:12:24 +02004111 EXPECT_TRUE_WAIT(!session_->waiting_for_certificate_for_testing(), 1000);
4112
4113 EXPECT_EQ(session_->certificate_for_testing(), certificate);
4114}
wu@webrtc.org91053e72013-08-10 07:18:04 +00004115
Henrik Boström87713d02015-08-25 09:53:21 +02004116// Verifies that CreateOffer succeeds when CreateOffer is called before async
4117// identity generation is finished (even if a certificate is provided this is
4118// an async op).
4119TEST_P(WebRtcSessionTest, TestCreateOfferBeforeIdentityRequestReturnSuccess) {
4120 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
4121 InitWithDtls(GetParam());
4122
Henrik Boströmd8281982015-08-27 10:12:24 +02004123 EXPECT_TRUE(session_->waiting_for_certificate_for_testing());
deadbeefab9b2d12015-10-14 11:33:11 -07004124 SendAudioVideoStream1();
kwibergd1fe2812016-04-27 06:47:29 -07004125 std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer());
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00004126
wu@webrtc.org91053e72013-08-10 07:18:04 +00004127 EXPECT_TRUE(offer != NULL);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00004128 VerifyNoCryptoParams(offer->description(), true);
4129 VerifyFingerprintStatus(offer->description(), true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00004130}
4131
4132// Verifies that CreateAnswer succeeds when CreateOffer is called before async
Henrik Boström87713d02015-08-25 09:53:21 +02004133// identity generation is finished (even if a certificate is provided this is
4134// an async op).
4135TEST_P(WebRtcSessionTest, TestCreateAnswerBeforeIdentityRequestReturnSuccess) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00004136 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
Henrik Boström87713d02015-08-25 09:53:21 +02004137 InitWithDtls(GetParam());
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00004138 SetFactoryDtlsSrtp();
wu@webrtc.org91053e72013-08-10 07:18:04 +00004139
4140 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00004141 options.recv_video = true;
kwibergd1fe2812016-04-27 06:47:29 -07004142 std::unique_ptr<JsepSessionDescription> offer(
4143 CreateRemoteOffer(options, cricket::SEC_DISABLED));
wu@webrtc.org91053e72013-08-10 07:18:04 +00004144 ASSERT_TRUE(offer.get() != NULL);
4145 SetRemoteDescriptionWithoutError(offer.release());
4146
kwibergd1fe2812016-04-27 06:47:29 -07004147 std::unique_ptr<SessionDescriptionInterface> answer(CreateAnswer());
wu@webrtc.org91053e72013-08-10 07:18:04 +00004148 EXPECT_TRUE(answer != NULL);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00004149 VerifyNoCryptoParams(answer->description(), true);
4150 VerifyFingerprintStatus(answer->description(), true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00004151}
4152
4153// Verifies that CreateOffer succeeds when CreateOffer is called after async
Henrik Boström87713d02015-08-25 09:53:21 +02004154// identity generation is finished (even if a certificate is provided this is
4155// an async op).
4156TEST_P(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnSuccess) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00004157 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
Henrik Boström87713d02015-08-25 09:53:21 +02004158 InitWithDtls(GetParam());
wu@webrtc.org91053e72013-08-10 07:18:04 +00004159
Henrik Boströmd8281982015-08-27 10:12:24 +02004160 EXPECT_TRUE_WAIT(!session_->waiting_for_certificate_for_testing(), 1000);
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00004161
kwibergd1fe2812016-04-27 06:47:29 -07004162 std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer());
wu@webrtc.org91053e72013-08-10 07:18:04 +00004163 EXPECT_TRUE(offer != NULL);
4164}
4165
4166// Verifies that CreateOffer fails when CreateOffer is called after async
4167// identity generation fails.
4168TEST_F(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnFailure) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00004169 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
Henrik Boström87713d02015-08-25 09:53:21 +02004170 InitWithDtlsIdentityGenFail();
wu@webrtc.org91053e72013-08-10 07:18:04 +00004171
Henrik Boströmd8281982015-08-27 10:12:24 +02004172 EXPECT_TRUE_WAIT(!session_->waiting_for_certificate_for_testing(), 1000);
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00004173
kwibergd1fe2812016-04-27 06:47:29 -07004174 std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer());
wu@webrtc.org91053e72013-08-10 07:18:04 +00004175 EXPECT_TRUE(offer == NULL);
4176}
4177
4178// Verifies that CreateOffer succeeds when Multiple CreateOffer calls are made
4179// before async identity generation is finished.
Henrik Boström87713d02015-08-25 09:53:21 +02004180TEST_P(WebRtcSessionTest,
wu@webrtc.org91053e72013-08-10 07:18:04 +00004181 TestMultipleCreateOfferBeforeIdentityRequestReturnSuccess) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00004182 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
deadbeefcbecd352015-09-23 11:50:27 -07004183 VerifyMultipleAsyncCreateDescription(GetParam(),
4184 CreateSessionDescriptionRequest::kOffer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00004185}
4186
4187// Verifies that CreateOffer fails when Multiple CreateOffer calls are made
4188// before async identity generation fails.
4189TEST_F(WebRtcSessionTest,
4190 TestMultipleCreateOfferBeforeIdentityRequestReturnFailure) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00004191 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
Henrik Boström87713d02015-08-25 09:53:21 +02004192 VerifyMultipleAsyncCreateDescriptionIdentityGenFailure(
4193 CreateSessionDescriptionRequest::kOffer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00004194}
4195
4196// Verifies that CreateAnswer succeeds when Multiple CreateAnswer calls are made
4197// before async identity generation is finished.
Henrik Boström87713d02015-08-25 09:53:21 +02004198TEST_P(WebRtcSessionTest,
wu@webrtc.org91053e72013-08-10 07:18:04 +00004199 TestMultipleCreateAnswerBeforeIdentityRequestReturnSuccess) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00004200 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
wu@webrtc.org91053e72013-08-10 07:18:04 +00004201 VerifyMultipleAsyncCreateDescription(
Henrik Boström87713d02015-08-25 09:53:21 +02004202 GetParam(), CreateSessionDescriptionRequest::kAnswer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00004203}
4204
4205// Verifies that CreateAnswer fails when Multiple CreateAnswer calls are made
4206// before async identity generation fails.
4207TEST_F(WebRtcSessionTest,
4208 TestMultipleCreateAnswerBeforeIdentityRequestReturnFailure) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00004209 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
Henrik Boström87713d02015-08-25 09:53:21 +02004210 VerifyMultipleAsyncCreateDescriptionIdentityGenFailure(
4211 CreateSessionDescriptionRequest::kAnswer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00004212}
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +00004213
4214// Verifies that setRemoteDescription fails when DTLS is disabled and the remote
4215// offer has no SDES crypto but only DTLS fingerprint.
4216TEST_F(WebRtcSessionTest, TestSetRemoteOfferFailIfDtlsDisabledAndNoCrypto) {
4217 // Init without DTLS.
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00004218 Init();
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +00004219 // Create a remote offer with secured transport disabled.
4220 cricket::MediaSessionOptions options;
4221 JsepSessionDescription* offer(CreateRemoteOffer(
4222 options, cricket::SEC_DISABLED));
4223 // Adds a DTLS fingerprint to the remote offer.
4224 cricket::SessionDescription* sdp = offer->description();
4225 TransportInfo* audio = sdp->GetTransportInfoByName("audio");
4226 ASSERT_TRUE(audio != NULL);
4227 ASSERT_TRUE(audio->description.identity_fingerprint.get() == NULL);
4228 audio->description.identity_fingerprint.reset(
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00004229 rtc::SSLFingerprint::CreateFromRfc4572(
4230 rtc::DIGEST_SHA_256, kFakeDtlsFingerprint));
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00004231 SetRemoteDescriptionOfferExpectError(kSdpWithoutSdesCrypto,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00004232 offer);
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +00004233}
4234
buildbot@webrtc.orgb4c7b092014-08-25 12:11:58 +00004235TEST_F(WebRtcSessionTest, TestCombinedAudioVideoBweConstraint) {
htaa2a49d92016-03-04 02:51:39 -08004236 configuration_.combined_audio_video_bwe = rtc::Optional<bool>(true);
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00004237 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07004238 SendAudioVideoStream1();
buildbot@webrtc.orgb4c7b092014-08-25 12:11:58 +00004239 SessionDescriptionInterface* offer = CreateOffer();
4240
4241 SetLocalDescriptionWithoutError(offer);
4242
4243 voice_channel_ = media_engine_->GetVoiceChannel(0);
4244
4245 ASSERT_TRUE(voice_channel_ != NULL);
solenberg66f43392015-09-09 01:36:22 -07004246 const cricket::AudioOptions& audio_options = voice_channel_->options();
Karl Wibergbe579832015-11-10 22:34:18 +01004247 EXPECT_EQ(rtc::Optional<bool>(true), audio_options.combined_audio_video_bwe);
buildbot@webrtc.orgb4c7b092014-08-25 12:11:58 +00004248}
4249
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00004250// Tests that we can renegotiate new media content with ICE candidates in the
4251// new remote SDP.
Henrik Boström87713d02015-08-25 09:53:21 +02004252TEST_P(WebRtcSessionTest, TestRenegotiateNewMediaWithCandidatesInSdp) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00004253 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
Henrik Boström87713d02015-08-25 09:53:21 +02004254 InitWithDtls(GetParam());
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00004255 SetFactoryDtlsSrtp();
4256
deadbeefab9b2d12015-10-14 11:33:11 -07004257 SendAudioOnlyStream2();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00004258 SessionDescriptionInterface* offer = CreateOffer();
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00004259 SetLocalDescriptionWithoutError(offer);
4260
4261 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
4262 SetRemoteDescriptionWithoutError(answer);
4263
4264 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00004265 options.recv_video = true;
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00004266 offer = CreateRemoteOffer(options, cricket::SEC_DISABLED);
4267
4268 cricket::Candidate candidate1;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00004269 candidate1.set_address(rtc::SocketAddress("1.1.1.1", 5000));
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00004270 candidate1.set_component(1);
4271 JsepIceCandidate ice_candidate(kMediaContentName1, kMediaContentIndex1,
4272 candidate1);
4273 EXPECT_TRUE(offer->AddCandidate(&ice_candidate));
4274 SetRemoteDescriptionWithoutError(offer);
4275
htaa2a49d92016-03-04 02:51:39 -08004276 answer = CreateAnswer();
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00004277 SetLocalDescriptionWithoutError(answer);
4278}
4279
4280// Tests that we can renegotiate new media content with ICE candidates separated
4281// from the remote SDP.
Henrik Boström87713d02015-08-25 09:53:21 +02004282TEST_P(WebRtcSessionTest, TestRenegotiateNewMediaWithCandidatesSeparated) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00004283 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
Henrik Boström87713d02015-08-25 09:53:21 +02004284 InitWithDtls(GetParam());
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00004285 SetFactoryDtlsSrtp();
4286
deadbeefab9b2d12015-10-14 11:33:11 -07004287 SendAudioOnlyStream2();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00004288 SessionDescriptionInterface* offer = CreateOffer();
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00004289 SetLocalDescriptionWithoutError(offer);
4290
4291 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
4292 SetRemoteDescriptionWithoutError(answer);
4293
4294 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00004295 options.recv_video = true;
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00004296 offer = CreateRemoteOffer(options, cricket::SEC_DISABLED);
4297 SetRemoteDescriptionWithoutError(offer);
4298
4299 cricket::Candidate candidate1;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00004300 candidate1.set_address(rtc::SocketAddress("1.1.1.1", 5000));
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00004301 candidate1.set_component(1);
4302 JsepIceCandidate ice_candidate(kMediaContentName1, kMediaContentIndex1,
4303 candidate1);
4304 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate));
4305
htaa2a49d92016-03-04 02:51:39 -08004306 answer = CreateAnswer();
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00004307 SetLocalDescriptionWithoutError(answer);
4308}
honghaiz7f777492016-02-02 21:54:01 -08004309
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00004310// Tests that RTX codec is removed from the answer when it isn't supported
4311// by local side.
zhihuang3a334652016-05-05 18:37:49 -07004312TEST_F(WebRtcSessionTest, TestRtxRemovedByCreateAnswer) {
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00004313 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07004314 SendAudioVideoStream1();
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00004315 std::string offer_sdp(kSdpWithRtx);
4316
4317 SessionDescriptionInterface* offer =
4318 CreateSessionDescription(JsepSessionDescription::kOffer, offer_sdp, NULL);
4319 EXPECT_TRUE(offer->ToString(&offer_sdp));
4320
4321 // Offer SDP contains the RTX codec.
zhihuang3a334652016-05-05 18:37:49 -07004322 EXPECT_TRUE(ContainsVideoCodecWithName(offer, "rtx"));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00004323 SetRemoteDescriptionWithoutError(offer);
4324
htaa2a49d92016-03-04 02:51:39 -08004325 SessionDescriptionInterface* answer = CreateAnswer();
zhihuang3a334652016-05-05 18:37:49 -07004326 // Answer SDP does not contain the RTX codec.
4327 EXPECT_FALSE(ContainsVideoCodecWithName(answer, "rtx"));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00004328 SetLocalDescriptionWithoutError(answer);
4329}
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00004330
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00004331// This verifies that the voice channel after bundle has both options from video
4332// and voice channels.
4333TEST_F(WebRtcSessionTest, TestSetSocketOptionBeforeBundle) {
4334 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyBalanced);
deadbeefab9b2d12015-10-14 11:33:11 -07004335 SendAudioVideoStream1();
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00004336
4337 PeerConnectionInterface::RTCOfferAnswerOptions options;
4338 options.use_rtp_mux = true;
4339
4340 SessionDescriptionInterface* offer = CreateOffer(options);
4341 SetLocalDescriptionWithoutError(offer);
4342
4343 session_->video_channel()->SetOption(cricket::BaseChannel::ST_RTP,
4344 rtc::Socket::Option::OPT_SNDBUF, 4000);
4345
4346 session_->voice_channel()->SetOption(cricket::BaseChannel::ST_RTP,
4347 rtc::Socket::Option::OPT_RCVBUF, 8000);
4348
4349 int option_val;
deadbeefcbecd352015-09-23 11:50:27 -07004350 EXPECT_TRUE(session_->video_rtp_transport_channel()->GetOption(
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00004351 rtc::Socket::Option::OPT_SNDBUF, &option_val));
4352 EXPECT_EQ(4000, option_val);
deadbeefcbecd352015-09-23 11:50:27 -07004353 EXPECT_FALSE(session_->voice_rtp_transport_channel()->GetOption(
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00004354 rtc::Socket::Option::OPT_SNDBUF, &option_val));
4355
deadbeefcbecd352015-09-23 11:50:27 -07004356 EXPECT_TRUE(session_->voice_rtp_transport_channel()->GetOption(
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00004357 rtc::Socket::Option::OPT_RCVBUF, &option_val));
4358 EXPECT_EQ(8000, option_val);
deadbeefcbecd352015-09-23 11:50:27 -07004359 EXPECT_FALSE(session_->video_rtp_transport_channel()->GetOption(
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00004360 rtc::Socket::Option::OPT_RCVBUF, &option_val));
4361
deadbeefcbecd352015-09-23 11:50:27 -07004362 EXPECT_NE(session_->voice_rtp_transport_channel(),
4363 session_->video_rtp_transport_channel());
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00004364
deadbeefab9b2d12015-10-14 11:33:11 -07004365 SendAudioVideoStream2();
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00004366 SessionDescriptionInterface* answer =
4367 CreateRemoteAnswer(session_->local_description());
4368 SetRemoteDescriptionWithoutError(answer);
4369
deadbeefcbecd352015-09-23 11:50:27 -07004370 EXPECT_TRUE(session_->voice_rtp_transport_channel()->GetOption(
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00004371 rtc::Socket::Option::OPT_SNDBUF, &option_val));
4372 EXPECT_EQ(4000, option_val);
4373
deadbeefcbecd352015-09-23 11:50:27 -07004374 EXPECT_TRUE(session_->voice_rtp_transport_channel()->GetOption(
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00004375 rtc::Socket::Option::OPT_RCVBUF, &option_val));
4376 EXPECT_EQ(8000, option_val);
4377}
4378
tommi0f620f42015-07-09 03:25:02 -07004379// Test creating a session, request multiple offers, destroy the session
4380// and make sure we got success/failure callbacks for all of the requests.
4381// Background: crbug.com/507307
4382TEST_F(WebRtcSessionTest, CreateOffersAndShutdown) {
4383 Init();
4384
4385 rtc::scoped_refptr<WebRtcSessionCreateSDPObserverForTest> observers[100];
4386 PeerConnectionInterface::RTCOfferAnswerOptions options;
4387 options.offer_to_receive_audio =
4388 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
deadbeefab9b2d12015-10-14 11:33:11 -07004389 cricket::MediaSessionOptions session_options;
4390 session_options.recv_audio = true;
tommi0f620f42015-07-09 03:25:02 -07004391
4392 for (auto& o : observers) {
4393 o = new WebRtcSessionCreateSDPObserverForTest();
deadbeefab9b2d12015-10-14 11:33:11 -07004394 session_->CreateOffer(o, options, session_options);
tommi0f620f42015-07-09 03:25:02 -07004395 }
4396
4397 session_.reset();
4398
tommi0f620f42015-07-09 03:25:02 -07004399 for (auto& o : observers) {
4400 // We expect to have received a notification now even if the session was
4401 // terminated. The offer creation may or may not have succeeded, but we
4402 // must have received a notification which, so the only invalid state
4403 // is kInit.
4404 EXPECT_NE(WebRtcSessionCreateSDPObserverForTest::kInit, o->state());
4405 }
4406}
4407
stefanc1aeaf02015-10-15 07:26:07 -07004408TEST_F(WebRtcSessionTest, TestPacketOptionsAndOnPacketSent) {
4409 TestPacketOptions();
4410}
4411
deadbeef057ecf02016-01-20 14:30:43 -08004412// Make sure the signal from "GetOnDestroyedSignal()" fires when the session
4413// is destroyed.
4414TEST_F(WebRtcSessionTest, TestOnDestroyedSignal) {
4415 Init();
4416 session_.reset();
4417 EXPECT_TRUE(session_destroyed_);
4418}
4419
henrike@webrtc.org28e20752013-07-10 00:45:36 +00004420// TODO(bemasc): Add a TestIceStatesBundle with BUNDLE enabled. That test
4421// currently fails because upon disconnection and reconnection OnIceComplete is
4422// called more than once without returning to IceGatheringGathering.
Henrik Boström87713d02015-08-25 09:53:21 +02004423
deadbeefcbecd352015-09-23 11:50:27 -07004424INSTANTIATE_TEST_CASE_P(WebRtcSessionTests,
4425 WebRtcSessionTest,
4426 testing::Values(ALREADY_GENERATED,
4427 DTLS_IDENTITY_STORE));