blob: a1c709cdb5e9212e17306cc5dd52bdba446c66a1 [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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "api/fakemetricsobserver.h"
16#include "api/jsepicecandidate.h"
17#include "api/jsepsessiondescription.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "media/base/fakemediaengine.h"
19#include "media/base/fakevideorenderer.h"
20#include "media/base/mediachannel.h"
21#include "media/engine/fakewebrtccall.h"
22#include "media/sctp/sctptransportinternal.h"
23#include "p2p/base/packettransportinternal.h"
24#include "p2p/base/stunserver.h"
25#include "p2p/base/teststunserver.h"
26#include "p2p/base/testturnserver.h"
27#include "p2p/client/basicportallocator.h"
28#include "pc/audiotrack.h"
29#include "pc/channelmanager.h"
30#include "pc/mediasession.h"
31#include "pc/peerconnection.h"
32#include "pc/sctputils.h"
33#include "pc/test/fakertccertificategenerator.h"
34#include "pc/videotrack.h"
35#include "pc/webrtcsession.h"
36#include "pc/webrtcsessiondescriptionfactory.h"
37#include "rtc_base/checks.h"
38#include "rtc_base/fakenetwork.h"
39#include "rtc_base/firewallsocketserver.h"
40#include "rtc_base/gunit.h"
41#include "rtc_base/logging.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020042#include "rtc_base/stringutils.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020043#include "rtc_base/virtualsocketserver.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000044
henrike@webrtc.org28e20752013-07-10 00:45:36 +000045using cricket::FakeVoiceMediaChannel;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000046using cricket::TransportInfo;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000047using rtc::SocketAddress;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000048using rtc::Thread;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000049using webrtc::CreateSessionDescription;
wu@webrtc.org91053e72013-08-10 07:18:04 +000050using webrtc::CreateSessionDescriptionObserver;
51using webrtc::CreateSessionDescriptionRequest;
deadbeefab9b2d12015-10-14 11:33:11 -070052using webrtc::DataChannel;
jbauchac8869e2015-07-03 01:36:14 -070053using webrtc::FakeMetricsObserver;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000054using webrtc::IceCandidateCollection;
deadbeefab9b2d12015-10-14 11:33:11 -070055using webrtc::InternalDataChannelInit;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000056using webrtc::JsepIceCandidate;
57using webrtc::JsepSessionDescription;
wu@webrtc.org97077a32013-10-25 21:18:33 +000058using webrtc::PeerConnectionFactoryInterface;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000059using webrtc::PeerConnectionInterface;
60using webrtc::SessionDescriptionInterface;
deadbeefd59daf82015-10-14 15:02:44 -070061using webrtc::SessionStats;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000062using webrtc::StreamCollection;
wu@webrtc.org91053e72013-08-10 07:18:04 +000063using webrtc::WebRtcSession;
wu@webrtc.org364f2042013-11-20 21:49:41 +000064using webrtc::kBundleWithoutRtcpMux;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +000065using webrtc::kCreateChannelFailed;
66using webrtc::kInvalidSdp;
Zhi Huang2a5e4262017-09-14 01:15:03 -070067using webrtc::kMlineMismatchInAnswer;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +000068using webrtc::kPushDownTDFailed;
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +000069using webrtc::kSdpWithoutIceUfragPwd;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +000070using webrtc::kSdpWithoutDtlsFingerprint;
71using webrtc::kSdpWithoutSdesCrypto;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000072using webrtc::kSessionError;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +000073using webrtc::kSessionErrorDesc;
buildbot@webrtc.org53df88c2014-08-07 22:46:01 +000074using webrtc::kMaxUnsignalledRecvStreams;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000075
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +000076typedef PeerConnectionInterface::RTCOfferAnswerOptions RTCOfferAnswerOptions;
77
wu@webrtc.org364f2042013-11-20 21:49:41 +000078static const int kClientAddrPort = 0;
79static const char kClientAddrHost1[] = "11.11.11.11";
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +000080static const char kClientIPv6AddrHost1[] =
81 "2620:0:aaaa:bbbb:cccc:dddd:eeee:ffff";
wu@webrtc.org364f2042013-11-20 21:49:41 +000082static const char kClientAddrHost2[] = "22.22.22.22";
83static const char kStunAddrHost[] = "99.99.99.1";
henrike@webrtc.org28e20752013-07-10 00:45:36 +000084
85static const char kSessionVersion[] = "1";
86
henrike@webrtc.org28e20752013-07-10 00:45:36 +000087// Media index of candidates belonging to the first media content.
88static const int kMediaContentIndex0 = 0;
89static const char kMediaContentName0[] = "audio";
90
91// Media index of candidates belonging to the second media content.
92static const int kMediaContentIndex1 = 1;
93static const char kMediaContentName1[] = "video";
94
deadbeef953c2ce2017-01-09 14:53:41 -080095static const int kDefaultTimeout = 10000; // 10 seconds.
henrike@webrtc.org28e20752013-07-10 00:45:36 +000096static const int kIceCandidatesTimeout = 10000;
97
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +000098static const char kSdpWithRtx[] =
99 "v=0\r\n"
100 "o=- 4104004319237231850 2 IN IP4 127.0.0.1\r\n"
101 "s=-\r\n"
102 "t=0 0\r\n"
103 "a=msid-semantic: WMS stream1\r\n"
104 "m=video 9 RTP/SAVPF 0 96\r\n"
105 "c=IN IP4 0.0.0.0\r\n"
106 "a=rtcp:9 IN IP4 0.0.0.0\r\n"
107 "a=ice-ufrag:CerjGp19G7wpXwl7\r\n"
108 "a=ice-pwd:cMvOlFvQ6ochez1ZOoC2uBEC\r\n"
109 "a=mid:video\r\n"
110 "a=sendrecv\r\n"
111 "a=rtcp-mux\r\n"
112 "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
113 "inline:5/4N5CDvMiyDArHtBByUM71VIkguH17ZNoX60GrA\r\n"
114 "a=rtpmap:0 fake_video_codec/90000\r\n"
115 "a=rtpmap:96 rtx/90000\r\n"
116 "a=fmtp:96 apt=0\r\n";
117
deadbeefab9b2d12015-10-14 11:33:11 -0700118static const char kStream1[] = "stream1";
119static const char kVideoTrack1[] = "video1";
120static const char kAudioTrack1[] = "audio1";
121
122static const char kStream2[] = "stream2";
123static const char kVideoTrack2[] = "video2";
124static const char kAudioTrack2[] = "audio2";
125
zhihuang1c378ed2017-08-17 14:10:50 -0700126static constexpr bool kStopped = true;
127static constexpr bool kActive = false;
128
Henrik Boström87713d02015-08-25 09:53:21 +0200129enum RTCCertificateGenerationMethod { ALREADY_GENERATED, DTLS_IDENTITY_STORE };
130
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000131class MockIceObserver : public webrtc::IceObserver {
132 public:
133 MockIceObserver()
134 : oncandidatesready_(false),
135 ice_connection_state_(PeerConnectionInterface::kIceConnectionNew),
136 ice_gathering_state_(PeerConnectionInterface::kIceGatheringNew) {
137 }
138
Henrik Kjellander3fe372d2016-05-12 08:10:52 +0200139 virtual ~MockIceObserver() = default;
140
zstein6dfd53a2017-03-06 13:49:03 -0800141 void OnIceConnectionStateChange(
perkjdfb769d2016-02-09 03:09:43 -0800142 PeerConnectionInterface::IceConnectionState new_state) override {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000143 ice_connection_state_ = new_state;
skvlad6c87a672016-05-17 17:49:52 -0700144 ice_connection_state_history_.push_back(new_state);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000145 }
perkjdfb769d2016-02-09 03:09:43 -0800146 void OnIceGatheringChange(
147 PeerConnectionInterface::IceGatheringState new_state) override {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000148 // We can never transition back to "new".
149 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, new_state);
150 ice_gathering_state_ = new_state;
perkjdfb769d2016-02-09 03:09:43 -0800151 oncandidatesready_ =
152 new_state == PeerConnectionInterface::kIceGatheringComplete;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000153 }
154
155 // Found a new candidate.
jbauch81bf7b02017-03-25 08:31:12 -0700156 void OnIceCandidate(
157 std::unique_ptr<webrtc::IceCandidateInterface> candidate) override {
wu@webrtc.org364f2042013-11-20 21:49:41 +0000158 switch (candidate->sdp_mline_index()) {
159 case kMediaContentIndex0:
160 mline_0_candidates_.push_back(candidate->candidate());
161 break;
162 case kMediaContentIndex1:
163 mline_1_candidates_.push_back(candidate->candidate());
164 break;
165 default:
nissec80e7412017-01-11 05:56:46 -0800166 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000167 }
wu@webrtc.org364f2042013-11-20 21:49:41 +0000168
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000169 // The ICE gathering state should always be Gathering when a candidate is
170 // received (or possibly Completed in the case of the final candidate).
171 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, ice_gathering_state_);
172 }
173
Honghai Zhang7fb69db2016-03-14 11:59:18 -0700174 // Some local candidates are removed.
175 void OnIceCandidatesRemoved(
nisseef8b61e2016-04-29 06:09:15 -0700176 const std::vector<cricket::Candidate>& candidates) override {
Honghai Zhang7fb69db2016-03-14 11:59:18 -0700177 num_candidates_removed_ += candidates.size();
178 }
179
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000180 bool oncandidatesready_;
181 std::vector<cricket::Candidate> mline_0_candidates_;
182 std::vector<cricket::Candidate> mline_1_candidates_;
183 PeerConnectionInterface::IceConnectionState ice_connection_state_;
184 PeerConnectionInterface::IceGatheringState ice_gathering_state_;
skvlad6c87a672016-05-17 17:49:52 -0700185 std::vector<PeerConnectionInterface::IceConnectionState>
186 ice_connection_state_history_;
Honghai Zhang7fb69db2016-03-14 11:59:18 -0700187 size_t num_candidates_removed_ = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000188};
189
deadbeef953c2ce2017-01-09 14:53:41 -0800190// Used for tests in this file to verify that WebRtcSession responds to signals
191// from the SctpTransport correctly, and calls Start with the correct
192// local/remote ports.
193class FakeSctpTransport : public cricket::SctpTransportInternal {
194 public:
deadbeef5bd5ca32017-02-10 11:31:50 -0800195 void SetTransportChannel(rtc::PacketTransportInternal* channel) override {}
deadbeef953c2ce2017-01-09 14:53:41 -0800196 bool Start(int local_port, int remote_port) override {
197 local_port_ = local_port;
198 remote_port_ = remote_port;
199 return true;
200 }
201 bool OpenStream(int sid) override { return true; }
202 bool ResetStream(int sid) override { return true; }
203 bool SendData(const cricket::SendDataParams& params,
204 const rtc::CopyOnWriteBuffer& payload,
205 cricket::SendDataResult* result = nullptr) override {
206 return true;
207 }
208 bool ReadyToSendData() override { return true; }
209 void set_debug_name_for_testing(const char* debug_name) override {}
210
211 int local_port() const { return local_port_; }
212 int remote_port() const { return remote_port_; }
213
214 private:
215 int local_port_ = -1;
216 int remote_port_ = -1;
217};
218
219class FakeSctpTransportFactory : public cricket::SctpTransportInternalFactory {
220 public:
221 std::unique_ptr<cricket::SctpTransportInternal> CreateSctpTransport(
deadbeef5bd5ca32017-02-10 11:31:50 -0800222 rtc::PacketTransportInternal*) override {
deadbeef953c2ce2017-01-09 14:53:41 -0800223 last_fake_sctp_transport_ = new FakeSctpTransport();
224 return std::unique_ptr<cricket::SctpTransportInternal>(
225 last_fake_sctp_transport_);
226 }
227
228 FakeSctpTransport* last_fake_sctp_transport() {
229 return last_fake_sctp_transport_;
230 }
231
232 private:
233 FakeSctpTransport* last_fake_sctp_transport_ = nullptr;
234};
235
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000236class WebRtcSessionForTest : public webrtc::WebRtcSession {
237 public:
zhihuang29ff8442016-07-27 11:07:25 -0700238 WebRtcSessionForTest(
nisseeaabdf62017-05-05 02:23:02 -0700239 webrtc::Call* fake_call,
240 cricket::ChannelManager* channel_manager,
241 const cricket::MediaConfig& media_config,
242 webrtc::RtcEventLog* event_log,
zhihuang29ff8442016-07-27 11:07:25 -0700243 rtc::Thread* network_thread,
244 rtc::Thread* worker_thread,
245 rtc::Thread* signaling_thread,
246 cricket::PortAllocator* port_allocator,
247 webrtc::IceObserver* ice_observer,
deadbeef953c2ce2017-01-09 14:53:41 -0800248 std::unique_ptr<cricket::TransportController> transport_controller,
249 std::unique_ptr<FakeSctpTransportFactory> sctp_factory)
nisseeaabdf62017-05-05 02:23:02 -0700250 : WebRtcSession(fake_call, channel_manager, media_config, event_log,
danilchape9021a32016-05-17 01:52:02 -0700251 network_thread,
stefanc1aeaf02015-10-15 07:26:07 -0700252 worker_thread,
danilchape9021a32016-05-17 01:52:02 -0700253 signaling_thread,
zhihuang29ff8442016-07-27 11:07:25 -0700254 port_allocator,
deadbeef953c2ce2017-01-09 14:53:41 -0800255 std::move(transport_controller),
256 std::move(sctp_factory)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000257 RegisterIceObserver(ice_observer);
258 }
259 virtual ~WebRtcSessionForTest() {}
260
deadbeefcbecd352015-09-23 11:50:27 -0700261 // Note that these methods are only safe to use if the signaling thread
262 // is the same as the worker thread
deadbeef5bd5ca32017-02-10 11:31:50 -0800263 rtc::PacketTransportInternal* voice_rtp_transport_channel() {
deadbeefcbecd352015-09-23 11:50:27 -0700264 return rtp_transport_channel(voice_channel());
265 }
266
deadbeef5bd5ca32017-02-10 11:31:50 -0800267 rtc::PacketTransportInternal* voice_rtcp_transport_channel() {
deadbeefcbecd352015-09-23 11:50:27 -0700268 return rtcp_transport_channel(voice_channel());
269 }
270
deadbeef5bd5ca32017-02-10 11:31:50 -0800271 rtc::PacketTransportInternal* video_rtp_transport_channel() {
deadbeefcbecd352015-09-23 11:50:27 -0700272 return rtp_transport_channel(video_channel());
273 }
274
deadbeef5bd5ca32017-02-10 11:31:50 -0800275 rtc::PacketTransportInternal* video_rtcp_transport_channel() {
deadbeefcbecd352015-09-23 11:50:27 -0700276 return rtcp_transport_channel(video_channel());
277 }
278
deadbeefcbecd352015-09-23 11:50:27 -0700279 private:
deadbeef5bd5ca32017-02-10 11:31:50 -0800280 rtc::PacketTransportInternal* rtp_transport_channel(
johan669d69b2016-11-08 14:14:08 -0800281 cricket::BaseChannel* ch) {
deadbeefcbecd352015-09-23 11:50:27 -0700282 if (!ch) {
283 return nullptr;
284 }
zhihuangb2cdd932017-01-19 16:54:25 -0800285 return ch->rtp_dtls_transport();
deadbeefcbecd352015-09-23 11:50:27 -0700286 }
287
deadbeef5bd5ca32017-02-10 11:31:50 -0800288 rtc::PacketTransportInternal* rtcp_transport_channel(
johan669d69b2016-11-08 14:14:08 -0800289 cricket::BaseChannel* ch) {
deadbeefcbecd352015-09-23 11:50:27 -0700290 if (!ch) {
291 return nullptr;
292 }
zhihuangb2cdd932017-01-19 16:54:25 -0800293 return ch->rtcp_dtls_transport();
deadbeefcbecd352015-09-23 11:50:27 -0700294 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000295};
296
wu@webrtc.org91053e72013-08-10 07:18:04 +0000297class WebRtcSessionCreateSDPObserverForTest
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000298 : public rtc::RefCountedObject<CreateSessionDescriptionObserver> {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000299 public:
wu@webrtc.org91053e72013-08-10 07:18:04 +0000300 enum State {
301 kInit,
302 kFailed,
303 kSucceeded,
304 };
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000305 WebRtcSessionCreateSDPObserverForTest() : state_(kInit) {}
wu@webrtc.org91053e72013-08-10 07:18:04 +0000306
307 // CreateSessionDescriptionObserver implementation.
308 virtual void OnSuccess(SessionDescriptionInterface* desc) {
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000309 description_.reset(desc);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000310 state_ = kSucceeded;
311 }
312 virtual void OnFailure(const std::string& error) {
313 state_ = kFailed;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000314 }
315
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000316 SessionDescriptionInterface* description() { return description_.get(); }
317
318 SessionDescriptionInterface* ReleaseDescription() {
319 return description_.release();
320 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000321
wu@webrtc.org91053e72013-08-10 07:18:04 +0000322 State state() const { return state_; }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000323
wu@webrtc.org91053e72013-08-10 07:18:04 +0000324 protected:
325 ~WebRtcSessionCreateSDPObserverForTest() {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000326
327 private:
kwibergd1fe2812016-04-27 06:47:29 -0700328 std::unique_ptr<SessionDescriptionInterface> description_;
wu@webrtc.org91053e72013-08-10 07:18:04 +0000329 State state_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000330};
331
Henrik Boström87713d02015-08-25 09:53:21 +0200332class WebRtcSessionTest
deadbeefab9b2d12015-10-14 11:33:11 -0700333 : public testing::TestWithParam<RTCCertificateGenerationMethod>,
334 public sigslot::has_slots<> {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000335 protected:
336 // TODO Investigate why ChannelManager crashes, if it's created
337 // after stun_server.
338 WebRtcSessionTest()
deadbeef98e186c2017-05-16 18:00:06 -0700339 : vss_(new rtc::VirtualSocketServer()),
nisse7eaa4ea2017-05-08 05:25:41 -0700340 fss_(new rtc::FirewallSocketServer(vss_.get())),
341 thread_(fss_.get()),
342 media_engine_(new cricket::FakeMediaEngine()),
stefanc1aeaf02015-10-15 07:26:07 -0700343 data_engine_(new cricket::FakeDataEngine()),
deadbeef112b2e92017-02-10 20:13:37 -0800344 channel_manager_(new cricket::ChannelManager(
345 std::unique_ptr<cricket::MediaEngineInterface>(media_engine_),
346 std::unique_ptr<cricket::DataEngineInterface>(data_engine_),
347 rtc::Thread::Current())),
skvlad11a9cbf2016-10-07 11:53:05 -0700348 fake_call_(webrtc::Call::Config(&event_log_)),
stefanc1aeaf02015-10-15 07:26:07 -0700349 tdesc_factory_(new cricket::TransportDescriptionFactory()),
350 desc_factory_(
351 new cricket::MediaSessionDescriptionFactory(channel_manager_.get(),
352 tdesc_factory_.get())),
stefanc1aeaf02015-10-15 07:26:07 -0700353 stun_socket_addr_(
354 rtc::SocketAddress(kStunAddrHost, cricket::STUN_SERVER_PORT)),
355 stun_server_(cricket::TestStunServer::Create(Thread::Current(),
356 stun_socket_addr_)),
stefanc1aeaf02015-10-15 07:26:07 -0700357 metrics_observer_(new rtc::RefCountedObject<FakeMetricsObserver>()) {
buildbot@webrtc.org51c55082014-07-28 22:26:15 +0000358 cricket::ServerAddresses stun_servers;
359 stun_servers.insert(stun_socket_addr_);
360 allocator_.reset(new cricket::BasicPortAllocator(
361 &network_manager_,
362 stun_servers,
363 SocketAddress(), SocketAddress(), SocketAddress()));
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000364 allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700365 cricket::PORTALLOCATOR_DISABLE_RELAY);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000366 EXPECT_TRUE(channel_manager_->Init());
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000367 allocator_->set_step_delay(cricket::kMinimumStepDelay);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000368 }
369
370 void AddInterface(const SocketAddress& addr) {
371 network_manager_.AddInterface(addr);
372 }
Honghai Zhang7fb69db2016-03-14 11:59:18 -0700373 void RemoveInterface(const SocketAddress& addr) {
374 network_manager_.RemoveInterface(addr);
375 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000376
Henrik Boströmd79599d2016-06-01 13:58:50 +0200377 // If |cert_generator| != null or |rtc_configuration| contains |certificates|
378 // then DTLS will be enabled unless explicitly disabled by |rtc_configuration|
379 // options. When DTLS is enabled a certificate will be used if provided,
380 // otherwise one will be generated using the |cert_generator|.
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +0000381 void Init(
zhihuang4dfb8ce2016-11-23 10:30:12 -0800382 std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator,
deadbeef7914b8c2017-04-21 03:23:33 -0700383 PeerConnectionInterface::RtcpMuxPolicy rtcp_mux_policy,
384 const rtc::CryptoOptions& crypto_options) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000385 ASSERT_TRUE(session_.get() == NULL);
deadbeef953c2ce2017-01-09 14:53:41 -0800386 fake_sctp_transport_factory_ = new FakeSctpTransportFactory();
nisseeaabdf62017-05-05 02:23:02 -0700387 session_.reset(new WebRtcSessionForTest(&fake_call_,
388 channel_manager_.get(), cricket::MediaConfig(), &event_log_,
389 rtc::Thread::Current(), rtc::Thread::Current(),
zhihuang29ff8442016-07-27 11:07:25 -0700390 rtc::Thread::Current(), allocator_.get(), &observer_,
391 std::unique_ptr<cricket::TransportController>(
deadbeef7914b8c2017-04-21 03:23:33 -0700392 new cricket::TransportController(
393 rtc::Thread::Current(), rtc::Thread::Current(),
394 allocator_.get(),
395 /*redetermine_role_on_ice_restart=*/true, crypto_options)),
deadbeef953c2ce2017-01-09 14:53:41 -0800396 std::unique_ptr<FakeSctpTransportFactory>(
397 fake_sctp_transport_factory_)));
deadbeefab9b2d12015-10-14 11:33:11 -0700398 session_->SignalDataChannelOpenMessage.connect(
399 this, &WebRtcSessionTest::OnDataChannelOpenMessage);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000400
zhihuang4dfb8ce2016-11-23 10:30:12 -0800401 configuration_.rtcp_mux_policy = rtcp_mux_policy;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000402 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
403 observer_.ice_connection_state_);
404 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
405 observer_.ice_gathering_state_);
406
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200407 EXPECT_TRUE(session_->Initialize(options_, std::move(cert_generator),
htaa2a49d92016-03-04 02:51:39 -0800408 configuration_));
jbauchac8869e2015-07-03 01:36:14 -0700409 session_->set_metrics_observer(metrics_observer_);
deadbeef7914b8c2017-04-21 03:23:33 -0700410 crypto_options_ = crypto_options;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000411 }
412
deadbeefab9b2d12015-10-14 11:33:11 -0700413 void OnDataChannelOpenMessage(const std::string& label,
414 const InternalDataChannelInit& config) {
415 last_data_channel_label_ = label;
416 last_data_channel_config_ = config;
417 }
418
zhihuang4dfb8ce2016-11-23 10:30:12 -0800419 void Init() {
deadbeef7914b8c2017-04-21 03:23:33 -0700420 Init(nullptr, PeerConnectionInterface::kRtcpMuxPolicyNegotiate,
421 rtc::CryptoOptions());
zhihuang4dfb8ce2016-11-23 10:30:12 -0800422 }
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +0000423
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +0000424 void InitWithBundlePolicy(
425 PeerConnectionInterface::BundlePolicy bundle_policy) {
htaa2a49d92016-03-04 02:51:39 -0800426 configuration_.bundle_policy = bundle_policy;
427 Init();
Peter Thatcheraf55ccc2015-05-21 07:48:41 -0700428 }
429
430 void InitWithRtcpMuxPolicy(
431 PeerConnectionInterface::RtcpMuxPolicy rtcp_mux_policy) {
432 PeerConnectionInterface::RTCConfiguration configuration;
deadbeef7914b8c2017-04-21 03:23:33 -0700433 Init(nullptr, rtcp_mux_policy, rtc::CryptoOptions());
434 }
435
Henrik Boström87713d02015-08-25 09:53:21 +0200436 // Successfully init with DTLS; with a certificate generated and supplied or
437 // with a store that generates it for us.
438 void InitWithDtls(RTCCertificateGenerationMethod cert_gen_method) {
Henrik Boströmd79599d2016-06-01 13:58:50 +0200439 std::unique_ptr<FakeRTCCertificateGenerator> cert_generator;
Henrik Boström87713d02015-08-25 09:53:21 +0200440 if (cert_gen_method == ALREADY_GENERATED) {
htaa2a49d92016-03-04 02:51:39 -0800441 configuration_.certificates.push_back(
Henrik Boströmd79599d2016-06-01 13:58:50 +0200442 FakeRTCCertificateGenerator::GenerateCertificate());
Henrik Boström87713d02015-08-25 09:53:21 +0200443 } else if (cert_gen_method == DTLS_IDENTITY_STORE) {
Henrik Boströmd79599d2016-06-01 13:58:50 +0200444 cert_generator.reset(new FakeRTCCertificateGenerator());
445 cert_generator->set_should_fail(false);
Henrik Boström87713d02015-08-25 09:53:21 +0200446 } else {
henrikg91d6ede2015-09-17 00:24:34 -0700447 RTC_CHECK(false);
Henrik Boström87713d02015-08-25 09:53:21 +0200448 }
zhihuang4dfb8ce2016-11-23 10:30:12 -0800449 Init(std::move(cert_generator),
deadbeef7914b8c2017-04-21 03:23:33 -0700450 PeerConnectionInterface::kRtcpMuxPolicyNegotiate,
451 rtc::CryptoOptions());
Henrik Boström87713d02015-08-25 09:53:21 +0200452 }
453
zhihuang1c378ed2017-08-17 14:10:50 -0700454 // The following convenience functions can be applied for both local side and
455 // remote side. The flags can be overwritten for different use cases.
deadbeefab9b2d12015-10-14 11:33:11 -0700456 void SendAudioVideoStream1() {
457 send_stream_1_ = true;
458 send_stream_2_ = false;
zhihuang1c378ed2017-08-17 14:10:50 -0700459 local_send_audio_ = true;
460 local_send_video_ = true;
461 remote_send_audio_ = true;
462 remote_send_video_ = true;
deadbeefab9b2d12015-10-14 11:33:11 -0700463 }
464
465 void SendAudioVideoStream2() {
466 send_stream_1_ = false;
467 send_stream_2_ = true;
zhihuang1c378ed2017-08-17 14:10:50 -0700468 local_send_audio_ = true;
469 local_send_video_ = true;
470 remote_send_audio_ = true;
471 remote_send_video_ = true;
deadbeefab9b2d12015-10-14 11:33:11 -0700472 }
473
474 void SendAudioVideoStream1And2() {
475 send_stream_1_ = true;
476 send_stream_2_ = true;
zhihuang1c378ed2017-08-17 14:10:50 -0700477 local_send_audio_ = true;
478 local_send_video_ = true;
479 remote_send_audio_ = true;
480 remote_send_video_ = true;
deadbeefab9b2d12015-10-14 11:33:11 -0700481 }
482
483 void SendNothing() {
484 send_stream_1_ = false;
485 send_stream_2_ = false;
zhihuang1c378ed2017-08-17 14:10:50 -0700486 local_send_audio_ = false;
487 local_send_video_ = false;
488 remote_send_audio_ = false;
489 remote_send_video_ = false;
deadbeefab9b2d12015-10-14 11:33:11 -0700490 }
491
492 void SendAudioOnlyStream2() {
493 send_stream_1_ = false;
494 send_stream_2_ = true;
zhihuang1c378ed2017-08-17 14:10:50 -0700495 local_send_audio_ = true;
496 local_send_video_ = false;
497 remote_send_audio_ = true;
498 remote_send_video_ = false;
deadbeefab9b2d12015-10-14 11:33:11 -0700499 }
500
501 void SendVideoOnlyStream2() {
502 send_stream_1_ = false;
503 send_stream_2_ = true;
zhihuang1c378ed2017-08-17 14:10:50 -0700504 local_send_audio_ = false;
505 local_send_video_ = true;
506 remote_send_audio_ = false;
507 remote_send_video_ = true;
deadbeefab9b2d12015-10-14 11:33:11 -0700508 }
509
zhihuang1c378ed2017-08-17 14:10:50 -0700510 // Helper function used to add a specific media section to the
511 // |session_options|.
512 void AddMediaSection(cricket::MediaType type,
513 const std::string& mid,
514 cricket::MediaContentDirection direction,
515 bool stopped,
516 cricket::MediaSessionOptions* opts) {
517 opts->media_description_options.push_back(cricket::MediaDescriptionOptions(
518 type, mid,
519 cricket::RtpTransceiverDirection::FromMediaContentDirection(direction),
520 stopped));
521 }
522
523 // Add the media sections to the options from |offered_media_sections_| when
524 // creating an answer or a new offer.
525 // This duplicates a lot of logic from PeerConnection but this can be fixed
526 // when PeerConnection and WebRtcSession are merged.
527 void AddExistingMediaSectionsAndSendersToOptions(
528 cricket::MediaSessionOptions* session_options,
529 bool send_audio,
530 bool recv_audio,
531 bool send_video,
532 bool recv_video) {
533 int num_sim_layer = 1;
534 for (auto media_description_options : offered_media_sections_) {
535 if (media_description_options.type == cricket::MEDIA_TYPE_AUDIO) {
536 bool stopped = !send_audio && !recv_audio;
537 auto media_desc_options = cricket::MediaDescriptionOptions(
538 cricket::MEDIA_TYPE_AUDIO, media_description_options.mid,
539 cricket::RtpTransceiverDirection(send_audio, recv_audio), stopped);
540 if (send_stream_1_ && send_audio) {
Steve Anton8ffb9c32017-08-31 15:45:38 -0700541 media_desc_options.AddAudioSender(kAudioTrack1, {kStream1});
zhihuang1c378ed2017-08-17 14:10:50 -0700542 }
543 if (send_stream_2_ && send_audio) {
Steve Anton8ffb9c32017-08-31 15:45:38 -0700544 media_desc_options.AddAudioSender(kAudioTrack2, {kStream2});
zhihuang1c378ed2017-08-17 14:10:50 -0700545 }
546 session_options->media_description_options.push_back(
547 media_desc_options);
548 } else if (media_description_options.type == cricket::MEDIA_TYPE_VIDEO) {
549 bool stopped = !send_video && !recv_video;
550 auto media_desc_options = cricket::MediaDescriptionOptions(
551 cricket::MEDIA_TYPE_VIDEO, media_description_options.mid,
552 cricket::RtpTransceiverDirection(send_video, recv_video), stopped);
553 if (send_stream_1_ && send_video) {
Steve Anton8ffb9c32017-08-31 15:45:38 -0700554 media_desc_options.AddVideoSender(kVideoTrack1, {kStream1},
zhihuang1c378ed2017-08-17 14:10:50 -0700555 num_sim_layer);
556 }
557 if (send_stream_2_ && send_video) {
Steve Anton8ffb9c32017-08-31 15:45:38 -0700558 media_desc_options.AddVideoSender(kVideoTrack2, {kStream2},
zhihuang1c378ed2017-08-17 14:10:50 -0700559 num_sim_layer);
560 }
561 session_options->media_description_options.push_back(
562 media_desc_options);
563 } else if (media_description_options.type == cricket::MEDIA_TYPE_DATA) {
564 session_options->media_description_options.push_back(
565 cricket::MediaDescriptionOptions(
566 cricket::MEDIA_TYPE_DATA, media_description_options.mid,
567 // Direction for data sections is meaningless, but legacy
568 // endpoints might expect sendrecv.
569 cricket::RtpTransceiverDirection(true, true), false));
570 } else {
571 RTC_NOTREACHED();
572 }
deadbeefab9b2d12015-10-14 11:33:11 -0700573 }
zhihuang1c378ed2017-08-17 14:10:50 -0700574 }
575
576 // Add the existing media sections first and then add new media sections if
577 // needed.
578 void AddMediaSectionsAndSendersToOptions(
579 cricket::MediaSessionOptions* session_options,
580 bool send_audio,
581 bool recv_audio,
582 bool send_video,
583 bool recv_video) {
584 AddExistingMediaSectionsAndSendersToOptions(
585 session_options, send_audio, recv_audio, send_video, recv_video);
586
587 if (!session_options->has_audio() && (send_audio || recv_audio)) {
588 cricket::MediaDescriptionOptions media_desc_options =
589 cricket::MediaDescriptionOptions(
590 cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO,
591 cricket::RtpTransceiverDirection(send_audio, recv_audio),
592 kActive);
593 if (send_stream_1_ && send_audio) {
Steve Anton8ffb9c32017-08-31 15:45:38 -0700594 media_desc_options.AddAudioSender(kAudioTrack1, {kStream1});
zhihuang1c378ed2017-08-17 14:10:50 -0700595 }
596 if (send_stream_2_ && send_audio) {
Steve Anton8ffb9c32017-08-31 15:45:38 -0700597 media_desc_options.AddAudioSender(kAudioTrack2, {kStream2});
zhihuang1c378ed2017-08-17 14:10:50 -0700598 }
599 session_options->media_description_options.push_back(media_desc_options);
600 offered_media_sections_.push_back(media_desc_options);
deadbeefab9b2d12015-10-14 11:33:11 -0700601 }
zhihuang1c378ed2017-08-17 14:10:50 -0700602
603 if (!session_options->has_video() && (send_video || recv_video)) {
604 cricket::MediaDescriptionOptions media_desc_options =
605 cricket::MediaDescriptionOptions(
606 cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO,
607 cricket::RtpTransceiverDirection(send_video, recv_video),
608 kActive);
609 int num_sim_layer = 1;
610 if (send_stream_1_ && send_video) {
Steve Anton8ffb9c32017-08-31 15:45:38 -0700611 media_desc_options.AddVideoSender(kVideoTrack1, {kStream1},
zhihuang1c378ed2017-08-17 14:10:50 -0700612 num_sim_layer);
613 }
614 if (send_stream_2_ && send_video) {
Steve Anton8ffb9c32017-08-31 15:45:38 -0700615 media_desc_options.AddVideoSender(kVideoTrack2, {kStream2},
zhihuang1c378ed2017-08-17 14:10:50 -0700616 num_sim_layer);
617 }
618 session_options->media_description_options.push_back(media_desc_options);
619 offered_media_sections_.push_back(media_desc_options);
deadbeefab9b2d12015-10-14 11:33:11 -0700620 }
zhihuang1c378ed2017-08-17 14:10:50 -0700621
622 if (!session_options->has_data() &&
623 (data_channel_ ||
624 session_options->data_channel_type != cricket::DCT_NONE)) {
625 cricket::MediaDescriptionOptions media_desc_options =
626 cricket::MediaDescriptionOptions(
627 cricket::MEDIA_TYPE_DATA, cricket::CN_DATA,
628 cricket::RtpTransceiverDirection(true, true), kActive);
629 if (session_options->data_channel_type == cricket::DCT_RTP) {
630 media_desc_options.AddRtpDataChannel(data_channel_->label(),
631 data_channel_->label());
632 }
633 session_options->media_description_options.push_back(media_desc_options);
634 offered_media_sections_.push_back(media_desc_options);
deadbeefab9b2d12015-10-14 11:33:11 -0700635 }
636 }
637
638 void GetOptionsForOffer(
639 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
640 cricket::MediaSessionOptions* session_options) {
zhihuang1c378ed2017-08-17 14:10:50 -0700641 ExtractSharedMediaSessionOptions(rtc_options, session_options);
deadbeefab9b2d12015-10-14 11:33:11 -0700642
zhihuang1c378ed2017-08-17 14:10:50 -0700643 // |recv_X| is true by default if |offer_to_receive_X| is undefined.
644 bool recv_audio = rtc_options.offer_to_receive_audio != 0;
645 bool recv_video = rtc_options.offer_to_receive_video != 0;
646
647 AddMediaSectionsAndSendersToOptions(session_options, local_send_audio_,
648 recv_audio, local_send_video_,
649 recv_video);
deadbeefc80741f2015-10-22 13:14:45 -0700650 session_options->bundle_enabled =
651 session_options->bundle_enabled &&
652 (session_options->has_audio() || session_options->has_video() ||
653 session_options->has_data());
654
zhihuang1c378ed2017-08-17 14:10:50 -0700655 session_options->crypto_options = crypto_options_;
656 }
657
658 void GetOptionsForAnswer(cricket::MediaSessionOptions* session_options) {
659 AddExistingMediaSectionsAndSendersToOptions(
660 session_options, local_send_audio_, local_recv_audio_,
661 local_send_video_, local_recv_video_);
662
663 session_options->bundle_enabled =
664 session_options->bundle_enabled &&
665 (session_options->has_audio() || session_options->has_video() ||
666 session_options->has_data());
667
668 if (session_->data_channel_type() != cricket::DCT_RTP) {
669 session_options->data_channel_type = session_->data_channel_type();
olka3c747662017-08-17 06:50:32 -0700670 }
671
zhihuanga77e6bb2017-08-14 18:17:48 -0700672 session_options->crypto_options = crypto_options_;
673 }
674
zhihuang1c378ed2017-08-17 14:10:50 -0700675 void GetOptionsForRemoteAnswer(
676 cricket::MediaSessionOptions* session_options) {
677 bool recv_audio = local_send_audio_ || remote_recv_audio_;
678 bool recv_video = local_send_video_ || remote_recv_video_;
679 bool send_audio = false;
680 bool send_video = false;
zhihuanga77e6bb2017-08-14 18:17:48 -0700681
zhihuang1c378ed2017-08-17 14:10:50 -0700682 AddExistingMediaSectionsAndSendersToOptions(
683 session_options, send_audio, recv_audio, send_video, recv_video);
684
zhihuanga77e6bb2017-08-14 18:17:48 -0700685 session_options->bundle_enabled =
686 session_options->bundle_enabled &&
687 (session_options->has_audio() || session_options->has_video() ||
688 session_options->has_data());
689
690 if (session_->data_channel_type() != cricket::DCT_RTP) {
691 session_options->data_channel_type = session_->data_channel_type();
deadbeefab9b2d12015-10-14 11:33:11 -0700692 }
jbauchcb560652016-08-04 05:20:32 -0700693
deadbeef7914b8c2017-04-21 03:23:33 -0700694 session_options->crypto_options = crypto_options_;
deadbeefab9b2d12015-10-14 11:33:11 -0700695 }
696
zhihuang1c378ed2017-08-17 14:10:50 -0700697 void GetOptionsForAudioOnlyRemoteOffer(
698 cricket::MediaSessionOptions* session_options) {
699 remote_recv_audio_ = true;
700 remote_recv_video_ = false;
701 GetOptionsForRemoteOffer(session_options);
702 }
703
704 void GetOptionsForRemoteOffer(cricket::MediaSessionOptions* session_options) {
705 AddMediaSectionsAndSendersToOptions(session_options, remote_send_audio_,
706 remote_recv_audio_, remote_send_video_,
707 remote_recv_video_);
708 session_options->bundle_enabled =
709 (session_options->has_audio() || session_options->has_video() ||
710 session_options->has_data());
711
712 if (session_->data_channel_type() != cricket::DCT_RTP) {
713 session_options->data_channel_type = session_->data_channel_type();
714 }
715
716 session_options->crypto_options = crypto_options_;
717 }
718
deadbeefab9b2d12015-10-14 11:33:11 -0700719 // Creates a local offer and applies it. Starts ICE.
720 // Call SendAudioVideoStreamX() before this function
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000721 // to decide which streams to create.
722 void InitiateCall() {
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000723 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000724 SetLocalDescriptionWithoutError(offer);
725 EXPECT_TRUE_WAIT(PeerConnectionInterface::kIceGatheringNew !=
726 observer_.ice_gathering_state_,
727 kIceCandidatesTimeout);
728 }
729
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000730 SessionDescriptionInterface* CreateOffer() {
731 PeerConnectionInterface::RTCOfferAnswerOptions options;
732 options.offer_to_receive_audio =
733 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000734 return CreateOffer(options);
735 }
736
wu@webrtc.org91053e72013-08-10 07:18:04 +0000737 SessionDescriptionInterface* CreateOffer(
htaa2a49d92016-03-04 02:51:39 -0800738 const PeerConnectionInterface::RTCOfferAnswerOptions options) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000739 rtc::scoped_refptr<WebRtcSessionCreateSDPObserverForTest>
wu@webrtc.org91053e72013-08-10 07:18:04 +0000740 observer = new WebRtcSessionCreateSDPObserverForTest();
deadbeefab9b2d12015-10-14 11:33:11 -0700741 cricket::MediaSessionOptions session_options;
742 GetOptionsForOffer(options, &session_options);
743 session_->CreateOffer(observer, options, session_options);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000744 EXPECT_TRUE_WAIT(
745 observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit,
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000746 2000);
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000747 return observer->ReleaseDescription();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000748 }
749
750 SessionDescriptionInterface* CreateAnswer(
htaa2a49d92016-03-04 02:51:39 -0800751 const cricket::MediaSessionOptions& options) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000752 rtc::scoped_refptr<WebRtcSessionCreateSDPObserverForTest> observer
wu@webrtc.org91053e72013-08-10 07:18:04 +0000753 = new WebRtcSessionCreateSDPObserverForTest();
htaa2a49d92016-03-04 02:51:39 -0800754 cricket::MediaSessionOptions session_options = options;
755 GetOptionsForAnswer(&session_options);
htaa2a49d92016-03-04 02:51:39 -0800756 session_->CreateAnswer(observer, session_options);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000757 EXPECT_TRUE_WAIT(
758 observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit,
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000759 2000);
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000760 return observer->ReleaseDescription();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000761 }
762
htaa2a49d92016-03-04 02:51:39 -0800763 SessionDescriptionInterface* CreateAnswer() {
764 cricket::MediaSessionOptions options;
zhihuang1c378ed2017-08-17 14:10:50 -0700765 options.bundle_enabled = true;
htaa2a49d92016-03-04 02:51:39 -0800766 return CreateAnswer(options);
767 }
768
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000769 // Set the internal fake description factories to do DTLS-SRTP.
770 void SetFactoryDtlsSrtp() {
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000771 desc_factory_->set_secure(cricket::SEC_DISABLED);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000772 std::string identity_name = "WebRTC" +
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000773 rtc::ToString(rtc::CreateRandomId());
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200774 // Confirmed to work with KT_RSA and KT_ECDSA.
kwiberg0eb15ed2015-12-17 03:04:15 -0800775 tdesc_factory_->set_certificate(
jbauch555604a2016-04-26 03:13:22 -0700776 rtc::RTCCertificate::Create(std::unique_ptr<rtc::SSLIdentity>(
kwiberg0eb15ed2015-12-17 03:04:15 -0800777 rtc::SSLIdentity::Generate(identity_name, rtc::KT_DEFAULT))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000778 tdesc_factory_->set_secure(cricket::SEC_REQUIRED);
779 }
780
deadbeef0ed85b22016-02-23 17:24:52 -0800781 // Compares ufrag/password only for the specified |media_type|.
782 bool IceUfragPwdEqual(const cricket::SessionDescription* desc1,
783 const cricket::SessionDescription* desc2,
784 cricket::MediaType media_type) {
785 if (desc1->contents().size() != desc2->contents().size()) {
786 return false;
787 }
788
789 const cricket::ContentInfo* cinfo =
790 cricket::GetFirstMediaContent(desc1->contents(), media_type);
791 const cricket::TransportDescription* transport_desc1 =
792 desc1->GetTransportDescriptionByName(cinfo->name);
793 const cricket::TransportDescription* transport_desc2 =
794 desc2->GetTransportDescriptionByName(cinfo->name);
795 if (!transport_desc1 || !transport_desc2) {
796 return false;
797 }
798 if (transport_desc1->ice_pwd != transport_desc2->ice_pwd ||
799 transport_desc1->ice_ufrag != transport_desc2->ice_ufrag) {
800 return false;
801 }
802 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000803 }
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000804
deadbeef0ed85b22016-02-23 17:24:52 -0800805 // Sets ufrag/pwd for specified |media_type|.
806 void SetIceUfragPwd(SessionDescriptionInterface* current_desc,
807 cricket::MediaType media_type,
808 const std::string& ufrag,
809 const std::string& pwd) {
810 cricket::SessionDescription* desc = current_desc->description();
811 const cricket::ContentInfo* cinfo =
812 cricket::GetFirstMediaContent(desc->contents(), media_type);
813 TransportInfo* transport_info = desc->GetTransportInfoByName(cinfo->name);
814 cricket::TransportDescription* transport_desc =
815 &transport_info->description;
816 transport_desc->ice_ufrag = ufrag;
817 transport_desc->ice_pwd = pwd;
818 }
819
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000820 // Creates a remote offer and and applies it as a remote description,
821 // creates a local answer and applies is as a local description.
deadbeefab9b2d12015-10-14 11:33:11 -0700822 // Call SendAudioVideoStreamX() before this function
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000823 // to decide which local and remote streams to create.
824 void CreateAndSetRemoteOfferAndLocalAnswer() {
825 SessionDescriptionInterface* offer = CreateRemoteOffer();
826 SetRemoteDescriptionWithoutError(offer);
htaa2a49d92016-03-04 02:51:39 -0800827 SessionDescriptionInterface* answer = CreateAnswer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000828 SetLocalDescriptionWithoutError(answer);
829 }
830 void SetLocalDescriptionWithoutError(SessionDescriptionInterface* desc) {
zhihuang1c378ed2017-08-17 14:10:50 -0700831 ASSERT_TRUE(session_->SetLocalDescription(desc, nullptr));
deadbeefcbecd352015-09-23 11:50:27 -0700832 session_->MaybeStartGathering();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000833 }
834 void SetLocalDescriptionExpectState(SessionDescriptionInterface* desc,
deadbeefd59daf82015-10-14 15:02:44 -0700835 WebRtcSession::State expected_state) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000836 SetLocalDescriptionWithoutError(desc);
837 EXPECT_EQ(expected_state, session_->state());
838 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000839 void SetLocalDescriptionExpectError(const std::string& action,
840 const std::string& expected_error,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000841 SessionDescriptionInterface* desc) {
842 std::string error;
843 EXPECT_FALSE(session_->SetLocalDescription(desc, &error));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000844 std::string sdp_type = "local ";
845 sdp_type.append(action);
846 EXPECT_NE(std::string::npos, error.find(sdp_type));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000847 EXPECT_NE(std::string::npos, error.find(expected_error));
848 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000849 void SetLocalDescriptionOfferExpectError(const std::string& expected_error,
850 SessionDescriptionInterface* desc) {
851 SetLocalDescriptionExpectError(SessionDescriptionInterface::kOffer,
852 expected_error, desc);
853 }
854 void SetLocalDescriptionAnswerExpectError(const std::string& expected_error,
855 SessionDescriptionInterface* desc) {
856 SetLocalDescriptionExpectError(SessionDescriptionInterface::kAnswer,
857 expected_error, desc);
858 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000859 void SetRemoteDescriptionWithoutError(SessionDescriptionInterface* desc) {
zhihuang1c378ed2017-08-17 14:10:50 -0700860 ASSERT_TRUE(session_->SetRemoteDescription(desc, nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000861 }
862 void SetRemoteDescriptionExpectState(SessionDescriptionInterface* desc,
deadbeefd59daf82015-10-14 15:02:44 -0700863 WebRtcSession::State expected_state) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000864 SetRemoteDescriptionWithoutError(desc);
865 EXPECT_EQ(expected_state, session_->state());
866 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000867 void SetRemoteDescriptionExpectError(const std::string& action,
868 const std::string& expected_error,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000869 SessionDescriptionInterface* desc) {
870 std::string error;
871 EXPECT_FALSE(session_->SetRemoteDescription(desc, &error));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000872 std::string sdp_type = "remote ";
873 sdp_type.append(action);
874 EXPECT_NE(std::string::npos, error.find(sdp_type));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000875 EXPECT_NE(std::string::npos, error.find(expected_error));
876 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000877 void SetRemoteDescriptionOfferExpectError(
878 const std::string& expected_error, SessionDescriptionInterface* desc) {
879 SetRemoteDescriptionExpectError(SessionDescriptionInterface::kOffer,
880 expected_error, desc);
881 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000882 void SetRemoteDescriptionAnswerExpectError(
883 const std::string& expected_error, SessionDescriptionInterface* desc) {
884 SetRemoteDescriptionExpectError(SessionDescriptionInterface::kAnswer,
885 expected_error, desc);
886 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000887
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000888 JsepSessionDescription* CreateRemoteOfferWithVersion(
889 cricket::MediaSessionOptions options,
890 cricket::SecurePolicy secure_policy,
891 const std::string& session_version,
892 const SessionDescriptionInterface* current_desc) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000893 std::string session_id = rtc::ToString(rtc::CreateRandomId64());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000894 const cricket::SessionDescription* cricket_desc = NULL;
895 if (current_desc) {
896 cricket_desc = current_desc->description();
897 session_id = current_desc->session_id();
898 }
899
900 desc_factory_->set_secure(secure_policy);
901 JsepSessionDescription* offer(
902 new JsepSessionDescription(JsepSessionDescription::kOffer));
903 if (!offer->Initialize(desc_factory_->CreateOffer(options, cricket_desc),
904 session_id, session_version)) {
905 delete offer;
906 offer = NULL;
907 }
908 return offer;
909 }
910 JsepSessionDescription* CreateRemoteOffer(
911 cricket::MediaSessionOptions options) {
912 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED,
913 kSessionVersion, NULL);
914 }
915 JsepSessionDescription* CreateRemoteOffer(
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000916 cricket::MediaSessionOptions options, cricket::SecurePolicy sdes_policy) {
917 return CreateRemoteOfferWithVersion(
918 options, sdes_policy, kSessionVersion, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000919 }
920 JsepSessionDescription* CreateRemoteOffer(
921 cricket::MediaSessionOptions options,
922 const SessionDescriptionInterface* current_desc) {
923 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED,
924 kSessionVersion, current_desc);
925 }
926
Steve Anton6d64e9a2017-09-12 09:44:05 -0700927 SessionDescriptionInterface* CreateRemoteOfferWithSctpPort(
928 const char* sctp_stream_name,
929 int new_port,
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000930 cricket::MediaSessionOptions options) {
931 options.data_channel_type = cricket::DCT_SCTP;
zhihuang1c378ed2017-08-17 14:10:50 -0700932 GetOptionsForRemoteOffer(&options);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000933 return ChangeSDPSctpPort(new_port, CreateRemoteOffer(options));
934 }
935
936 // Takes ownership of offer_basis (and deletes it).
Steve Anton6d64e9a2017-09-12 09:44:05 -0700937 SessionDescriptionInterface* ChangeSDPSctpPort(
938 int new_port,
939 webrtc::SessionDescriptionInterface* offer_basis) {
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000940 // Stringify the input SDP, swap the 5000 for 'new_port' and create a new
941 // SessionDescription from the mutated string.
942 const char* default_port_str = "5000";
943 char new_port_str[16];
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000944 rtc::sprintfn(new_port_str, sizeof(new_port_str), "%d", new_port);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000945 std::string offer_str;
946 offer_basis->ToString(&offer_str);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000947 rtc::replace_substrs(default_port_str, strlen(default_port_str),
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000948 new_port_str, strlen(new_port_str),
949 &offer_str);
Steve Anton6d64e9a2017-09-12 09:44:05 -0700950 SessionDescriptionInterface* offer =
951 CreateSessionDescription(offer_basis->type(), offer_str, nullptr);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000952 delete offer_basis;
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000953 return offer;
954 }
955
deadbeefab9b2d12015-10-14 11:33:11 -0700956 // Create a remote offer. Call SendAudioVideoStreamX()
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000957 // before this function to decide which streams to create.
958 JsepSessionDescription* CreateRemoteOffer() {
959 cricket::MediaSessionOptions options;
zhihuang1c378ed2017-08-17 14:10:50 -0700960 GetOptionsForRemoteOffer(&options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000961 return CreateRemoteOffer(options, session_->remote_description());
962 }
963
964 JsepSessionDescription* CreateRemoteAnswer(
965 const SessionDescriptionInterface* offer,
966 cricket::MediaSessionOptions options,
967 cricket::SecurePolicy policy) {
968 desc_factory_->set_secure(policy);
969 const std::string session_id =
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000970 rtc::ToString(rtc::CreateRandomId64());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000971 JsepSessionDescription* answer(
972 new JsepSessionDescription(JsepSessionDescription::kAnswer));
973 if (!answer->Initialize(desc_factory_->CreateAnswer(offer->description(),
974 options, NULL),
975 session_id, kSessionVersion)) {
976 delete answer;
977 answer = NULL;
978 }
979 return answer;
980 }
981
982 JsepSessionDescription* CreateRemoteAnswer(
983 const SessionDescriptionInterface* offer,
984 cricket::MediaSessionOptions options) {
985 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED);
986 }
987
deadbeefab9b2d12015-10-14 11:33:11 -0700988 // Creates an answer session description.
989 // Call SendAudioVideoStreamX() before this function
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000990 // to decide which streams to create.
991 JsepSessionDescription* CreateRemoteAnswer(
992 const SessionDescriptionInterface* offer) {
993 cricket::MediaSessionOptions options;
htaa2a49d92016-03-04 02:51:39 -0800994 GetOptionsForAnswer(&options);
zhihuang1c378ed2017-08-17 14:10:50 -0700995 options.bundle_enabled = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000996 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED);
997 }
998
999 void TestSessionCandidatesWithBundleRtcpMux(bool bundle, bool rtcp_mux) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001000 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001001 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001002 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001003
1004 PeerConnectionInterface::RTCOfferAnswerOptions options;
1005 options.use_rtp_mux = bundle;
1006
1007 SessionDescriptionInterface* offer = CreateOffer(options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001008 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
1009 // and answer.
1010 SetLocalDescriptionWithoutError(offer);
1011
kwibergd1fe2812016-04-27 06:47:29 -07001012 std::unique_ptr<SessionDescriptionInterface> answer(
henrike@webrtc.org723d6832013-07-12 16:04:50 +00001013 CreateRemoteAnswer(session_->local_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001014 std::string sdp;
1015 EXPECT_TRUE(answer->ToString(&sdp));
1016
1017 size_t expected_candidate_num = 2;
1018 if (!rtcp_mux) {
1019 // If rtcp_mux is enabled we should expect 4 candidates - host and srflex
1020 // for rtp and rtcp.
1021 expected_candidate_num = 4;
1022 // Disable rtcp-mux from the answer
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001023 const std::string kRtcpMux = "a=rtcp-mux";
1024 const std::string kXRtcpMux = "a=xrtcp-mux";
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001025 rtc::replace_substrs(kRtcpMux.c_str(), kRtcpMux.length(),
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001026 kXRtcpMux.c_str(), kXRtcpMux.length(),
1027 &sdp);
1028 }
1029
1030 SessionDescriptionInterface* new_answer = CreateSessionDescription(
1031 JsepSessionDescription::kAnswer, sdp, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001032
1033 // SetRemoteDescription to enable rtcp mux.
henrike@webrtc.org723d6832013-07-12 16:04:50 +00001034 SetRemoteDescriptionWithoutError(new_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001035 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1036 EXPECT_EQ(expected_candidate_num, observer_.mline_0_candidates_.size());
deadbeefcbecd352015-09-23 11:50:27 -07001037 if (bundle) {
1038 EXPECT_EQ(0, observer_.mline_1_candidates_.size());
1039 } else {
1040 EXPECT_EQ(expected_candidate_num, observer_.mline_1_candidates_.size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001041 }
1042 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001043
zhihuang3a334652016-05-05 18:37:49 -07001044 bool ContainsVideoCodecWithName(const SessionDescriptionInterface* desc,
1045 const std::string& codec_name) {
1046 for (const auto& content : desc->description()->contents()) {
1047 if (static_cast<cricket::MediaContentDescription*>(content.description)
1048 ->type() == cricket::MEDIA_TYPE_VIDEO) {
1049 const auto* mdesc =
1050 static_cast<cricket::VideoContentDescription*>(content.description);
1051 for (const auto& codec : mdesc->codecs()) {
1052 if (codec.name == codec_name) {
1053 return true;
1054 }
1055 }
1056 }
1057 }
1058 return false;
1059 }
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001060 // Helper class to configure loopback network and verify Best
1061 // Connection using right IP protocol for TestLoopbackCall
1062 // method. LoopbackNetworkManager applies firewall rules to block
1063 // all ping traffic once ICE completed, and remove them to observe
1064 // ICE reconnected again. This LoopbackNetworkConfiguration struct
1065 // verifies the best connection is using the right IP protocol after
1066 // initial ICE convergences.
1067
1068 class LoopbackNetworkConfiguration {
deadbeefcbecd352015-09-23 11:50:27 -07001069 public:
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001070 LoopbackNetworkConfiguration()
1071 : test_ipv6_network_(false),
1072 test_extra_ipv4_network_(false),
1073 best_connection_after_initial_ice_converged_(1, 0) {}
1074
1075 // Used to track the expected best connection count in each IP protocol.
1076 struct ExpectedBestConnection {
1077 ExpectedBestConnection(int ipv4_count, int ipv6_count)
1078 : ipv4_count_(ipv4_count),
1079 ipv6_count_(ipv6_count) {}
1080
1081 int ipv4_count_;
1082 int ipv6_count_;
1083 };
1084
1085 bool test_ipv6_network_;
1086 bool test_extra_ipv4_network_;
1087 ExpectedBestConnection best_connection_after_initial_ice_converged_;
1088
1089 void VerifyBestConnectionAfterIceConverge(
jbauchac8869e2015-07-03 01:36:14 -07001090 const rtc::scoped_refptr<FakeMetricsObserver> metrics_observer) const {
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001091 Verify(metrics_observer, best_connection_after_initial_ice_converged_);
1092 }
1093
1094 private:
jbauchac8869e2015-07-03 01:36:14 -07001095 void Verify(const rtc::scoped_refptr<FakeMetricsObserver> metrics_observer,
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001096 const ExpectedBestConnection& expected) const {
1097 EXPECT_EQ(
Guo-wei Shieh3d564c12015-08-19 16:51:15 -07001098 metrics_observer->GetEnumCounter(webrtc::kEnumCounterAddressFamily,
1099 webrtc::kBestConnections_IPv4),
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001100 expected.ipv4_count_);
1101 EXPECT_EQ(
Guo-wei Shieh3d564c12015-08-19 16:51:15 -07001102 metrics_observer->GetEnumCounter(webrtc::kEnumCounterAddressFamily,
1103 webrtc::kBestConnections_IPv6),
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001104 expected.ipv6_count_);
Guo-wei Shieh3d564c12015-08-19 16:51:15 -07001105 // This is used in the loopback call so there is only single host to host
1106 // candidate pair.
1107 EXPECT_EQ(metrics_observer->GetEnumCounter(
1108 webrtc::kEnumCounterIceCandidatePairTypeUdp,
1109 webrtc::kIceCandidatePairHostHost),
Guo-wei Shieh3cc834a2015-09-04 15:52:14 -07001110 0);
1111 EXPECT_EQ(metrics_observer->GetEnumCounter(
1112 webrtc::kEnumCounterIceCandidatePairTypeUdp,
1113 webrtc::kIceCandidatePairHostPublicHostPublic),
Guo-wei Shieh3d564c12015-08-19 16:51:15 -07001114 1);
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001115 }
1116 };
1117
1118 class LoopbackNetworkManager {
1119 public:
1120 LoopbackNetworkManager(WebRtcSessionTest* session,
1121 const LoopbackNetworkConfiguration& config)
1122 : config_(config) {
1123 session->AddInterface(
1124 rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
1125 if (config_.test_extra_ipv4_network_) {
1126 session->AddInterface(
1127 rtc::SocketAddress(kClientAddrHost2, kClientAddrPort));
1128 }
1129 if (config_.test_ipv6_network_) {
1130 session->AddInterface(
1131 rtc::SocketAddress(kClientIPv6AddrHost1, kClientAddrPort));
1132 }
1133 }
1134
1135 void ApplyFirewallRules(rtc::FirewallSocketServer* fss) {
1136 fss->AddRule(false, rtc::FP_ANY, rtc::FD_ANY,
1137 rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
1138 if (config_.test_extra_ipv4_network_) {
1139 fss->AddRule(false, rtc::FP_ANY, rtc::FD_ANY,
1140 rtc::SocketAddress(kClientAddrHost2, kClientAddrPort));
1141 }
1142 if (config_.test_ipv6_network_) {
1143 fss->AddRule(false, rtc::FP_ANY, rtc::FD_ANY,
1144 rtc::SocketAddress(kClientIPv6AddrHost1, kClientAddrPort));
1145 }
1146 }
1147
1148 void ClearRules(rtc::FirewallSocketServer* fss) { fss->ClearRules(); }
1149
1150 private:
1151 LoopbackNetworkConfiguration config_;
1152 };
1153
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001154 // The method sets up a call from the session to itself, in a loopback
1155 // arrangement. It also uses a firewall rule to create a temporary
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00001156 // disconnection, and then a permanent disconnection.
1157 // This code is placed in a method so that it can be invoked
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001158 // by multiple tests with different allocators (e.g. with and without BUNDLE).
1159 // While running the call, this method also checks if the session goes through
1160 // the correct sequence of ICE states when a connection is established,
1161 // broken, and re-established.
1162 // The Connection state should go:
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00001163 // New -> Checking -> (Connected) -> Completed -> Disconnected -> Completed
1164 // -> Failed.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001165 // The Gathering state should go: New -> Gathering -> Completed.
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001166
stefanc1aeaf02015-10-15 07:26:07 -07001167 void SetupLoopbackCall() {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001168 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001169 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001170 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001171
1172 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
1173 observer_.ice_gathering_state_);
1174 SetLocalDescriptionWithoutError(offer);
1175 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
1176 observer_.ice_connection_state_);
1177 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringGathering,
stefanc1aeaf02015-10-15 07:26:07 -07001178 observer_.ice_gathering_state_, kIceCandidatesTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001179 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1180 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringComplete,
stefanc1aeaf02015-10-15 07:26:07 -07001181 observer_.ice_gathering_state_, kIceCandidatesTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001182
1183 std::string sdp;
1184 offer->ToString(&sdp);
stefanc1aeaf02015-10-15 07:26:07 -07001185 SessionDescriptionInterface* desc = webrtc::CreateSessionDescription(
1186 JsepSessionDescription::kAnswer, sdp, nullptr);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001187 ASSERT_TRUE(desc != NULL);
1188 SetRemoteDescriptionWithoutError(desc);
1189
1190 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionChecking,
stefanc1aeaf02015-10-15 07:26:07 -07001191 observer_.ice_connection_state_, kIceCandidatesTimeout);
mallinath@webrtc.orgd3dc4242014-03-01 00:05:52 +00001192
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00001193 // The ice connection state is "Connected" too briefly to catch in a test.
1194 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
stefanc1aeaf02015-10-15 07:26:07 -07001195 observer_.ice_connection_state_, kIceCandidatesTimeout);
1196 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001197
stefanc1aeaf02015-10-15 07:26:07 -07001198 void TestLoopbackCall(const LoopbackNetworkConfiguration& config) {
1199 LoopbackNetworkManager loopback_network_manager(this, config);
1200 SetupLoopbackCall();
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001201 config.VerifyBestConnectionAfterIceConverge(metrics_observer_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001202 // Adding firewall rule to block ping requests, which should cause
1203 // transport channel failure.
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001204
1205 loopback_network_manager.ApplyFirewallRules(fss_.get());
1206
1207 LOG(LS_INFO) << "Firewall Rules applied";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001208 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionDisconnected,
1209 observer_.ice_connection_state_,
1210 kIceCandidatesTimeout);
1211
jbauchac8869e2015-07-03 01:36:14 -07001212 metrics_observer_->Reset();
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001213
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001214 // Clearing the rules, session should move back to completed state.
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001215 loopback_network_manager.ClearRules(fss_.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001216
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001217 LOG(LS_INFO) << "Firewall Rules cleared";
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00001218 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001219 observer_.ice_connection_state_,
1220 kIceCandidatesTimeout);
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00001221
1222 // Now we block ping requests and wait until the ICE connection transitions
1223 // to the Failed state. This will take at least 30 seconds because it must
1224 // wait for the Port to timeout.
1225 int port_timeout = 30000;
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001226
1227 loopback_network_manager.ApplyFirewallRules(fss_.get());
1228 LOG(LS_INFO) << "Firewall Rules applied again";
jlmiller@webrtc.org804eb462015-02-20 02:20:03 +00001229 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionDisconnected,
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00001230 observer_.ice_connection_state_,
1231 kIceCandidatesTimeout + port_timeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001232 }
1233
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001234 void TestLoopbackCall() {
1235 LoopbackNetworkConfiguration config;
1236 TestLoopbackCall(config);
1237 }
1238
stefanc1aeaf02015-10-15 07:26:07 -07001239 void TestPacketOptions() {
stefanc1aeaf02015-10-15 07:26:07 -07001240 LoopbackNetworkConfiguration config;
1241 LoopbackNetworkManager loopback_network_manager(this, config);
1242
1243 SetupLoopbackCall();
1244
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001245 // Wait for channel to be ready for sending.
1246 EXPECT_TRUE_WAIT(media_engine_->GetVideoChannel(0)->sending(), 100);
stefanc1aeaf02015-10-15 07:26:07 -07001247 uint8_t test_packet[15] = {0};
1248 rtc::PacketOptions options;
1249 options.packet_id = 10;
1250 media_engine_->GetVideoChannel(0)
1251 ->SendRtp(test_packet, sizeof(test_packet), options);
1252
1253 const int kPacketTimeout = 2000;
deadbeef14461d42016-06-15 11:06:57 -07001254 EXPECT_EQ_WAIT(10, fake_call_.last_sent_nonnegative_packet_id(),
1255 kPacketTimeout);
stefanc1aeaf02015-10-15 07:26:07 -07001256 EXPECT_GT(fake_call_.last_sent_packet().send_time_ms, -1);
1257 }
1258
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001259 // Adds CN codecs to FakeMediaEngine and MediaDescriptionFactory.
1260 void AddCNCodecs() {
deadbeef67cf2c12016-04-13 10:07:16 -07001261 const cricket::AudioCodec kCNCodec1(102, "CN", 8000, 0, 1);
1262 const cricket::AudioCodec kCNCodec2(103, "CN", 16000, 0, 1);
wu@webrtc.org364f2042013-11-20 21:49:41 +00001263
1264 // Add kCNCodec for dtmf test.
ossudedfd282016-06-14 07:12:39 -07001265 std::vector<cricket::AudioCodec> codecs =
1266 media_engine_->audio_send_codecs();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001267 codecs.push_back(kCNCodec1);
1268 codecs.push_back(kCNCodec2);
1269 media_engine_->SetAudioCodecs(codecs);
ossu075af922016-06-14 03:29:38 -07001270 desc_factory_->set_audio_codecs(codecs, codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001271 }
1272
1273 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
1274 const cricket::ContentDescription* description = content->description;
nissec8ee8822017-01-18 07:20:55 -08001275 RTC_CHECK(description != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001276 const cricket::AudioContentDescription* audio_content_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00001277 static_cast<const cricket::AudioContentDescription*>(description);
nissec8ee8822017-01-18 07:20:55 -08001278 RTC_CHECK(audio_content_desc != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001279 for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
1280 if (audio_content_desc->codecs()[i].name == "CN")
1281 return false;
1282 }
1283 return true;
1284 }
1285
deadbeefab9b2d12015-10-14 11:33:11 -07001286 void CreateDataChannel() {
deadbeeffc648b62015-10-13 16:42:33 -07001287 webrtc::InternalDataChannelInit dci;
nissec8ee8822017-01-18 07:20:55 -08001288 RTC_CHECK(session_.get());
deadbeefab9b2d12015-10-14 11:33:11 -07001289 dci.reliable = session_->data_channel_type() == cricket::DCT_SCTP;
1290 data_channel_ = DataChannel::Create(
1291 session_.get(), session_->data_channel_type(), "datachannel", dci);
1292 }
1293
1294 void SetLocalDescriptionWithDataChannel() {
1295 CreateDataChannel();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001296 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001297 SetLocalDescriptionWithoutError(offer);
1298 }
1299
skvlad11a9cbf2016-10-07 11:53:05 -07001300 webrtc::RtcEventLogNullImpl event_log_;
nisse7eaa4ea2017-05-08 05:25:41 -07001301 std::unique_ptr<rtc::VirtualSocketServer> vss_;
1302 std::unique_ptr<rtc::FirewallSocketServer> fss_;
1303 rtc::AutoSocketServerThread thread_;
deadbeef112b2e92017-02-10 20:13:37 -08001304 // |media_engine_| and |data_engine_| are actually owned by
1305 // |channel_manager_|.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001306 cricket::FakeMediaEngine* media_engine_;
1307 cricket::FakeDataEngine* data_engine_;
deadbeef953c2ce2017-01-09 14:53:41 -08001308 // Actually owned by session_.
1309 FakeSctpTransportFactory* fake_sctp_transport_factory_ = nullptr;
kwibergd1fe2812016-04-27 06:47:29 -07001310 std::unique_ptr<cricket::ChannelManager> channel_manager_;
stefanc1aeaf02015-10-15 07:26:07 -07001311 cricket::FakeCall fake_call_;
kwibergd1fe2812016-04-27 06:47:29 -07001312 std::unique_ptr<cricket::TransportDescriptionFactory> tdesc_factory_;
1313 std::unique_ptr<cricket::MediaSessionDescriptionFactory> desc_factory_;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001314 rtc::SocketAddress stun_socket_addr_;
kwibergd1fe2812016-04-27 06:47:29 -07001315 std::unique_ptr<cricket::TestStunServer> stun_server_;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001316 rtc::FakeNetworkManager network_manager_;
kwibergd1fe2812016-04-27 06:47:29 -07001317 std::unique_ptr<cricket::BasicPortAllocator> allocator_;
wu@webrtc.org97077a32013-10-25 21:18:33 +00001318 PeerConnectionFactoryInterface::Options options_;
htaa2a49d92016-03-04 02:51:39 -08001319 PeerConnectionInterface::RTCConfiguration configuration_;
kwibergd1fe2812016-04-27 06:47:29 -07001320 std::unique_ptr<WebRtcSessionForTest> session_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001321 MockIceObserver observer_;
1322 cricket::FakeVideoMediaChannel* video_channel_;
1323 cricket::FakeVoiceMediaChannel* voice_channel_;
jbauchac8869e2015-07-03 01:36:14 -07001324 rtc::scoped_refptr<FakeMetricsObserver> metrics_observer_;
deadbeefab9b2d12015-10-14 11:33:11 -07001325 // The following flags affect options created for CreateOffer/CreateAnswer.
1326 bool send_stream_1_ = false;
1327 bool send_stream_2_ = false;
zhihuang1c378ed2017-08-17 14:10:50 -07001328 bool local_send_audio_ = false;
1329 bool local_send_video_ = false;
1330 bool local_recv_audio_ = true;
1331 bool local_recv_video_ = true;
1332 bool remote_send_audio_ = false;
1333 bool remote_send_video_ = false;
1334 bool remote_recv_audio_ = true;
1335 bool remote_recv_video_ = true;
1336 std::vector<cricket::MediaDescriptionOptions> offered_media_sections_;
deadbeefab9b2d12015-10-14 11:33:11 -07001337 rtc::scoped_refptr<DataChannel> data_channel_;
1338 // Last values received from data channel creation signal.
1339 std::string last_data_channel_label_;
1340 InternalDataChannelInit last_data_channel_config_;
deadbeef7914b8c2017-04-21 03:23:33 -07001341 rtc::CryptoOptions crypto_options_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001342};
1343
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001344TEST_F(WebRtcSessionTest, TestSessionCandidates) {
1345 TestSessionCandidatesWithBundleRtcpMux(false, false);
1346}
1347
1348// Below test cases (TestSessionCandidatesWith*) verify the candidates gathered
1349// with rtcp-mux and/or bundle.
1350TEST_F(WebRtcSessionTest, TestSessionCandidatesWithRtcpMux) {
1351 TestSessionCandidatesWithBundleRtcpMux(false, true);
1352}
1353
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001354TEST_F(WebRtcSessionTest, TestSessionCandidatesWithBundleRtcpMux) {
1355 TestSessionCandidatesWithBundleRtcpMux(true, true);
1356}
1357
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001358TEST_F(WebRtcSessionTest, SetSdpFailedOnInvalidSdp) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001359 Init();
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001360 SessionDescriptionInterface* offer = NULL;
1361 // Since |offer| is NULL, there's no way to tell if it's an offer or answer.
1362 std::string unknown_action;
1363 SetLocalDescriptionExpectError(unknown_action, kInvalidSdp, offer);
1364 SetRemoteDescriptionExpectError(unknown_action, kInvalidSdp, offer);
1365}
1366
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001367// Test creating offers and receive answers and make sure the
1368// media engine creates the expected send and receive streams.
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001369TEST_F(WebRtcSessionTest, TestCreateSdesOfferReceiveSdesAnswer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001370 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001371 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001372 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001373 const std::string session_id_orig = offer->session_id();
1374 const std::string session_version_orig = offer->session_version();
1375 SetLocalDescriptionWithoutError(offer);
1376
deadbeefab9b2d12015-10-14 11:33:11 -07001377 SendAudioVideoStream2();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001378 SessionDescriptionInterface* answer =
1379 CreateRemoteAnswer(session_->local_description());
1380 SetRemoteDescriptionWithoutError(answer);
1381
1382 video_channel_ = media_engine_->GetVideoChannel(0);
1383 voice_channel_ = media_engine_->GetVoiceChannel(0);
1384
1385 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1386 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1387
1388 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1389 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1390
1391 ASSERT_EQ(1u, video_channel_->send_streams().size());
1392 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
1393 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1394 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
1395
1396 // Create new offer without send streams.
deadbeefab9b2d12015-10-14 11:33:11 -07001397 SendNothing();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001398 offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001399
1400 // Verify the session id is the same and the session version is
1401 // increased.
1402 EXPECT_EQ(session_id_orig, offer->session_id());
Peter Boström0c4e06b2015-10-07 12:23:21 +02001403 EXPECT_LT(rtc::FromString<uint64_t>(session_version_orig),
1404 rtc::FromString<uint64_t>(offer->session_version()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001405
1406 SetLocalDescriptionWithoutError(offer);
jiayl@webrtc.org7d4891d2014-09-09 21:43:15 +00001407 EXPECT_EQ(0u, video_channel_->send_streams().size());
1408 EXPECT_EQ(0u, voice_channel_->send_streams().size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001409
deadbeefab9b2d12015-10-14 11:33:11 -07001410 SendAudioVideoStream2();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001411 answer = CreateRemoteAnswer(session_->local_description());
1412 SetRemoteDescriptionWithoutError(answer);
1413
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001414 // Make sure the receive streams have not changed.
1415 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1416 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1417 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1418 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1419}
1420
1421// Test receiving offers and creating answers and make sure the
1422// media engine creates the expected send and receive streams.
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001423TEST_F(WebRtcSessionTest, TestReceiveSdesOfferCreateSdesAnswer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001424 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001425 SendAudioVideoStream2();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001426 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001427 SetRemoteDescriptionWithoutError(offer);
1428
deadbeefab9b2d12015-10-14 11:33:11 -07001429 SendAudioVideoStream1();
htaa2a49d92016-03-04 02:51:39 -08001430 SessionDescriptionInterface* answer = CreateAnswer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001431 SetLocalDescriptionWithoutError(answer);
1432
1433 const std::string session_id_orig = answer->session_id();
1434 const std::string session_version_orig = answer->session_version();
1435
1436 video_channel_ = media_engine_->GetVideoChannel(0);
1437 voice_channel_ = media_engine_->GetVoiceChannel(0);
1438
htaa2a49d92016-03-04 02:51:39 -08001439 ASSERT_TRUE(video_channel_);
1440 ASSERT_TRUE(voice_channel_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001441 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1442 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1443
1444 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1445 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1446
1447 ASSERT_EQ(1u, video_channel_->send_streams().size());
1448 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
1449 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1450 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
1451
deadbeefab9b2d12015-10-14 11:33:11 -07001452 SendAudioVideoStream1And2();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001453 offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001454 SetRemoteDescriptionWithoutError(offer);
1455
1456 // Answer by turning off all send streams.
deadbeefab9b2d12015-10-14 11:33:11 -07001457 SendNothing();
htaa2a49d92016-03-04 02:51:39 -08001458 answer = CreateAnswer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001459
1460 // Verify the session id is the same and the session version is
1461 // increased.
1462 EXPECT_EQ(session_id_orig, answer->session_id());
Peter Boström0c4e06b2015-10-07 12:23:21 +02001463 EXPECT_LT(rtc::FromString<uint64_t>(session_version_orig),
1464 rtc::FromString<uint64_t>(answer->session_version()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001465 SetLocalDescriptionWithoutError(answer);
1466
1467 ASSERT_EQ(2u, video_channel_->recv_streams().size());
1468 EXPECT_TRUE(kVideoTrack1 == video_channel_->recv_streams()[0].id);
1469 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[1].id);
1470 ASSERT_EQ(2u, voice_channel_->recv_streams().size());
1471 EXPECT_TRUE(kAudioTrack1 == voice_channel_->recv_streams()[0].id);
1472 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[1].id);
1473
1474 // Make sure we have no send streams.
1475 EXPECT_EQ(0u, video_channel_->send_streams().size());
1476 EXPECT_EQ(0u, voice_channel_->send_streams().size());
1477}
1478
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001479TEST_F(WebRtcSessionTest, SetLocalSdpFailedOnCreateChannel) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001480 Init();
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001481 media_engine_->set_fail_create_channel(true);
1482
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001483 SessionDescriptionInterface* offer = CreateOffer();
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001484 ASSERT_TRUE(offer != NULL);
1485 // SetRemoteDescription and SetLocalDescription will take the ownership of
1486 // the offer.
1487 SetRemoteDescriptionOfferExpectError(kCreateChannelFailed, offer);
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001488 offer = CreateOffer();
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001489 ASSERT_TRUE(offer != NULL);
1490 SetLocalDescriptionOfferExpectError(kCreateChannelFailed, offer);
1491}
1492
Taylor Brandstetterf475d362016-01-08 15:35:57 -08001493// Test that we can create and set an answer correctly when different
1494// SSL roles have been negotiated for different transports.
1495// See: https://bugs.chromium.org/p/webrtc/issues/detail?id=4525
1496TEST_P(WebRtcSessionTest, TestCreateAnswerWithDifferentSslRoles) {
1497 SendAudioVideoStream1();
1498 InitWithDtls(GetParam());
1499 SetFactoryDtlsSrtp();
1500
1501 SessionDescriptionInterface* offer = CreateOffer();
1502 SetLocalDescriptionWithoutError(offer);
1503
1504 cricket::MediaSessionOptions options;
zhihuang1c378ed2017-08-17 14:10:50 -07001505 GetOptionsForAnswer(&options);
Taylor Brandstetterf475d362016-01-08 15:35:57 -08001506
1507 // First, negotiate different SSL roles.
1508 SessionDescriptionInterface* answer =
1509 CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED);
1510 TransportInfo* audio_transport_info =
1511 answer->description()->GetTransportInfoByName("audio");
1512 audio_transport_info->description.connection_role =
1513 cricket::CONNECTIONROLE_ACTIVE;
1514 TransportInfo* video_transport_info =
1515 answer->description()->GetTransportInfoByName("video");
1516 video_transport_info->description.connection_role =
1517 cricket::CONNECTIONROLE_PASSIVE;
1518 SetRemoteDescriptionWithoutError(answer);
1519
1520 // Now create an offer in the reverse direction, and ensure the initial
1521 // offerer responds with an answer with correct SSL roles.
1522 offer = CreateRemoteOfferWithVersion(options, cricket::SEC_DISABLED,
1523 kSessionVersion,
1524 session_->remote_description());
1525 SetRemoteDescriptionWithoutError(offer);
1526
zhihuang1c378ed2017-08-17 14:10:50 -07001527 cricket::MediaSessionOptions answer_options;
1528 answer_options.bundle_enabled = true;
1529 answer = CreateAnswer(answer_options);
Taylor Brandstetterf475d362016-01-08 15:35:57 -08001530 audio_transport_info = answer->description()->GetTransportInfoByName("audio");
1531 EXPECT_EQ(cricket::CONNECTIONROLE_PASSIVE,
1532 audio_transport_info->description.connection_role);
1533 video_transport_info = answer->description()->GetTransportInfoByName("video");
1534 EXPECT_EQ(cricket::CONNECTIONROLE_ACTIVE,
1535 video_transport_info->description.connection_role);
1536 SetLocalDescriptionWithoutError(answer);
1537
1538 // Lastly, start BUNDLE-ing on "audio", expecting that the "passive" role of
1539 // audio is transferred over to video in the answer that completes the BUNDLE
1540 // negotiation.
1541 options.bundle_enabled = true;
1542 offer = CreateRemoteOfferWithVersion(options, cricket::SEC_DISABLED,
1543 kSessionVersion,
1544 session_->remote_description());
1545 SetRemoteDescriptionWithoutError(offer);
zhihuang1c378ed2017-08-17 14:10:50 -07001546 answer = CreateAnswer(answer_options);
Taylor Brandstetterf475d362016-01-08 15:35:57 -08001547 audio_transport_info = answer->description()->GetTransportInfoByName("audio");
1548 EXPECT_EQ(cricket::CONNECTIONROLE_PASSIVE,
1549 audio_transport_info->description.connection_role);
1550 video_transport_info = answer->description()->GetTransportInfoByName("video");
1551 EXPECT_EQ(cricket::CONNECTIONROLE_PASSIVE,
1552 video_transport_info->description.connection_role);
1553 SetLocalDescriptionWithoutError(answer);
1554}
1555
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001556TEST_F(WebRtcSessionTest, TestSetLocalOfferTwice) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001557 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001558 SendNothing();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001559 // SetLocalDescription take ownership of offer.
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001560 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001561 SetLocalDescriptionWithoutError(offer);
1562
1563 // SetLocalDescription take ownership of offer.
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001564 SessionDescriptionInterface* offer2 = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001565 SetLocalDescriptionWithoutError(offer2);
1566}
1567
1568TEST_F(WebRtcSessionTest, TestSetRemoteOfferTwice) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001569 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001570 SendNothing();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001571 // SetLocalDescription take ownership of offer.
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001572 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001573 SetRemoteDescriptionWithoutError(offer);
1574
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001575 SessionDescriptionInterface* offer2 = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001576 SetRemoteDescriptionWithoutError(offer2);
1577}
1578
1579TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteOffer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001580 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001581 SendNothing();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001582 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001583 SetLocalDescriptionWithoutError(offer);
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001584 offer = CreateOffer();
deadbeefd59daf82015-10-14 15:02:44 -07001585 SetRemoteDescriptionOfferExpectError("Called in wrong state: STATE_SENTOFFER",
1586 offer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001587}
1588
1589TEST_F(WebRtcSessionTest, TestSetRemoteAndLocalOffer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001590 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001591 SendNothing();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001592 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001593 SetRemoteDescriptionWithoutError(offer);
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001594 offer = CreateOffer();
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001595 SetLocalDescriptionOfferExpectError(
deadbeefd59daf82015-10-14 15:02:44 -07001596 "Called in wrong state: STATE_RECEIVEDOFFER", offer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001597}
1598
1599TEST_F(WebRtcSessionTest, TestSetLocalPrAnswer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001600 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001601 SendNothing();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001602 SessionDescriptionInterface* offer = CreateRemoteOffer();
deadbeefd59daf82015-10-14 15:02:44 -07001603 SetRemoteDescriptionExpectState(offer, WebRtcSession::STATE_RECEIVEDOFFER);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001604
htaa2a49d92016-03-04 02:51:39 -08001605 JsepSessionDescription* pranswer =
1606 static_cast<JsepSessionDescription*>(CreateAnswer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001607 pranswer->set_type(SessionDescriptionInterface::kPrAnswer);
deadbeefd59daf82015-10-14 15:02:44 -07001608 SetLocalDescriptionExpectState(pranswer, WebRtcSession::STATE_SENTPRANSWER);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001609
deadbeefab9b2d12015-10-14 11:33:11 -07001610 SendAudioVideoStream1();
htaa2a49d92016-03-04 02:51:39 -08001611 JsepSessionDescription* pranswer2 =
1612 static_cast<JsepSessionDescription*>(CreateAnswer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001613 pranswer2->set_type(SessionDescriptionInterface::kPrAnswer);
1614
deadbeefd59daf82015-10-14 15:02:44 -07001615 SetLocalDescriptionExpectState(pranswer2, WebRtcSession::STATE_SENTPRANSWER);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001616
deadbeefab9b2d12015-10-14 11:33:11 -07001617 SendAudioVideoStream2();
htaa2a49d92016-03-04 02:51:39 -08001618 SessionDescriptionInterface* answer = CreateAnswer();
deadbeefd59daf82015-10-14 15:02:44 -07001619 SetLocalDescriptionExpectState(answer, WebRtcSession::STATE_INPROGRESS);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001620}
1621
1622TEST_F(WebRtcSessionTest, TestSetRemotePrAnswer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001623 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001624 SendNothing();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001625 SessionDescriptionInterface* offer = CreateOffer();
deadbeefd59daf82015-10-14 15:02:44 -07001626 SetLocalDescriptionExpectState(offer, WebRtcSession::STATE_SENTOFFER);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001627
1628 JsepSessionDescription* pranswer =
1629 CreateRemoteAnswer(session_->local_description());
1630 pranswer->set_type(SessionDescriptionInterface::kPrAnswer);
1631
1632 SetRemoteDescriptionExpectState(pranswer,
deadbeefd59daf82015-10-14 15:02:44 -07001633 WebRtcSession::STATE_RECEIVEDPRANSWER);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001634
deadbeefab9b2d12015-10-14 11:33:11 -07001635 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001636 JsepSessionDescription* pranswer2 =
1637 CreateRemoteAnswer(session_->local_description());
1638 pranswer2->set_type(SessionDescriptionInterface::kPrAnswer);
1639
1640 SetRemoteDescriptionExpectState(pranswer2,
deadbeefd59daf82015-10-14 15:02:44 -07001641 WebRtcSession::STATE_RECEIVEDPRANSWER);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001642
deadbeefab9b2d12015-10-14 11:33:11 -07001643 SendAudioVideoStream2();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001644 SessionDescriptionInterface* answer =
1645 CreateRemoteAnswer(session_->local_description());
deadbeefd59daf82015-10-14 15:02:44 -07001646 SetRemoteDescriptionExpectState(answer, WebRtcSession::STATE_INPROGRESS);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001647}
1648
1649TEST_F(WebRtcSessionTest, TestSetLocalAnswerWithoutOffer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001650 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001651 SendNothing();
kwibergd1fe2812016-04-27 06:47:29 -07001652 std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer());
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001653
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001654 SessionDescriptionInterface* answer =
1655 CreateRemoteAnswer(offer.get());
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001656 SetLocalDescriptionAnswerExpectError("Called in wrong state: STATE_INIT",
1657 answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001658}
1659
1660TEST_F(WebRtcSessionTest, TestSetRemoteAnswerWithoutOffer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001661 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001662 SendNothing();
kwibergd1fe2812016-04-27 06:47:29 -07001663 std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer());
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001664
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001665 SessionDescriptionInterface* answer =
1666 CreateRemoteAnswer(offer.get());
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001667 SetRemoteDescriptionAnswerExpectError(
1668 "Called in wrong state: STATE_INIT", answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001669}
1670
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001671// Verifies TransportProxy and media channels are created with content names
1672// present in the SessionDescription.
1673TEST_F(WebRtcSessionTest, TestChannelCreationsWithContentNames) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001674 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001675 SendAudioVideoStream1();
kwibergd1fe2812016-04-27 06:47:29 -07001676 std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001677
1678 // CreateOffer creates session description with the content names "audio" and
deadbeefd59daf82015-10-14 15:02:44 -07001679 // "video". Goal is to modify these content names and verify transport
1680 // channels
1681 // in the WebRtcSession, as channels are created with the content names
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001682 // present in SDP.
1683 std::string sdp;
1684 EXPECT_TRUE(offer->ToString(&sdp));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001685
1686 SessionDescriptionInterface* modified_offer =
1687 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
1688
1689 SetRemoteDescriptionWithoutError(modified_offer);
1690
zhihuang1c378ed2017-08-17 14:10:50 -07001691 cricket::MediaSessionOptions answer_options;
1692 answer_options.bundle_enabled = false;
1693 SessionDescriptionInterface* answer = CreateAnswer(answer_options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001694 SetLocalDescriptionWithoutError(answer);
1695
deadbeef5bd5ca32017-02-10 11:31:50 -08001696 rtc::PacketTransportInternal* voice_transport_channel =
deadbeefcbecd352015-09-23 11:50:27 -07001697 session_->voice_rtp_transport_channel();
1698 EXPECT_TRUE(voice_transport_channel != NULL);
johan669d69b2016-11-08 14:14:08 -08001699 EXPECT_EQ(voice_transport_channel->debug_name(),
zhihuang1c378ed2017-08-17 14:10:50 -07001700 "audio " + std::to_string(cricket::ICE_CANDIDATE_COMPONENT_RTP));
deadbeef5bd5ca32017-02-10 11:31:50 -08001701 rtc::PacketTransportInternal* video_transport_channel =
deadbeefcbecd352015-09-23 11:50:27 -07001702 session_->video_rtp_transport_channel();
htaa2a49d92016-03-04 02:51:39 -08001703 ASSERT_TRUE(video_transport_channel != NULL);
johan669d69b2016-11-08 14:14:08 -08001704 EXPECT_EQ(video_transport_channel->debug_name(),
zhihuang1c378ed2017-08-17 14:10:50 -07001705 "video " + std::to_string(cricket::ICE_CANDIDATE_COMPONENT_RTP));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001706 EXPECT_TRUE((video_channel_ = media_engine_->GetVideoChannel(0)) != NULL);
1707 EXPECT_TRUE((voice_channel_ = media_engine_->GetVoiceChannel(0)) != NULL);
1708}
1709
1710// Test that an offer contains the correct media content descriptions based on
1711// the send streams when no constraints have been set.
1712TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraintsOrStreams) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001713 Init();
kwibergd1fe2812016-04-27 06:47:29 -07001714 std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer());
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001715
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001716 ASSERT_TRUE(offer != NULL);
1717 const cricket::ContentInfo* content =
1718 cricket::GetFirstAudioContent(offer->description());
zhihuang1c378ed2017-08-17 14:10:50 -07001719 ASSERT_TRUE(content != NULL);
1720 EXPECT_EQ(
1721 cricket::MD_RECVONLY,
1722 static_cast<const cricket::AudioContentDescription*>(content->description)
1723 ->direction());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001724 content = cricket::GetFirstVideoContent(offer->description());
zhihuang1c378ed2017-08-17 14:10:50 -07001725 ASSERT_TRUE(content != NULL);
1726 EXPECT_EQ(
1727 cricket::MD_RECVONLY,
1728 static_cast<const cricket::VideoContentDescription*>(content->description)
1729 ->direction());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001730}
1731
1732// Test that an offer contains the correct media content descriptions based on
1733// the send streams when no constraints have been set.
1734TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraints) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001735 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001736 // Test Audio only offer.
deadbeefab9b2d12015-10-14 11:33:11 -07001737 SendAudioOnlyStream2();
kwibergd1fe2812016-04-27 06:47:29 -07001738 std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer());
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001739
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001740 const cricket::ContentInfo* content =
1741 cricket::GetFirstAudioContent(offer->description());
zhihuang1c378ed2017-08-17 14:10:50 -07001742 ASSERT_TRUE(content != NULL);
1743 EXPECT_EQ(
1744 cricket::MD_SENDRECV,
1745 static_cast<const cricket::AudioContentDescription*>(content->description)
1746 ->direction());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001747 content = cricket::GetFirstVideoContent(offer->description());
zhihuang1c378ed2017-08-17 14:10:50 -07001748 ASSERT_TRUE(content != NULL);
1749 EXPECT_EQ(
1750 cricket::MD_RECVONLY,
1751 static_cast<const cricket::VideoContentDescription*>(content->description)
1752 ->direction());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001753
1754 // Test Audio / Video offer.
deadbeefab9b2d12015-10-14 11:33:11 -07001755 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001756 offer.reset(CreateOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001757 content = cricket::GetFirstAudioContent(offer->description());
zhihuang1c378ed2017-08-17 14:10:50 -07001758 ASSERT_TRUE(content != NULL);
1759 EXPECT_EQ(
1760 cricket::MD_SENDRECV,
1761 static_cast<const cricket::AudioContentDescription*>(content->description)
1762 ->direction());
1763
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001764 content = cricket::GetFirstVideoContent(offer->description());
zhihuang1c378ed2017-08-17 14:10:50 -07001765 ASSERT_TRUE(content != NULL);
1766 EXPECT_EQ(
1767 cricket::MD_SENDRECV,
1768 static_cast<const cricket::VideoContentDescription*>(content->description)
1769 ->direction());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001770}
1771
1772// Test that an offer contains no media content descriptions if
1773// kOfferToReceiveVideo and kOfferToReceiveAudio constraints are set to false.
1774TEST_F(WebRtcSessionTest, CreateOfferWithConstraintsWithoutStreams) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001775 Init();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001776 PeerConnectionInterface::RTCOfferAnswerOptions options;
1777 options.offer_to_receive_audio = 0;
1778 options.offer_to_receive_video = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001779
kwibergd1fe2812016-04-27 06:47:29 -07001780 std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer(options));
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001781
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001782 ASSERT_TRUE(offer != NULL);
1783 const cricket::ContentInfo* content =
1784 cricket::GetFirstAudioContent(offer->description());
1785 EXPECT_TRUE(content == NULL);
1786 content = cricket::GetFirstVideoContent(offer->description());
1787 EXPECT_TRUE(content == NULL);
1788}
1789
1790// Test that an offer contains only audio media content descriptions if
1791// kOfferToReceiveAudio constraints are set to true.
1792TEST_F(WebRtcSessionTest, CreateAudioOnlyOfferWithConstraints) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001793 Init();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001794 PeerConnectionInterface::RTCOfferAnswerOptions options;
1795 options.offer_to_receive_audio =
1796 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
zhihuang1c378ed2017-08-17 14:10:50 -07001797 options.offer_to_receive_video = 0;
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001798
kwibergd1fe2812016-04-27 06:47:29 -07001799 std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer(options));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001800
1801 const cricket::ContentInfo* content =
1802 cricket::GetFirstAudioContent(offer->description());
1803 EXPECT_TRUE(content != NULL);
1804 content = cricket::GetFirstVideoContent(offer->description());
1805 EXPECT_TRUE(content == NULL);
1806}
1807
1808// Test that an offer contains audio and video media content descriptions if
1809// kOfferToReceiveAudio and kOfferToReceiveVideo constraints are set to true.
1810TEST_F(WebRtcSessionTest, CreateOfferWithConstraints) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001811 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001812 // Test Audio / Video offer.
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001813 PeerConnectionInterface::RTCOfferAnswerOptions options;
1814 options.offer_to_receive_audio =
1815 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
1816 options.offer_to_receive_video =
1817 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
1818
kwibergd1fe2812016-04-27 06:47:29 -07001819 std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer(options));
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001820
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001821 const cricket::ContentInfo* content =
1822 cricket::GetFirstAudioContent(offer->description());
jiayl@webrtc.orgc1723202014-09-08 20:44:36 +00001823 EXPECT_TRUE(content != NULL);
jiayl@webrtc.org7d4891d2014-09-09 21:43:15 +00001824
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001825 content = cricket::GetFirstVideoContent(offer->description());
1826 EXPECT_TRUE(content != NULL);
1827
jiayl@webrtc.org7d4891d2014-09-09 21:43:15 +00001828 // Sets constraints to false and verifies that audio/video contents are
1829 // removed.
1830 options.offer_to_receive_audio = 0;
1831 options.offer_to_receive_video = 0;
zhihuang1c378ed2017-08-17 14:10:50 -07001832 // Remove the media sections added in previous offer.
1833 offered_media_sections_.clear();
jiayl@webrtc.org7d4891d2014-09-09 21:43:15 +00001834 offer.reset(CreateOffer(options));
1835
1836 content = cricket::GetFirstAudioContent(offer->description());
1837 EXPECT_TRUE(content == NULL);
1838 content = cricket::GetFirstVideoContent(offer->description());
1839 EXPECT_TRUE(content == NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001840}
1841
1842// Test that an answer can not be created if the last remote description is not
1843// an offer.
1844TEST_F(WebRtcSessionTest, CreateAnswerWithoutAnOffer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001845 Init();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001846 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001847 SetLocalDescriptionWithoutError(offer);
1848 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
1849 SetRemoteDescriptionWithoutError(answer);
htaa2a49d92016-03-04 02:51:39 -08001850 EXPECT_TRUE(CreateAnswer() == NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001851}
1852
1853// Test that an answer contains the correct media content descriptions when no
1854// constraints have been set.
1855TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraintsOrStreams) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001856 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001857 // Create a remote offer with audio and video content.
kwibergd1fe2812016-04-27 06:47:29 -07001858 std::unique_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001859 SetRemoteDescriptionWithoutError(offer.release());
kwibergd1fe2812016-04-27 06:47:29 -07001860 std::unique_ptr<SessionDescriptionInterface> answer(CreateAnswer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001861 const cricket::ContentInfo* content =
1862 cricket::GetFirstAudioContent(answer->description());
1863 ASSERT_TRUE(content != NULL);
1864 EXPECT_FALSE(content->rejected);
1865
1866 content = cricket::GetFirstVideoContent(answer->description());
1867 ASSERT_TRUE(content != NULL);
1868 EXPECT_FALSE(content->rejected);
1869}
1870
1871// Test that an answer contains the correct media content descriptions when no
1872// constraints have been set and the offer only contain audio.
1873TEST_F(WebRtcSessionTest, CreateAudioAnswerWithoutConstraintsOrStreams) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001874 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001875 // Create a remote offer with audio only.
1876 cricket::MediaSessionOptions options;
zhihuang1c378ed2017-08-17 14:10:50 -07001877 GetOptionsForAudioOnlyRemoteOffer(&options);
jiayl@webrtc.org7d4891d2014-09-09 21:43:15 +00001878
kwibergd1fe2812016-04-27 06:47:29 -07001879 std::unique_ptr<JsepSessionDescription> offer(CreateRemoteOffer(options));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001880 ASSERT_TRUE(cricket::GetFirstVideoContent(offer->description()) == NULL);
1881 ASSERT_TRUE(cricket::GetFirstAudioContent(offer->description()) != NULL);
1882
1883 SetRemoteDescriptionWithoutError(offer.release());
kwibergd1fe2812016-04-27 06:47:29 -07001884 std::unique_ptr<SessionDescriptionInterface> answer(CreateAnswer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001885 const cricket::ContentInfo* content =
1886 cricket::GetFirstAudioContent(answer->description());
1887 ASSERT_TRUE(content != NULL);
1888 EXPECT_FALSE(content->rejected);
1889
1890 EXPECT_TRUE(cricket::GetFirstVideoContent(answer->description()) == NULL);
1891}
1892
1893// Test that an answer contains the correct media content descriptions when no
1894// constraints have been set.
1895TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraints) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001896 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001897 // Create a remote offer with audio and video content.
kwibergd1fe2812016-04-27 06:47:29 -07001898 std::unique_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001899 SetRemoteDescriptionWithoutError(offer.release());
1900 // Test with a stream with tracks.
deadbeefab9b2d12015-10-14 11:33:11 -07001901 SendAudioVideoStream1();
kwibergd1fe2812016-04-27 06:47:29 -07001902 std::unique_ptr<SessionDescriptionInterface> answer(CreateAnswer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001903 const cricket::ContentInfo* content =
1904 cricket::GetFirstAudioContent(answer->description());
1905 ASSERT_TRUE(content != NULL);
1906 EXPECT_FALSE(content->rejected);
1907
1908 content = cricket::GetFirstVideoContent(answer->description());
1909 ASSERT_TRUE(content != NULL);
1910 EXPECT_FALSE(content->rejected);
1911}
1912
1913// Test that an answer contains the correct media content descriptions when
1914// constraints have been set but no stream is sent.
1915TEST_F(WebRtcSessionTest, CreateAnswerWithConstraintsWithoutStreams) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001916 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001917 // Create a remote offer with audio and video content.
kwibergd1fe2812016-04-27 06:47:29 -07001918 std::unique_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001919 SetRemoteDescriptionWithoutError(offer.release());
1920
htaa2a49d92016-03-04 02:51:39 -08001921 cricket::MediaSessionOptions session_options;
zhihuang1c378ed2017-08-17 14:10:50 -07001922 remote_send_audio_ = false;
1923 remote_send_video_ = false;
1924 local_recv_audio_ = false;
1925 local_recv_video_ = false;
kwibergd1fe2812016-04-27 06:47:29 -07001926 std::unique_ptr<SessionDescriptionInterface> answer(
htaa2a49d92016-03-04 02:51:39 -08001927 CreateAnswer(session_options));
1928
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001929 const cricket::ContentInfo* content =
1930 cricket::GetFirstAudioContent(answer->description());
1931 ASSERT_TRUE(content != NULL);
1932 EXPECT_TRUE(content->rejected);
1933
1934 content = cricket::GetFirstVideoContent(answer->description());
1935 ASSERT_TRUE(content != NULL);
1936 EXPECT_TRUE(content->rejected);
1937}
1938
1939// Test that an answer contains the correct media content descriptions when
1940// constraints have been set and streams are sent.
1941TEST_F(WebRtcSessionTest, CreateAnswerWithConstraints) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001942 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001943 // Create a remote offer with audio and video content.
kwibergd1fe2812016-04-27 06:47:29 -07001944 std::unique_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001945 SetRemoteDescriptionWithoutError(offer.release());
1946
htaa2a49d92016-03-04 02:51:39 -08001947 cricket::MediaSessionOptions options;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001948 // Test with a stream with tracks.
deadbeefab9b2d12015-10-14 11:33:11 -07001949 SendAudioVideoStream1();
kwibergd1fe2812016-04-27 06:47:29 -07001950 std::unique_ptr<SessionDescriptionInterface> answer(CreateAnswer(options));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001951
1952 // TODO(perkj): Should the direction be set to SEND_ONLY?
1953 const cricket::ContentInfo* content =
1954 cricket::GetFirstAudioContent(answer->description());
1955 ASSERT_TRUE(content != NULL);
1956 EXPECT_FALSE(content->rejected);
1957
1958 // TODO(perkj): Should the direction be set to SEND_ONLY?
1959 content = cricket::GetFirstVideoContent(answer->description());
1960 ASSERT_TRUE(content != NULL);
1961 EXPECT_FALSE(content->rejected);
1962}
1963
1964TEST_F(WebRtcSessionTest, CreateOfferWithoutCNCodecs) {
1965 AddCNCodecs();
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001966 Init();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001967 PeerConnectionInterface::RTCOfferAnswerOptions options;
1968 options.offer_to_receive_audio =
1969 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
1970 options.voice_activity_detection = false;
1971
kwibergd1fe2812016-04-27 06:47:29 -07001972 std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer(options));
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001973
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001974 const cricket::ContentInfo* content =
1975 cricket::GetFirstAudioContent(offer->description());
1976 EXPECT_TRUE(content != NULL);
1977 EXPECT_TRUE(VerifyNoCNCodecs(content));
1978}
1979
1980TEST_F(WebRtcSessionTest, CreateAnswerWithoutCNCodecs) {
1981 AddCNCodecs();
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001982 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001983 // Create a remote offer with audio and video content.
kwibergd1fe2812016-04-27 06:47:29 -07001984 std::unique_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001985 SetRemoteDescriptionWithoutError(offer.release());
1986
htaa2a49d92016-03-04 02:51:39 -08001987 cricket::MediaSessionOptions options;
1988 options.vad_enabled = false;
kwibergd1fe2812016-04-27 06:47:29 -07001989 std::unique_ptr<SessionDescriptionInterface> answer(CreateAnswer(options));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001990 const cricket::ContentInfo* content =
1991 cricket::GetFirstAudioContent(answer->description());
1992 ASSERT_TRUE(content != NULL);
1993 EXPECT_TRUE(VerifyNoCNCodecs(content));
1994}
1995
1996// This test verifies the call setup when remote answer with audio only and
1997// later updates with video.
1998TEST_F(WebRtcSessionTest, TestAVOfferWithAudioOnlyAnswer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001999 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002000 EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL);
2001 EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL);
2002
deadbeefab9b2d12015-10-14 11:33:11 -07002003 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002004 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002005
2006 cricket::MediaSessionOptions options;
zhihuang1c378ed2017-08-17 14:10:50 -07002007 AddMediaSection(cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO,
2008 cricket::MD_RECVONLY, kActive, &options);
2009 AddMediaSection(cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO,
2010 cricket::MD_INACTIVE, kStopped, &options);
2011 local_recv_video_ = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002012 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer, options);
2013
2014 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
2015 // and answer;
2016 SetLocalDescriptionWithoutError(offer);
2017 SetRemoteDescriptionWithoutError(answer);
2018
2019 video_channel_ = media_engine_->GetVideoChannel(0);
2020 voice_channel_ = media_engine_->GetVoiceChannel(0);
2021
zhihuang1c378ed2017-08-17 14:10:50 -07002022 ASSERT_TRUE(video_channel_ == nullptr);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002023
2024 ASSERT_EQ(0u, voice_channel_->recv_streams().size());
2025 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2026 EXPECT_EQ(kAudioTrack1, voice_channel_->send_streams()[0].id);
2027
2028 // Let the remote end update the session descriptions, with Audio and Video.
deadbeefab9b2d12015-10-14 11:33:11 -07002029 SendAudioVideoStream2();
zhihuang1c378ed2017-08-17 14:10:50 -07002030 local_recv_video_ = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002031 CreateAndSetRemoteOfferAndLocalAnswer();
2032
2033 video_channel_ = media_engine_->GetVideoChannel(0);
2034 voice_channel_ = media_engine_->GetVoiceChannel(0);
2035
zhihuang1c378ed2017-08-17 14:10:50 -07002036 ASSERT_TRUE(video_channel_ != nullptr);
2037 ASSERT_TRUE(voice_channel_ != nullptr);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002038
2039 ASSERT_EQ(1u, video_channel_->recv_streams().size());
2040 ASSERT_EQ(1u, video_channel_->send_streams().size());
2041 EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id);
2042 EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id);
2043 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
2044 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2045 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
2046 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
2047
2048 // Change session back to audio only.
zhihuang1c378ed2017-08-17 14:10:50 -07002049 // The remote side doesn't send and recv video.
deadbeefab9b2d12015-10-14 11:33:11 -07002050 SendAudioOnlyStream2();
zhihuang1c378ed2017-08-17 14:10:50 -07002051 remote_recv_video_ = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002052 CreateAndSetRemoteOfferAndLocalAnswer();
2053
zhihuang1c378ed2017-08-17 14:10:50 -07002054 video_channel_ = media_engine_->GetVideoChannel(0);
2055 voice_channel_ = media_engine_->GetVoiceChannel(0);
2056
2057 // The audio is expected to be rejected.
2058 EXPECT_TRUE(video_channel_ == nullptr);
2059
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002060 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
2061 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
2062 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2063 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
2064}
2065
2066// This test verifies the call setup when remote answer with video only and
2067// later updates with audio.
2068TEST_F(WebRtcSessionTest, TestAVOfferWithVideoOnlyAnswer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002069 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002070 EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL);
2071 EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL);
deadbeefab9b2d12015-10-14 11:33:11 -07002072 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002073 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002074
2075 cricket::MediaSessionOptions options;
zhihuang1c378ed2017-08-17 14:10:50 -07002076 AddMediaSection(cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO,
2077 cricket::MD_INACTIVE, kStopped, &options);
2078 AddMediaSection(cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO,
2079 cricket::MD_RECVONLY, kActive, &options);
2080 local_recv_audio_ = false;
2081 SessionDescriptionInterface* answer =
2082 CreateRemoteAnswer(offer, options, cricket::SEC_ENABLED);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002083
2084 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
2085 // and answer.
2086 SetLocalDescriptionWithoutError(offer);
2087 SetRemoteDescriptionWithoutError(answer);
2088
2089 video_channel_ = media_engine_->GetVideoChannel(0);
2090 voice_channel_ = media_engine_->GetVoiceChannel(0);
2091
2092 ASSERT_TRUE(voice_channel_ == NULL);
2093 ASSERT_TRUE(video_channel_ != NULL);
2094
2095 EXPECT_EQ(0u, video_channel_->recv_streams().size());
2096 ASSERT_EQ(1u, video_channel_->send_streams().size());
2097 EXPECT_EQ(kVideoTrack1, video_channel_->send_streams()[0].id);
2098
2099 // Update the session descriptions, with Audio and Video.
deadbeefab9b2d12015-10-14 11:33:11 -07002100 SendAudioVideoStream2();
zhihuang1c378ed2017-08-17 14:10:50 -07002101 local_recv_audio_ = true;
2102 SessionDescriptionInterface* offer2 = CreateRemoteOffer();
2103 SetRemoteDescriptionWithoutError(offer2);
2104 cricket::MediaSessionOptions answer_options;
2105 // Disable the bundling here. If the media is bundled on audio
2106 // transport, then we can't reject the audio because switching the bundled
2107 // transport is not currently supported.
2108 // (https://bugs.chromium.org/p/webrtc/issues/detail?id=6704)
2109 answer_options.bundle_enabled = false;
2110 SessionDescriptionInterface* answer2 = CreateAnswer(answer_options);
2111 SetLocalDescriptionWithoutError(answer2);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002112
2113 voice_channel_ = media_engine_->GetVoiceChannel(0);
olka3c747662017-08-17 06:50:32 -07002114
zhihuang1c378ed2017-08-17 14:10:50 -07002115 ASSERT_TRUE(voice_channel_ != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002116 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
2117 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2118 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
2119 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
2120
2121 // Change session back to video only.
zhihuang1c378ed2017-08-17 14:10:50 -07002122 // The remote side doesn't send and recv audio.
deadbeefab9b2d12015-10-14 11:33:11 -07002123 SendVideoOnlyStream2();
zhihuang1c378ed2017-08-17 14:10:50 -07002124 remote_recv_audio_ = false;
2125 SessionDescriptionInterface* offer3 = CreateRemoteOffer();
2126 SetRemoteDescriptionWithoutError(offer3);
2127 SessionDescriptionInterface* answer3 = CreateAnswer(answer_options);
2128 SetLocalDescriptionWithoutError(answer3);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002129
2130 video_channel_ = media_engine_->GetVideoChannel(0);
2131 voice_channel_ = media_engine_->GetVoiceChannel(0);
2132
zhihuang1c378ed2017-08-17 14:10:50 -07002133 // The video is expected to be rejected.
2134 EXPECT_TRUE(voice_channel_ == nullptr);
2135
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002136 ASSERT_EQ(1u, video_channel_->recv_streams().size());
2137 EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id);
2138 ASSERT_EQ(1u, video_channel_->send_streams().size());
2139 EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id);
2140}
2141
Donald Curtisd4f769d2015-05-28 09:48:21 -07002142// Test that candidates sent to the "video" transport do not get pushed down to
deadbeefd59daf82015-10-14 15:02:44 -07002143// the "audio" transport channel when bundling.
Donald Curtisd4f769d2015-05-28 09:48:21 -07002144TEST_F(WebRtcSessionTest, TestIgnoreCandidatesForUnusedTransportWhenBundling) {
2145 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
2146
2147 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyBalanced);
deadbeefab9b2d12015-10-14 11:33:11 -07002148 SendAudioVideoStream1();
Donald Curtisd4f769d2015-05-28 09:48:21 -07002149
zhihuang1c378ed2017-08-17 14:10:50 -07002150 cricket::MediaSessionOptions offer_options;
2151 GetOptionsForRemoteOffer(&offer_options);
2152 offer_options.bundle_enabled = true;
Donald Curtisd4f769d2015-05-28 09:48:21 -07002153
zhihuang1c378ed2017-08-17 14:10:50 -07002154 SessionDescriptionInterface* offer = CreateRemoteOffer(offer_options);
Donald Curtisd4f769d2015-05-28 09:48:21 -07002155 SetRemoteDescriptionWithoutError(offer);
2156
zhihuang1c378ed2017-08-17 14:10:50 -07002157 cricket::MediaSessionOptions answer_options;
2158 answer_options.bundle_enabled = true;
2159 SessionDescriptionInterface* answer = CreateAnswer(answer_options);
Donald Curtisd4f769d2015-05-28 09:48:21 -07002160 SetLocalDescriptionWithoutError(answer);
2161
deadbeefcbecd352015-09-23 11:50:27 -07002162 EXPECT_EQ(session_->voice_rtp_transport_channel(),
2163 session_->video_rtp_transport_channel());
Donald Curtisd4f769d2015-05-28 09:48:21 -07002164
deadbeefcbecd352015-09-23 11:50:27 -07002165 cricket::BaseChannel* voice_channel = session_->voice_channel();
nissec8ee8822017-01-18 07:20:55 -08002166 ASSERT_TRUE(voice_channel != NULL);
Donald Curtisd4f769d2015-05-28 09:48:21 -07002167
2168 // Checks if one of the transport channels contains a connection using a given
2169 // port.
eladalon1cc5fc32017-08-23 04:15:18 -07002170 auto connection_with_remote_port = [this](int port) {
hbosdf6075a2016-12-19 04:58:02 -08002171 std::unique_ptr<webrtc::SessionStats> stats = session_->GetStats_s();
2172 for (auto& kv : stats->transport_stats) {
deadbeefcbecd352015-09-23 11:50:27 -07002173 for (auto& chan_stat : kv.second.channel_stats) {
2174 for (auto& conn_info : chan_stat.connection_infos) {
2175 if (conn_info.remote_candidate.address().port() == port) {
2176 return true;
2177 }
Donald Curtisd4f769d2015-05-28 09:48:21 -07002178 }
2179 }
2180 }
2181 return false;
2182 };
2183
2184 EXPECT_FALSE(connection_with_remote_port(5000));
2185 EXPECT_FALSE(connection_with_remote_port(5001));
2186 EXPECT_FALSE(connection_with_remote_port(6000));
2187
2188 // The way the *_WAIT checks work is they only wait if the condition fails,
2189 // which does not help in the case where state is not changing. This is
2190 // problematic in this test since we want to verify that adding a video
2191 // candidate does _not_ change state. So we interleave candidates and assume
2192 // that messages are executed in the order they were posted.
2193
2194 // First audio candidate.
2195 cricket::Candidate candidate0;
2196 candidate0.set_address(rtc::SocketAddress("1.1.1.1", 5000));
2197 candidate0.set_component(1);
2198 candidate0.set_protocol("udp");
zhihuang38989e52017-03-21 11:04:53 -07002199 candidate0.set_type("local");
Donald Curtisd4f769d2015-05-28 09:48:21 -07002200 JsepIceCandidate ice_candidate0(kMediaContentName0, kMediaContentIndex0,
2201 candidate0);
2202 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate0));
2203
2204 // Video candidate.
2205 cricket::Candidate candidate1;
2206 candidate1.set_address(rtc::SocketAddress("1.1.1.1", 6000));
2207 candidate1.set_component(1);
2208 candidate1.set_protocol("udp");
zhihuang38989e52017-03-21 11:04:53 -07002209 candidate1.set_type("local");
Donald Curtisd4f769d2015-05-28 09:48:21 -07002210 JsepIceCandidate ice_candidate1(kMediaContentName1, kMediaContentIndex1,
2211 candidate1);
2212 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
2213
2214 // Second audio candidate.
2215 cricket::Candidate candidate2;
2216 candidate2.set_address(rtc::SocketAddress("1.1.1.1", 5001));
2217 candidate2.set_component(1);
2218 candidate2.set_protocol("udp");
zhihuang38989e52017-03-21 11:04:53 -07002219 candidate2.set_type("local");
Donald Curtisd4f769d2015-05-28 09:48:21 -07002220 JsepIceCandidate ice_candidate2(kMediaContentName0, kMediaContentIndex0,
2221 candidate2);
2222 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
2223
2224 EXPECT_TRUE_WAIT(connection_with_remote_port(5000), 1000);
2225 EXPECT_TRUE_WAIT(connection_with_remote_port(5001), 1000);
2226
2227 // No need here for a _WAIT check since we are checking that state hasn't
2228 // changed: if this is false we would be doing waits for nothing and if this
2229 // is true then there will be no messages processed anyways.
2230 EXPECT_FALSE(connection_with_remote_port(6000));
2231}
2232
deadbeefcbecd352015-09-23 11:50:27 -07002233// kBundlePolicyBalanced BUNDLE policy and answer contains BUNDLE.
Donald Curtis0e209b02015-03-24 09:29:54 -07002234TEST_F(WebRtcSessionTest, TestBalancedBundleInAnswer) {
2235 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyBalanced);
deadbeefab9b2d12015-10-14 11:33:11 -07002236 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002237
2238 PeerConnectionInterface::RTCOfferAnswerOptions options;
2239 options.use_rtp_mux = true;
2240
2241 SessionDescriptionInterface* offer = CreateOffer(options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002242 SetLocalDescriptionWithoutError(offer);
Donald Curtis0e209b02015-03-24 09:29:54 -07002243
deadbeefcbecd352015-09-23 11:50:27 -07002244 EXPECT_NE(session_->voice_rtp_transport_channel(),
2245 session_->video_rtp_transport_channel());
Donald Curtis0e209b02015-03-24 09:29:54 -07002246
deadbeefab9b2d12015-10-14 11:33:11 -07002247 SendAudioVideoStream2();
Donald Curtis0e209b02015-03-24 09:29:54 -07002248 SessionDescriptionInterface* answer =
2249 CreateRemoteAnswer(session_->local_description());
2250 SetRemoteDescriptionWithoutError(answer);
2251
deadbeefcbecd352015-09-23 11:50:27 -07002252 EXPECT_EQ(session_->voice_rtp_transport_channel(),
2253 session_->video_rtp_transport_channel());
Donald Curtis0e209b02015-03-24 09:29:54 -07002254}
2255
deadbeefcbecd352015-09-23 11:50:27 -07002256// kBundlePolicyBalanced BUNDLE policy but no BUNDLE in the answer.
Donald Curtis0e209b02015-03-24 09:29:54 -07002257TEST_F(WebRtcSessionTest, TestBalancedNoBundleInAnswer) {
2258 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyBalanced);
deadbeefab9b2d12015-10-14 11:33:11 -07002259 SendAudioVideoStream1();
Peter Thatcher4eddf182015-04-30 10:55:59 -07002260
Donald Curtis0e209b02015-03-24 09:29:54 -07002261 PeerConnectionInterface::RTCOfferAnswerOptions options;
2262 options.use_rtp_mux = true;
2263
2264 SessionDescriptionInterface* offer = CreateOffer(options);
2265 SetLocalDescriptionWithoutError(offer);
2266
deadbeefcbecd352015-09-23 11:50:27 -07002267 EXPECT_NE(session_->voice_rtp_transport_channel(),
2268 session_->video_rtp_transport_channel());
Donald Curtis0e209b02015-03-24 09:29:54 -07002269
deadbeefab9b2d12015-10-14 11:33:11 -07002270 SendAudioVideoStream2();
Donald Curtis0e209b02015-03-24 09:29:54 -07002271
2272 // Remove BUNDLE from the answer.
kwibergd1fe2812016-04-27 06:47:29 -07002273 std::unique_ptr<SessionDescriptionInterface> answer(
Donald Curtis0e209b02015-03-24 09:29:54 -07002274 CreateRemoteAnswer(session_->local_description()));
2275 cricket::SessionDescription* answer_copy = answer->description()->Copy();
2276 answer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
2277 JsepSessionDescription* modified_answer =
2278 new JsepSessionDescription(JsepSessionDescription::kAnswer);
2279 modified_answer->Initialize(answer_copy, "1", "1");
2280 SetRemoteDescriptionWithoutError(modified_answer); //
2281
deadbeefcbecd352015-09-23 11:50:27 -07002282 EXPECT_NE(session_->voice_rtp_transport_channel(),
2283 session_->video_rtp_transport_channel());
Donald Curtis0e209b02015-03-24 09:29:54 -07002284}
2285
2286// kBundlePolicyMaxBundle policy with BUNDLE in the answer.
2287TEST_F(WebRtcSessionTest, TestMaxBundleBundleInAnswer) {
2288 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle);
deadbeefab9b2d12015-10-14 11:33:11 -07002289 SendAudioVideoStream1();
Donald Curtis0e209b02015-03-24 09:29:54 -07002290
2291 PeerConnectionInterface::RTCOfferAnswerOptions options;
2292 options.use_rtp_mux = true;
2293
2294 SessionDescriptionInterface* offer = CreateOffer(options);
2295 SetLocalDescriptionWithoutError(offer);
2296
deadbeefcbecd352015-09-23 11:50:27 -07002297 EXPECT_EQ(session_->voice_rtp_transport_channel(),
2298 session_->video_rtp_transport_channel());
Donald Curtis0e209b02015-03-24 09:29:54 -07002299
deadbeefab9b2d12015-10-14 11:33:11 -07002300 SendAudioVideoStream2();
Donald Curtis0e209b02015-03-24 09:29:54 -07002301 SessionDescriptionInterface* answer =
2302 CreateRemoteAnswer(session_->local_description());
2303 SetRemoteDescriptionWithoutError(answer);
2304
deadbeefcbecd352015-09-23 11:50:27 -07002305 EXPECT_EQ(session_->voice_rtp_transport_channel(),
2306 session_->video_rtp_transport_channel());
2307}
2308
2309// kBundlePolicyMaxBundle policy with BUNDLE in the answer, but no
2310// audio content in the answer.
2311TEST_F(WebRtcSessionTest, TestMaxBundleRejectAudio) {
2312 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle);
deadbeefab9b2d12015-10-14 11:33:11 -07002313 SendAudioVideoStream1();
deadbeefcbecd352015-09-23 11:50:27 -07002314
2315 PeerConnectionInterface::RTCOfferAnswerOptions options;
2316 options.use_rtp_mux = true;
2317
2318 SessionDescriptionInterface* offer = CreateOffer(options);
2319 SetLocalDescriptionWithoutError(offer);
2320
2321 EXPECT_EQ(session_->voice_rtp_transport_channel(),
2322 session_->video_rtp_transport_channel());
2323
zhihuang1c378ed2017-08-17 14:10:50 -07002324 SendVideoOnlyStream2();
2325 local_send_audio_ = false;
2326 remote_recv_audio_ = false;
deadbeefcbecd352015-09-23 11:50:27 -07002327 cricket::MediaSessionOptions recv_options;
zhihuang1c378ed2017-08-17 14:10:50 -07002328 GetOptionsForRemoteAnswer(&recv_options);
deadbeefcbecd352015-09-23 11:50:27 -07002329 SessionDescriptionInterface* answer =
2330 CreateRemoteAnswer(session_->local_description(), recv_options);
2331 SetRemoteDescriptionWithoutError(answer);
2332
deadbeefd59daf82015-10-14 15:02:44 -07002333 EXPECT_TRUE(nullptr == session_->voice_channel());
2334 EXPECT_TRUE(nullptr != session_->video_rtp_transport_channel());
deadbeefcbecd352015-09-23 11:50:27 -07002335
deadbeefd59daf82015-10-14 15:02:44 -07002336 session_->Close();
2337 EXPECT_TRUE(nullptr == session_->voice_rtp_transport_channel());
2338 EXPECT_TRUE(nullptr == session_->voice_rtcp_transport_channel());
2339 EXPECT_TRUE(nullptr == session_->video_rtp_transport_channel());
2340 EXPECT_TRUE(nullptr == session_->video_rtcp_transport_channel());
Donald Curtis0e209b02015-03-24 09:29:54 -07002341}
2342
2343// kBundlePolicyMaxBundle policy but no BUNDLE in the answer.
2344TEST_F(WebRtcSessionTest, TestMaxBundleNoBundleInAnswer) {
2345 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle);
deadbeefab9b2d12015-10-14 11:33:11 -07002346 SendAudioVideoStream1();
Peter Thatcher4eddf182015-04-30 10:55:59 -07002347
Donald Curtis0e209b02015-03-24 09:29:54 -07002348 PeerConnectionInterface::RTCOfferAnswerOptions options;
2349 options.use_rtp_mux = true;
2350
2351 SessionDescriptionInterface* offer = CreateOffer(options);
2352 SetLocalDescriptionWithoutError(offer);
2353
deadbeefcbecd352015-09-23 11:50:27 -07002354 EXPECT_EQ(session_->voice_rtp_transport_channel(),
2355 session_->video_rtp_transport_channel());
Donald Curtis0e209b02015-03-24 09:29:54 -07002356
deadbeefab9b2d12015-10-14 11:33:11 -07002357 SendAudioVideoStream2();
Donald Curtis0e209b02015-03-24 09:29:54 -07002358
2359 // Remove BUNDLE from the answer.
kwibergd1fe2812016-04-27 06:47:29 -07002360 std::unique_ptr<SessionDescriptionInterface> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002361 CreateRemoteAnswer(session_->local_description()));
2362 cricket::SessionDescription* answer_copy = answer->description()->Copy();
2363 answer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
2364 JsepSessionDescription* modified_answer =
2365 new JsepSessionDescription(JsepSessionDescription::kAnswer);
2366 modified_answer->Initialize(answer_copy, "1", "1");
2367 SetRemoteDescriptionWithoutError(modified_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002368
deadbeefcbecd352015-09-23 11:50:27 -07002369 EXPECT_EQ(session_->voice_rtp_transport_channel(),
2370 session_->video_rtp_transport_channel());
2371}
2372
2373// kBundlePolicyMaxBundle policy with BUNDLE in the remote offer.
2374TEST_F(WebRtcSessionTest, TestMaxBundleBundleInRemoteOffer) {
2375 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle);
deadbeefab9b2d12015-10-14 11:33:11 -07002376 SendAudioVideoStream1();
deadbeefcbecd352015-09-23 11:50:27 -07002377
2378 SessionDescriptionInterface* offer = CreateRemoteOffer();
2379 SetRemoteDescriptionWithoutError(offer);
2380
2381 EXPECT_EQ(session_->voice_rtp_transport_channel(),
2382 session_->video_rtp_transport_channel());
2383
deadbeefab9b2d12015-10-14 11:33:11 -07002384 SendAudioVideoStream2();
htaa2a49d92016-03-04 02:51:39 -08002385 SessionDescriptionInterface* answer = CreateAnswer();
deadbeefcbecd352015-09-23 11:50:27 -07002386 SetLocalDescriptionWithoutError(answer);
2387
2388 EXPECT_EQ(session_->voice_rtp_transport_channel(),
2389 session_->video_rtp_transport_channel());
2390}
2391
2392// kBundlePolicyMaxBundle policy but no BUNDLE in the remote offer.
2393TEST_F(WebRtcSessionTest, TestMaxBundleNoBundleInRemoteOffer) {
2394 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle);
deadbeefab9b2d12015-10-14 11:33:11 -07002395 SendAudioVideoStream1();
deadbeefcbecd352015-09-23 11:50:27 -07002396
2397 // Remove BUNDLE from the offer.
kwibergd1fe2812016-04-27 06:47:29 -07002398 std::unique_ptr<SessionDescriptionInterface> offer(CreateRemoteOffer());
deadbeefcbecd352015-09-23 11:50:27 -07002399 cricket::SessionDescription* offer_copy = offer->description()->Copy();
2400 offer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
2401 JsepSessionDescription* modified_offer =
2402 new JsepSessionDescription(JsepSessionDescription::kOffer);
2403 modified_offer->Initialize(offer_copy, "1", "1");
2404
2405 // Expect an error when applying the remote description
2406 SetRemoteDescriptionExpectError(JsepSessionDescription::kOffer,
2407 kCreateChannelFailed, modified_offer);
Donald Curtis0e209b02015-03-24 09:29:54 -07002408}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002409
Peter Thatcher4eddf182015-04-30 10:55:59 -07002410// kBundlePolicyMaxCompat bundle policy and answer contains BUNDLE.
Donald Curtis0e209b02015-03-24 09:29:54 -07002411TEST_F(WebRtcSessionTest, TestMaxCompatBundleInAnswer) {
2412 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxCompat);
deadbeefab9b2d12015-10-14 11:33:11 -07002413 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002414
zhihuang1c378ed2017-08-17 14:10:50 -07002415 PeerConnectionInterface::RTCOfferAnswerOptions rtc_options;
2416 rtc_options.use_rtp_mux = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002417
zhihuang1c378ed2017-08-17 14:10:50 -07002418 SessionDescriptionInterface* offer = CreateOffer(rtc_options);
Donald Curtis0e209b02015-03-24 09:29:54 -07002419 SetLocalDescriptionWithoutError(offer);
2420
deadbeefcbecd352015-09-23 11:50:27 -07002421 EXPECT_NE(session_->voice_rtp_transport_channel(),
2422 session_->video_rtp_transport_channel());
Donald Curtis0e209b02015-03-24 09:29:54 -07002423
deadbeefab9b2d12015-10-14 11:33:11 -07002424 SendAudioVideoStream2();
Donald Curtis0e209b02015-03-24 09:29:54 -07002425 SessionDescriptionInterface* answer =
2426 CreateRemoteAnswer(session_->local_description());
2427 SetRemoteDescriptionWithoutError(answer);
2428
2429 // This should lead to an audio-only call but isn't implemented
2430 // correctly yet.
deadbeefcbecd352015-09-23 11:50:27 -07002431 EXPECT_EQ(session_->voice_rtp_transport_channel(),
2432 session_->video_rtp_transport_channel());
Donald Curtis0e209b02015-03-24 09:29:54 -07002433}
2434
deadbeefcbecd352015-09-23 11:50:27 -07002435// kBundlePolicyMaxCompat BUNDLE policy but no BUNDLE in the answer.
Donald Curtis0e209b02015-03-24 09:29:54 -07002436TEST_F(WebRtcSessionTest, TestMaxCompatNoBundleInAnswer) {
2437 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxCompat);
deadbeefab9b2d12015-10-14 11:33:11 -07002438 SendAudioVideoStream1();
Donald Curtis0e209b02015-03-24 09:29:54 -07002439 PeerConnectionInterface::RTCOfferAnswerOptions options;
2440 options.use_rtp_mux = true;
2441
2442 SessionDescriptionInterface* offer = CreateOffer(options);
2443 SetLocalDescriptionWithoutError(offer);
2444
deadbeefcbecd352015-09-23 11:50:27 -07002445 EXPECT_NE(session_->voice_rtp_transport_channel(),
2446 session_->video_rtp_transport_channel());
Donald Curtis0e209b02015-03-24 09:29:54 -07002447
deadbeefab9b2d12015-10-14 11:33:11 -07002448 SendAudioVideoStream2();
Donald Curtis0e209b02015-03-24 09:29:54 -07002449
2450 // Remove BUNDLE from the answer.
kwibergd1fe2812016-04-27 06:47:29 -07002451 std::unique_ptr<SessionDescriptionInterface> answer(
Donald Curtis0e209b02015-03-24 09:29:54 -07002452 CreateRemoteAnswer(session_->local_description()));
2453 cricket::SessionDescription* answer_copy = answer->description()->Copy();
2454 answer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
2455 JsepSessionDescription* modified_answer =
2456 new JsepSessionDescription(JsepSessionDescription::kAnswer);
2457 modified_answer->Initialize(answer_copy, "1", "1");
2458 SetRemoteDescriptionWithoutError(modified_answer); //
2459
deadbeefcbecd352015-09-23 11:50:27 -07002460 EXPECT_NE(session_->voice_rtp_transport_channel(),
2461 session_->video_rtp_transport_channel());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002462}
2463
Peter Thatcher4eddf182015-04-30 10:55:59 -07002464// kBundlePolicyMaxbundle and then we call SetRemoteDescription first.
2465TEST_F(WebRtcSessionTest, TestMaxBundleWithSetRemoteDescriptionFirst) {
2466 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle);
deadbeefab9b2d12015-10-14 11:33:11 -07002467 SendAudioVideoStream1();
Peter Thatcher4eddf182015-04-30 10:55:59 -07002468
2469 PeerConnectionInterface::RTCOfferAnswerOptions options;
2470 options.use_rtp_mux = true;
2471
2472 SessionDescriptionInterface* offer = CreateOffer(options);
2473 SetRemoteDescriptionWithoutError(offer);
2474
deadbeefcbecd352015-09-23 11:50:27 -07002475 EXPECT_EQ(session_->voice_rtp_transport_channel(),
2476 session_->video_rtp_transport_channel());
Peter Thatcher4eddf182015-04-30 10:55:59 -07002477}
2478
skvlad6c87a672016-05-17 17:49:52 -07002479// Adding a new channel to a BUNDLE which is already connected should directly
2480// assign the bundle transport to the channel, without first setting a
2481// disconnected non-bundle transport and then replacing it. The application
2482// should not receive any changes in the ICE state.
2483TEST_F(WebRtcSessionTest, TestAddChannelToConnectedBundle) {
2484 LoopbackNetworkConfiguration config;
2485 LoopbackNetworkManager loopback_network_manager(this, config);
2486 // Both BUNDLE and RTCP-mux need to be enabled for the ICE state to remain
2487 // connected. Disabling either of these two means that we need to wait for the
2488 // answer to find out if more transports are needed.
2489 configuration_.bundle_policy =
2490 PeerConnectionInterface::kBundlePolicyMaxBundle;
skvlad6c87a672016-05-17 17:49:52 -07002491 options_.disable_encryption = true;
deadbeef7914b8c2017-04-21 03:23:33 -07002492 InitWithRtcpMuxPolicy(PeerConnectionInterface::kRtcpMuxPolicyRequire);
skvlad6c87a672016-05-17 17:49:52 -07002493
2494 // Negotiate an audio channel with MAX_BUNDLE enabled.
2495 SendAudioOnlyStream2();
2496 SessionDescriptionInterface* offer = CreateOffer();
2497 SetLocalDescriptionWithoutError(offer);
2498 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringComplete,
2499 observer_.ice_gathering_state_, kIceCandidatesTimeout);
2500 std::string sdp;
2501 offer->ToString(&sdp);
2502 SessionDescriptionInterface* answer = webrtc::CreateSessionDescription(
2503 JsepSessionDescription::kAnswer, sdp, nullptr);
2504 ASSERT_TRUE(answer != NULL);
2505 SetRemoteDescriptionWithoutError(answer);
2506
2507 // Wait for the ICE state to stabilize.
2508 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
2509 observer_.ice_connection_state_, kIceCandidatesTimeout);
2510 observer_.ice_connection_state_history_.clear();
2511
2512 // Now add a video channel which should be using the same bundle transport.
2513 SendAudioVideoStream2();
2514 offer = CreateOffer();
2515 offer->ToString(&sdp);
2516 SetLocalDescriptionWithoutError(offer);
2517 answer = webrtc::CreateSessionDescription(JsepSessionDescription::kAnswer,
2518 sdp, nullptr);
2519 ASSERT_TRUE(answer != NULL);
2520 SetRemoteDescriptionWithoutError(answer);
2521
2522 // Wait for ICE state to stabilize
2523 rtc::Thread::Current()->ProcessMessages(0);
2524 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
2525 observer_.ice_connection_state_, kIceCandidatesTimeout);
2526
2527 // No ICE state changes are expected to happen.
2528 EXPECT_EQ(0, observer_.ice_connection_state_history_.size());
2529}
2530
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07002531TEST_F(WebRtcSessionTest, TestRequireRtcpMux) {
2532 InitWithRtcpMuxPolicy(PeerConnectionInterface::kRtcpMuxPolicyRequire);
deadbeefab9b2d12015-10-14 11:33:11 -07002533 SendAudioVideoStream1();
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07002534
2535 PeerConnectionInterface::RTCOfferAnswerOptions options;
2536 SessionDescriptionInterface* offer = CreateOffer(options);
2537 SetLocalDescriptionWithoutError(offer);
2538
deadbeefcbecd352015-09-23 11:50:27 -07002539 EXPECT_TRUE(session_->voice_rtcp_transport_channel() == NULL);
2540 EXPECT_TRUE(session_->video_rtcp_transport_channel() == NULL);
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07002541
deadbeefab9b2d12015-10-14 11:33:11 -07002542 SendAudioVideoStream2();
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07002543 SessionDescriptionInterface* answer =
2544 CreateRemoteAnswer(session_->local_description());
2545 SetRemoteDescriptionWithoutError(answer);
2546
deadbeefcbecd352015-09-23 11:50:27 -07002547 EXPECT_TRUE(session_->voice_rtcp_transport_channel() == NULL);
2548 EXPECT_TRUE(session_->video_rtcp_transport_channel() == NULL);
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07002549}
2550
2551TEST_F(WebRtcSessionTest, TestNegotiateRtcpMux) {
2552 InitWithRtcpMuxPolicy(PeerConnectionInterface::kRtcpMuxPolicyNegotiate);
deadbeefab9b2d12015-10-14 11:33:11 -07002553 SendAudioVideoStream1();
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07002554
2555 PeerConnectionInterface::RTCOfferAnswerOptions options;
2556 SessionDescriptionInterface* offer = CreateOffer(options);
2557 SetLocalDescriptionWithoutError(offer);
2558
deadbeefcbecd352015-09-23 11:50:27 -07002559 EXPECT_TRUE(session_->voice_rtcp_transport_channel() != NULL);
2560 EXPECT_TRUE(session_->video_rtcp_transport_channel() != NULL);
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07002561
deadbeefab9b2d12015-10-14 11:33:11 -07002562 SendAudioVideoStream2();
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07002563 SessionDescriptionInterface* answer =
2564 CreateRemoteAnswer(session_->local_description());
2565 SetRemoteDescriptionWithoutError(answer);
2566
deadbeefcbecd352015-09-23 11:50:27 -07002567 EXPECT_TRUE(session_->voice_rtcp_transport_channel() == NULL);
2568 EXPECT_TRUE(session_->video_rtcp_transport_channel() == NULL);
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07002569}
2570
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002571// This test verifies that SetLocalDescription and SetRemoteDescription fails
2572// if BUNDLE is enabled but rtcp-mux is disabled in m-lines.
2573TEST_F(WebRtcSessionTest, TestDisabledRtcpMuxWithBundleEnabled) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002574 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07002575 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002576
2577 PeerConnectionInterface::RTCOfferAnswerOptions options;
2578 options.use_rtp_mux = true;
2579
2580 SessionDescriptionInterface* offer = CreateOffer(options);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002581 std::string offer_str;
2582 offer->ToString(&offer_str);
2583 // Disable rtcp-mux
2584 const std::string rtcp_mux = "rtcp-mux";
2585 const std::string xrtcp_mux = "xrtcp-mux";
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002586 rtc::replace_substrs(rtcp_mux.c_str(), rtcp_mux.length(),
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002587 xrtcp_mux.c_str(), xrtcp_mux.length(),
2588 &offer_str);
Steve Anton6d64e9a2017-09-12 09:44:05 -07002589 SessionDescriptionInterface* local_offer = CreateSessionDescription(
2590 SessionDescriptionInterface::kOffer, offer_str, nullptr);
2591 ASSERT_TRUE(local_offer);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002592 SetLocalDescriptionOfferExpectError(kBundleWithoutRtcpMux, local_offer);
Steve Anton6d64e9a2017-09-12 09:44:05 -07002593
2594 SessionDescriptionInterface* remote_offer = CreateSessionDescription(
2595 SessionDescriptionInterface::kOffer, offer_str, nullptr);
2596 ASSERT_TRUE(remote_offer);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002597 SetRemoteDescriptionOfferExpectError(kBundleWithoutRtcpMux, remote_offer);
Steve Anton6d64e9a2017-09-12 09:44:05 -07002598
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002599 // Trying unmodified SDP.
2600 SetLocalDescriptionWithoutError(offer);
2601}
2602
deadbeefd59daf82015-10-14 15:02:44 -07002603// This test verifies the |initial_offerer| flag when session initiates the
2604// call.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002605TEST_F(WebRtcSessionTest, TestInitiatorFlagAsOriginator) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002606 Init();
deadbeefd59daf82015-10-14 15:02:44 -07002607 EXPECT_FALSE(session_->initial_offerer());
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002608 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002609 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
2610 SetLocalDescriptionWithoutError(offer);
deadbeefd59daf82015-10-14 15:02:44 -07002611 EXPECT_TRUE(session_->initial_offerer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002612 SetRemoteDescriptionWithoutError(answer);
deadbeefd59daf82015-10-14 15:02:44 -07002613 EXPECT_TRUE(session_->initial_offerer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002614}
2615
deadbeefd59daf82015-10-14 15:02:44 -07002616// This test verifies the |initial_offerer| flag when session receives the call.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002617TEST_F(WebRtcSessionTest, TestInitiatorFlagAsReceiver) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002618 Init();
deadbeefd59daf82015-10-14 15:02:44 -07002619 EXPECT_FALSE(session_->initial_offerer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002620 SessionDescriptionInterface* offer = CreateRemoteOffer();
2621 SetRemoteDescriptionWithoutError(offer);
htaa2a49d92016-03-04 02:51:39 -08002622 SessionDescriptionInterface* answer = CreateAnswer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002623
deadbeefd59daf82015-10-14 15:02:44 -07002624 EXPECT_FALSE(session_->initial_offerer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002625 SetLocalDescriptionWithoutError(answer);
deadbeefd59daf82015-10-14 15:02:44 -07002626 EXPECT_FALSE(session_->initial_offerer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002627}
2628
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002629// Verifing local offer and remote answer have matching m-lines as per RFC 3264.
2630TEST_F(WebRtcSessionTest, TestIncorrectMLinesInRemoteAnswer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002631 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07002632 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002633 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002634 SetLocalDescriptionWithoutError(offer);
kwibergd1fe2812016-04-27 06:47:29 -07002635 std::unique_ptr<SessionDescriptionInterface> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002636 CreateRemoteAnswer(session_->local_description()));
2637
2638 cricket::SessionDescription* answer_copy = answer->description()->Copy();
2639 answer_copy->RemoveContentByName("video");
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002640 JsepSessionDescription* modified_answer =
2641 new JsepSessionDescription(JsepSessionDescription::kAnswer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002642
2643 EXPECT_TRUE(modified_answer->Initialize(answer_copy,
2644 answer->session_id(),
2645 answer->session_version()));
Zhi Huang2a5e4262017-09-14 01:15:03 -07002646 SetRemoteDescriptionAnswerExpectError(kMlineMismatchInAnswer,
2647 modified_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002648
wu@webrtc.org4e393072014-04-07 17:04:35 +00002649 // Different content names.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002650 std::string sdp;
2651 EXPECT_TRUE(answer->ToString(&sdp));
2652 const std::string kAudioMid = "a=mid:audio";
2653 const std::string kAudioMidReplaceStr = "a=mid:audio_content_name";
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002654 rtc::replace_substrs(kAudioMid.c_str(), kAudioMid.length(),
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002655 kAudioMidReplaceStr.c_str(),
2656 kAudioMidReplaceStr.length(),
2657 &sdp);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002658 SessionDescriptionInterface* modified_answer1 =
2659 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
Zhi Huang2a5e4262017-09-14 01:15:03 -07002660 SetRemoteDescriptionAnswerExpectError(kMlineMismatchInAnswer,
2661 modified_answer1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002662
wu@webrtc.org4e393072014-04-07 17:04:35 +00002663 // Different media types.
2664 EXPECT_TRUE(answer->ToString(&sdp));
2665 const std::string kAudioMline = "m=audio";
2666 const std::string kAudioMlineReplaceStr = "m=video";
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002667 rtc::replace_substrs(kAudioMline.c_str(), kAudioMline.length(),
wu@webrtc.org4e393072014-04-07 17:04:35 +00002668 kAudioMlineReplaceStr.c_str(),
2669 kAudioMlineReplaceStr.length(),
2670 &sdp);
2671 SessionDescriptionInterface* modified_answer2 =
2672 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
Zhi Huang2a5e4262017-09-14 01:15:03 -07002673 SetRemoteDescriptionAnswerExpectError(kMlineMismatchInAnswer,
2674 modified_answer2);
wu@webrtc.org4e393072014-04-07 17:04:35 +00002675
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002676 SetRemoteDescriptionWithoutError(answer.release());
2677}
2678
2679// Verifying remote offer and local answer have matching m-lines as per
2680// RFC 3264.
2681TEST_F(WebRtcSessionTest, TestIncorrectMLinesInLocalAnswer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002682 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07002683 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002684 SessionDescriptionInterface* offer = CreateRemoteOffer();
2685 SetRemoteDescriptionWithoutError(offer);
htaa2a49d92016-03-04 02:51:39 -08002686 SessionDescriptionInterface* answer = CreateAnswer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002687
2688 cricket::SessionDescription* answer_copy = answer->description()->Copy();
2689 answer_copy->RemoveContentByName("video");
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002690 JsepSessionDescription* modified_answer =
2691 new JsepSessionDescription(JsepSessionDescription::kAnswer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002692
2693 EXPECT_TRUE(modified_answer->Initialize(answer_copy,
2694 answer->session_id(),
2695 answer->session_version()));
Zhi Huang2a5e4262017-09-14 01:15:03 -07002696 SetLocalDescriptionAnswerExpectError(kMlineMismatchInAnswer, modified_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002697 SetLocalDescriptionWithoutError(answer);
2698}
2699
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002700TEST_F(WebRtcSessionTest, TestSessionContentError) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002701 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07002702 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002703 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002704 const std::string session_id_orig = offer->session_id();
2705 const std::string session_version_orig = offer->session_version();
2706 SetLocalDescriptionWithoutError(offer);
2707
2708 video_channel_ = media_engine_->GetVideoChannel(0);
2709 video_channel_->set_fail_set_send_codecs(true);
2710
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002711 SessionDescriptionInterface* answer =
2712 CreateRemoteAnswer(session_->local_description());
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002713 SetRemoteDescriptionAnswerExpectError("ERROR_CONTENT", answer);
deadbeefd59daf82015-10-14 15:02:44 -07002714
2715 // Test that after a content error, setting any description will
2716 // result in an error.
2717 video_channel_->set_fail_set_send_codecs(false);
2718 answer = CreateRemoteAnswer(session_->local_description());
2719 SetRemoteDescriptionExpectError("", "ERROR_CONTENT", answer);
2720 offer = CreateRemoteOffer();
2721 SetLocalDescriptionExpectError("", "ERROR_CONTENT", offer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002722}
2723
2724// Runs the loopback call test with BUNDLE and STUN disabled.
2725TEST_F(WebRtcSessionTest, TestIceStatesBasic) {
2726 // Lets try with only UDP ports.
Peter Thatcher7cbd1882015-09-17 18:54:52 -07002727 allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00002728 cricket::PORTALLOCATOR_DISABLE_STUN |
2729 cricket::PORTALLOCATOR_DISABLE_RELAY);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002730 TestLoopbackCall();
2731}
2732
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00002733TEST_F(WebRtcSessionTest, TestIceStatesBasicIPv6) {
Peter Thatcher7cbd1882015-09-17 18:54:52 -07002734 allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00002735 cricket::PORTALLOCATOR_DISABLE_STUN |
2736 cricket::PORTALLOCATOR_ENABLE_IPV6 |
2737 cricket::PORTALLOCATOR_DISABLE_RELAY);
2738
2739 // best connection is IPv6 since it has higher network preference.
2740 LoopbackNetworkConfiguration config;
2741 config.test_ipv6_network_ = true;
2742 config.best_connection_after_initial_ice_converged_ =
2743 LoopbackNetworkConfiguration::ExpectedBestConnection(0, 1);
2744
2745 TestLoopbackCall(config);
2746}
2747
mallinath@webrtc.orgd3dc4242014-03-01 00:05:52 +00002748// Runs the loopback call test with BUNDLE and STUN enabled.
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00002749TEST_F(WebRtcSessionTest, TestIceStatesBundle) {
Peter Thatcher7cbd1882015-09-17 18:54:52 -07002750 allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
2751 cricket::PORTALLOCATOR_DISABLE_RELAY);
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00002752 TestLoopbackCall();
2753}
2754
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002755TEST_F(WebRtcSessionTest, TestRtpDataChannel) {
htaa2a49d92016-03-04 02:51:39 -08002756 configuration_.enable_rtp_data_channel = true;
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002757 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002758 SetLocalDescriptionWithDataChannel();
htaa2a49d92016-03-04 02:51:39 -08002759 ASSERT_TRUE(data_engine_);
deadbeef953c2ce2017-01-09 14:53:41 -08002760 EXPECT_NE(nullptr, data_engine_->GetChannel(0));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002761}
2762
Henrik Boström87713d02015-08-25 09:53:21 +02002763TEST_P(WebRtcSessionTest, TestRtpDataChannelConstraintTakesPrecedence) {
htaa2a49d92016-03-04 02:51:39 -08002764 configuration_.enable_rtp_data_channel = true;
wu@webrtc.org97077a32013-10-25 21:18:33 +00002765 options_.disable_sctp_data_channels = false;
2766
Henrik Boström87713d02015-08-25 09:53:21 +02002767 InitWithDtls(GetParam());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002768
2769 SetLocalDescriptionWithDataChannel();
deadbeef953c2ce2017-01-09 14:53:41 -08002770 EXPECT_NE(nullptr, data_engine_->GetChannel(0));
2771}
2772
2773// Test that sctp_content_name/sctp_transport_name (used for stats) are correct
2774// before and after BUNDLE is negotiated.
2775TEST_P(WebRtcSessionTest, SctpContentAndTransportName) {
deadbeef953c2ce2017-01-09 14:53:41 -08002776 SetFactoryDtlsSrtp();
2777 InitWithDtls(GetParam());
2778
2779 // Initially these fields should be empty.
2780 EXPECT_FALSE(session_->sctp_content_name());
2781 EXPECT_FALSE(session_->sctp_transport_name());
2782
2783 // Create offer with audio/video/data.
2784 // Default bundle policy is "balanced", so data should be using its own
2785 // transport.
2786 SendAudioVideoStream1();
2787 CreateDataChannel();
2788 InitiateCall();
2789 ASSERT_TRUE(session_->sctp_content_name());
2790 ASSERT_TRUE(session_->sctp_transport_name());
2791 EXPECT_EQ("data", *session_->sctp_content_name());
2792 EXPECT_EQ("data", *session_->sctp_transport_name());
2793
2794 // Create answer that finishes BUNDLE negotiation, which means everything
2795 // should be bundled on the first transport (audio).
2796 cricket::MediaSessionOptions answer_options;
deadbeef953c2ce2017-01-09 14:53:41 -08002797 answer_options.bundle_enabled = true;
2798 answer_options.data_channel_type = cricket::DCT_SCTP;
zhihuang1c378ed2017-08-17 14:10:50 -07002799 GetOptionsForAnswer(&answer_options);
deadbeef953c2ce2017-01-09 14:53:41 -08002800 SetRemoteDescriptionWithoutError(CreateRemoteAnswer(
2801 session_->local_description(), answer_options, cricket::SEC_DISABLED));
2802 ASSERT_TRUE(session_->sctp_content_name());
2803 ASSERT_TRUE(session_->sctp_transport_name());
2804 EXPECT_EQ("data", *session_->sctp_content_name());
2805 EXPECT_EQ("audio", *session_->sctp_transport_name());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002806}
2807
Henrik Boström87713d02015-08-25 09:53:21 +02002808TEST_P(WebRtcSessionTest, TestCreateOfferWithSctpEnabledWithoutStreams) {
Henrik Boström87713d02015-08-25 09:53:21 +02002809 InitWithDtls(GetParam());
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00002810
kwibergd1fe2812016-04-27 06:47:29 -07002811 std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer());
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00002812 EXPECT_TRUE(offer->description()->GetContentByName("data") == NULL);
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00002813 EXPECT_TRUE(offer->description()->GetTransportInfoByName("data") == NULL);
2814}
2815
Henrik Boström87713d02015-08-25 09:53:21 +02002816TEST_P(WebRtcSessionTest, TestCreateAnswerWithSctpInOfferAndNoStreams) {
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00002817 SetFactoryDtlsSrtp();
Henrik Boström87713d02015-08-25 09:53:21 +02002818 InitWithDtls(GetParam());
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00002819
2820 // Create remote offer with SCTP.
2821 cricket::MediaSessionOptions options;
2822 options.data_channel_type = cricket::DCT_SCTP;
zhihuang1c378ed2017-08-17 14:10:50 -07002823 GetOptionsForRemoteOffer(&options);
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00002824 JsepSessionDescription* offer =
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00002825 CreateRemoteOffer(options, cricket::SEC_DISABLED);
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00002826 SetRemoteDescriptionWithoutError(offer);
2827
2828 // Verifies the answer contains SCTP.
kwibergd1fe2812016-04-27 06:47:29 -07002829 std::unique_ptr<SessionDescriptionInterface> answer(CreateAnswer());
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00002830 EXPECT_TRUE(answer != NULL);
2831 EXPECT_TRUE(answer->description()->GetContentByName("data") != NULL);
2832 EXPECT_TRUE(answer->description()->GetTransportInfoByName("data") != NULL);
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00002833}
2834
deadbeef953c2ce2017-01-09 14:53:41 -08002835// Test that if DTLS is disabled, we don't end up with an SctpTransport
2836// created (or an RtpDataChannel).
Henrik Boström87713d02015-08-25 09:53:21 +02002837TEST_P(WebRtcSessionTest, TestSctpDataChannelWithoutDtls) {
htaa2a49d92016-03-04 02:51:39 -08002838 configuration_.enable_dtls_srtp = rtc::Optional<bool>(false);
Henrik Boström87713d02015-08-25 09:53:21 +02002839 InitWithDtls(GetParam());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002840
2841 SetLocalDescriptionWithDataChannel();
deadbeef953c2ce2017-01-09 14:53:41 -08002842 EXPECT_EQ(nullptr, data_engine_->GetChannel(0));
2843 EXPECT_EQ(nullptr, fake_sctp_transport_factory_->last_fake_sctp_transport());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002844}
2845
deadbeef953c2ce2017-01-09 14:53:41 -08002846// Test that if DTLS is enabled, we end up with an SctpTransport created
2847// (and not an RtpDataChannel).
Henrik Boström87713d02015-08-25 09:53:21 +02002848TEST_P(WebRtcSessionTest, TestSctpDataChannelWithDtls) {
Henrik Boström87713d02015-08-25 09:53:21 +02002849 InitWithDtls(GetParam());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002850
2851 SetLocalDescriptionWithDataChannel();
deadbeef953c2ce2017-01-09 14:53:41 -08002852 EXPECT_EQ(nullptr, data_engine_->GetChannel(0));
2853 EXPECT_NE(nullptr, fake_sctp_transport_factory_->last_fake_sctp_transport());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002854}
wu@webrtc.org91053e72013-08-10 07:18:04 +00002855
deadbeef953c2ce2017-01-09 14:53:41 -08002856// Test that if SCTP is disabled, we don't end up with an SctpTransport
2857// created (or an RtpDataChannel).
Henrik Boström87713d02015-08-25 09:53:21 +02002858TEST_P(WebRtcSessionTest, TestDisableSctpDataChannels) {
wu@webrtc.org97077a32013-10-25 21:18:33 +00002859 options_.disable_sctp_data_channels = true;
Henrik Boström87713d02015-08-25 09:53:21 +02002860 InitWithDtls(GetParam());
wu@webrtc.org97077a32013-10-25 21:18:33 +00002861
2862 SetLocalDescriptionWithDataChannel();
deadbeef953c2ce2017-01-09 14:53:41 -08002863 EXPECT_EQ(nullptr, data_engine_->GetChannel(0));
2864 EXPECT_EQ(nullptr, fake_sctp_transport_factory_->last_fake_sctp_transport());
wu@webrtc.org97077a32013-10-25 21:18:33 +00002865}
2866
Henrik Boström87713d02015-08-25 09:53:21 +02002867TEST_P(WebRtcSessionTest, TestSctpDataChannelSendPortParsing) {
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002868 const int new_send_port = 9998;
2869 const int new_recv_port = 7775;
2870
Henrik Boström87713d02015-08-25 09:53:21 +02002871 InitWithDtls(GetParam());
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002872 SetFactoryDtlsSrtp();
2873
2874 // By default, don't actually add the codecs to desc_factory_; they don't
2875 // actually get serialized for SCTP in BuildMediaDescription(). Instead,
2876 // let the session description get parsed. That'll get the proper codecs
2877 // into the stream.
2878 cricket::MediaSessionOptions options;
Steve Anton6d64e9a2017-09-12 09:44:05 -07002879 SessionDescriptionInterface* offer =
2880 CreateRemoteOfferWithSctpPort("stream1", new_send_port, options);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002881
2882 // SetRemoteDescription will take the ownership of the offer.
2883 SetRemoteDescriptionWithoutError(offer);
2884
htaa2a49d92016-03-04 02:51:39 -08002885 SessionDescriptionInterface* answer =
2886 ChangeSDPSctpPort(new_recv_port, CreateAnswer());
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002887 ASSERT_TRUE(answer != NULL);
2888
2889 // Now set the local description, which'll take ownership of the answer.
2890 SetLocalDescriptionWithoutError(answer);
2891
2892 // TEST PLAN: Set the port number to something new, set it in the SDP,
2893 // and pass it all the way down.
deadbeef953c2ce2017-01-09 14:53:41 -08002894 EXPECT_EQ(nullptr, data_engine_->GetChannel(0));
deadbeefab9b2d12015-10-14 11:33:11 -07002895 CreateDataChannel();
deadbeef953c2ce2017-01-09 14:53:41 -08002896 ASSERT_NE(nullptr, fake_sctp_transport_factory_->last_fake_sctp_transport());
2897 EXPECT_EQ(
2898 new_recv_port,
2899 fake_sctp_transport_factory_->last_fake_sctp_transport()->local_port());
2900 EXPECT_EQ(
2901 new_send_port,
2902 fake_sctp_transport_factory_->last_fake_sctp_transport()->remote_port());
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002903}
2904
deadbeef953c2ce2017-01-09 14:53:41 -08002905// Verifies that when a session's SctpTransport receives an OPEN message,
2906// WebRtcSession signals the SctpTransport creation request with the expected
deadbeefab9b2d12015-10-14 11:33:11 -07002907// config.
2908TEST_P(WebRtcSessionTest, TestSctpDataChannelOpenMessage) {
deadbeefab9b2d12015-10-14 11:33:11 -07002909 InitWithDtls(GetParam());
2910
2911 SetLocalDescriptionWithDataChannel();
deadbeef953c2ce2017-01-09 14:53:41 -08002912 EXPECT_EQ(nullptr, data_engine_->GetChannel(0));
2913 ASSERT_NE(nullptr, fake_sctp_transport_factory_->last_fake_sctp_transport());
deadbeefab9b2d12015-10-14 11:33:11 -07002914
deadbeef953c2ce2017-01-09 14:53:41 -08002915 // Make the fake SCTP transport pretend it received an OPEN message.
deadbeefab9b2d12015-10-14 11:33:11 -07002916 webrtc::DataChannelInit config;
2917 config.id = 1;
jbaucheec21bd2016-03-20 06:15:43 -07002918 rtc::CopyOnWriteBuffer payload;
deadbeefab9b2d12015-10-14 11:33:11 -07002919 webrtc::WriteDataChannelOpenMessage("a", config, &payload);
2920 cricket::ReceiveDataParams params;
2921 params.ssrc = config.id;
2922 params.type = cricket::DMT_CONTROL;
deadbeef953c2ce2017-01-09 14:53:41 -08002923 fake_sctp_transport_factory_->last_fake_sctp_transport()->SignalDataReceived(
2924 params, payload);
deadbeefab9b2d12015-10-14 11:33:11 -07002925
deadbeef953c2ce2017-01-09 14:53:41 -08002926 EXPECT_EQ_WAIT("a", last_data_channel_label_, kDefaultTimeout);
deadbeefab9b2d12015-10-14 11:33:11 -07002927 EXPECT_EQ(config.id, last_data_channel_config_.id);
2928 EXPECT_FALSE(last_data_channel_config_.negotiated);
2929 EXPECT_EQ(webrtc::InternalDataChannelInit::kAcker,
2930 last_data_channel_config_.open_handshake_role);
2931}
2932
buildbot@webrtc.orgb4c7b092014-08-25 12:11:58 +00002933TEST_F(WebRtcSessionTest, TestCombinedAudioVideoBweConstraint) {
htaa2a49d92016-03-04 02:51:39 -08002934 configuration_.combined_audio_video_bwe = rtc::Optional<bool>(true);
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002935 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07002936 SendAudioVideoStream1();
buildbot@webrtc.orgb4c7b092014-08-25 12:11:58 +00002937 SessionDescriptionInterface* offer = CreateOffer();
2938
2939 SetLocalDescriptionWithoutError(offer);
2940
2941 voice_channel_ = media_engine_->GetVoiceChannel(0);
2942
2943 ASSERT_TRUE(voice_channel_ != NULL);
solenberg66f43392015-09-09 01:36:22 -07002944 const cricket::AudioOptions& audio_options = voice_channel_->options();
Karl Wibergbe579832015-11-10 22:34:18 +01002945 EXPECT_EQ(rtc::Optional<bool>(true), audio_options.combined_audio_video_bwe);
buildbot@webrtc.orgb4c7b092014-08-25 12:11:58 +00002946}
2947
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00002948// Tests that we can renegotiate new media content with ICE candidates in the
2949// new remote SDP.
Henrik Boström87713d02015-08-25 09:53:21 +02002950TEST_P(WebRtcSessionTest, TestRenegotiateNewMediaWithCandidatesInSdp) {
Henrik Boström87713d02015-08-25 09:53:21 +02002951 InitWithDtls(GetParam());
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00002952 SetFactoryDtlsSrtp();
2953
deadbeefab9b2d12015-10-14 11:33:11 -07002954 SendAudioOnlyStream2();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002955 SessionDescriptionInterface* offer = CreateOffer();
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00002956 SetLocalDescriptionWithoutError(offer);
2957
2958 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
2959 SetRemoteDescriptionWithoutError(answer);
2960
2961 cricket::MediaSessionOptions options;
zhihuang1c378ed2017-08-17 14:10:50 -07002962 GetOptionsForRemoteOffer(&options);
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00002963 offer = CreateRemoteOffer(options, cricket::SEC_DISABLED);
2964
2965 cricket::Candidate candidate1;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002966 candidate1.set_address(rtc::SocketAddress("1.1.1.1", 5000));
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00002967 candidate1.set_component(1);
2968 JsepIceCandidate ice_candidate(kMediaContentName1, kMediaContentIndex1,
2969 candidate1);
2970 EXPECT_TRUE(offer->AddCandidate(&ice_candidate));
2971 SetRemoteDescriptionWithoutError(offer);
2972
htaa2a49d92016-03-04 02:51:39 -08002973 answer = CreateAnswer();
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00002974 SetLocalDescriptionWithoutError(answer);
2975}
2976
2977// Tests that we can renegotiate new media content with ICE candidates separated
2978// from the remote SDP.
Henrik Boström87713d02015-08-25 09:53:21 +02002979TEST_P(WebRtcSessionTest, TestRenegotiateNewMediaWithCandidatesSeparated) {
Henrik Boström87713d02015-08-25 09:53:21 +02002980 InitWithDtls(GetParam());
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00002981 SetFactoryDtlsSrtp();
2982
deadbeefab9b2d12015-10-14 11:33:11 -07002983 SendAudioOnlyStream2();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002984 SessionDescriptionInterface* offer = CreateOffer();
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00002985 SetLocalDescriptionWithoutError(offer);
2986
2987 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
2988 SetRemoteDescriptionWithoutError(answer);
2989
2990 cricket::MediaSessionOptions options;
zhihuang1c378ed2017-08-17 14:10:50 -07002991 GetOptionsForRemoteOffer(&options);
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00002992 offer = CreateRemoteOffer(options, cricket::SEC_DISABLED);
2993 SetRemoteDescriptionWithoutError(offer);
2994
2995 cricket::Candidate candidate1;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002996 candidate1.set_address(rtc::SocketAddress("1.1.1.1", 5000));
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00002997 candidate1.set_component(1);
2998 JsepIceCandidate ice_candidate(kMediaContentName1, kMediaContentIndex1,
2999 candidate1);
3000 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate));
3001
htaa2a49d92016-03-04 02:51:39 -08003002 answer = CreateAnswer();
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00003003 SetLocalDescriptionWithoutError(answer);
3004}
honghaiz7f777492016-02-02 21:54:01 -08003005
zhihuang9763d562016-08-05 11:14:50 -07003006#ifdef HAVE_QUIC
3007TEST_P(WebRtcSessionTest, TestNegotiateQuic) {
3008 configuration_.enable_quic = true;
3009 InitWithDtls(GetParam());
3010 EXPECT_TRUE(session_->data_channel_type() == cricket::DCT_QUIC);
3011 SessionDescriptionInterface* offer = CreateOffer();
3012 ASSERT_TRUE(offer);
3013 ASSERT_TRUE(offer->description());
3014 SetLocalDescriptionWithoutError(offer);
3015 cricket::MediaSessionOptions options;
zhihuang1c378ed2017-08-17 14:10:50 -07003016 GetOptionsForAnswer(&options);
zhihuang9763d562016-08-05 11:14:50 -07003017 SessionDescriptionInterface* answer =
3018 CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED);
3019 ASSERT_TRUE(answer);
3020 ASSERT_TRUE(answer->description());
3021 SetRemoteDescriptionWithoutError(answer);
3022}
3023#endif // HAVE_QUIC
3024
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00003025// Tests that RTX codec is removed from the answer when it isn't supported
3026// by local side.
zhihuang3a334652016-05-05 18:37:49 -07003027TEST_F(WebRtcSessionTest, TestRtxRemovedByCreateAnswer) {
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00003028 Init();
zhihuang1c378ed2017-08-17 14:10:50 -07003029 // Send video only to match the |kSdpWithRtx|.
3030 SendVideoOnlyStream2();
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00003031 std::string offer_sdp(kSdpWithRtx);
3032
3033 SessionDescriptionInterface* offer =
3034 CreateSessionDescription(JsepSessionDescription::kOffer, offer_sdp, NULL);
3035 EXPECT_TRUE(offer->ToString(&offer_sdp));
3036
3037 // Offer SDP contains the RTX codec.
zhihuang3a334652016-05-05 18:37:49 -07003038 EXPECT_TRUE(ContainsVideoCodecWithName(offer, "rtx"));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00003039 SetRemoteDescriptionWithoutError(offer);
3040
zhihuang1c378ed2017-08-17 14:10:50 -07003041 // |offered_media_sections_| is used when creating answer.
3042 offered_media_sections_.push_back(cricket::MediaDescriptionOptions(
3043 cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO,
3044 cricket::RtpTransceiverDirection(true, true), false));
3045 // Don't create media section for audio in the answer.
htaa2a49d92016-03-04 02:51:39 -08003046 SessionDescriptionInterface* answer = CreateAnswer();
zhihuang3a334652016-05-05 18:37:49 -07003047 // Answer SDP does not contain the RTX codec.
3048 EXPECT_FALSE(ContainsVideoCodecWithName(answer, "rtx"));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00003049 SetLocalDescriptionWithoutError(answer);
3050}
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00003051
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00003052// This verifies that the voice channel after bundle has both options from video
3053// and voice channels.
3054TEST_F(WebRtcSessionTest, TestSetSocketOptionBeforeBundle) {
3055 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyBalanced);
deadbeefab9b2d12015-10-14 11:33:11 -07003056 SendAudioVideoStream1();
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00003057
3058 PeerConnectionInterface::RTCOfferAnswerOptions options;
3059 options.use_rtp_mux = true;
3060
3061 SessionDescriptionInterface* offer = CreateOffer(options);
3062 SetLocalDescriptionWithoutError(offer);
3063
3064 session_->video_channel()->SetOption(cricket::BaseChannel::ST_RTP,
3065 rtc::Socket::Option::OPT_SNDBUF, 4000);
3066
3067 session_->voice_channel()->SetOption(cricket::BaseChannel::ST_RTP,
3068 rtc::Socket::Option::OPT_RCVBUF, 8000);
3069
3070 int option_val;
deadbeefcbecd352015-09-23 11:50:27 -07003071 EXPECT_TRUE(session_->video_rtp_transport_channel()->GetOption(
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00003072 rtc::Socket::Option::OPT_SNDBUF, &option_val));
3073 EXPECT_EQ(4000, option_val);
deadbeefcbecd352015-09-23 11:50:27 -07003074 EXPECT_FALSE(session_->voice_rtp_transport_channel()->GetOption(
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00003075 rtc::Socket::Option::OPT_SNDBUF, &option_val));
3076
deadbeefcbecd352015-09-23 11:50:27 -07003077 EXPECT_TRUE(session_->voice_rtp_transport_channel()->GetOption(
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00003078 rtc::Socket::Option::OPT_RCVBUF, &option_val));
3079 EXPECT_EQ(8000, option_val);
deadbeefcbecd352015-09-23 11:50:27 -07003080 EXPECT_FALSE(session_->video_rtp_transport_channel()->GetOption(
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00003081 rtc::Socket::Option::OPT_RCVBUF, &option_val));
3082
deadbeefcbecd352015-09-23 11:50:27 -07003083 EXPECT_NE(session_->voice_rtp_transport_channel(),
3084 session_->video_rtp_transport_channel());
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00003085
deadbeefab9b2d12015-10-14 11:33:11 -07003086 SendAudioVideoStream2();
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00003087 SessionDescriptionInterface* answer =
3088 CreateRemoteAnswer(session_->local_description());
3089 SetRemoteDescriptionWithoutError(answer);
3090
deadbeefcbecd352015-09-23 11:50:27 -07003091 EXPECT_TRUE(session_->voice_rtp_transport_channel()->GetOption(
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00003092 rtc::Socket::Option::OPT_SNDBUF, &option_val));
3093 EXPECT_EQ(4000, option_val);
3094
deadbeefcbecd352015-09-23 11:50:27 -07003095 EXPECT_TRUE(session_->voice_rtp_transport_channel()->GetOption(
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00003096 rtc::Socket::Option::OPT_RCVBUF, &option_val));
3097 EXPECT_EQ(8000, option_val);
3098}
3099
tommi0f620f42015-07-09 03:25:02 -07003100// Test creating a session, request multiple offers, destroy the session
3101// and make sure we got success/failure callbacks for all of the requests.
3102// Background: crbug.com/507307
3103TEST_F(WebRtcSessionTest, CreateOffersAndShutdown) {
3104 Init();
3105
3106 rtc::scoped_refptr<WebRtcSessionCreateSDPObserverForTest> observers[100];
3107 PeerConnectionInterface::RTCOfferAnswerOptions options;
3108 options.offer_to_receive_audio =
3109 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
deadbeefab9b2d12015-10-14 11:33:11 -07003110 cricket::MediaSessionOptions session_options;
zhihuang1c378ed2017-08-17 14:10:50 -07003111 GetOptionsForOffer(options, &session_options);
tommi0f620f42015-07-09 03:25:02 -07003112 for (auto& o : observers) {
3113 o = new WebRtcSessionCreateSDPObserverForTest();
deadbeefab9b2d12015-10-14 11:33:11 -07003114 session_->CreateOffer(o, options, session_options);
tommi0f620f42015-07-09 03:25:02 -07003115 }
3116
3117 session_.reset();
3118
tommi0f620f42015-07-09 03:25:02 -07003119 for (auto& o : observers) {
3120 // We expect to have received a notification now even if the session was
3121 // terminated. The offer creation may or may not have succeeded, but we
3122 // must have received a notification which, so the only invalid state
3123 // is kInit.
3124 EXPECT_NE(WebRtcSessionCreateSDPObserverForTest::kInit, o->state());
3125 }
3126}
3127
stefanc1aeaf02015-10-15 07:26:07 -07003128TEST_F(WebRtcSessionTest, TestPacketOptionsAndOnPacketSent) {
3129 TestPacketOptions();
3130}
3131
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003132// TODO(bemasc): Add a TestIceStatesBundle with BUNDLE enabled. That test
3133// currently fails because upon disconnection and reconnection OnIceComplete is
3134// called more than once without returning to IceGatheringGathering.
Henrik Boström87713d02015-08-25 09:53:21 +02003135
deadbeefcbecd352015-09-23 11:50:27 -07003136INSTANTIATE_TEST_CASE_P(WebRtcSessionTests,
3137 WebRtcSessionTest,
3138 testing::Values(ALREADY_GENERATED,
3139 DTLS_IDENTITY_STORE));