blob: 0c54abc9cbac421852f7e5e263530e43ffb02b40 [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";
wu@webrtc.org364f2042013-11-20 21:49:41 +000080static const char kStunAddrHost[] = "99.99.99.1";
henrike@webrtc.org28e20752013-07-10 00:45:36 +000081
82static const char kSessionVersion[] = "1";
83
henrike@webrtc.org28e20752013-07-10 00:45:36 +000084// Media index of candidates belonging to the first media content.
85static const int kMediaContentIndex0 = 0;
Olga Sharonovab49b6612017-10-20 12:56:51 +000086static const char kMediaContentName0[] = "audio";
henrike@webrtc.org28e20752013-07-10 00:45:36 +000087
88// Media index of candidates belonging to the second media content.
89static const int kMediaContentIndex1 = 1;
Olga Sharonovab49b6612017-10-20 12:56:51 +000090static const char kMediaContentName1[] = "video";
henrike@webrtc.org28e20752013-07-10 00:45:36 +000091
deadbeef953c2ce2017-01-09 14:53:41 -080092static const int kDefaultTimeout = 10000; // 10 seconds.
henrike@webrtc.org28e20752013-07-10 00:45:36 +000093static const int kIceCandidatesTimeout = 10000;
94
deadbeefab9b2d12015-10-14 11:33:11 -070095static const char kStream1[] = "stream1";
96static const char kVideoTrack1[] = "video1";
97static const char kAudioTrack1[] = "audio1";
98
99static const char kStream2[] = "stream2";
100static const char kVideoTrack2[] = "video2";
101static const char kAudioTrack2[] = "audio2";
102
zhihuang1c378ed2017-08-17 14:10:50 -0700103static constexpr bool kActive = false;
104
Henrik Boström87713d02015-08-25 09:53:21 +0200105enum RTCCertificateGenerationMethod { ALREADY_GENERATED, DTLS_IDENTITY_STORE };
106
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000107class MockIceObserver : public webrtc::IceObserver {
108 public:
109 MockIceObserver()
110 : oncandidatesready_(false),
111 ice_connection_state_(PeerConnectionInterface::kIceConnectionNew),
112 ice_gathering_state_(PeerConnectionInterface::kIceGatheringNew) {
113 }
114
Henrik Kjellander3fe372d2016-05-12 08:10:52 +0200115 virtual ~MockIceObserver() = default;
116
zstein6dfd53a2017-03-06 13:49:03 -0800117 void OnIceConnectionStateChange(
perkjdfb769d2016-02-09 03:09:43 -0800118 PeerConnectionInterface::IceConnectionState new_state) override {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000119 ice_connection_state_ = new_state;
skvlad6c87a672016-05-17 17:49:52 -0700120 ice_connection_state_history_.push_back(new_state);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000121 }
perkjdfb769d2016-02-09 03:09:43 -0800122 void OnIceGatheringChange(
123 PeerConnectionInterface::IceGatheringState new_state) override {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000124 // We can never transition back to "new".
125 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, new_state);
126 ice_gathering_state_ = new_state;
perkjdfb769d2016-02-09 03:09:43 -0800127 oncandidatesready_ =
128 new_state == PeerConnectionInterface::kIceGatheringComplete;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000129 }
130
131 // Found a new candidate.
jbauch81bf7b02017-03-25 08:31:12 -0700132 void OnIceCandidate(
133 std::unique_ptr<webrtc::IceCandidateInterface> candidate) override {
wu@webrtc.org364f2042013-11-20 21:49:41 +0000134 switch (candidate->sdp_mline_index()) {
135 case kMediaContentIndex0:
136 mline_0_candidates_.push_back(candidate->candidate());
137 break;
138 case kMediaContentIndex1:
139 mline_1_candidates_.push_back(candidate->candidate());
140 break;
141 default:
nissec80e7412017-01-11 05:56:46 -0800142 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000143 }
wu@webrtc.org364f2042013-11-20 21:49:41 +0000144
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000145 // The ICE gathering state should always be Gathering when a candidate is
146 // received (or possibly Completed in the case of the final candidate).
147 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, ice_gathering_state_);
148 }
149
Honghai Zhang7fb69db2016-03-14 11:59:18 -0700150 // Some local candidates are removed.
151 void OnIceCandidatesRemoved(
nisseef8b61e2016-04-29 06:09:15 -0700152 const std::vector<cricket::Candidate>& candidates) override {
Honghai Zhang7fb69db2016-03-14 11:59:18 -0700153 num_candidates_removed_ += candidates.size();
154 }
155
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000156 bool oncandidatesready_;
157 std::vector<cricket::Candidate> mline_0_candidates_;
158 std::vector<cricket::Candidate> mline_1_candidates_;
159 PeerConnectionInterface::IceConnectionState ice_connection_state_;
160 PeerConnectionInterface::IceGatheringState ice_gathering_state_;
skvlad6c87a672016-05-17 17:49:52 -0700161 std::vector<PeerConnectionInterface::IceConnectionState>
162 ice_connection_state_history_;
Honghai Zhang7fb69db2016-03-14 11:59:18 -0700163 size_t num_candidates_removed_ = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000164};
165
deadbeef953c2ce2017-01-09 14:53:41 -0800166// Used for tests in this file to verify that WebRtcSession responds to signals
167// from the SctpTransport correctly, and calls Start with the correct
168// local/remote ports.
169class FakeSctpTransport : public cricket::SctpTransportInternal {
170 public:
deadbeef5bd5ca32017-02-10 11:31:50 -0800171 void SetTransportChannel(rtc::PacketTransportInternal* channel) override {}
deadbeef953c2ce2017-01-09 14:53:41 -0800172 bool Start(int local_port, int remote_port) override {
173 local_port_ = local_port;
174 remote_port_ = remote_port;
175 return true;
176 }
177 bool OpenStream(int sid) override { return true; }
178 bool ResetStream(int sid) override { return true; }
179 bool SendData(const cricket::SendDataParams& params,
180 const rtc::CopyOnWriteBuffer& payload,
181 cricket::SendDataResult* result = nullptr) override {
182 return true;
183 }
184 bool ReadyToSendData() override { return true; }
185 void set_debug_name_for_testing(const char* debug_name) override {}
186
187 int local_port() const { return local_port_; }
188 int remote_port() const { return remote_port_; }
189
190 private:
191 int local_port_ = -1;
192 int remote_port_ = -1;
193};
194
195class FakeSctpTransportFactory : public cricket::SctpTransportInternalFactory {
196 public:
197 std::unique_ptr<cricket::SctpTransportInternal> CreateSctpTransport(
deadbeef5bd5ca32017-02-10 11:31:50 -0800198 rtc::PacketTransportInternal*) override {
deadbeef953c2ce2017-01-09 14:53:41 -0800199 last_fake_sctp_transport_ = new FakeSctpTransport();
200 return std::unique_ptr<cricket::SctpTransportInternal>(
201 last_fake_sctp_transport_);
202 }
203
204 FakeSctpTransport* last_fake_sctp_transport() {
205 return last_fake_sctp_transport_;
206 }
207
208 private:
209 FakeSctpTransport* last_fake_sctp_transport_ = nullptr;
210};
211
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000212class WebRtcSessionForTest : public webrtc::WebRtcSession {
213 public:
zhihuang29ff8442016-07-27 11:07:25 -0700214 WebRtcSessionForTest(
nisseeaabdf62017-05-05 02:23:02 -0700215 webrtc::Call* fake_call,
216 cricket::ChannelManager* channel_manager,
217 const cricket::MediaConfig& media_config,
218 webrtc::RtcEventLog* event_log,
zhihuang29ff8442016-07-27 11:07:25 -0700219 rtc::Thread* network_thread,
220 rtc::Thread* worker_thread,
221 rtc::Thread* signaling_thread,
222 cricket::PortAllocator* port_allocator,
223 webrtc::IceObserver* ice_observer,
deadbeef953c2ce2017-01-09 14:53:41 -0800224 std::unique_ptr<cricket::TransportController> transport_controller,
225 std::unique_ptr<FakeSctpTransportFactory> sctp_factory)
nisseeaabdf62017-05-05 02:23:02 -0700226 : WebRtcSession(fake_call, channel_manager, media_config, event_log,
danilchape9021a32016-05-17 01:52:02 -0700227 network_thread,
stefanc1aeaf02015-10-15 07:26:07 -0700228 worker_thread,
danilchape9021a32016-05-17 01:52:02 -0700229 signaling_thread,
zhihuang29ff8442016-07-27 11:07:25 -0700230 port_allocator,
deadbeef953c2ce2017-01-09 14:53:41 -0800231 std::move(transport_controller),
232 std::move(sctp_factory)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000233 RegisterIceObserver(ice_observer);
234 }
235 virtual ~WebRtcSessionForTest() {}
236
deadbeefcbecd352015-09-23 11:50:27 -0700237 // Note that these methods are only safe to use if the signaling thread
238 // is the same as the worker thread
deadbeef5bd5ca32017-02-10 11:31:50 -0800239 rtc::PacketTransportInternal* voice_rtp_transport_channel() {
deadbeefcbecd352015-09-23 11:50:27 -0700240 return rtp_transport_channel(voice_channel());
241 }
242
deadbeef5bd5ca32017-02-10 11:31:50 -0800243 rtc::PacketTransportInternal* voice_rtcp_transport_channel() {
deadbeefcbecd352015-09-23 11:50:27 -0700244 return rtcp_transport_channel(voice_channel());
245 }
246
deadbeef5bd5ca32017-02-10 11:31:50 -0800247 rtc::PacketTransportInternal* video_rtp_transport_channel() {
deadbeefcbecd352015-09-23 11:50:27 -0700248 return rtp_transport_channel(video_channel());
249 }
250
deadbeef5bd5ca32017-02-10 11:31:50 -0800251 rtc::PacketTransportInternal* video_rtcp_transport_channel() {
deadbeefcbecd352015-09-23 11:50:27 -0700252 return rtcp_transport_channel(video_channel());
253 }
254
deadbeefcbecd352015-09-23 11:50:27 -0700255 private:
deadbeef5bd5ca32017-02-10 11:31:50 -0800256 rtc::PacketTransportInternal* rtp_transport_channel(
johan669d69b2016-11-08 14:14:08 -0800257 cricket::BaseChannel* ch) {
deadbeefcbecd352015-09-23 11:50:27 -0700258 if (!ch) {
259 return nullptr;
260 }
zhihuangb2cdd932017-01-19 16:54:25 -0800261 return ch->rtp_dtls_transport();
deadbeefcbecd352015-09-23 11:50:27 -0700262 }
263
deadbeef5bd5ca32017-02-10 11:31:50 -0800264 rtc::PacketTransportInternal* rtcp_transport_channel(
johan669d69b2016-11-08 14:14:08 -0800265 cricket::BaseChannel* ch) {
deadbeefcbecd352015-09-23 11:50:27 -0700266 if (!ch) {
267 return nullptr;
268 }
zhihuangb2cdd932017-01-19 16:54:25 -0800269 return ch->rtcp_dtls_transport();
deadbeefcbecd352015-09-23 11:50:27 -0700270 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000271};
272
wu@webrtc.org91053e72013-08-10 07:18:04 +0000273class WebRtcSessionCreateSDPObserverForTest
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000274 : public rtc::RefCountedObject<CreateSessionDescriptionObserver> {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000275 public:
wu@webrtc.org91053e72013-08-10 07:18:04 +0000276 enum State {
277 kInit,
278 kFailed,
279 kSucceeded,
280 };
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000281 WebRtcSessionCreateSDPObserverForTest() : state_(kInit) {}
wu@webrtc.org91053e72013-08-10 07:18:04 +0000282
283 // CreateSessionDescriptionObserver implementation.
284 virtual void OnSuccess(SessionDescriptionInterface* desc) {
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000285 description_.reset(desc);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000286 state_ = kSucceeded;
287 }
288 virtual void OnFailure(const std::string& error) {
289 state_ = kFailed;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000290 }
291
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000292 SessionDescriptionInterface* description() { return description_.get(); }
293
294 SessionDescriptionInterface* ReleaseDescription() {
295 return description_.release();
296 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000297
wu@webrtc.org91053e72013-08-10 07:18:04 +0000298 State state() const { return state_; }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000299
wu@webrtc.org91053e72013-08-10 07:18:04 +0000300 protected:
301 ~WebRtcSessionCreateSDPObserverForTest() {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000302
303 private:
kwibergd1fe2812016-04-27 06:47:29 -0700304 std::unique_ptr<SessionDescriptionInterface> description_;
wu@webrtc.org91053e72013-08-10 07:18:04 +0000305 State state_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000306};
307
Henrik Boström87713d02015-08-25 09:53:21 +0200308class WebRtcSessionTest
deadbeefab9b2d12015-10-14 11:33:11 -0700309 : public testing::TestWithParam<RTCCertificateGenerationMethod>,
310 public sigslot::has_slots<> {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000311 protected:
312 // TODO Investigate why ChannelManager crashes, if it's created
313 // after stun_server.
314 WebRtcSessionTest()
deadbeef98e186c2017-05-16 18:00:06 -0700315 : vss_(new rtc::VirtualSocketServer()),
nisse7eaa4ea2017-05-08 05:25:41 -0700316 fss_(new rtc::FirewallSocketServer(vss_.get())),
317 thread_(fss_.get()),
318 media_engine_(new cricket::FakeMediaEngine()),
stefanc1aeaf02015-10-15 07:26:07 -0700319 data_engine_(new cricket::FakeDataEngine()),
deadbeef112b2e92017-02-10 20:13:37 -0800320 channel_manager_(new cricket::ChannelManager(
321 std::unique_ptr<cricket::MediaEngineInterface>(media_engine_),
322 std::unique_ptr<cricket::DataEngineInterface>(data_engine_),
323 rtc::Thread::Current())),
skvlad11a9cbf2016-10-07 11:53:05 -0700324 fake_call_(webrtc::Call::Config(&event_log_)),
stefanc1aeaf02015-10-15 07:26:07 -0700325 tdesc_factory_(new cricket::TransportDescriptionFactory()),
326 desc_factory_(
327 new cricket::MediaSessionDescriptionFactory(channel_manager_.get(),
328 tdesc_factory_.get())),
stefanc1aeaf02015-10-15 07:26:07 -0700329 stun_socket_addr_(
330 rtc::SocketAddress(kStunAddrHost, cricket::STUN_SERVER_PORT)),
331 stun_server_(cricket::TestStunServer::Create(Thread::Current(),
332 stun_socket_addr_)),
stefanc1aeaf02015-10-15 07:26:07 -0700333 metrics_observer_(new rtc::RefCountedObject<FakeMetricsObserver>()) {
buildbot@webrtc.org51c55082014-07-28 22:26:15 +0000334 cricket::ServerAddresses stun_servers;
335 stun_servers.insert(stun_socket_addr_);
336 allocator_.reset(new cricket::BasicPortAllocator(
337 &network_manager_,
338 stun_servers,
339 SocketAddress(), SocketAddress(), SocketAddress()));
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000340 allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700341 cricket::PORTALLOCATOR_DISABLE_RELAY);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000342 EXPECT_TRUE(channel_manager_->Init());
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000343 allocator_->set_step_delay(cricket::kMinimumStepDelay);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000344 }
345
346 void AddInterface(const SocketAddress& addr) {
347 network_manager_.AddInterface(addr);
348 }
349
Henrik Boströmd79599d2016-06-01 13:58:50 +0200350 // If |cert_generator| != null or |rtc_configuration| contains |certificates|
351 // then DTLS will be enabled unless explicitly disabled by |rtc_configuration|
352 // options. When DTLS is enabled a certificate will be used if provided,
353 // otherwise one will be generated using the |cert_generator|.
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +0000354 void Init(
zhihuang4dfb8ce2016-11-23 10:30:12 -0800355 std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator,
deadbeef7914b8c2017-04-21 03:23:33 -0700356 PeerConnectionInterface::RtcpMuxPolicy rtcp_mux_policy,
357 const rtc::CryptoOptions& crypto_options) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000358 ASSERT_TRUE(session_.get() == NULL);
deadbeef953c2ce2017-01-09 14:53:41 -0800359 fake_sctp_transport_factory_ = new FakeSctpTransportFactory();
nisseeaabdf62017-05-05 02:23:02 -0700360 session_.reset(new WebRtcSessionForTest(&fake_call_,
361 channel_manager_.get(), cricket::MediaConfig(), &event_log_,
362 rtc::Thread::Current(), rtc::Thread::Current(),
zhihuang29ff8442016-07-27 11:07:25 -0700363 rtc::Thread::Current(), allocator_.get(), &observer_,
364 std::unique_ptr<cricket::TransportController>(
deadbeef7914b8c2017-04-21 03:23:33 -0700365 new cricket::TransportController(
366 rtc::Thread::Current(), rtc::Thread::Current(),
367 allocator_.get(),
368 /*redetermine_role_on_ice_restart=*/true, crypto_options)),
deadbeef953c2ce2017-01-09 14:53:41 -0800369 std::unique_ptr<FakeSctpTransportFactory>(
370 fake_sctp_transport_factory_)));
deadbeefab9b2d12015-10-14 11:33:11 -0700371 session_->SignalDataChannelOpenMessage.connect(
372 this, &WebRtcSessionTest::OnDataChannelOpenMessage);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000373
zhihuang4dfb8ce2016-11-23 10:30:12 -0800374 configuration_.rtcp_mux_policy = rtcp_mux_policy;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000375 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
376 observer_.ice_connection_state_);
377 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
378 observer_.ice_gathering_state_);
379
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200380 EXPECT_TRUE(session_->Initialize(options_, std::move(cert_generator),
htaa2a49d92016-03-04 02:51:39 -0800381 configuration_));
jbauchac8869e2015-07-03 01:36:14 -0700382 session_->set_metrics_observer(metrics_observer_);
deadbeef7914b8c2017-04-21 03:23:33 -0700383 crypto_options_ = crypto_options;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000384 }
385
deadbeefab9b2d12015-10-14 11:33:11 -0700386 void OnDataChannelOpenMessage(const std::string& label,
387 const InternalDataChannelInit& config) {
388 last_data_channel_label_ = label;
389 last_data_channel_config_ = config;
390 }
391
zhihuang4dfb8ce2016-11-23 10:30:12 -0800392 void Init() {
deadbeef7914b8c2017-04-21 03:23:33 -0700393 Init(nullptr, PeerConnectionInterface::kRtcpMuxPolicyNegotiate,
394 rtc::CryptoOptions());
zhihuang4dfb8ce2016-11-23 10:30:12 -0800395 }
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +0000396
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +0000397 void InitWithBundlePolicy(
398 PeerConnectionInterface::BundlePolicy bundle_policy) {
htaa2a49d92016-03-04 02:51:39 -0800399 configuration_.bundle_policy = bundle_policy;
400 Init();
Peter Thatcheraf55ccc2015-05-21 07:48:41 -0700401 }
402
Olga Sharonovab49b6612017-10-20 12:56:51 +0000403 void InitWithRtcpMuxPolicy(
404 PeerConnectionInterface::RtcpMuxPolicy rtcp_mux_policy) {
405 PeerConnectionInterface::RTCConfiguration configuration;
406 Init(nullptr, rtcp_mux_policy, rtc::CryptoOptions());
407 }
408
Henrik Boström87713d02015-08-25 09:53:21 +0200409 // Successfully init with DTLS; with a certificate generated and supplied or
410 // with a store that generates it for us.
411 void InitWithDtls(RTCCertificateGenerationMethod cert_gen_method) {
Henrik Boströmd79599d2016-06-01 13:58:50 +0200412 std::unique_ptr<FakeRTCCertificateGenerator> cert_generator;
Henrik Boström87713d02015-08-25 09:53:21 +0200413 if (cert_gen_method == ALREADY_GENERATED) {
htaa2a49d92016-03-04 02:51:39 -0800414 configuration_.certificates.push_back(
Henrik Boströmd79599d2016-06-01 13:58:50 +0200415 FakeRTCCertificateGenerator::GenerateCertificate());
Henrik Boström87713d02015-08-25 09:53:21 +0200416 } else if (cert_gen_method == DTLS_IDENTITY_STORE) {
Henrik Boströmd79599d2016-06-01 13:58:50 +0200417 cert_generator.reset(new FakeRTCCertificateGenerator());
418 cert_generator->set_should_fail(false);
Henrik Boström87713d02015-08-25 09:53:21 +0200419 } else {
henrikg91d6ede2015-09-17 00:24:34 -0700420 RTC_CHECK(false);
Henrik Boström87713d02015-08-25 09:53:21 +0200421 }
zhihuang4dfb8ce2016-11-23 10:30:12 -0800422 Init(std::move(cert_generator),
deadbeef7914b8c2017-04-21 03:23:33 -0700423 PeerConnectionInterface::kRtcpMuxPolicyNegotiate,
424 rtc::CryptoOptions());
Henrik Boström87713d02015-08-25 09:53:21 +0200425 }
426
zhihuang1c378ed2017-08-17 14:10:50 -0700427 // The following convenience functions can be applied for both local side and
428 // remote side. The flags can be overwritten for different use cases.
deadbeefab9b2d12015-10-14 11:33:11 -0700429 void SendAudioVideoStream1() {
430 send_stream_1_ = true;
431 send_stream_2_ = false;
zhihuang1c378ed2017-08-17 14:10:50 -0700432 local_send_audio_ = true;
433 local_send_video_ = true;
434 remote_send_audio_ = true;
435 remote_send_video_ = true;
deadbeefab9b2d12015-10-14 11:33:11 -0700436 }
437
438 void SendAudioVideoStream2() {
439 send_stream_1_ = false;
440 send_stream_2_ = true;
zhihuang1c378ed2017-08-17 14:10:50 -0700441 local_send_audio_ = true;
442 local_send_video_ = true;
443 remote_send_audio_ = true;
444 remote_send_video_ = true;
deadbeefab9b2d12015-10-14 11:33:11 -0700445 }
446
deadbeefab9b2d12015-10-14 11:33:11 -0700447 void SendAudioOnlyStream2() {
448 send_stream_1_ = false;
449 send_stream_2_ = true;
zhihuang1c378ed2017-08-17 14:10:50 -0700450 local_send_audio_ = true;
451 local_send_video_ = false;
452 remote_send_audio_ = true;
453 remote_send_video_ = false;
deadbeefab9b2d12015-10-14 11:33:11 -0700454 }
455
456 void SendVideoOnlyStream2() {
457 send_stream_1_ = false;
458 send_stream_2_ = true;
zhihuang1c378ed2017-08-17 14:10:50 -0700459 local_send_audio_ = false;
460 local_send_video_ = true;
461 remote_send_audio_ = false;
462 remote_send_video_ = true;
deadbeefab9b2d12015-10-14 11:33:11 -0700463 }
464
zhihuang1c378ed2017-08-17 14:10:50 -0700465 // Add the media sections to the options from |offered_media_sections_| when
466 // creating an answer or a new offer.
467 // This duplicates a lot of logic from PeerConnection but this can be fixed
468 // when PeerConnection and WebRtcSession are merged.
469 void AddExistingMediaSectionsAndSendersToOptions(
470 cricket::MediaSessionOptions* session_options,
471 bool send_audio,
472 bool recv_audio,
473 bool send_video,
474 bool recv_video) {
475 int num_sim_layer = 1;
476 for (auto media_description_options : offered_media_sections_) {
477 if (media_description_options.type == cricket::MEDIA_TYPE_AUDIO) {
478 bool stopped = !send_audio && !recv_audio;
479 auto media_desc_options = cricket::MediaDescriptionOptions(
480 cricket::MEDIA_TYPE_AUDIO, media_description_options.mid,
481 cricket::RtpTransceiverDirection(send_audio, recv_audio), stopped);
482 if (send_stream_1_ && send_audio) {
Steve Anton8ffb9c32017-08-31 15:45:38 -0700483 media_desc_options.AddAudioSender(kAudioTrack1, {kStream1});
zhihuang1c378ed2017-08-17 14:10:50 -0700484 }
485 if (send_stream_2_ && send_audio) {
Steve Anton8ffb9c32017-08-31 15:45:38 -0700486 media_desc_options.AddAudioSender(kAudioTrack2, {kStream2});
zhihuang1c378ed2017-08-17 14:10:50 -0700487 }
488 session_options->media_description_options.push_back(
489 media_desc_options);
490 } else if (media_description_options.type == cricket::MEDIA_TYPE_VIDEO) {
491 bool stopped = !send_video && !recv_video;
492 auto media_desc_options = cricket::MediaDescriptionOptions(
493 cricket::MEDIA_TYPE_VIDEO, media_description_options.mid,
494 cricket::RtpTransceiverDirection(send_video, recv_video), stopped);
495 if (send_stream_1_ && send_video) {
Steve Anton8ffb9c32017-08-31 15:45:38 -0700496 media_desc_options.AddVideoSender(kVideoTrack1, {kStream1},
zhihuang1c378ed2017-08-17 14:10:50 -0700497 num_sim_layer);
498 }
499 if (send_stream_2_ && send_video) {
Steve Anton8ffb9c32017-08-31 15:45:38 -0700500 media_desc_options.AddVideoSender(kVideoTrack2, {kStream2},
zhihuang1c378ed2017-08-17 14:10:50 -0700501 num_sim_layer);
502 }
503 session_options->media_description_options.push_back(
504 media_desc_options);
505 } else if (media_description_options.type == cricket::MEDIA_TYPE_DATA) {
506 session_options->media_description_options.push_back(
507 cricket::MediaDescriptionOptions(
508 cricket::MEDIA_TYPE_DATA, media_description_options.mid,
509 // Direction for data sections is meaningless, but legacy
510 // endpoints might expect sendrecv.
511 cricket::RtpTransceiverDirection(true, true), false));
512 } else {
513 RTC_NOTREACHED();
514 }
deadbeefab9b2d12015-10-14 11:33:11 -0700515 }
zhihuang1c378ed2017-08-17 14:10:50 -0700516 }
517
518 // Add the existing media sections first and then add new media sections if
519 // needed.
520 void AddMediaSectionsAndSendersToOptions(
521 cricket::MediaSessionOptions* session_options,
522 bool send_audio,
523 bool recv_audio,
524 bool send_video,
525 bool recv_video) {
526 AddExistingMediaSectionsAndSendersToOptions(
527 session_options, send_audio, recv_audio, send_video, recv_video);
528
529 if (!session_options->has_audio() && (send_audio || recv_audio)) {
530 cricket::MediaDescriptionOptions media_desc_options =
531 cricket::MediaDescriptionOptions(
532 cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO,
533 cricket::RtpTransceiverDirection(send_audio, recv_audio),
534 kActive);
535 if (send_stream_1_ && send_audio) {
Steve Anton8ffb9c32017-08-31 15:45:38 -0700536 media_desc_options.AddAudioSender(kAudioTrack1, {kStream1});
zhihuang1c378ed2017-08-17 14:10:50 -0700537 }
538 if (send_stream_2_ && send_audio) {
Steve Anton8ffb9c32017-08-31 15:45:38 -0700539 media_desc_options.AddAudioSender(kAudioTrack2, {kStream2});
zhihuang1c378ed2017-08-17 14:10:50 -0700540 }
541 session_options->media_description_options.push_back(media_desc_options);
542 offered_media_sections_.push_back(media_desc_options);
deadbeefab9b2d12015-10-14 11:33:11 -0700543 }
zhihuang1c378ed2017-08-17 14:10:50 -0700544
545 if (!session_options->has_video() && (send_video || recv_video)) {
546 cricket::MediaDescriptionOptions media_desc_options =
547 cricket::MediaDescriptionOptions(
548 cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO,
549 cricket::RtpTransceiverDirection(send_video, recv_video),
550 kActive);
551 int num_sim_layer = 1;
552 if (send_stream_1_ && send_video) {
Steve Anton8ffb9c32017-08-31 15:45:38 -0700553 media_desc_options.AddVideoSender(kVideoTrack1, {kStream1},
zhihuang1c378ed2017-08-17 14:10:50 -0700554 num_sim_layer);
555 }
556 if (send_stream_2_ && send_video) {
Steve Anton8ffb9c32017-08-31 15:45:38 -0700557 media_desc_options.AddVideoSender(kVideoTrack2, {kStream2},
zhihuang1c378ed2017-08-17 14:10:50 -0700558 num_sim_layer);
559 }
560 session_options->media_description_options.push_back(media_desc_options);
561 offered_media_sections_.push_back(media_desc_options);
deadbeefab9b2d12015-10-14 11:33:11 -0700562 }
zhihuang1c378ed2017-08-17 14:10:50 -0700563
564 if (!session_options->has_data() &&
565 (data_channel_ ||
566 session_options->data_channel_type != cricket::DCT_NONE)) {
567 cricket::MediaDescriptionOptions media_desc_options =
568 cricket::MediaDescriptionOptions(
569 cricket::MEDIA_TYPE_DATA, cricket::CN_DATA,
570 cricket::RtpTransceiverDirection(true, true), kActive);
571 if (session_options->data_channel_type == cricket::DCT_RTP) {
572 media_desc_options.AddRtpDataChannel(data_channel_->label(),
573 data_channel_->label());
574 }
575 session_options->media_description_options.push_back(media_desc_options);
576 offered_media_sections_.push_back(media_desc_options);
deadbeefab9b2d12015-10-14 11:33:11 -0700577 }
578 }
579
580 void GetOptionsForOffer(
581 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
582 cricket::MediaSessionOptions* session_options) {
zhihuang1c378ed2017-08-17 14:10:50 -0700583 ExtractSharedMediaSessionOptions(rtc_options, session_options);
deadbeefab9b2d12015-10-14 11:33:11 -0700584
zhihuang1c378ed2017-08-17 14:10:50 -0700585 // |recv_X| is true by default if |offer_to_receive_X| is undefined.
586 bool recv_audio = rtc_options.offer_to_receive_audio != 0;
587 bool recv_video = rtc_options.offer_to_receive_video != 0;
588
589 AddMediaSectionsAndSendersToOptions(session_options, local_send_audio_,
590 recv_audio, local_send_video_,
591 recv_video);
deadbeefc80741f2015-10-22 13:14:45 -0700592 session_options->bundle_enabled =
593 session_options->bundle_enabled &&
594 (session_options->has_audio() || session_options->has_video() ||
595 session_options->has_data());
596
zhihuang1c378ed2017-08-17 14:10:50 -0700597 session_options->crypto_options = crypto_options_;
598 }
599
600 void GetOptionsForAnswer(cricket::MediaSessionOptions* session_options) {
601 AddExistingMediaSectionsAndSendersToOptions(
602 session_options, local_send_audio_, local_recv_audio_,
603 local_send_video_, local_recv_video_);
604
605 session_options->bundle_enabled =
606 session_options->bundle_enabled &&
607 (session_options->has_audio() || session_options->has_video() ||
608 session_options->has_data());
609
610 if (session_->data_channel_type() != cricket::DCT_RTP) {
611 session_options->data_channel_type = session_->data_channel_type();
olka3c747662017-08-17 06:50:32 -0700612 }
613
zhihuanga77e6bb2017-08-14 18:17:48 -0700614 session_options->crypto_options = crypto_options_;
615 }
616
zhihuang1c378ed2017-08-17 14:10:50 -0700617 void GetOptionsForRemoteAnswer(
618 cricket::MediaSessionOptions* session_options) {
619 bool recv_audio = local_send_audio_ || remote_recv_audio_;
620 bool recv_video = local_send_video_ || remote_recv_video_;
621 bool send_audio = false;
622 bool send_video = false;
zhihuanga77e6bb2017-08-14 18:17:48 -0700623
zhihuang1c378ed2017-08-17 14:10:50 -0700624 AddExistingMediaSectionsAndSendersToOptions(
625 session_options, send_audio, recv_audio, send_video, recv_video);
626
zhihuanga77e6bb2017-08-14 18:17:48 -0700627 session_options->bundle_enabled =
628 session_options->bundle_enabled &&
629 (session_options->has_audio() || session_options->has_video() ||
630 session_options->has_data());
631
632 if (session_->data_channel_type() != cricket::DCT_RTP) {
633 session_options->data_channel_type = session_->data_channel_type();
deadbeefab9b2d12015-10-14 11:33:11 -0700634 }
jbauchcb560652016-08-04 05:20:32 -0700635
deadbeef7914b8c2017-04-21 03:23:33 -0700636 session_options->crypto_options = crypto_options_;
deadbeefab9b2d12015-10-14 11:33:11 -0700637 }
638
zhihuang1c378ed2017-08-17 14:10:50 -0700639 void GetOptionsForRemoteOffer(cricket::MediaSessionOptions* session_options) {
640 AddMediaSectionsAndSendersToOptions(session_options, remote_send_audio_,
641 remote_recv_audio_, remote_send_video_,
642 remote_recv_video_);
643 session_options->bundle_enabled =
644 (session_options->has_audio() || session_options->has_video() ||
645 session_options->has_data());
646
647 if (session_->data_channel_type() != cricket::DCT_RTP) {
648 session_options->data_channel_type = session_->data_channel_type();
649 }
650
651 session_options->crypto_options = crypto_options_;
652 }
653
deadbeefab9b2d12015-10-14 11:33:11 -0700654 // Creates a local offer and applies it. Starts ICE.
655 // Call SendAudioVideoStreamX() before this function
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000656 // to decide which streams to create.
657 void InitiateCall() {
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000658 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000659 SetLocalDescriptionWithoutError(offer);
660 EXPECT_TRUE_WAIT(PeerConnectionInterface::kIceGatheringNew !=
661 observer_.ice_gathering_state_,
662 kIceCandidatesTimeout);
663 }
664
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000665 SessionDescriptionInterface* CreateOffer() {
666 PeerConnectionInterface::RTCOfferAnswerOptions options;
667 options.offer_to_receive_audio =
668 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000669 return CreateOffer(options);
670 }
671
wu@webrtc.org91053e72013-08-10 07:18:04 +0000672 SessionDescriptionInterface* CreateOffer(
htaa2a49d92016-03-04 02:51:39 -0800673 const PeerConnectionInterface::RTCOfferAnswerOptions options) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000674 rtc::scoped_refptr<WebRtcSessionCreateSDPObserverForTest>
wu@webrtc.org91053e72013-08-10 07:18:04 +0000675 observer = new WebRtcSessionCreateSDPObserverForTest();
deadbeefab9b2d12015-10-14 11:33:11 -0700676 cricket::MediaSessionOptions session_options;
677 GetOptionsForOffer(options, &session_options);
678 session_->CreateOffer(observer, options, session_options);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000679 EXPECT_TRUE_WAIT(
680 observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit,
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000681 2000);
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000682 return observer->ReleaseDescription();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000683 }
684
685 SessionDescriptionInterface* CreateAnswer(
htaa2a49d92016-03-04 02:51:39 -0800686 const cricket::MediaSessionOptions& options) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000687 rtc::scoped_refptr<WebRtcSessionCreateSDPObserverForTest> observer
wu@webrtc.org91053e72013-08-10 07:18:04 +0000688 = new WebRtcSessionCreateSDPObserverForTest();
htaa2a49d92016-03-04 02:51:39 -0800689 cricket::MediaSessionOptions session_options = options;
690 GetOptionsForAnswer(&session_options);
htaa2a49d92016-03-04 02:51:39 -0800691 session_->CreateAnswer(observer, session_options);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000692 EXPECT_TRUE_WAIT(
693 observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit,
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000694 2000);
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000695 return observer->ReleaseDescription();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000696 }
697
htaa2a49d92016-03-04 02:51:39 -0800698 SessionDescriptionInterface* CreateAnswer() {
699 cricket::MediaSessionOptions options;
zhihuang1c378ed2017-08-17 14:10:50 -0700700 options.bundle_enabled = true;
htaa2a49d92016-03-04 02:51:39 -0800701 return CreateAnswer(options);
702 }
703
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000704 // Set the internal fake description factories to do DTLS-SRTP.
705 void SetFactoryDtlsSrtp() {
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000706 desc_factory_->set_secure(cricket::SEC_DISABLED);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000707 std::string identity_name = "WebRTC" +
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000708 rtc::ToString(rtc::CreateRandomId());
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200709 // Confirmed to work with KT_RSA and KT_ECDSA.
kwiberg0eb15ed2015-12-17 03:04:15 -0800710 tdesc_factory_->set_certificate(
jbauch555604a2016-04-26 03:13:22 -0700711 rtc::RTCCertificate::Create(std::unique_ptr<rtc::SSLIdentity>(
kwiberg0eb15ed2015-12-17 03:04:15 -0800712 rtc::SSLIdentity::Generate(identity_name, rtc::KT_DEFAULT))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000713 tdesc_factory_->set_secure(cricket::SEC_REQUIRED);
714 }
715
deadbeef0ed85b22016-02-23 17:24:52 -0800716 // Compares ufrag/password only for the specified |media_type|.
717 bool IceUfragPwdEqual(const cricket::SessionDescription* desc1,
718 const cricket::SessionDescription* desc2,
719 cricket::MediaType media_type) {
720 if (desc1->contents().size() != desc2->contents().size()) {
721 return false;
722 }
723
724 const cricket::ContentInfo* cinfo =
725 cricket::GetFirstMediaContent(desc1->contents(), media_type);
726 const cricket::TransportDescription* transport_desc1 =
727 desc1->GetTransportDescriptionByName(cinfo->name);
728 const cricket::TransportDescription* transport_desc2 =
729 desc2->GetTransportDescriptionByName(cinfo->name);
730 if (!transport_desc1 || !transport_desc2) {
731 return false;
732 }
733 if (transport_desc1->ice_pwd != transport_desc2->ice_pwd ||
734 transport_desc1->ice_ufrag != transport_desc2->ice_ufrag) {
735 return false;
736 }
737 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000738 }
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000739
deadbeef0ed85b22016-02-23 17:24:52 -0800740 // Sets ufrag/pwd for specified |media_type|.
741 void SetIceUfragPwd(SessionDescriptionInterface* current_desc,
742 cricket::MediaType media_type,
743 const std::string& ufrag,
744 const std::string& pwd) {
745 cricket::SessionDescription* desc = current_desc->description();
746 const cricket::ContentInfo* cinfo =
747 cricket::GetFirstMediaContent(desc->contents(), media_type);
748 TransportInfo* transport_info = desc->GetTransportInfoByName(cinfo->name);
749 cricket::TransportDescription* transport_desc =
750 &transport_info->description;
751 transport_desc->ice_ufrag = ufrag;
752 transport_desc->ice_pwd = pwd;
753 }
754
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000755 void SetLocalDescriptionWithoutError(SessionDescriptionInterface* desc) {
Steve Anton3df5dca2017-10-19 16:11:30 -0700756 ASSERT_TRUE(session_->SetLocalDescription(rtc::WrapUnique(desc), nullptr));
deadbeefcbecd352015-09-23 11:50:27 -0700757 session_->MaybeStartGathering();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000758 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000759 void SetLocalDescriptionExpectError(const std::string& action,
760 const std::string& expected_error,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000761 SessionDescriptionInterface* desc) {
762 std::string error;
Steve Anton3df5dca2017-10-19 16:11:30 -0700763 EXPECT_FALSE(session_->SetLocalDescription(rtc::WrapUnique(desc), &error));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000764 std::string sdp_type = "local ";
765 sdp_type.append(action);
766 EXPECT_NE(std::string::npos, error.find(sdp_type));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000767 EXPECT_NE(std::string::npos, error.find(expected_error));
768 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000769 void SetLocalDescriptionOfferExpectError(const std::string& expected_error,
770 SessionDescriptionInterface* desc) {
771 SetLocalDescriptionExpectError(SessionDescriptionInterface::kOffer,
772 expected_error, desc);
773 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000774 void SetRemoteDescriptionWithoutError(SessionDescriptionInterface* desc) {
Steve Anton3df5dca2017-10-19 16:11:30 -0700775 ASSERT_TRUE(session_->SetRemoteDescription(rtc::WrapUnique(desc), nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000776 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000777 void SetRemoteDescriptionExpectError(const std::string& action,
778 const std::string& expected_error,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000779 SessionDescriptionInterface* desc) {
780 std::string error;
Steve Anton3df5dca2017-10-19 16:11:30 -0700781 EXPECT_FALSE(session_->SetRemoteDescription(rtc::WrapUnique(desc), &error));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000782 std::string sdp_type = "remote ";
783 sdp_type.append(action);
784 EXPECT_NE(std::string::npos, error.find(sdp_type));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000785 EXPECT_NE(std::string::npos, error.find(expected_error));
786 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000787 void SetRemoteDescriptionOfferExpectError(
788 const std::string& expected_error, SessionDescriptionInterface* desc) {
789 SetRemoteDescriptionExpectError(SessionDescriptionInterface::kOffer,
790 expected_error, desc);
791 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000792
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000793 JsepSessionDescription* CreateRemoteOfferWithVersion(
794 cricket::MediaSessionOptions options,
795 cricket::SecurePolicy secure_policy,
796 const std::string& session_version,
797 const SessionDescriptionInterface* current_desc) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000798 std::string session_id = rtc::ToString(rtc::CreateRandomId64());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000799 const cricket::SessionDescription* cricket_desc = NULL;
800 if (current_desc) {
801 cricket_desc = current_desc->description();
802 session_id = current_desc->session_id();
803 }
804
805 desc_factory_->set_secure(secure_policy);
806 JsepSessionDescription* offer(
807 new JsepSessionDescription(JsepSessionDescription::kOffer));
808 if (!offer->Initialize(desc_factory_->CreateOffer(options, cricket_desc),
809 session_id, session_version)) {
810 delete offer;
811 offer = NULL;
812 }
813 return offer;
814 }
815 JsepSessionDescription* CreateRemoteOffer(
816 cricket::MediaSessionOptions options) {
817 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED,
818 kSessionVersion, NULL);
819 }
820 JsepSessionDescription* CreateRemoteOffer(
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000821 cricket::MediaSessionOptions options, cricket::SecurePolicy sdes_policy) {
822 return CreateRemoteOfferWithVersion(
823 options, sdes_policy, kSessionVersion, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000824 }
825 JsepSessionDescription* CreateRemoteOffer(
826 cricket::MediaSessionOptions options,
827 const SessionDescriptionInterface* current_desc) {
828 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED,
829 kSessionVersion, current_desc);
830 }
831
Steve Anton6d64e9a2017-09-12 09:44:05 -0700832 SessionDescriptionInterface* CreateRemoteOfferWithSctpPort(
833 const char* sctp_stream_name,
834 int new_port,
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000835 cricket::MediaSessionOptions options) {
836 options.data_channel_type = cricket::DCT_SCTP;
zhihuang1c378ed2017-08-17 14:10:50 -0700837 GetOptionsForRemoteOffer(&options);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000838 return ChangeSDPSctpPort(new_port, CreateRemoteOffer(options));
839 }
840
841 // Takes ownership of offer_basis (and deletes it).
Steve Anton6d64e9a2017-09-12 09:44:05 -0700842 SessionDescriptionInterface* ChangeSDPSctpPort(
843 int new_port,
844 webrtc::SessionDescriptionInterface* offer_basis) {
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000845 // Stringify the input SDP, swap the 5000 for 'new_port' and create a new
846 // SessionDescription from the mutated string.
847 const char* default_port_str = "5000";
848 char new_port_str[16];
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000849 rtc::sprintfn(new_port_str, sizeof(new_port_str), "%d", new_port);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000850 std::string offer_str;
851 offer_basis->ToString(&offer_str);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000852 rtc::replace_substrs(default_port_str, strlen(default_port_str),
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000853 new_port_str, strlen(new_port_str),
854 &offer_str);
Steve Anton6d64e9a2017-09-12 09:44:05 -0700855 SessionDescriptionInterface* offer =
856 CreateSessionDescription(offer_basis->type(), offer_str, nullptr);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000857 delete offer_basis;
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000858 return offer;
859 }
860
deadbeefab9b2d12015-10-14 11:33:11 -0700861 // Create a remote offer. Call SendAudioVideoStreamX()
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000862 // before this function to decide which streams to create.
863 JsepSessionDescription* CreateRemoteOffer() {
864 cricket::MediaSessionOptions options;
zhihuang1c378ed2017-08-17 14:10:50 -0700865 GetOptionsForRemoteOffer(&options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000866 return CreateRemoteOffer(options, session_->remote_description());
867 }
868
869 JsepSessionDescription* CreateRemoteAnswer(
870 const SessionDescriptionInterface* offer,
871 cricket::MediaSessionOptions options,
872 cricket::SecurePolicy policy) {
873 desc_factory_->set_secure(policy);
874 const std::string session_id =
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000875 rtc::ToString(rtc::CreateRandomId64());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000876 JsepSessionDescription* answer(
877 new JsepSessionDescription(JsepSessionDescription::kAnswer));
878 if (!answer->Initialize(desc_factory_->CreateAnswer(offer->description(),
879 options, NULL),
880 session_id, kSessionVersion)) {
881 delete answer;
882 answer = NULL;
883 }
884 return answer;
885 }
886
887 JsepSessionDescription* CreateRemoteAnswer(
888 const SessionDescriptionInterface* offer,
889 cricket::MediaSessionOptions options) {
890 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED);
891 }
892
deadbeefab9b2d12015-10-14 11:33:11 -0700893 // Creates an answer session description.
894 // Call SendAudioVideoStreamX() before this function
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000895 // to decide which streams to create.
896 JsepSessionDescription* CreateRemoteAnswer(
897 const SessionDescriptionInterface* offer) {
898 cricket::MediaSessionOptions options;
htaa2a49d92016-03-04 02:51:39 -0800899 GetOptionsForAnswer(&options);
zhihuang1c378ed2017-08-17 14:10:50 -0700900 options.bundle_enabled = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000901 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED);
902 }
903
Olga Sharonovab49b6612017-10-20 12:56:51 +0000904 void TestSessionCandidatesWithBundleRtcpMux(bool bundle, bool rtcp_mux) {
905 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
906 Init();
907 SendAudioVideoStream1();
908
909 PeerConnectionInterface::RTCOfferAnswerOptions options;
910 options.use_rtp_mux = bundle;
911
912 SessionDescriptionInterface* offer = CreateOffer(options);
913 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
914 // and answer.
915 SetLocalDescriptionWithoutError(offer);
916
917 std::unique_ptr<SessionDescriptionInterface> answer(
918 CreateRemoteAnswer(session_->local_description()));
919 std::string sdp;
920 EXPECT_TRUE(answer->ToString(&sdp));
921
922 size_t expected_candidate_num = 2;
923 if (!rtcp_mux) {
924 // If rtcp_mux is enabled we should expect 4 candidates - host and srflex
925 // for rtp and rtcp.
926 expected_candidate_num = 4;
927 // Disable rtcp-mux from the answer
928 const std::string kRtcpMux = "a=rtcp-mux";
929 const std::string kXRtcpMux = "a=xrtcp-mux";
930 rtc::replace_substrs(kRtcpMux.c_str(), kRtcpMux.length(),
931 kXRtcpMux.c_str(), kXRtcpMux.length(),
932 &sdp);
933 }
934
935 SessionDescriptionInterface* new_answer = CreateSessionDescription(
936 JsepSessionDescription::kAnswer, sdp, NULL);
937
938 // SetRemoteDescription to enable rtcp mux.
939 SetRemoteDescriptionWithoutError(new_answer);
940 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
941 EXPECT_EQ(expected_candidate_num, observer_.mline_0_candidates_.size());
942 if (bundle) {
943 EXPECT_EQ(0, observer_.mline_1_candidates_.size());
944 } else {
945 EXPECT_EQ(expected_candidate_num, observer_.mline_1_candidates_.size());
946 }
947 }
948
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000949 // The method sets up a call from the session to itself, in a loopback
950 // arrangement. It also uses a firewall rule to create a temporary
mallinath@webrtc.org385857d2014-02-14 00:56:12 +0000951 // disconnection, and then a permanent disconnection.
952 // This code is placed in a method so that it can be invoked
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000953 // by multiple tests with different allocators (e.g. with and without BUNDLE).
954 // While running the call, this method also checks if the session goes through
955 // the correct sequence of ICE states when a connection is established,
956 // broken, and re-established.
957 // The Connection state should go:
mallinath@webrtc.org385857d2014-02-14 00:56:12 +0000958 // New -> Checking -> (Connected) -> Completed -> Disconnected -> Completed
959 // -> Failed.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000960 // The Gathering state should go: New -> Gathering -> Completed.
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +0000961
stefanc1aeaf02015-10-15 07:26:07 -0700962 void SetupLoopbackCall() {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +0000963 Init();
deadbeefab9b2d12015-10-14 11:33:11 -0700964 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000965 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000966
967 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
968 observer_.ice_gathering_state_);
969 SetLocalDescriptionWithoutError(offer);
970 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
971 observer_.ice_connection_state_);
972 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringGathering,
stefanc1aeaf02015-10-15 07:26:07 -0700973 observer_.ice_gathering_state_, kIceCandidatesTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000974 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
975 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringComplete,
stefanc1aeaf02015-10-15 07:26:07 -0700976 observer_.ice_gathering_state_, kIceCandidatesTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000977
978 std::string sdp;
979 offer->ToString(&sdp);
stefanc1aeaf02015-10-15 07:26:07 -0700980 SessionDescriptionInterface* desc = webrtc::CreateSessionDescription(
981 JsepSessionDescription::kAnswer, sdp, nullptr);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000982 ASSERT_TRUE(desc != NULL);
983 SetRemoteDescriptionWithoutError(desc);
984
985 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionChecking,
stefanc1aeaf02015-10-15 07:26:07 -0700986 observer_.ice_connection_state_, kIceCandidatesTimeout);
mallinath@webrtc.orgd3dc4242014-03-01 00:05:52 +0000987
mallinath@webrtc.org385857d2014-02-14 00:56:12 +0000988 // The ice connection state is "Connected" too briefly to catch in a test.
989 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
stefanc1aeaf02015-10-15 07:26:07 -0700990 observer_.ice_connection_state_, kIceCandidatesTimeout);
991 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000992
stefanc1aeaf02015-10-15 07:26:07 -0700993 void TestPacketOptions() {
Steve Antonede9ca52017-10-16 13:04:27 -0700994 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
stefanc1aeaf02015-10-15 07:26:07 -0700995
996 SetupLoopbackCall();
997
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200998 // Wait for channel to be ready for sending.
999 EXPECT_TRUE_WAIT(media_engine_->GetVideoChannel(0)->sending(), 100);
stefanc1aeaf02015-10-15 07:26:07 -07001000 uint8_t test_packet[15] = {0};
1001 rtc::PacketOptions options;
1002 options.packet_id = 10;
1003 media_engine_->GetVideoChannel(0)
1004 ->SendRtp(test_packet, sizeof(test_packet), options);
1005
1006 const int kPacketTimeout = 2000;
deadbeef14461d42016-06-15 11:06:57 -07001007 EXPECT_EQ_WAIT(10, fake_call_.last_sent_nonnegative_packet_id(),
1008 kPacketTimeout);
stefanc1aeaf02015-10-15 07:26:07 -07001009 EXPECT_GT(fake_call_.last_sent_packet().send_time_ms, -1);
1010 }
1011
deadbeefab9b2d12015-10-14 11:33:11 -07001012 void CreateDataChannel() {
deadbeeffc648b62015-10-13 16:42:33 -07001013 webrtc::InternalDataChannelInit dci;
nissec8ee8822017-01-18 07:20:55 -08001014 RTC_CHECK(session_.get());
deadbeefab9b2d12015-10-14 11:33:11 -07001015 dci.reliable = session_->data_channel_type() == cricket::DCT_SCTP;
1016 data_channel_ = DataChannel::Create(
1017 session_.get(), session_->data_channel_type(), "datachannel", dci);
1018 }
1019
1020 void SetLocalDescriptionWithDataChannel() {
1021 CreateDataChannel();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001022 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001023 SetLocalDescriptionWithoutError(offer);
1024 }
1025
skvlad11a9cbf2016-10-07 11:53:05 -07001026 webrtc::RtcEventLogNullImpl event_log_;
nisse7eaa4ea2017-05-08 05:25:41 -07001027 std::unique_ptr<rtc::VirtualSocketServer> vss_;
1028 std::unique_ptr<rtc::FirewallSocketServer> fss_;
1029 rtc::AutoSocketServerThread thread_;
deadbeef112b2e92017-02-10 20:13:37 -08001030 // |media_engine_| and |data_engine_| are actually owned by
1031 // |channel_manager_|.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001032 cricket::FakeMediaEngine* media_engine_;
1033 cricket::FakeDataEngine* data_engine_;
deadbeef953c2ce2017-01-09 14:53:41 -08001034 // Actually owned by session_.
1035 FakeSctpTransportFactory* fake_sctp_transport_factory_ = nullptr;
kwibergd1fe2812016-04-27 06:47:29 -07001036 std::unique_ptr<cricket::ChannelManager> channel_manager_;
stefanc1aeaf02015-10-15 07:26:07 -07001037 cricket::FakeCall fake_call_;
kwibergd1fe2812016-04-27 06:47:29 -07001038 std::unique_ptr<cricket::TransportDescriptionFactory> tdesc_factory_;
1039 std::unique_ptr<cricket::MediaSessionDescriptionFactory> desc_factory_;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001040 rtc::SocketAddress stun_socket_addr_;
kwibergd1fe2812016-04-27 06:47:29 -07001041 std::unique_ptr<cricket::TestStunServer> stun_server_;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001042 rtc::FakeNetworkManager network_manager_;
kwibergd1fe2812016-04-27 06:47:29 -07001043 std::unique_ptr<cricket::BasicPortAllocator> allocator_;
wu@webrtc.org97077a32013-10-25 21:18:33 +00001044 PeerConnectionFactoryInterface::Options options_;
htaa2a49d92016-03-04 02:51:39 -08001045 PeerConnectionInterface::RTCConfiguration configuration_;
kwibergd1fe2812016-04-27 06:47:29 -07001046 std::unique_ptr<WebRtcSessionForTest> session_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001047 MockIceObserver observer_;
1048 cricket::FakeVideoMediaChannel* video_channel_;
1049 cricket::FakeVoiceMediaChannel* voice_channel_;
jbauchac8869e2015-07-03 01:36:14 -07001050 rtc::scoped_refptr<FakeMetricsObserver> metrics_observer_;
deadbeefab9b2d12015-10-14 11:33:11 -07001051 // The following flags affect options created for CreateOffer/CreateAnswer.
1052 bool send_stream_1_ = false;
1053 bool send_stream_2_ = false;
zhihuang1c378ed2017-08-17 14:10:50 -07001054 bool local_send_audio_ = false;
1055 bool local_send_video_ = false;
1056 bool local_recv_audio_ = true;
1057 bool local_recv_video_ = true;
1058 bool remote_send_audio_ = false;
1059 bool remote_send_video_ = false;
1060 bool remote_recv_audio_ = true;
1061 bool remote_recv_video_ = true;
1062 std::vector<cricket::MediaDescriptionOptions> offered_media_sections_;
deadbeefab9b2d12015-10-14 11:33:11 -07001063 rtc::scoped_refptr<DataChannel> data_channel_;
1064 // Last values received from data channel creation signal.
1065 std::string last_data_channel_label_;
1066 InternalDataChannelInit last_data_channel_config_;
deadbeef7914b8c2017-04-21 03:23:33 -07001067 rtc::CryptoOptions crypto_options_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001068};
1069
Olga Sharonovab49b6612017-10-20 12:56:51 +00001070TEST_F(WebRtcSessionTest, TestSessionCandidates) {
1071 TestSessionCandidatesWithBundleRtcpMux(false, false);
1072}
1073
1074// Below test cases (TestSessionCandidatesWith*) verify the candidates gathered
1075// with rtcp-mux and/or bundle.
1076TEST_F(WebRtcSessionTest, TestSessionCandidatesWithRtcpMux) {
1077 TestSessionCandidatesWithBundleRtcpMux(false, true);
1078}
1079
1080TEST_F(WebRtcSessionTest, TestSessionCandidatesWithBundleRtcpMux) {
1081 TestSessionCandidatesWithBundleRtcpMux(true, true);
1082}
1083
Taylor Brandstetterf475d362016-01-08 15:35:57 -08001084// Test that we can create and set an answer correctly when different
1085// SSL roles have been negotiated for different transports.
1086// See: https://bugs.chromium.org/p/webrtc/issues/detail?id=4525
1087TEST_P(WebRtcSessionTest, TestCreateAnswerWithDifferentSslRoles) {
1088 SendAudioVideoStream1();
1089 InitWithDtls(GetParam());
1090 SetFactoryDtlsSrtp();
1091
1092 SessionDescriptionInterface* offer = CreateOffer();
1093 SetLocalDescriptionWithoutError(offer);
1094
1095 cricket::MediaSessionOptions options;
zhihuang1c378ed2017-08-17 14:10:50 -07001096 GetOptionsForAnswer(&options);
Taylor Brandstetterf475d362016-01-08 15:35:57 -08001097
1098 // First, negotiate different SSL roles.
1099 SessionDescriptionInterface* answer =
1100 CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED);
1101 TransportInfo* audio_transport_info =
1102 answer->description()->GetTransportInfoByName("audio");
1103 audio_transport_info->description.connection_role =
1104 cricket::CONNECTIONROLE_ACTIVE;
1105 TransportInfo* video_transport_info =
1106 answer->description()->GetTransportInfoByName("video");
1107 video_transport_info->description.connection_role =
1108 cricket::CONNECTIONROLE_PASSIVE;
1109 SetRemoteDescriptionWithoutError(answer);
1110
1111 // Now create an offer in the reverse direction, and ensure the initial
1112 // offerer responds with an answer with correct SSL roles.
1113 offer = CreateRemoteOfferWithVersion(options, cricket::SEC_DISABLED,
1114 kSessionVersion,
1115 session_->remote_description());
1116 SetRemoteDescriptionWithoutError(offer);
1117
zhihuang1c378ed2017-08-17 14:10:50 -07001118 cricket::MediaSessionOptions answer_options;
1119 answer_options.bundle_enabled = true;
1120 answer = CreateAnswer(answer_options);
Taylor Brandstetterf475d362016-01-08 15:35:57 -08001121 audio_transport_info = answer->description()->GetTransportInfoByName("audio");
1122 EXPECT_EQ(cricket::CONNECTIONROLE_PASSIVE,
1123 audio_transport_info->description.connection_role);
1124 video_transport_info = answer->description()->GetTransportInfoByName("video");
1125 EXPECT_EQ(cricket::CONNECTIONROLE_ACTIVE,
1126 video_transport_info->description.connection_role);
1127 SetLocalDescriptionWithoutError(answer);
1128
1129 // Lastly, start BUNDLE-ing on "audio", expecting that the "passive" role of
1130 // audio is transferred over to video in the answer that completes the BUNDLE
1131 // negotiation.
1132 options.bundle_enabled = true;
1133 offer = CreateRemoteOfferWithVersion(options, cricket::SEC_DISABLED,
1134 kSessionVersion,
1135 session_->remote_description());
1136 SetRemoteDescriptionWithoutError(offer);
zhihuang1c378ed2017-08-17 14:10:50 -07001137 answer = CreateAnswer(answer_options);
Taylor Brandstetterf475d362016-01-08 15:35:57 -08001138 audio_transport_info = answer->description()->GetTransportInfoByName("audio");
1139 EXPECT_EQ(cricket::CONNECTIONROLE_PASSIVE,
1140 audio_transport_info->description.connection_role);
1141 video_transport_info = answer->description()->GetTransportInfoByName("video");
1142 EXPECT_EQ(cricket::CONNECTIONROLE_PASSIVE,
1143 video_transport_info->description.connection_role);
1144 SetLocalDescriptionWithoutError(answer);
1145}
1146
Olga Sharonovab49b6612017-10-20 12:56:51 +00001147// Test that candidates sent to the "video" transport do not get pushed down to
1148// the "audio" transport channel when bundling.
1149TEST_F(WebRtcSessionTest, TestIgnoreCandidatesForUnusedTransportWhenBundling) {
1150 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
1151
1152 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyBalanced);
1153 SendAudioVideoStream1();
1154
1155 cricket::MediaSessionOptions offer_options;
1156 GetOptionsForRemoteOffer(&offer_options);
1157 offer_options.bundle_enabled = true;
1158
1159 SessionDescriptionInterface* offer = CreateRemoteOffer(offer_options);
1160 SetRemoteDescriptionWithoutError(offer);
1161
1162 cricket::MediaSessionOptions answer_options;
1163 answer_options.bundle_enabled = true;
1164 SessionDescriptionInterface* answer = CreateAnswer(answer_options);
1165 SetLocalDescriptionWithoutError(answer);
1166
1167 EXPECT_EQ(session_->voice_rtp_transport_channel(),
1168 session_->video_rtp_transport_channel());
1169
1170 cricket::BaseChannel* voice_channel = session_->voice_channel();
1171 ASSERT_TRUE(voice_channel != NULL);
1172
1173 // Checks if one of the transport channels contains a connection using a given
1174 // port.
1175 auto connection_with_remote_port = [this](int port) {
1176 std::unique_ptr<webrtc::SessionStats> stats = session_->GetStats_s();
1177 for (auto& kv : stats->transport_stats) {
1178 for (auto& chan_stat : kv.second.channel_stats) {
1179 for (auto& conn_info : chan_stat.connection_infos) {
1180 if (conn_info.remote_candidate.address().port() == port) {
1181 return true;
1182 }
1183 }
1184 }
1185 }
1186 return false;
1187 };
1188
1189 EXPECT_FALSE(connection_with_remote_port(5000));
1190 EXPECT_FALSE(connection_with_remote_port(5001));
1191 EXPECT_FALSE(connection_with_remote_port(6000));
1192
1193 // The way the *_WAIT checks work is they only wait if the condition fails,
1194 // which does not help in the case where state is not changing. This is
1195 // problematic in this test since we want to verify that adding a video
1196 // candidate does _not_ change state. So we interleave candidates and assume
1197 // that messages are executed in the order they were posted.
1198
1199 // First audio candidate.
1200 cricket::Candidate candidate0;
1201 candidate0.set_address(rtc::SocketAddress("1.1.1.1", 5000));
1202 candidate0.set_component(1);
1203 candidate0.set_protocol("udp");
1204 candidate0.set_type("local");
1205 JsepIceCandidate ice_candidate0(kMediaContentName0, kMediaContentIndex0,
1206 candidate0);
1207 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate0));
1208
1209 // Video candidate.
1210 cricket::Candidate candidate1;
1211 candidate1.set_address(rtc::SocketAddress("1.1.1.1", 6000));
1212 candidate1.set_component(1);
1213 candidate1.set_protocol("udp");
1214 candidate1.set_type("local");
1215 JsepIceCandidate ice_candidate1(kMediaContentName1, kMediaContentIndex1,
1216 candidate1);
1217 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
1218
1219 // Second audio candidate.
1220 cricket::Candidate candidate2;
1221 candidate2.set_address(rtc::SocketAddress("1.1.1.1", 5001));
1222 candidate2.set_component(1);
1223 candidate2.set_protocol("udp");
1224 candidate2.set_type("local");
1225 JsepIceCandidate ice_candidate2(kMediaContentName0, kMediaContentIndex0,
1226 candidate2);
1227 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
1228
1229 EXPECT_TRUE_WAIT(connection_with_remote_port(5000), 1000);
1230 EXPECT_TRUE_WAIT(connection_with_remote_port(5001), 1000);
1231
1232 // No need here for a _WAIT check since we are checking that state hasn't
1233 // changed: if this is false we would be doing waits for nothing and if this
1234 // is true then there will be no messages processed anyways.
1235 EXPECT_FALSE(connection_with_remote_port(6000));
1236}
1237
1238// kBundlePolicyBalanced BUNDLE policy and answer contains BUNDLE.
1239TEST_F(WebRtcSessionTest, TestBalancedBundleInAnswer) {
1240 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyBalanced);
1241 SendAudioVideoStream1();
1242
1243 PeerConnectionInterface::RTCOfferAnswerOptions options;
1244 options.use_rtp_mux = true;
1245
1246 SessionDescriptionInterface* offer = CreateOffer(options);
1247 SetLocalDescriptionWithoutError(offer);
1248
1249 EXPECT_NE(session_->voice_rtp_transport_channel(),
1250 session_->video_rtp_transport_channel());
1251
1252 SendAudioVideoStream2();
1253 SessionDescriptionInterface* answer =
1254 CreateRemoteAnswer(session_->local_description());
1255 SetRemoteDescriptionWithoutError(answer);
1256
1257 EXPECT_EQ(session_->voice_rtp_transport_channel(),
1258 session_->video_rtp_transport_channel());
1259}
1260
1261// kBundlePolicyBalanced BUNDLE policy but no BUNDLE in the answer.
1262TEST_F(WebRtcSessionTest, TestBalancedNoBundleInAnswer) {
1263 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyBalanced);
1264 SendAudioVideoStream1();
1265
1266 PeerConnectionInterface::RTCOfferAnswerOptions options;
1267 options.use_rtp_mux = true;
1268
1269 SessionDescriptionInterface* offer = CreateOffer(options);
1270 SetLocalDescriptionWithoutError(offer);
1271
1272 EXPECT_NE(session_->voice_rtp_transport_channel(),
1273 session_->video_rtp_transport_channel());
1274
1275 SendAudioVideoStream2();
1276
1277 // Remove BUNDLE from the answer.
1278 std::unique_ptr<SessionDescriptionInterface> answer(
1279 CreateRemoteAnswer(session_->local_description()));
1280 cricket::SessionDescription* answer_copy = answer->description()->Copy();
1281 answer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
1282 JsepSessionDescription* modified_answer =
1283 new JsepSessionDescription(JsepSessionDescription::kAnswer);
1284 modified_answer->Initialize(answer_copy, "1", "1");
1285 SetRemoteDescriptionWithoutError(modified_answer); //
1286
1287 EXPECT_NE(session_->voice_rtp_transport_channel(),
1288 session_->video_rtp_transport_channel());
1289}
1290
1291// kBundlePolicyMaxBundle policy with BUNDLE in the answer.
1292TEST_F(WebRtcSessionTest, TestMaxBundleBundleInAnswer) {
1293 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle);
1294 SendAudioVideoStream1();
1295
1296 PeerConnectionInterface::RTCOfferAnswerOptions options;
1297 options.use_rtp_mux = true;
1298
1299 SessionDescriptionInterface* offer = CreateOffer(options);
1300 SetLocalDescriptionWithoutError(offer);
1301
1302 EXPECT_EQ(session_->voice_rtp_transport_channel(),
1303 session_->video_rtp_transport_channel());
1304
1305 SendAudioVideoStream2();
1306 SessionDescriptionInterface* answer =
1307 CreateRemoteAnswer(session_->local_description());
1308 SetRemoteDescriptionWithoutError(answer);
1309
1310 EXPECT_EQ(session_->voice_rtp_transport_channel(),
1311 session_->video_rtp_transport_channel());
1312}
1313
1314// kBundlePolicyMaxBundle policy with BUNDLE in the answer, but no
1315// audio content in the answer.
1316TEST_F(WebRtcSessionTest, TestMaxBundleRejectAudio) {
1317 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle);
1318 SendAudioVideoStream1();
1319
1320 PeerConnectionInterface::RTCOfferAnswerOptions options;
1321 options.use_rtp_mux = true;
1322
1323 SessionDescriptionInterface* offer = CreateOffer(options);
1324 SetLocalDescriptionWithoutError(offer);
1325
1326 EXPECT_EQ(session_->voice_rtp_transport_channel(),
1327 session_->video_rtp_transport_channel());
1328
1329 SendVideoOnlyStream2();
1330 local_send_audio_ = false;
1331 remote_recv_audio_ = false;
1332 cricket::MediaSessionOptions recv_options;
1333 GetOptionsForRemoteAnswer(&recv_options);
1334 SessionDescriptionInterface* answer =
1335 CreateRemoteAnswer(session_->local_description(), recv_options);
1336 SetRemoteDescriptionWithoutError(answer);
1337
1338 EXPECT_TRUE(nullptr == session_->voice_channel());
1339 EXPECT_TRUE(nullptr != session_->video_rtp_transport_channel());
1340
1341 session_->Close();
1342 EXPECT_TRUE(nullptr == session_->voice_rtp_transport_channel());
1343 EXPECT_TRUE(nullptr == session_->voice_rtcp_transport_channel());
1344 EXPECT_TRUE(nullptr == session_->video_rtp_transport_channel());
1345 EXPECT_TRUE(nullptr == session_->video_rtcp_transport_channel());
1346}
1347
1348// kBundlePolicyMaxBundle policy but no BUNDLE in the answer.
1349TEST_F(WebRtcSessionTest, TestMaxBundleNoBundleInAnswer) {
1350 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle);
1351 SendAudioVideoStream1();
1352
1353 PeerConnectionInterface::RTCOfferAnswerOptions options;
1354 options.use_rtp_mux = true;
1355
1356 SessionDescriptionInterface* offer = CreateOffer(options);
1357 SetLocalDescriptionWithoutError(offer);
1358
1359 EXPECT_EQ(session_->voice_rtp_transport_channel(),
1360 session_->video_rtp_transport_channel());
1361
1362 SendAudioVideoStream2();
1363
1364 // Remove BUNDLE from the answer.
1365 std::unique_ptr<SessionDescriptionInterface> answer(
1366 CreateRemoteAnswer(session_->local_description()));
1367 cricket::SessionDescription* answer_copy = answer->description()->Copy();
1368 answer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
1369 JsepSessionDescription* modified_answer =
1370 new JsepSessionDescription(JsepSessionDescription::kAnswer);
1371 modified_answer->Initialize(answer_copy, "1", "1");
1372 SetRemoteDescriptionWithoutError(modified_answer);
1373
1374 EXPECT_EQ(session_->voice_rtp_transport_channel(),
1375 session_->video_rtp_transport_channel());
1376}
1377
1378// kBundlePolicyMaxBundle policy with BUNDLE in the remote offer.
1379TEST_F(WebRtcSessionTest, TestMaxBundleBundleInRemoteOffer) {
1380 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle);
1381 SendAudioVideoStream1();
1382
1383 SessionDescriptionInterface* offer = CreateRemoteOffer();
1384 SetRemoteDescriptionWithoutError(offer);
1385
1386 EXPECT_EQ(session_->voice_rtp_transport_channel(),
1387 session_->video_rtp_transport_channel());
1388
1389 SendAudioVideoStream2();
1390 SessionDescriptionInterface* answer = CreateAnswer();
1391 SetLocalDescriptionWithoutError(answer);
1392
1393 EXPECT_EQ(session_->voice_rtp_transport_channel(),
1394 session_->video_rtp_transport_channel());
1395}
1396
1397// kBundlePolicyMaxBundle policy but no BUNDLE in the remote offer.
1398TEST_F(WebRtcSessionTest, TestMaxBundleNoBundleInRemoteOffer) {
1399 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle);
1400 SendAudioVideoStream1();
1401
1402 // Remove BUNDLE from the offer.
1403 std::unique_ptr<SessionDescriptionInterface> offer(CreateRemoteOffer());
1404 cricket::SessionDescription* offer_copy = offer->description()->Copy();
1405 offer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
1406 JsepSessionDescription* modified_offer =
1407 new JsepSessionDescription(JsepSessionDescription::kOffer);
1408 modified_offer->Initialize(offer_copy, "1", "1");
1409
1410 // Expect an error when applying the remote description
1411 SetRemoteDescriptionExpectError(JsepSessionDescription::kOffer,
1412 kCreateChannelFailed, modified_offer);
1413}
1414
1415// kBundlePolicyMaxCompat bundle policy and answer contains BUNDLE.
1416TEST_F(WebRtcSessionTest, TestMaxCompatBundleInAnswer) {
1417 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxCompat);
1418 SendAudioVideoStream1();
1419
1420 PeerConnectionInterface::RTCOfferAnswerOptions rtc_options;
1421 rtc_options.use_rtp_mux = true;
1422
1423 SessionDescriptionInterface* offer = CreateOffer(rtc_options);
1424 SetLocalDescriptionWithoutError(offer);
1425
1426 EXPECT_NE(session_->voice_rtp_transport_channel(),
1427 session_->video_rtp_transport_channel());
1428
1429 SendAudioVideoStream2();
1430 SessionDescriptionInterface* answer =
1431 CreateRemoteAnswer(session_->local_description());
1432 SetRemoteDescriptionWithoutError(answer);
1433
1434 // This should lead to an audio-only call but isn't implemented
1435 // correctly yet.
1436 EXPECT_EQ(session_->voice_rtp_transport_channel(),
1437 session_->video_rtp_transport_channel());
1438}
1439
1440// kBundlePolicyMaxCompat BUNDLE policy but no BUNDLE in the answer.
1441TEST_F(WebRtcSessionTest, TestMaxCompatNoBundleInAnswer) {
1442 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxCompat);
1443 SendAudioVideoStream1();
1444 PeerConnectionInterface::RTCOfferAnswerOptions options;
1445 options.use_rtp_mux = true;
1446
1447 SessionDescriptionInterface* offer = CreateOffer(options);
1448 SetLocalDescriptionWithoutError(offer);
1449
1450 EXPECT_NE(session_->voice_rtp_transport_channel(),
1451 session_->video_rtp_transport_channel());
1452
1453 SendAudioVideoStream2();
1454
1455 // Remove BUNDLE from the answer.
1456 std::unique_ptr<SessionDescriptionInterface> answer(
1457 CreateRemoteAnswer(session_->local_description()));
1458 cricket::SessionDescription* answer_copy = answer->description()->Copy();
1459 answer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
1460 JsepSessionDescription* modified_answer =
1461 new JsepSessionDescription(JsepSessionDescription::kAnswer);
1462 modified_answer->Initialize(answer_copy, "1", "1");
1463 SetRemoteDescriptionWithoutError(modified_answer); //
1464
1465 EXPECT_NE(session_->voice_rtp_transport_channel(),
1466 session_->video_rtp_transport_channel());
1467}
1468
1469// kBundlePolicyMaxbundle and then we call SetRemoteDescription first.
1470TEST_F(WebRtcSessionTest, TestMaxBundleWithSetRemoteDescriptionFirst) {
1471 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle);
1472 SendAudioVideoStream1();
1473
1474 PeerConnectionInterface::RTCOfferAnswerOptions options;
1475 options.use_rtp_mux = true;
1476
1477 SessionDescriptionInterface* offer = CreateOffer(options);
1478 SetRemoteDescriptionWithoutError(offer);
1479
1480 EXPECT_EQ(session_->voice_rtp_transport_channel(),
1481 session_->video_rtp_transport_channel());
1482}
1483
1484// Adding a new channel to a BUNDLE which is already connected should directly
1485// assign the bundle transport to the channel, without first setting a
1486// disconnected non-bundle transport and then replacing it. The application
1487// should not receive any changes in the ICE state.
1488TEST_F(WebRtcSessionTest, TestAddChannelToConnectedBundle) {
1489 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
1490 // Both BUNDLE and RTCP-mux need to be enabled for the ICE state to remain
1491 // connected. Disabling either of these two means that we need to wait for the
1492 // answer to find out if more transports are needed.
1493 configuration_.bundle_policy =
1494 PeerConnectionInterface::kBundlePolicyMaxBundle;
1495 options_.disable_encryption = true;
1496 InitWithRtcpMuxPolicy(PeerConnectionInterface::kRtcpMuxPolicyRequire);
1497
1498 // Negotiate an audio channel with MAX_BUNDLE enabled.
1499 SendAudioOnlyStream2();
1500 SessionDescriptionInterface* offer = CreateOffer();
1501 SetLocalDescriptionWithoutError(offer);
1502 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringComplete,
1503 observer_.ice_gathering_state_, kIceCandidatesTimeout);
1504 std::string sdp;
1505 offer->ToString(&sdp);
1506 SessionDescriptionInterface* answer = webrtc::CreateSessionDescription(
1507 JsepSessionDescription::kAnswer, sdp, nullptr);
1508 ASSERT_TRUE(answer != NULL);
1509 SetRemoteDescriptionWithoutError(answer);
1510
1511 // Wait for the ICE state to stabilize.
1512 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
1513 observer_.ice_connection_state_, kIceCandidatesTimeout);
1514 observer_.ice_connection_state_history_.clear();
1515
1516 // Now add a video channel which should be using the same bundle transport.
1517 SendAudioVideoStream2();
1518 offer = CreateOffer();
1519 offer->ToString(&sdp);
1520 SetLocalDescriptionWithoutError(offer);
1521 answer = webrtc::CreateSessionDescription(JsepSessionDescription::kAnswer,
1522 sdp, nullptr);
1523 ASSERT_TRUE(answer != NULL);
1524 SetRemoteDescriptionWithoutError(answer);
1525
1526 // Wait for ICE state to stabilize
1527 rtc::Thread::Current()->ProcessMessages(0);
1528 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
1529 observer_.ice_connection_state_, kIceCandidatesTimeout);
1530
1531 // No ICE state changes are expected to happen.
1532 EXPECT_EQ(0, observer_.ice_connection_state_history_.size());
1533}
1534
1535TEST_F(WebRtcSessionTest, TestRequireRtcpMux) {
1536 InitWithRtcpMuxPolicy(PeerConnectionInterface::kRtcpMuxPolicyRequire);
1537 SendAudioVideoStream1();
1538
1539 PeerConnectionInterface::RTCOfferAnswerOptions options;
1540 SessionDescriptionInterface* offer = CreateOffer(options);
1541 SetLocalDescriptionWithoutError(offer);
1542
1543 EXPECT_TRUE(session_->voice_rtcp_transport_channel() == NULL);
1544 EXPECT_TRUE(session_->video_rtcp_transport_channel() == NULL);
1545
1546 SendAudioVideoStream2();
1547 SessionDescriptionInterface* answer =
1548 CreateRemoteAnswer(session_->local_description());
1549 SetRemoteDescriptionWithoutError(answer);
1550
1551 EXPECT_TRUE(session_->voice_rtcp_transport_channel() == NULL);
1552 EXPECT_TRUE(session_->video_rtcp_transport_channel() == NULL);
1553}
1554
1555TEST_F(WebRtcSessionTest, TestNegotiateRtcpMux) {
1556 InitWithRtcpMuxPolicy(PeerConnectionInterface::kRtcpMuxPolicyNegotiate);
1557 SendAudioVideoStream1();
1558
1559 PeerConnectionInterface::RTCOfferAnswerOptions options;
1560 SessionDescriptionInterface* offer = CreateOffer(options);
1561 SetLocalDescriptionWithoutError(offer);
1562
1563 EXPECT_TRUE(session_->voice_rtcp_transport_channel() != NULL);
1564 EXPECT_TRUE(session_->video_rtcp_transport_channel() != NULL);
1565
1566 SendAudioVideoStream2();
1567 SessionDescriptionInterface* answer =
1568 CreateRemoteAnswer(session_->local_description());
1569 SetRemoteDescriptionWithoutError(answer);
1570
1571 EXPECT_TRUE(session_->voice_rtcp_transport_channel() == NULL);
1572 EXPECT_TRUE(session_->video_rtcp_transport_channel() == NULL);
1573}
1574
1575// This test verifies that SetLocalDescription and SetRemoteDescription fails
1576// if BUNDLE is enabled but rtcp-mux is disabled in m-lines.
1577TEST_F(WebRtcSessionTest, TestDisabledRtcpMuxWithBundleEnabled) {
1578 Init();
1579 SendAudioVideoStream1();
1580
1581 PeerConnectionInterface::RTCOfferAnswerOptions options;
1582 options.use_rtp_mux = true;
1583
1584 SessionDescriptionInterface* offer = CreateOffer(options);
1585 std::string offer_str;
1586 offer->ToString(&offer_str);
1587 // Disable rtcp-mux
1588 const std::string rtcp_mux = "rtcp-mux";
1589 const std::string xrtcp_mux = "xrtcp-mux";
1590 rtc::replace_substrs(rtcp_mux.c_str(), rtcp_mux.length(),
1591 xrtcp_mux.c_str(), xrtcp_mux.length(),
1592 &offer_str);
1593 SessionDescriptionInterface* local_offer = CreateSessionDescription(
1594 SessionDescriptionInterface::kOffer, offer_str, nullptr);
1595 ASSERT_TRUE(local_offer);
1596 SetLocalDescriptionOfferExpectError(kBundleWithoutRtcpMux, local_offer);
1597
1598 SessionDescriptionInterface* remote_offer = CreateSessionDescription(
1599 SessionDescriptionInterface::kOffer, offer_str, nullptr);
1600 ASSERT_TRUE(remote_offer);
1601 SetRemoteDescriptionOfferExpectError(kBundleWithoutRtcpMux, remote_offer);
1602
1603 // Trying unmodified SDP.
1604 SetLocalDescriptionWithoutError(offer);
1605}
1606
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001607TEST_F(WebRtcSessionTest, TestRtpDataChannel) {
htaa2a49d92016-03-04 02:51:39 -08001608 configuration_.enable_rtp_data_channel = true;
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001609 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001610 SetLocalDescriptionWithDataChannel();
htaa2a49d92016-03-04 02:51:39 -08001611 ASSERT_TRUE(data_engine_);
deadbeef953c2ce2017-01-09 14:53:41 -08001612 EXPECT_NE(nullptr, data_engine_->GetChannel(0));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001613}
1614
Henrik Boström87713d02015-08-25 09:53:21 +02001615TEST_P(WebRtcSessionTest, TestRtpDataChannelConstraintTakesPrecedence) {
htaa2a49d92016-03-04 02:51:39 -08001616 configuration_.enable_rtp_data_channel = true;
wu@webrtc.org97077a32013-10-25 21:18:33 +00001617 options_.disable_sctp_data_channels = false;
1618
Henrik Boström87713d02015-08-25 09:53:21 +02001619 InitWithDtls(GetParam());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001620
1621 SetLocalDescriptionWithDataChannel();
deadbeef953c2ce2017-01-09 14:53:41 -08001622 EXPECT_NE(nullptr, data_engine_->GetChannel(0));
1623}
1624
1625// Test that sctp_content_name/sctp_transport_name (used for stats) are correct
1626// before and after BUNDLE is negotiated.
1627TEST_P(WebRtcSessionTest, SctpContentAndTransportName) {
deadbeef953c2ce2017-01-09 14:53:41 -08001628 SetFactoryDtlsSrtp();
1629 InitWithDtls(GetParam());
1630
1631 // Initially these fields should be empty.
1632 EXPECT_FALSE(session_->sctp_content_name());
1633 EXPECT_FALSE(session_->sctp_transport_name());
1634
1635 // Create offer with audio/video/data.
1636 // Default bundle policy is "balanced", so data should be using its own
1637 // transport.
1638 SendAudioVideoStream1();
1639 CreateDataChannel();
1640 InitiateCall();
1641 ASSERT_TRUE(session_->sctp_content_name());
1642 ASSERT_TRUE(session_->sctp_transport_name());
1643 EXPECT_EQ("data", *session_->sctp_content_name());
1644 EXPECT_EQ("data", *session_->sctp_transport_name());
1645
1646 // Create answer that finishes BUNDLE negotiation, which means everything
1647 // should be bundled on the first transport (audio).
1648 cricket::MediaSessionOptions answer_options;
deadbeef953c2ce2017-01-09 14:53:41 -08001649 answer_options.bundle_enabled = true;
1650 answer_options.data_channel_type = cricket::DCT_SCTP;
zhihuang1c378ed2017-08-17 14:10:50 -07001651 GetOptionsForAnswer(&answer_options);
deadbeef953c2ce2017-01-09 14:53:41 -08001652 SetRemoteDescriptionWithoutError(CreateRemoteAnswer(
1653 session_->local_description(), answer_options, cricket::SEC_DISABLED));
1654 ASSERT_TRUE(session_->sctp_content_name());
1655 ASSERT_TRUE(session_->sctp_transport_name());
1656 EXPECT_EQ("data", *session_->sctp_content_name());
1657 EXPECT_EQ("audio", *session_->sctp_transport_name());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001658}
1659
Henrik Boström87713d02015-08-25 09:53:21 +02001660TEST_P(WebRtcSessionTest, TestCreateOfferWithSctpEnabledWithoutStreams) {
Henrik Boström87713d02015-08-25 09:53:21 +02001661 InitWithDtls(GetParam());
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00001662
kwibergd1fe2812016-04-27 06:47:29 -07001663 std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer());
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00001664 EXPECT_TRUE(offer->description()->GetContentByName("data") == NULL);
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00001665 EXPECT_TRUE(offer->description()->GetTransportInfoByName("data") == NULL);
1666}
1667
Henrik Boström87713d02015-08-25 09:53:21 +02001668TEST_P(WebRtcSessionTest, TestCreateAnswerWithSctpInOfferAndNoStreams) {
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00001669 SetFactoryDtlsSrtp();
Henrik Boström87713d02015-08-25 09:53:21 +02001670 InitWithDtls(GetParam());
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00001671
1672 // Create remote offer with SCTP.
1673 cricket::MediaSessionOptions options;
1674 options.data_channel_type = cricket::DCT_SCTP;
zhihuang1c378ed2017-08-17 14:10:50 -07001675 GetOptionsForRemoteOffer(&options);
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00001676 JsepSessionDescription* offer =
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001677 CreateRemoteOffer(options, cricket::SEC_DISABLED);
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00001678 SetRemoteDescriptionWithoutError(offer);
1679
1680 // Verifies the answer contains SCTP.
kwibergd1fe2812016-04-27 06:47:29 -07001681 std::unique_ptr<SessionDescriptionInterface> answer(CreateAnswer());
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00001682 EXPECT_TRUE(answer != NULL);
1683 EXPECT_TRUE(answer->description()->GetContentByName("data") != NULL);
1684 EXPECT_TRUE(answer->description()->GetTransportInfoByName("data") != NULL);
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00001685}
1686
deadbeef953c2ce2017-01-09 14:53:41 -08001687// Test that if DTLS is disabled, we don't end up with an SctpTransport
1688// created (or an RtpDataChannel).
Henrik Boström87713d02015-08-25 09:53:21 +02001689TEST_P(WebRtcSessionTest, TestSctpDataChannelWithoutDtls) {
htaa2a49d92016-03-04 02:51:39 -08001690 configuration_.enable_dtls_srtp = rtc::Optional<bool>(false);
Henrik Boström87713d02015-08-25 09:53:21 +02001691 InitWithDtls(GetParam());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001692
1693 SetLocalDescriptionWithDataChannel();
deadbeef953c2ce2017-01-09 14:53:41 -08001694 EXPECT_EQ(nullptr, data_engine_->GetChannel(0));
1695 EXPECT_EQ(nullptr, fake_sctp_transport_factory_->last_fake_sctp_transport());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001696}
1697
deadbeef953c2ce2017-01-09 14:53:41 -08001698// Test that if DTLS is enabled, we end up with an SctpTransport created
1699// (and not an RtpDataChannel).
Henrik Boström87713d02015-08-25 09:53:21 +02001700TEST_P(WebRtcSessionTest, TestSctpDataChannelWithDtls) {
Henrik Boström87713d02015-08-25 09:53:21 +02001701 InitWithDtls(GetParam());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001702
1703 SetLocalDescriptionWithDataChannel();
deadbeef953c2ce2017-01-09 14:53:41 -08001704 EXPECT_EQ(nullptr, data_engine_->GetChannel(0));
1705 EXPECT_NE(nullptr, fake_sctp_transport_factory_->last_fake_sctp_transport());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001706}
wu@webrtc.org91053e72013-08-10 07:18:04 +00001707
deadbeef953c2ce2017-01-09 14:53:41 -08001708// Test that if SCTP is disabled, we don't end up with an SctpTransport
1709// created (or an RtpDataChannel).
Henrik Boström87713d02015-08-25 09:53:21 +02001710TEST_P(WebRtcSessionTest, TestDisableSctpDataChannels) {
wu@webrtc.org97077a32013-10-25 21:18:33 +00001711 options_.disable_sctp_data_channels = true;
Henrik Boström87713d02015-08-25 09:53:21 +02001712 InitWithDtls(GetParam());
wu@webrtc.org97077a32013-10-25 21:18:33 +00001713
1714 SetLocalDescriptionWithDataChannel();
deadbeef953c2ce2017-01-09 14:53:41 -08001715 EXPECT_EQ(nullptr, data_engine_->GetChannel(0));
1716 EXPECT_EQ(nullptr, fake_sctp_transport_factory_->last_fake_sctp_transport());
wu@webrtc.org97077a32013-10-25 21:18:33 +00001717}
1718
Henrik Boström87713d02015-08-25 09:53:21 +02001719TEST_P(WebRtcSessionTest, TestSctpDataChannelSendPortParsing) {
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001720 const int new_send_port = 9998;
1721 const int new_recv_port = 7775;
1722
Henrik Boström87713d02015-08-25 09:53:21 +02001723 InitWithDtls(GetParam());
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001724 SetFactoryDtlsSrtp();
1725
1726 // By default, don't actually add the codecs to desc_factory_; they don't
1727 // actually get serialized for SCTP in BuildMediaDescription(). Instead,
1728 // let the session description get parsed. That'll get the proper codecs
1729 // into the stream.
1730 cricket::MediaSessionOptions options;
Steve Anton6d64e9a2017-09-12 09:44:05 -07001731 SessionDescriptionInterface* offer =
1732 CreateRemoteOfferWithSctpPort("stream1", new_send_port, options);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001733
1734 // SetRemoteDescription will take the ownership of the offer.
1735 SetRemoteDescriptionWithoutError(offer);
1736
htaa2a49d92016-03-04 02:51:39 -08001737 SessionDescriptionInterface* answer =
1738 ChangeSDPSctpPort(new_recv_port, CreateAnswer());
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001739 ASSERT_TRUE(answer != NULL);
1740
1741 // Now set the local description, which'll take ownership of the answer.
1742 SetLocalDescriptionWithoutError(answer);
1743
1744 // TEST PLAN: Set the port number to something new, set it in the SDP,
1745 // and pass it all the way down.
deadbeef953c2ce2017-01-09 14:53:41 -08001746 EXPECT_EQ(nullptr, data_engine_->GetChannel(0));
deadbeefab9b2d12015-10-14 11:33:11 -07001747 CreateDataChannel();
deadbeef953c2ce2017-01-09 14:53:41 -08001748 ASSERT_NE(nullptr, fake_sctp_transport_factory_->last_fake_sctp_transport());
1749 EXPECT_EQ(
1750 new_recv_port,
1751 fake_sctp_transport_factory_->last_fake_sctp_transport()->local_port());
1752 EXPECT_EQ(
1753 new_send_port,
1754 fake_sctp_transport_factory_->last_fake_sctp_transport()->remote_port());
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001755}
1756
deadbeef953c2ce2017-01-09 14:53:41 -08001757// Verifies that when a session's SctpTransport receives an OPEN message,
1758// WebRtcSession signals the SctpTransport creation request with the expected
deadbeefab9b2d12015-10-14 11:33:11 -07001759// config.
1760TEST_P(WebRtcSessionTest, TestSctpDataChannelOpenMessage) {
deadbeefab9b2d12015-10-14 11:33:11 -07001761 InitWithDtls(GetParam());
1762
1763 SetLocalDescriptionWithDataChannel();
deadbeef953c2ce2017-01-09 14:53:41 -08001764 EXPECT_EQ(nullptr, data_engine_->GetChannel(0));
1765 ASSERT_NE(nullptr, fake_sctp_transport_factory_->last_fake_sctp_transport());
deadbeefab9b2d12015-10-14 11:33:11 -07001766
deadbeef953c2ce2017-01-09 14:53:41 -08001767 // Make the fake SCTP transport pretend it received an OPEN message.
deadbeefab9b2d12015-10-14 11:33:11 -07001768 webrtc::DataChannelInit config;
1769 config.id = 1;
jbaucheec21bd2016-03-20 06:15:43 -07001770 rtc::CopyOnWriteBuffer payload;
deadbeefab9b2d12015-10-14 11:33:11 -07001771 webrtc::WriteDataChannelOpenMessage("a", config, &payload);
1772 cricket::ReceiveDataParams params;
1773 params.ssrc = config.id;
1774 params.type = cricket::DMT_CONTROL;
deadbeef953c2ce2017-01-09 14:53:41 -08001775 fake_sctp_transport_factory_->last_fake_sctp_transport()->SignalDataReceived(
1776 params, payload);
deadbeefab9b2d12015-10-14 11:33:11 -07001777
deadbeef953c2ce2017-01-09 14:53:41 -08001778 EXPECT_EQ_WAIT("a", last_data_channel_label_, kDefaultTimeout);
deadbeefab9b2d12015-10-14 11:33:11 -07001779 EXPECT_EQ(config.id, last_data_channel_config_.id);
1780 EXPECT_FALSE(last_data_channel_config_.negotiated);
1781 EXPECT_EQ(webrtc::InternalDataChannelInit::kAcker,
1782 last_data_channel_config_.open_handshake_role);
1783}
1784
zhihuang9763d562016-08-05 11:14:50 -07001785#ifdef HAVE_QUIC
1786TEST_P(WebRtcSessionTest, TestNegotiateQuic) {
1787 configuration_.enable_quic = true;
1788 InitWithDtls(GetParam());
1789 EXPECT_TRUE(session_->data_channel_type() == cricket::DCT_QUIC);
1790 SessionDescriptionInterface* offer = CreateOffer();
1791 ASSERT_TRUE(offer);
1792 ASSERT_TRUE(offer->description());
1793 SetLocalDescriptionWithoutError(offer);
1794 cricket::MediaSessionOptions options;
zhihuang1c378ed2017-08-17 14:10:50 -07001795 GetOptionsForAnswer(&options);
zhihuang9763d562016-08-05 11:14:50 -07001796 SessionDescriptionInterface* answer =
1797 CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED);
1798 ASSERT_TRUE(answer);
1799 ASSERT_TRUE(answer->description());
1800 SetRemoteDescriptionWithoutError(answer);
1801}
1802#endif // HAVE_QUIC
1803
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00001804// This verifies that the voice channel after bundle has both options from video
1805// and voice channels.
1806TEST_F(WebRtcSessionTest, TestSetSocketOptionBeforeBundle) {
1807 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyBalanced);
deadbeefab9b2d12015-10-14 11:33:11 -07001808 SendAudioVideoStream1();
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00001809
1810 PeerConnectionInterface::RTCOfferAnswerOptions options;
1811 options.use_rtp_mux = true;
1812
1813 SessionDescriptionInterface* offer = CreateOffer(options);
1814 SetLocalDescriptionWithoutError(offer);
1815
1816 session_->video_channel()->SetOption(cricket::BaseChannel::ST_RTP,
1817 rtc::Socket::Option::OPT_SNDBUF, 4000);
1818
1819 session_->voice_channel()->SetOption(cricket::BaseChannel::ST_RTP,
1820 rtc::Socket::Option::OPT_RCVBUF, 8000);
1821
1822 int option_val;
deadbeefcbecd352015-09-23 11:50:27 -07001823 EXPECT_TRUE(session_->video_rtp_transport_channel()->GetOption(
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00001824 rtc::Socket::Option::OPT_SNDBUF, &option_val));
1825 EXPECT_EQ(4000, option_val);
deadbeefcbecd352015-09-23 11:50:27 -07001826 EXPECT_FALSE(session_->voice_rtp_transport_channel()->GetOption(
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00001827 rtc::Socket::Option::OPT_SNDBUF, &option_val));
1828
deadbeefcbecd352015-09-23 11:50:27 -07001829 EXPECT_TRUE(session_->voice_rtp_transport_channel()->GetOption(
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00001830 rtc::Socket::Option::OPT_RCVBUF, &option_val));
1831 EXPECT_EQ(8000, option_val);
deadbeefcbecd352015-09-23 11:50:27 -07001832 EXPECT_FALSE(session_->video_rtp_transport_channel()->GetOption(
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00001833 rtc::Socket::Option::OPT_RCVBUF, &option_val));
1834
deadbeefcbecd352015-09-23 11:50:27 -07001835 EXPECT_NE(session_->voice_rtp_transport_channel(),
1836 session_->video_rtp_transport_channel());
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00001837
deadbeefab9b2d12015-10-14 11:33:11 -07001838 SendAudioVideoStream2();
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00001839 SessionDescriptionInterface* answer =
1840 CreateRemoteAnswer(session_->local_description());
1841 SetRemoteDescriptionWithoutError(answer);
1842
deadbeefcbecd352015-09-23 11:50:27 -07001843 EXPECT_TRUE(session_->voice_rtp_transport_channel()->GetOption(
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00001844 rtc::Socket::Option::OPT_SNDBUF, &option_val));
1845 EXPECT_EQ(4000, option_val);
1846
deadbeefcbecd352015-09-23 11:50:27 -07001847 EXPECT_TRUE(session_->voice_rtp_transport_channel()->GetOption(
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00001848 rtc::Socket::Option::OPT_RCVBUF, &option_val));
1849 EXPECT_EQ(8000, option_val);
1850}
1851
stefanc1aeaf02015-10-15 07:26:07 -07001852TEST_F(WebRtcSessionTest, TestPacketOptionsAndOnPacketSent) {
1853 TestPacketOptions();
1854}
1855
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001856// TODO(bemasc): Add a TestIceStatesBundle with BUNDLE enabled. That test
1857// currently fails because upon disconnection and reconnection OnIceComplete is
1858// called more than once without returning to IceGatheringGathering.
Henrik Boström87713d02015-08-25 09:53:21 +02001859
deadbeefcbecd352015-09-23 11:50:27 -07001860INSTANTIATE_TEST_CASE_P(WebRtcSessionTests,
1861 WebRtcSessionTest,
1862 testing::Values(ALREADY_GENERATED,
1863 DTLS_IDENTITY_STORE));