blob: 13b54d995d11384f79cf5f0f385f4b527890a4bb [file] [log] [blame]
Steve Anton8d3444d2017-10-20 22:30:511/*
2 * Copyright 2017 The WebRTC project authors. All Rights Reserved.
3 *
4 * 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.
9 */
10
11// This file contains tests that check the PeerConnection's signaling state
12// machine, as well as tests that check basic, media-agnostic aspects of SDP.
13
Philipp Hancke64a79c72021-05-10 15:28:3714#include <algorithm>
Mirko Bonadei317a1f02019-09-17 15:06:1815#include <memory>
Steve Anton8d3444d2017-10-20 22:30:5116#include <tuple>
17
18#include "api/audio_codecs/builtin_audio_decoder_factory.h"
19#include "api/audio_codecs/builtin_audio_encoder_factory.h"
Mirko Bonadei2ff3f492018-11-22 08:00:1320#include "api/create_peerconnection_factory.h"
Philipp Hancke4e8c1152020-10-13 10:43:1521#include "api/jsep_session_description.h"
Anders Carlsson67537952018-05-03 09:28:2922#include "api/video_codecs/builtin_video_decoder_factory.h"
23#include "api/video_codecs/builtin_video_encoder_factory.h"
Steve Anton10542f22019-01-11 17:11:0024#include "pc/peer_connection.h"
Markus Handella1b82012021-05-26 16:56:3025#include "pc/peer_connection_proxy.h"
Steve Anton10542f22019-01-11 17:11:0026#include "pc/peer_connection_wrapper.h"
27#include "pc/sdp_utils.h"
Philipp Hancke4e8c1152020-10-13 10:43:1528#include "pc/webrtc_sdp.h"
Steve Anton8d3444d2017-10-20 22:30:5129#ifdef WEBRTC_ANDROID
Steve Anton10542f22019-01-11 17:11:0030#include "pc/test/android_test_initializer.h"
Steve Anton8d3444d2017-10-20 22:30:5131#endif
Steve Anton10542f22019-01-11 17:11:0032#include "pc/test/fake_audio_capture_module.h"
33#include "pc/test/fake_rtc_certificate_generator.h"
Steve Anton8d3444d2017-10-20 22:30:5134#include "rtc_base/gunit.h"
Steve Anton10542f22019-01-11 17:11:0035#include "rtc_base/virtual_socket_server.h"
Steve Anton8d3444d2017-10-20 22:30:5136#include "test/gmock.h"
37
38namespace webrtc {
39
40using SignalingState = PeerConnectionInterface::SignalingState;
41using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
42using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
43using ::testing::Bool;
44using ::testing::Combine;
45using ::testing::Values;
46
Henrik Boströma3728d32019-10-28 11:09:4947namespace {
48const int64_t kWaitTimeout = 10000;
49} // namespace
50
Steve Anton8d3444d2017-10-20 22:30:5151class PeerConnectionWrapperForSignalingTest : public PeerConnectionWrapper {
52 public:
53 using PeerConnectionWrapper::PeerConnectionWrapper;
54
55 bool initial_offerer() {
56 return GetInternalPeerConnection()->initial_offerer();
57 }
58
59 PeerConnection* GetInternalPeerConnection() {
Mirko Bonadeie97de912017-12-13 10:29:3460 auto* pci =
61 static_cast<PeerConnectionProxyWithInternal<PeerConnectionInterface>*>(
62 pc());
63 return static_cast<PeerConnection*>(pci->internal());
Steve Anton8d3444d2017-10-20 22:30:5164 }
65};
66
Henrik Boströma3728d32019-10-28 11:09:4967class ExecuteFunctionOnCreateSessionDescriptionObserver
68 : public CreateSessionDescriptionObserver {
69 public:
70 ExecuteFunctionOnCreateSessionDescriptionObserver(
71 std::function<void(SessionDescriptionInterface*)> function)
72 : function_(std::move(function)) {}
73 ~ExecuteFunctionOnCreateSessionDescriptionObserver() override {
74 RTC_DCHECK(was_called_);
75 }
76
77 bool was_called() const { return was_called_; }
78
79 void OnSuccess(SessionDescriptionInterface* desc) override {
80 RTC_DCHECK(!was_called_);
81 was_called_ = true;
82 function_(desc);
83 }
84
85 void OnFailure(RTCError error) override { RTC_NOTREACHED(); }
86
87 private:
88 bool was_called_ = false;
89 std::function<void(SessionDescriptionInterface*)> function_;
90};
91
Steve Anton8acdd1a2018-02-08 01:27:3692class PeerConnectionSignalingBaseTest : public ::testing::Test {
Steve Anton8d3444d2017-10-20 22:30:5193 protected:
94 typedef std::unique_ptr<PeerConnectionWrapperForSignalingTest> WrapperPtr;
95
Steve Anton8acdd1a2018-02-08 01:27:3696 explicit PeerConnectionSignalingBaseTest(SdpSemantics sdp_semantics)
97 : vss_(new rtc::VirtualSocketServer()),
98 main_(vss_.get()),
99 sdp_semantics_(sdp_semantics) {
Steve Anton8d3444d2017-10-20 22:30:51100#ifdef WEBRTC_ANDROID
101 InitializeAndroidObjects();
102#endif
103 pc_factory_ = CreatePeerConnectionFactory(
104 rtc::Thread::Current(), rtc::Thread::Current(), rtc::Thread::Current(),
Anders Carlsson67537952018-05-03 09:28:29105 rtc::scoped_refptr<AudioDeviceModule>(FakeAudioCaptureModule::Create()),
106 CreateBuiltinAudioEncoderFactory(), CreateBuiltinAudioDecoderFactory(),
107 CreateBuiltinVideoEncoderFactory(), CreateBuiltinVideoDecoderFactory(),
108 nullptr /* audio_mixer */, nullptr /* audio_processing */);
Steve Anton8d3444d2017-10-20 22:30:51109 }
110
111 WrapperPtr CreatePeerConnection() {
112 return CreatePeerConnection(RTCConfiguration());
113 }
114
115 WrapperPtr CreatePeerConnection(const RTCConfiguration& config) {
Mirko Bonadei317a1f02019-09-17 15:06:18116 auto observer = std::make_unique<MockPeerConnectionObserver>();
Steve Anton8acdd1a2018-02-08 01:27:36117 RTCConfiguration modified_config = config;
118 modified_config.sdp_semantics = sdp_semantics_;
119 auto pc = pc_factory_->CreatePeerConnection(modified_config, nullptr,
120 nullptr, observer.get());
Steve Anton8d3444d2017-10-20 22:30:51121 if (!pc) {
122 return nullptr;
123 }
124
Yves Gerey4e933292018-10-31 14:36:05125 observer->SetPeerConnectionInterface(pc.get());
Mirko Bonadei317a1f02019-09-17 15:06:18126 return std::make_unique<PeerConnectionWrapperForSignalingTest>(
Steve Anton8d3444d2017-10-20 22:30:51127 pc_factory_, pc, std::move(observer));
128 }
129
130 // Accepts the same arguments as CreatePeerConnection and adds default audio
131 // and video tracks.
132 template <typename... Args>
133 WrapperPtr CreatePeerConnectionWithAudioVideo(Args&&... args) {
134 auto wrapper = CreatePeerConnection(std::forward<Args>(args)...);
135 if (!wrapper) {
136 return nullptr;
137 }
138 wrapper->AddAudioTrack("a");
139 wrapper->AddVideoTrack("v");
140 return wrapper;
141 }
142
Harald Alvestrand4a7b3ac2019-01-17 09:39:40143 int NumberOfDtlsTransports(const WrapperPtr& pc_wrapper) {
144 std::set<DtlsTransportInterface*> transports;
145 auto transceivers = pc_wrapper->pc()->GetTransceivers();
146
147 for (auto& transceiver : transceivers) {
148 if (transceiver->sender()->dtls_transport()) {
149 EXPECT_TRUE(transceiver->receiver()->dtls_transport());
150 EXPECT_EQ(transceiver->sender()->dtls_transport().get(),
151 transceiver->receiver()->dtls_transport().get());
152 transports.insert(transceiver->sender()->dtls_transport().get());
153 } else {
154 // If one transceiver is missing, they all should be.
155 EXPECT_EQ(0UL, transports.size());
156 }
157 }
158 return transports.size();
159 }
160
161 bool HasDtlsTransport(const WrapperPtr& pc_wrapper) {
162 return NumberOfDtlsTransports(pc_wrapper) > 0;
163 }
164
Steve Anton8d3444d2017-10-20 22:30:51165 std::unique_ptr<rtc::VirtualSocketServer> vss_;
166 rtc::AutoSocketServerThread main_;
167 rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_;
Steve Anton8acdd1a2018-02-08 01:27:36168 const SdpSemantics sdp_semantics_;
Steve Anton8d3444d2017-10-20 22:30:51169};
170
Steve Anton8acdd1a2018-02-08 01:27:36171class PeerConnectionSignalingTest
172 : public PeerConnectionSignalingBaseTest,
173 public ::testing::WithParamInterface<SdpSemantics> {
174 protected:
175 PeerConnectionSignalingTest() : PeerConnectionSignalingBaseTest(GetParam()) {}
176};
177
178TEST_P(PeerConnectionSignalingTest, SetLocalOfferTwiceWorks) {
Steve Anton8d3444d2017-10-20 22:30:51179 auto caller = CreatePeerConnection();
180
181 EXPECT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
182 EXPECT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
183}
184
Steve Anton8acdd1a2018-02-08 01:27:36185TEST_P(PeerConnectionSignalingTest, SetRemoteOfferTwiceWorks) {
Steve Anton8d3444d2017-10-20 22:30:51186 auto caller = CreatePeerConnection();
187 auto callee = CreatePeerConnection();
188
189 EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
190 EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
191}
192
Steve Anton8acdd1a2018-02-08 01:27:36193TEST_P(PeerConnectionSignalingTest, FailToSetNullLocalDescription) {
Steve Anton8d3444d2017-10-20 22:30:51194 auto caller = CreatePeerConnection();
195 std::string error;
196 ASSERT_FALSE(caller->SetLocalDescription(nullptr, &error));
197 EXPECT_EQ("SessionDescription is NULL.", error);
198}
199
Steve Anton8acdd1a2018-02-08 01:27:36200TEST_P(PeerConnectionSignalingTest, FailToSetNullRemoteDescription) {
Steve Anton8d3444d2017-10-20 22:30:51201 auto caller = CreatePeerConnection();
202 std::string error;
203 ASSERT_FALSE(caller->SetRemoteDescription(nullptr, &error));
204 EXPECT_EQ("SessionDescription is NULL.", error);
205}
206
207// The following parameterized test verifies that calls to various signaling
208// methods on PeerConnection will succeed/fail depending on what is the
209// PeerConnection's signaling state. Note that the test tries many different
210// forms of SignalingState::kClosed by arriving at a valid state then calling
Artem Titov880fa812021-07-30 20:30:23211// `Close()`. This is intended to catch cases where the PeerConnection signaling
Steve Anton8d3444d2017-10-20 22:30:51212// method ignores the closed flag but may work/not work because of the single
213// state the PeerConnection was created in before it was closed.
214
215class PeerConnectionSignalingStateTest
Steve Anton8acdd1a2018-02-08 01:27:36216 : public PeerConnectionSignalingBaseTest,
217 public ::testing::WithParamInterface<
218 std::tuple<SdpSemantics, SignalingState, bool>> {
Steve Anton8d3444d2017-10-20 22:30:51219 protected:
Steve Anton8acdd1a2018-02-08 01:27:36220 PeerConnectionSignalingStateTest()
221 : PeerConnectionSignalingBaseTest(std::get<0>(GetParam())),
222 state_under_test_(std::make_tuple(std::get<1>(GetParam()),
223 std::get<2>(GetParam()))) {}
224
Steve Anton8d3444d2017-10-20 22:30:51225 RTCConfiguration GetConfig() {
226 RTCConfiguration config;
227 config.certificates.push_back(
228 FakeRTCCertificateGenerator::GenerateCertificate());
229 return config;
230 }
231
Steve Anton8acdd1a2018-02-08 01:27:36232 WrapperPtr CreatePeerConnectionUnderTest() {
233 return CreatePeerConnectionInState(state_under_test_);
234 }
235
Steve Anton8d3444d2017-10-20 22:30:51236 WrapperPtr CreatePeerConnectionInState(SignalingState state) {
237 return CreatePeerConnectionInState(std::make_tuple(state, false));
238 }
239
240 WrapperPtr CreatePeerConnectionInState(
241 std::tuple<SignalingState, bool> state_tuple) {
242 SignalingState state = std::get<0>(state_tuple);
243 bool closed = std::get<1>(state_tuple);
244
245 auto wrapper = CreatePeerConnectionWithAudioVideo(GetConfig());
246 switch (state) {
247 case SignalingState::kStable: {
248 break;
249 }
250 case SignalingState::kHaveLocalOffer: {
251 wrapper->SetLocalDescription(wrapper->CreateOffer());
252 break;
253 }
254 case SignalingState::kHaveLocalPrAnswer: {
255 auto caller = CreatePeerConnectionWithAudioVideo(GetConfig());
256 wrapper->SetRemoteDescription(caller->CreateOffer());
257 auto answer = wrapper->CreateAnswer();
Steve Antona3a92c22017-12-07 18:27:41258 wrapper->SetLocalDescription(
259 CloneSessionDescriptionAsType(answer.get(), SdpType::kPrAnswer));
Steve Anton8d3444d2017-10-20 22:30:51260 break;
261 }
262 case SignalingState::kHaveRemoteOffer: {
263 auto caller = CreatePeerConnectionWithAudioVideo(GetConfig());
264 wrapper->SetRemoteDescription(caller->CreateOffer());
265 break;
266 }
267 case SignalingState::kHaveRemotePrAnswer: {
268 auto callee = CreatePeerConnectionWithAudioVideo(GetConfig());
269 callee->SetRemoteDescription(wrapper->CreateOfferAndSetAsLocal());
270 auto answer = callee->CreateAnswer();
Steve Antona3a92c22017-12-07 18:27:41271 wrapper->SetRemoteDescription(
272 CloneSessionDescriptionAsType(answer.get(), SdpType::kPrAnswer));
Steve Anton8d3444d2017-10-20 22:30:51273 break;
274 }
275 case SignalingState::kClosed: {
276 RTC_NOTREACHED() << "Set the second member of the tuple to true to "
277 "achieve a closed state from an existing, valid "
278 "state.";
279 }
280 }
281
282 RTC_DCHECK_EQ(state, wrapper->pc()->signaling_state());
283
284 if (closed) {
285 wrapper->pc()->Close();
286 RTC_DCHECK_EQ(SignalingState::kClosed, wrapper->signaling_state());
287 }
288
289 return wrapper;
290 }
Steve Anton8acdd1a2018-02-08 01:27:36291
292 std::tuple<SignalingState, bool> state_under_test_;
Steve Anton8d3444d2017-10-20 22:30:51293};
294
Steve Anton8d3444d2017-10-20 22:30:51295TEST_P(PeerConnectionSignalingStateTest, CreateOffer) {
Steve Anton8acdd1a2018-02-08 01:27:36296 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 22:30:51297 if (wrapper->signaling_state() != SignalingState::kClosed) {
298 EXPECT_TRUE(wrapper->CreateOffer());
299 } else {
300 std::string error;
301 ASSERT_FALSE(wrapper->CreateOffer(RTCOfferAnswerOptions(), &error));
302 EXPECT_PRED_FORMAT2(AssertStartsWith, error,
303 "CreateOffer called when PeerConnection is closed.");
304 }
305}
306
307TEST_P(PeerConnectionSignalingStateTest, CreateAnswer) {
Steve Anton8acdd1a2018-02-08 01:27:36308 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 22:30:51309 if (wrapper->signaling_state() == SignalingState::kHaveLocalPrAnswer ||
310 wrapper->signaling_state() == SignalingState::kHaveRemoteOffer) {
311 EXPECT_TRUE(wrapper->CreateAnswer());
312 } else {
313 std::string error;
314 ASSERT_FALSE(wrapper->CreateAnswer(RTCOfferAnswerOptions(), &error));
Steve Antondffead82018-02-06 18:31:29315 EXPECT_EQ(error,
316 "PeerConnection cannot create an answer in a state other than "
317 "have-remote-offer or have-local-pranswer.");
Steve Anton8d3444d2017-10-20 22:30:51318 }
319}
320
321TEST_P(PeerConnectionSignalingStateTest, SetLocalOffer) {
Steve Anton8acdd1a2018-02-08 01:27:36322 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 22:30:51323 if (wrapper->signaling_state() == SignalingState::kStable ||
324 wrapper->signaling_state() == SignalingState::kHaveLocalOffer) {
325 // Need to call CreateOffer on the PeerConnection under test, otherwise when
326 // setting the local offer it will want to verify the DTLS fingerprint
327 // against the locally generated certificate, but without a call to
328 // CreateOffer the certificate will never be generated.
329 EXPECT_TRUE(wrapper->SetLocalDescription(wrapper->CreateOffer()));
330 } else {
331 auto wrapper_for_offer =
332 CreatePeerConnectionInState(SignalingState::kHaveLocalOffer);
333 auto offer =
334 CloneSessionDescription(wrapper_for_offer->pc()->local_description());
335
336 std::string error;
337 ASSERT_FALSE(wrapper->SetLocalDescription(std::move(offer), &error));
338 EXPECT_PRED_FORMAT2(
339 AssertStartsWith, error,
340 "Failed to set local offer sdp: Called in wrong state:");
341 }
342}
343
344TEST_P(PeerConnectionSignalingStateTest, SetLocalPrAnswer) {
345 auto wrapper_for_pranswer =
346 CreatePeerConnectionInState(SignalingState::kHaveLocalPrAnswer);
347 auto pranswer =
348 CloneSessionDescription(wrapper_for_pranswer->pc()->local_description());
349
Steve Anton8acdd1a2018-02-08 01:27:36350 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 22:30:51351 if (wrapper->signaling_state() == SignalingState::kHaveLocalPrAnswer ||
352 wrapper->signaling_state() == SignalingState::kHaveRemoteOffer) {
353 EXPECT_TRUE(wrapper->SetLocalDescription(std::move(pranswer)));
354 } else {
355 std::string error;
356 ASSERT_FALSE(wrapper->SetLocalDescription(std::move(pranswer), &error));
357 EXPECT_PRED_FORMAT2(
358 AssertStartsWith, error,
359 "Failed to set local pranswer sdp: Called in wrong state:");
360 }
361}
362
363TEST_P(PeerConnectionSignalingStateTest, SetLocalAnswer) {
364 auto wrapper_for_answer =
365 CreatePeerConnectionInState(SignalingState::kHaveRemoteOffer);
366 auto answer = wrapper_for_answer->CreateAnswer();
367
Steve Anton8acdd1a2018-02-08 01:27:36368 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 22:30:51369 if (wrapper->signaling_state() == SignalingState::kHaveLocalPrAnswer ||
370 wrapper->signaling_state() == SignalingState::kHaveRemoteOffer) {
371 EXPECT_TRUE(wrapper->SetLocalDescription(std::move(answer)));
372 } else {
373 std::string error;
374 ASSERT_FALSE(wrapper->SetLocalDescription(std::move(answer), &error));
375 EXPECT_PRED_FORMAT2(
376 AssertStartsWith, error,
377 "Failed to set local answer sdp: Called in wrong state:");
378 }
379}
380
381TEST_P(PeerConnectionSignalingStateTest, SetRemoteOffer) {
382 auto wrapper_for_offer =
383 CreatePeerConnectionInState(SignalingState::kHaveRemoteOffer);
384 auto offer =
385 CloneSessionDescription(wrapper_for_offer->pc()->remote_description());
386
Steve Anton8acdd1a2018-02-08 01:27:36387 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 22:30:51388 if (wrapper->signaling_state() == SignalingState::kStable ||
389 wrapper->signaling_state() == SignalingState::kHaveRemoteOffer) {
390 EXPECT_TRUE(wrapper->SetRemoteDescription(std::move(offer)));
391 } else {
392 std::string error;
393 ASSERT_FALSE(wrapper->SetRemoteDescription(std::move(offer), &error));
394 EXPECT_PRED_FORMAT2(
395 AssertStartsWith, error,
396 "Failed to set remote offer sdp: Called in wrong state:");
397 }
398}
399
400TEST_P(PeerConnectionSignalingStateTest, SetRemotePrAnswer) {
401 auto wrapper_for_pranswer =
402 CreatePeerConnectionInState(SignalingState::kHaveRemotePrAnswer);
403 auto pranswer =
404 CloneSessionDescription(wrapper_for_pranswer->pc()->remote_description());
405
Steve Anton8acdd1a2018-02-08 01:27:36406 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 22:30:51407 if (wrapper->signaling_state() == SignalingState::kHaveLocalOffer ||
408 wrapper->signaling_state() == SignalingState::kHaveRemotePrAnswer) {
409 EXPECT_TRUE(wrapper->SetRemoteDescription(std::move(pranswer)));
410 } else {
411 std::string error;
412 ASSERT_FALSE(wrapper->SetRemoteDescription(std::move(pranswer), &error));
413 EXPECT_PRED_FORMAT2(
414 AssertStartsWith, error,
415 "Failed to set remote pranswer sdp: Called in wrong state:");
416 }
417}
418
419TEST_P(PeerConnectionSignalingStateTest, SetRemoteAnswer) {
420 auto wrapper_for_answer =
421 CreatePeerConnectionInState(SignalingState::kHaveRemoteOffer);
422 auto answer = wrapper_for_answer->CreateAnswer();
423
Steve Anton8acdd1a2018-02-08 01:27:36424 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 22:30:51425 if (wrapper->signaling_state() == SignalingState::kHaveLocalOffer ||
426 wrapper->signaling_state() == SignalingState::kHaveRemotePrAnswer) {
427 EXPECT_TRUE(wrapper->SetRemoteDescription(std::move(answer)));
428 } else {
429 std::string error;
430 ASSERT_FALSE(wrapper->SetRemoteDescription(std::move(answer), &error));
431 EXPECT_PRED_FORMAT2(
432 AssertStartsWith, error,
433 "Failed to set remote answer sdp: Called in wrong state:");
434 }
435}
436
Mirko Bonadeic84f6612019-01-31 11:20:57437INSTANTIATE_TEST_SUITE_P(PeerConnectionSignalingTest,
438 PeerConnectionSignalingStateTest,
439 Combine(Values(SdpSemantics::kPlanB,
440 SdpSemantics::kUnifiedPlan),
441 Values(SignalingState::kStable,
442 SignalingState::kHaveLocalOffer,
443 SignalingState::kHaveLocalPrAnswer,
444 SignalingState::kHaveRemoteOffer,
445 SignalingState::kHaveRemotePrAnswer),
446 Bool()));
Steve Anton8d3444d2017-10-20 22:30:51447
Steve Antondffead82018-02-06 18:31:29448// Test that CreateAnswer fails if a round of offer/answer has been done and
449// the PeerConnection is in the stable state.
Steve Anton8acdd1a2018-02-08 01:27:36450TEST_P(PeerConnectionSignalingTest, CreateAnswerFailsIfStable) {
Steve Anton8d3444d2017-10-20 22:30:51451 auto caller = CreatePeerConnection();
452 auto callee = CreatePeerConnection();
453
Steve Antondffead82018-02-06 18:31:29454 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
Oleh Prypinc22d6a82018-02-02 08:42:18455
456 ASSERT_EQ(SignalingState::kStable, caller->signaling_state());
Steve Antondffead82018-02-06 18:31:29457 EXPECT_FALSE(caller->CreateAnswer());
458
459 ASSERT_EQ(SignalingState::kStable, callee->signaling_state());
460 EXPECT_FALSE(callee->CreateAnswer());
Steve Anton8d3444d2017-10-20 22:30:51461}
462
463// According to https://tools.ietf.org/html/rfc3264#section-8, the session id
464// stays the same but the version must be incremented if a later, different
465// session description is generated. These two tests verify that is the case for
466// both offers and answers.
Steve Anton8acdd1a2018-02-08 01:27:36467TEST_P(PeerConnectionSignalingTest,
Steve Anton8d3444d2017-10-20 22:30:51468 SessionVersionIncrementedInSubsequentDifferentOffer) {
469 auto caller = CreatePeerConnection();
470 auto callee = CreatePeerConnection();
471
472 auto original_offer = caller->CreateOfferAndSetAsLocal();
473 const std::string original_id = original_offer->session_id();
474 const std::string original_version = original_offer->session_version();
475
476 ASSERT_TRUE(callee->SetRemoteDescription(std::move(original_offer)));
477 ASSERT_TRUE(caller->SetRemoteDescription(callee->CreateAnswer()));
478
479 // Add track to get a different offer.
480 caller->AddAudioTrack("a");
481
482 auto later_offer = caller->CreateOffer();
483
484 EXPECT_EQ(original_id, later_offer->session_id());
485 EXPECT_LT(rtc::FromString<uint64_t>(original_version),
486 rtc::FromString<uint64_t>(later_offer->session_version()));
487}
Steve Anton8acdd1a2018-02-08 01:27:36488TEST_P(PeerConnectionSignalingTest,
Steve Anton8d3444d2017-10-20 22:30:51489 SessionVersionIncrementedInSubsequentDifferentAnswer) {
490 auto caller = CreatePeerConnection();
491 auto callee = CreatePeerConnection();
492
493 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
494
Steve Antondffead82018-02-06 18:31:29495 auto original_answer = callee->CreateAnswer();
Steve Anton8d3444d2017-10-20 22:30:51496 const std::string original_id = original_answer->session_id();
497 const std::string original_version = original_answer->session_version();
498
499 // Add track to get a different answer.
500 callee->AddAudioTrack("a");
501
502 auto later_answer = callee->CreateAnswer();
503
504 EXPECT_EQ(original_id, later_answer->session_id());
505 EXPECT_LT(rtc::FromString<uint64_t>(original_version),
506 rtc::FromString<uint64_t>(later_answer->session_version()));
507}
508
Steve Anton8acdd1a2018-02-08 01:27:36509TEST_P(PeerConnectionSignalingTest, InitiatorFlagSetOnCallerAndNotOnCallee) {
Steve Anton8d3444d2017-10-20 22:30:51510 auto caller = CreatePeerConnectionWithAudioVideo();
511 auto callee = CreatePeerConnectionWithAudioVideo();
512
513 EXPECT_FALSE(caller->initial_offerer());
514 EXPECT_FALSE(callee->initial_offerer());
515
516 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
517
518 EXPECT_TRUE(caller->initial_offerer());
519 EXPECT_FALSE(callee->initial_offerer());
520
521 ASSERT_TRUE(
522 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
523
524 EXPECT_TRUE(caller->initial_offerer());
525 EXPECT_FALSE(callee->initial_offerer());
526}
527
528// Test creating a PeerConnection, request multiple offers, destroy the
529// PeerConnection and make sure we get success/failure callbacks for all of the
530// requests.
531// Background: crbug.com/507307
Steve Anton8acdd1a2018-02-08 01:27:36532TEST_P(PeerConnectionSignalingTest, CreateOffersAndShutdown) {
Steve Anton8d3444d2017-10-20 22:30:51533 auto caller = CreatePeerConnection();
534
535 RTCOfferAnswerOptions options;
536 options.offer_to_receive_audio =
537 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
538
539 rtc::scoped_refptr<MockCreateSessionDescriptionObserver> observers[100];
540 for (auto& observer : observers) {
Tommi87f70902021-04-27 12:43:08541 observer = rtc::make_ref_counted<MockCreateSessionDescriptionObserver>();
Steve Anton8d3444d2017-10-20 22:30:51542 caller->pc()->CreateOffer(observer, options);
543 }
544
545 // Destroy the PeerConnection.
546 caller.reset(nullptr);
547
548 for (auto& observer : observers) {
549 // We expect to have received a notification now even if the PeerConnection
550 // was terminated. The offer creation may or may not have succeeded, but we
551 // must have received a notification.
552 EXPECT_TRUE(observer->called());
553 }
554}
555
Henrik Boströma3728d32019-10-28 11:09:49556// Similar to the above test, but by closing the PC first the CreateOffer() will
557// fail "early", which triggers a codepath where the PeerConnection is
558// reponsible for invoking the observer, instead of the normal codepath where
559// the WebRtcSessionDescriptionFactory is responsible for it.
560TEST_P(PeerConnectionSignalingTest, CloseCreateOfferAndShutdown) {
561 auto caller = CreatePeerConnection();
Tommi87f70902021-04-27 12:43:08562 auto observer = rtc::make_ref_counted<MockCreateSessionDescriptionObserver>();
Henrik Boströma3728d32019-10-28 11:09:49563 caller->pc()->Close();
564 caller->pc()->CreateOffer(observer, RTCOfferAnswerOptions());
565 caller.reset(nullptr);
566 EXPECT_TRUE(observer->called());
567}
568
Henrik Boström831ae4e2020-07-29 10:04:00569TEST_P(PeerConnectionSignalingTest,
570 ImplicitCreateOfferAndShutdownWithOldObserver) {
Henrik Boströmd4089ca2020-07-28 08:39:36571 auto caller = CreatePeerConnection();
Henrik Boström4c9c75a2020-07-29 09:46:40572 auto observer = MockSetSessionDescriptionObserver::Create();
Henrik Boström831ae4e2020-07-29 10:04:00573 caller->pc()->SetLocalDescription(observer.get());
574 caller.reset(nullptr);
575 // The old observer does not get invoked because posted messages are lost.
576 EXPECT_FALSE(observer->called());
577}
578
579TEST_P(PeerConnectionSignalingTest, ImplicitCreateOfferAndShutdown) {
580 auto caller = CreatePeerConnection();
581 rtc::scoped_refptr<FakeSetLocalDescriptionObserver> observer(
582 new FakeSetLocalDescriptionObserver());
Henrik Boström4e196702019-10-30 09:35:50583 caller->pc()->SetLocalDescription(observer);
584 caller.reset(nullptr);
Henrik Boström831ae4e2020-07-29 10:04:00585 // The new observer gets invoked because it is called immediately.
586 EXPECT_TRUE(observer->called());
587 EXPECT_FALSE(observer->error().ok());
588}
589
590TEST_P(PeerConnectionSignalingTest,
591 CloseBeforeImplicitCreateOfferAndShutdownWithOldObserver) {
592 auto caller = CreatePeerConnection();
593 auto observer = MockSetSessionDescriptionObserver::Create();
594 caller->pc()->Close();
595 caller->pc()->SetLocalDescription(observer.get());
596 caller.reset(nullptr);
597 // The old observer does not get invoked because posted messages are lost.
Henrik Boström4e196702019-10-30 09:35:50598 EXPECT_FALSE(observer->called());
599}
600
601TEST_P(PeerConnectionSignalingTest, CloseBeforeImplicitCreateOfferAndShutdown) {
602 auto caller = CreatePeerConnection();
Henrik Boström831ae4e2020-07-29 10:04:00603 rtc::scoped_refptr<FakeSetLocalDescriptionObserver> observer(
604 new FakeSetLocalDescriptionObserver());
Henrik Boström4e196702019-10-30 09:35:50605 caller->pc()->Close();
606 caller->pc()->SetLocalDescription(observer);
607 caller.reset(nullptr);
Henrik Boström831ae4e2020-07-29 10:04:00608 // The new observer gets invoked because it is called immediately.
609 EXPECT_TRUE(observer->called());
610 EXPECT_FALSE(observer->error().ok());
611}
612
613TEST_P(PeerConnectionSignalingTest,
614 CloseAfterImplicitCreateOfferAndShutdownWithOldObserver) {
615 auto caller = CreatePeerConnection();
616 auto observer = MockSetSessionDescriptionObserver::Create();
617 caller->pc()->SetLocalDescription(observer.get());
618 caller->pc()->Close();
619 caller.reset(nullptr);
620 // The old observer does not get invoked because posted messages are lost.
Henrik Boström4e196702019-10-30 09:35:50621 EXPECT_FALSE(observer->called());
622}
623
624TEST_P(PeerConnectionSignalingTest, CloseAfterImplicitCreateOfferAndShutdown) {
625 auto caller = CreatePeerConnection();
Henrik Boström831ae4e2020-07-29 10:04:00626 rtc::scoped_refptr<FakeSetLocalDescriptionObserver> observer(
627 new FakeSetLocalDescriptionObserver());
Henrik Boström4e196702019-10-30 09:35:50628 caller->pc()->SetLocalDescription(observer);
629 caller->pc()->Close();
630 caller.reset(nullptr);
Henrik Boström831ae4e2020-07-29 10:04:00631 // The new observer gets invoked because it is called immediately.
632 EXPECT_TRUE(observer->called());
633 EXPECT_FALSE(observer->error().ok());
634}
635
636TEST_P(PeerConnectionSignalingTest,
637 SetLocalDescriptionNewObserverIsInvokedImmediately) {
638 auto caller = CreatePeerConnection();
639 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
640
641 rtc::scoped_refptr<FakeSetLocalDescriptionObserver> observer(
642 new FakeSetLocalDescriptionObserver());
643 caller->pc()->SetLocalDescription(std::move(offer), observer);
644 // The new observer is invoked immediately.
645 EXPECT_TRUE(observer->called());
646 EXPECT_TRUE(observer->error().ok());
647}
648
649TEST_P(PeerConnectionSignalingTest,
650 SetLocalDescriptionOldObserverIsInvokedInAPostedMessage) {
651 auto caller = CreatePeerConnection();
652 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
653
654 auto observer = MockSetSessionDescriptionObserver::Create();
655 caller->pc()->SetLocalDescription(observer, offer.release());
656 // The old observer is not invoked immediately.
Henrik Boström4e196702019-10-30 09:35:50657 EXPECT_FALSE(observer->called());
Henrik Boström831ae4e2020-07-29 10:04:00658 // Process all currently pending messages by waiting for a posted task to run.
659 bool checkpoint_reached = false;
660 rtc::Thread::Current()->PostTask(
661 RTC_FROM_HERE, [&checkpoint_reached] { checkpoint_reached = true; });
662 EXPECT_TRUE_WAIT(checkpoint_reached, kWaitTimeout);
663 // If resolving the observer was pending, it must now have been called.
664 EXPECT_TRUE(observer->called());
Henrik Boström4e196702019-10-30 09:35:50665}
666
Henrik Boströma3728d32019-10-28 11:09:49667TEST_P(PeerConnectionSignalingTest, SetRemoteDescriptionExecutesImmediately) {
668 auto caller = CreatePeerConnectionWithAudioVideo();
669 auto callee = CreatePeerConnection();
670
671 // This offer will cause receivers to be created.
672 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
673
674 // By not waiting for the observer's callback we can verify that the operation
675 // executed immediately.
676 callee->pc()->SetRemoteDescription(std::move(offer),
Henrik Boström831ae4e2020-07-29 10:04:00677 new FakeSetRemoteDescriptionObserver());
Henrik Boströma3728d32019-10-28 11:09:49678 EXPECT_EQ(2u, callee->pc()->GetReceivers().size());
679}
680
681TEST_P(PeerConnectionSignalingTest, CreateOfferBlocksSetRemoteDescription) {
682 auto caller = CreatePeerConnectionWithAudioVideo();
683 auto callee = CreatePeerConnection();
684
685 // This offer will cause receivers to be created.
686 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
687
688 EXPECT_EQ(0u, callee->pc()->GetReceivers().size());
Tommi87f70902021-04-27 12:43:08689 auto offer_observer =
690 rtc::make_ref_counted<MockCreateSessionDescriptionObserver>();
Henrik Boströma3728d32019-10-28 11:09:49691 // Synchronously invoke CreateOffer() and SetRemoteDescription(). The
692 // SetRemoteDescription() operation should be chained to be executed
693 // asynchronously, when CreateOffer() completes.
694 callee->pc()->CreateOffer(offer_observer, RTCOfferAnswerOptions());
695 callee->pc()->SetRemoteDescription(std::move(offer),
Henrik Boström831ae4e2020-07-29 10:04:00696 new FakeSetRemoteDescriptionObserver());
Henrik Boströma3728d32019-10-28 11:09:49697 // CreateOffer() is asynchronous; without message processing this operation
698 // should not have completed.
699 EXPECT_FALSE(offer_observer->called());
700 // Due to chaining, the receivers should not have been created by the offer
701 // yet.
702 EXPECT_EQ(0u, callee->pc()->GetReceivers().size());
703 // EXPECT_TRUE_WAIT causes messages to be processed...
704 EXPECT_TRUE_WAIT(offer_observer->called(), kWaitTimeout);
705 // Now that the offer has been completed, SetRemoteDescription() will have
706 // been executed next in the chain.
707 EXPECT_EQ(2u, callee->pc()->GetReceivers().size());
708}
709
Henrik Boström4e196702019-10-30 09:35:50710TEST_P(PeerConnectionSignalingTest,
711 ParameterlessSetLocalDescriptionCreatesOffer) {
712 auto caller = CreatePeerConnectionWithAudioVideo();
713
714 auto observer = MockSetSessionDescriptionObserver::Create();
Henrik Boström831ae4e2020-07-29 10:04:00715 caller->pc()->SetLocalDescription(observer.get());
Henrik Boström4e196702019-10-30 09:35:50716
717 // The offer is created asynchronously; message processing is needed for it to
718 // complete.
719 EXPECT_FALSE(observer->called());
720 EXPECT_FALSE(caller->pc()->pending_local_description());
721 EXPECT_EQ(PeerConnection::kStable, caller->signaling_state());
722
723 // Wait for messages to be processed.
724 EXPECT_TRUE_WAIT(observer->called(), kWaitTimeout);
725 EXPECT_TRUE(observer->result());
726 EXPECT_TRUE(caller->pc()->pending_local_description());
727 EXPECT_EQ(SdpType::kOffer,
728 caller->pc()->pending_local_description()->GetType());
729 EXPECT_EQ(PeerConnection::kHaveLocalOffer, caller->signaling_state());
730}
731
732TEST_P(PeerConnectionSignalingTest,
733 ParameterlessSetLocalDescriptionCreatesAnswer) {
734 auto caller = CreatePeerConnectionWithAudioVideo();
735 auto callee = CreatePeerConnectionWithAudioVideo();
736
737 callee->SetRemoteDescription(caller->CreateOffer());
738 EXPECT_EQ(PeerConnection::kHaveRemoteOffer, callee->signaling_state());
739
740 auto observer = MockSetSessionDescriptionObserver::Create();
Henrik Boström831ae4e2020-07-29 10:04:00741 callee->pc()->SetLocalDescription(observer.get());
Henrik Boström4e196702019-10-30 09:35:50742
743 // The answer is created asynchronously; message processing is needed for it
744 // to complete.
745 EXPECT_FALSE(observer->called());
746 EXPECT_FALSE(callee->pc()->current_local_description());
747
748 // Wait for messages to be processed.
749 EXPECT_TRUE_WAIT(observer->called(), kWaitTimeout);
750 EXPECT_TRUE(observer->result());
751 EXPECT_TRUE(callee->pc()->current_local_description());
752 EXPECT_EQ(SdpType::kAnswer,
753 callee->pc()->current_local_description()->GetType());
754 EXPECT_EQ(PeerConnection::kStable, callee->signaling_state());
755}
756
757TEST_P(PeerConnectionSignalingTest,
758 ParameterlessSetLocalDescriptionFullExchange) {
759 auto caller = CreatePeerConnectionWithAudioVideo();
760 auto callee = CreatePeerConnectionWithAudioVideo();
761
762 // SetLocalDescription(), implicitly creating an offer.
Henrik Boström831ae4e2020-07-29 10:04:00763 auto caller_set_local_description_observer =
764 MockSetSessionDescriptionObserver::Create();
765 caller->pc()->SetLocalDescription(
766 caller_set_local_description_observer.get());
Henrik Boström4e196702019-10-30 09:35:50767 EXPECT_TRUE_WAIT(caller_set_local_description_observer->called(),
768 kWaitTimeout);
769 ASSERT_TRUE(caller->pc()->pending_local_description());
770
771 // SetRemoteDescription(offer)
Henrik Boström831ae4e2020-07-29 10:04:00772 auto callee_set_remote_description_observer =
773 MockSetSessionDescriptionObserver::Create();
Henrik Boström4e196702019-10-30 09:35:50774 callee->pc()->SetRemoteDescription(
Henrik Boström831ae4e2020-07-29 10:04:00775 callee_set_remote_description_observer,
Henrik Boström4e196702019-10-30 09:35:50776 CloneSessionDescription(caller->pc()->pending_local_description())
777 .release());
778
779 // SetLocalDescription(), implicitly creating an answer.
Henrik Boström831ae4e2020-07-29 10:04:00780 auto callee_set_local_description_observer =
781 MockSetSessionDescriptionObserver::Create();
782 callee->pc()->SetLocalDescription(
783 callee_set_local_description_observer.get());
Henrik Boström4e196702019-10-30 09:35:50784 EXPECT_TRUE_WAIT(callee_set_local_description_observer->called(),
785 kWaitTimeout);
786 // Chaining guarantees SetRemoteDescription() happened before
787 // SetLocalDescription().
788 EXPECT_TRUE(callee_set_remote_description_observer->called());
789 EXPECT_TRUE(callee->pc()->current_local_description());
790
791 // SetRemoteDescription(answer)
Henrik Boström831ae4e2020-07-29 10:04:00792 auto caller_set_remote_description_observer =
793 MockSetSessionDescriptionObserver::Create();
Henrik Boström4e196702019-10-30 09:35:50794 caller->pc()->SetRemoteDescription(
795 caller_set_remote_description_observer,
796 CloneSessionDescription(callee->pc()->current_local_description())
797 .release());
798 EXPECT_TRUE_WAIT(caller_set_remote_description_observer->called(),
799 kWaitTimeout);
800
801 EXPECT_EQ(PeerConnection::kStable, caller->signaling_state());
802 EXPECT_EQ(PeerConnection::kStable, callee->signaling_state());
803}
804
805TEST_P(PeerConnectionSignalingTest,
806 ParameterlessSetLocalDescriptionCloseBeforeCreatingOffer) {
807 auto caller = CreatePeerConnectionWithAudioVideo();
808
809 auto observer = MockSetSessionDescriptionObserver::Create();
810 caller->pc()->Close();
Henrik Boström831ae4e2020-07-29 10:04:00811 caller->pc()->SetLocalDescription(observer.get());
Henrik Boström4e196702019-10-30 09:35:50812
813 // The operation should fail asynchronously.
814 EXPECT_FALSE(observer->called());
815 EXPECT_TRUE_WAIT(observer->called(), kWaitTimeout);
816 EXPECT_FALSE(observer->result());
817 // This did not affect the signaling state.
818 EXPECT_EQ(PeerConnection::kClosed, caller->pc()->signaling_state());
819 EXPECT_EQ(
820 "SetLocalDescription failed to create session description - "
821 "SetLocalDescription called when PeerConnection is closed.",
822 observer->error());
823}
824
825TEST_P(PeerConnectionSignalingTest,
826 ParameterlessSetLocalDescriptionCloseWhileCreatingOffer) {
827 auto caller = CreatePeerConnectionWithAudioVideo();
828
829 auto observer = MockSetSessionDescriptionObserver::Create();
Henrik Boström831ae4e2020-07-29 10:04:00830 caller->pc()->SetLocalDescription(observer.get());
Henrik Boström4e196702019-10-30 09:35:50831 caller->pc()->Close();
832
833 // The operation should fail asynchronously.
834 EXPECT_FALSE(observer->called());
835 EXPECT_TRUE_WAIT(observer->called(), kWaitTimeout);
836 EXPECT_FALSE(observer->result());
837 // This did not affect the signaling state.
838 EXPECT_EQ(PeerConnection::kClosed, caller->pc()->signaling_state());
839 EXPECT_EQ(
840 "SetLocalDescription failed to create session description - "
841 "CreateOffer failed because the session was shut down",
842 observer->error());
843}
844
Philipp Hancke4e8c1152020-10-13 10:43:15845TEST_P(PeerConnectionSignalingTest, UnsupportedContentType) {
846 auto caller = CreatePeerConnection();
847
848 // Call setRemoteDescription with a m= line we don't understand.
849 std::string sdp =
850 "v=0\r\n"
851 "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
852 "s=-\r\n"
853 "t=0 0\r\n"
854 "m=bogus 9 FOO 0 8\r\n"
855 "c=IN IP4 0.0.0.0\r\n"
856 "a=mid:bogusmid\r\n";
857 std::unique_ptr<webrtc::SessionDescriptionInterface> remote_description =
858 webrtc::CreateSessionDescription(SdpType::kOffer, sdp, nullptr);
859
860 EXPECT_TRUE(caller->SetRemoteDescription(std::move(remote_description)));
861
862 // Assert we respond back with something meaningful.
863 auto answer = caller->CreateAnswer();
864 ASSERT_EQ(answer->description()->contents().size(), 1u);
865 EXPECT_NE(answer->description()
866 ->contents()[0]
867 .media_description()
868 ->as_unsupported(),
869 nullptr);
870 EXPECT_EQ(answer->description()
871 ->contents()[0]
872 .media_description()
873 ->as_unsupported()
874 ->media_type(),
875 "bogus");
876 EXPECT_TRUE(answer->description()->contents()[0].rejected);
877 EXPECT_EQ(answer->description()->contents()[0].mid(), "bogusmid");
878 EXPECT_EQ(
879 answer->description()->contents()[0].media_description()->protocol(),
880 "FOO");
881 EXPECT_FALSE(
882 answer->description()->contents()[0].media_description()->has_codecs());
883
884 EXPECT_TRUE(caller->SetLocalDescription(std::move(answer)));
885
886 // Assert we keep this in susequent offers.
887 auto offer = caller->CreateOffer();
888 EXPECT_EQ(offer->description()
889 ->contents()[0]
890 .media_description()
891 ->as_unsupported()
892 ->media_type(),
893 "bogus");
894 EXPECT_TRUE(offer->description()->contents()[0].rejected);
895 EXPECT_EQ(offer->description()->contents()[0].media_description()->protocol(),
896 "FOO");
897 EXPECT_EQ(offer->description()->contents()[0].mid(), "bogusmid");
898 EXPECT_FALSE(
899 offer->description()->contents()[0].media_description()->has_codecs());
900 EXPECT_TRUE(caller->SetLocalDescription(std::move(offer)));
901}
902
Philipp Hanckeb7bc2432021-03-11 14:28:00903TEST_P(PeerConnectionSignalingTest, ReceiveFlexFec) {
904 auto caller = CreatePeerConnection();
905
906 std::string sdp =
907 "v=0\r\n"
908 "o=- 8403615332048243445 2 IN IP4 127.0.0.1\r\n"
909 "s=-\r\n"
910 "t=0 0\r\n"
911 "a=group:BUNDLE 0\r\n"
912 "m=video 9 UDP/TLS/RTP/SAVPF 102 122\r\n"
913 "c=IN IP4 0.0.0.0\r\n"
914 "a=rtcp:9 IN IP4 0.0.0.0\r\n"
915 "a=ice-ufrag:IZeV\r\n"
916 "a=ice-pwd:uaZhQD4rYM/Tta2qWBT1Bbt4\r\n"
917 "a=ice-options:trickle\r\n"
918 "a=fingerprint:sha-256 "
919 "D8:6C:3D:FA:23:E2:2C:63:11:2D:D0:86:BE:C4:D0:65:F9:42:F7:1C:06:04:27:E6:"
920 "1C:2C:74:01:8D:50:67:23\r\n"
921 "a=setup:actpass\r\n"
922 "a=mid:0\r\n"
923 "a=sendrecv\r\n"
924 "a=msid:stream track\r\n"
925 "a=rtcp-mux\r\n"
926 "a=rtcp-rsize\r\n"
927 "a=rtpmap:102 VP8/90000\r\n"
928 "a=rtcp-fb:102 goog-remb\r\n"
929 "a=rtcp-fb:102 transport-cc\r\n"
930 "a=rtcp-fb:102 ccm fir\r\n"
931 "a=rtcp-fb:102 nack\r\n"
932 "a=rtcp-fb:102 nack pli\r\n"
933 "a=rtpmap:122 flexfec-03/90000\r\n"
934 "a=fmtp:122 repair-window=10000000\r\n"
935 "a=ssrc-group:FEC-FR 1224551896 1953032773\r\n"
936 "a=ssrc:1224551896 cname:/exJcmhSLpyu9FgV\r\n"
937 "a=ssrc:1953032773 cname:/exJcmhSLpyu9FgV\r\n";
938 std::unique_ptr<webrtc::SessionDescriptionInterface> remote_description =
939 webrtc::CreateSessionDescription(SdpType::kOffer, sdp, nullptr);
940
941 EXPECT_TRUE(caller->SetRemoteDescription(std::move(remote_description)));
942
943 auto answer = caller->CreateAnswer();
944 ASSERT_EQ(answer->description()->contents().size(), 1u);
945 ASSERT_NE(
946 answer->description()->contents()[0].media_description()->as_video(),
947 nullptr);
948 auto codecs = answer->description()
949 ->contents()[0]
950 .media_description()
951 ->as_video()
952 ->codecs();
953 ASSERT_EQ(codecs.size(), 2u);
954 EXPECT_EQ(codecs[1].name, "flexfec-03");
955
956 EXPECT_TRUE(caller->SetLocalDescription(std::move(answer)));
957}
958
Philipp Hancke64a79c72021-05-10 15:28:37959TEST_P(PeerConnectionSignalingTest, ReceiveFlexFecReoffer) {
960 auto caller = CreatePeerConnection();
961
962 std::string sdp =
963 "v=0\r\n"
964 "o=- 8403615332048243445 2 IN IP4 127.0.0.1\r\n"
965 "s=-\r\n"
966 "t=0 0\r\n"
967 "a=group:BUNDLE 0\r\n"
968 "m=video 9 UDP/TLS/RTP/SAVPF 102 35\r\n"
969 "c=IN IP4 0.0.0.0\r\n"
970 "a=rtcp:9 IN IP4 0.0.0.0\r\n"
971 "a=ice-ufrag:IZeV\r\n"
972 "a=ice-pwd:uaZhQD4rYM/Tta2qWBT1Bbt4\r\n"
973 "a=ice-options:trickle\r\n"
974 "a=fingerprint:sha-256 "
975 "D8:6C:3D:FA:23:E2:2C:63:11:2D:D0:86:BE:C4:D0:65:F9:42:F7:1C:06:04:27:E6:"
976 "1C:2C:74:01:8D:50:67:23\r\n"
977 "a=setup:actpass\r\n"
978 "a=mid:0\r\n"
979 "a=sendrecv\r\n"
980 "a=msid:stream track\r\n"
981 "a=rtcp-mux\r\n"
982 "a=rtcp-rsize\r\n"
983 "a=rtpmap:102 VP8/90000\r\n"
984 "a=rtcp-fb:102 goog-remb\r\n"
985 "a=rtcp-fb:102 transport-cc\r\n"
986 "a=rtcp-fb:102 ccm fir\r\n"
987 "a=rtcp-fb:102 nack\r\n"
988 "a=rtcp-fb:102 nack pli\r\n"
989 "a=rtpmap:35 flexfec-03/90000\r\n"
990 "a=fmtp:35 repair-window=10000000\r\n"
991 "a=ssrc-group:FEC-FR 1224551896 1953032773\r\n"
992 "a=ssrc:1224551896 cname:/exJcmhSLpyu9FgV\r\n"
993 "a=ssrc:1953032773 cname:/exJcmhSLpyu9FgV\r\n";
994 std::unique_ptr<webrtc::SessionDescriptionInterface> remote_description =
995 webrtc::CreateSessionDescription(SdpType::kOffer, sdp, nullptr);
996
997 EXPECT_TRUE(caller->SetRemoteDescription(std::move(remote_description)));
998
999 auto answer = caller->CreateAnswer();
1000 ASSERT_EQ(answer->description()->contents().size(), 1u);
1001 ASSERT_NE(
1002 answer->description()->contents()[0].media_description()->as_video(),
1003 nullptr);
1004 auto codecs = answer->description()
1005 ->contents()[0]
1006 .media_description()
1007 ->as_video()
1008 ->codecs();
1009 ASSERT_EQ(codecs.size(), 2u);
1010 EXPECT_EQ(codecs[1].name, "flexfec-03");
1011 EXPECT_EQ(codecs[1].id, 35);
1012
1013 EXPECT_TRUE(caller->SetLocalDescription(std::move(answer)));
1014
1015 // This generates a collision for AV1 which needs to be remapped.
1016 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
1017 auto offer_codecs = offer->description()
1018 ->contents()[0]
1019 .media_description()
1020 ->as_video()
1021 ->codecs();
1022 auto flexfec_it = std::find_if(
1023 offer_codecs.begin(), offer_codecs.end(),
1024 [](const cricket::Codec& codec) { return codec.name == "flexfec-03"; });
1025 ASSERT_EQ(flexfec_it->id, 35);
1026 auto av1_it = std::find_if(
1027 offer_codecs.begin(), offer_codecs.end(),
Sergey Silkin6b19d822021-09-09 13:09:111028 [](const cricket::Codec& codec) { return codec.name == "AV1"; });
Philipp Hancke64a79c72021-05-10 15:28:371029 if (av1_it != offer_codecs.end()) {
1030 ASSERT_NE(av1_it->id, 35);
1031 }
1032}
1033
Mirko Bonadeic84f6612019-01-31 11:20:571034INSTANTIATE_TEST_SUITE_P(PeerConnectionSignalingTest,
1035 PeerConnectionSignalingTest,
1036 Values(SdpSemantics::kPlanB,
1037 SdpSemantics::kUnifiedPlan));
Steve Anton8acdd1a2018-02-08 01:27:361038
Harald Alvestrand4a7b3ac2019-01-17 09:39:401039class PeerConnectionSignalingUnifiedPlanTest
1040 : public PeerConnectionSignalingBaseTest {
1041 protected:
1042 PeerConnectionSignalingUnifiedPlanTest()
1043 : PeerConnectionSignalingBaseTest(SdpSemantics::kUnifiedPlan) {}
1044};
1045
Henrik Boströma3728d32019-10-28 11:09:491046// We verify that SetLocalDescription() executed immediately by verifying that
1047// the transceiver mid values got assigned. SLD executing immeditately is not
1048// unique to Unified Plan, but the transceivers used to verify this are only
1049// available in Unified Plan.
1050TEST_F(PeerConnectionSignalingUnifiedPlanTest,
Henrik Boström831ae4e2020-07-29 10:04:001051 SetLocalDescriptionExecutesImmediatelyUsingOldObserver) {
Henrik Boströma3728d32019-10-28 11:09:491052 auto caller = CreatePeerConnectionWithAudioVideo();
1053
1054 // This offer will cause transceiver mids to get assigned.
1055 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
1056
1057 // By not waiting for the observer's callback we can verify that the operation
Henrik Boström831ae4e2020-07-29 10:04:001058 // executed immediately. The old observer is invoked in a posted message, so
1059 // waiting for it would not ensure synchronicity.
Henrik Boströma3728d32019-10-28 11:09:491060 RTC_DCHECK(!caller->pc()->GetTransceivers()[0]->mid().has_value());
1061 caller->pc()->SetLocalDescription(
Tommi87f70902021-04-27 12:43:081062 rtc::make_ref_counted<MockSetSessionDescriptionObserver>(),
Henrik Boströma3728d32019-10-28 11:09:491063 offer.release());
1064 EXPECT_TRUE(caller->pc()->GetTransceivers()[0]->mid().has_value());
1065}
1066
1067TEST_F(PeerConnectionSignalingUnifiedPlanTest,
Henrik Boström831ae4e2020-07-29 10:04:001068 SetLocalDescriptionExecutesImmediatelyUsingNewObserver) {
1069 auto caller = CreatePeerConnectionWithAudioVideo();
1070
1071 // This offer will cause transceiver mids to get assigned.
1072 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
1073
1074 // Verify that mids were assigned without waiting for the observer. (However,
1075 // the new observer should also be invoked synchronously - as is ensured by
1076 // other tests.)
1077 RTC_DCHECK(!caller->pc()->GetTransceivers()[0]->mid().has_value());
1078 caller->pc()->SetLocalDescription(std::move(offer),
1079 new FakeSetLocalDescriptionObserver());
1080 EXPECT_TRUE(caller->pc()->GetTransceivers()[0]->mid().has_value());
1081}
1082
1083TEST_F(PeerConnectionSignalingUnifiedPlanTest,
Henrik Boströma3728d32019-10-28 11:09:491084 SetLocalDescriptionExecutesImmediatelyInsideCreateOfferCallback) {
1085 auto caller = CreatePeerConnectionWithAudioVideo();
1086
1087 // This offer will cause transceiver mids to get assigned.
1088 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
1089
Tommi87f70902021-04-27 12:43:081090 auto offer_observer =
1091 rtc::make_ref_counted<ExecuteFunctionOnCreateSessionDescriptionObserver>(
Henrik Boströma3728d32019-10-28 11:09:491092 [pc = caller->pc()](SessionDescriptionInterface* desc) {
1093 // By not waiting for the observer's callback we can verify that the
1094 // operation executed immediately.
1095 RTC_DCHECK(!pc->GetTransceivers()[0]->mid().has_value());
1096 pc->SetLocalDescription(
1097 new rtc::RefCountedObject<MockSetSessionDescriptionObserver>(),
1098 desc);
1099 EXPECT_TRUE(pc->GetTransceivers()[0]->mid().has_value());
Tommi87f70902021-04-27 12:43:081100 });
Henrik Boströma3728d32019-10-28 11:09:491101 caller->pc()->CreateOffer(offer_observer, RTCOfferAnswerOptions());
1102 EXPECT_TRUE_WAIT(offer_observer->was_called(), kWaitTimeout);
1103}
1104
Harald Alvestrand4a7b3ac2019-01-17 09:39:401105// Test that transports are shown in the sender/receiver API after offer/answer.
1106// This only works in Unified Plan.
1107TEST_F(PeerConnectionSignalingUnifiedPlanTest,
1108 DtlsTransportsInstantiateInOfferAnswer) {
1109 auto caller = CreatePeerConnectionWithAudioVideo();
1110 auto callee = CreatePeerConnection();
1111
1112 EXPECT_FALSE(HasDtlsTransport(caller));
1113 EXPECT_FALSE(HasDtlsTransport(callee));
1114 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
1115 caller->SetLocalDescription(CloneSessionDescription(offer.get()));
1116 EXPECT_TRUE(HasDtlsTransport(caller));
1117 callee->SetRemoteDescription(std::move(offer));
1118 EXPECT_FALSE(HasDtlsTransport(callee));
1119 auto answer = callee->CreateAnswer(RTCOfferAnswerOptions());
1120 callee->SetLocalDescription(CloneSessionDescription(answer.get()));
1121 EXPECT_TRUE(HasDtlsTransport(callee));
1122 caller->SetRemoteDescription(std::move(answer));
1123 EXPECT_TRUE(HasDtlsTransport(caller));
1124
1125 ASSERT_EQ(SignalingState::kStable, caller->signaling_state());
1126}
1127
1128TEST_F(PeerConnectionSignalingUnifiedPlanTest, DtlsTransportsMergeWhenBundled) {
1129 auto caller = CreatePeerConnectionWithAudioVideo();
1130 auto callee = CreatePeerConnection();
1131
1132 EXPECT_FALSE(HasDtlsTransport(caller));
1133 EXPECT_FALSE(HasDtlsTransport(callee));
1134 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
1135 caller->SetLocalDescription(CloneSessionDescription(offer.get()));
1136 EXPECT_EQ(2, NumberOfDtlsTransports(caller));
1137 callee->SetRemoteDescription(std::move(offer));
1138 auto answer = callee->CreateAnswer(RTCOfferAnswerOptions());
1139 callee->SetLocalDescription(CloneSessionDescription(answer.get()));
1140 caller->SetRemoteDescription(std::move(answer));
1141 EXPECT_EQ(1, NumberOfDtlsTransports(caller));
1142
1143 ASSERT_EQ(SignalingState::kStable, caller->signaling_state());
1144}
1145
1146TEST_F(PeerConnectionSignalingUnifiedPlanTest,
1147 DtlsTransportsAreSeparateeWhenUnbundled) {
1148 auto caller = CreatePeerConnectionWithAudioVideo();
1149 auto callee = CreatePeerConnection();
1150
1151 EXPECT_FALSE(HasDtlsTransport(caller));
1152 EXPECT_FALSE(HasDtlsTransport(callee));
1153 RTCOfferAnswerOptions unbundle_options;
1154 unbundle_options.use_rtp_mux = false;
1155 auto offer = caller->CreateOffer(unbundle_options);
1156 caller->SetLocalDescription(CloneSessionDescription(offer.get()));
1157 EXPECT_EQ(2, NumberOfDtlsTransports(caller));
1158 callee->SetRemoteDescription(std::move(offer));
1159 auto answer = callee->CreateAnswer(RTCOfferAnswerOptions());
1160 callee->SetLocalDescription(CloneSessionDescription(answer.get()));
1161 EXPECT_EQ(2, NumberOfDtlsTransports(callee));
1162 caller->SetRemoteDescription(std::move(answer));
1163 EXPECT_EQ(2, NumberOfDtlsTransports(caller));
1164
1165 ASSERT_EQ(SignalingState::kStable, caller->signaling_state());
1166}
1167
Henrik Boströme574a312020-08-25 08:20:111168TEST_F(PeerConnectionSignalingUnifiedPlanTest,
1169 ShouldFireNegotiationNeededWhenNoChangesArePending) {
1170 auto caller = CreatePeerConnection();
1171 EXPECT_FALSE(caller->observer()->has_negotiation_needed_event());
1172 auto transceiver =
1173 caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO, RtpTransceiverInit());
1174 EXPECT_TRUE(caller->observer()->has_negotiation_needed_event());
1175 EXPECT_TRUE(caller->pc()->ShouldFireNegotiationNeededEvent(
1176 caller->observer()->latest_negotiation_needed_event()));
1177}
1178
1179TEST_F(PeerConnectionSignalingUnifiedPlanTest,
1180 SuppressNegotiationNeededWhenOperationChainIsNotEmpty) {
1181 auto caller = CreatePeerConnection();
1182 EXPECT_FALSE(caller->observer()->has_negotiation_needed_event());
1183 auto transceiver =
1184 caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO, RtpTransceiverInit());
1185 EXPECT_TRUE(caller->observer()->has_negotiation_needed_event());
1186
Tommi87f70902021-04-27 12:43:081187 auto observer = rtc::make_ref_counted<MockCreateSessionDescriptionObserver>();
Henrik Boströme574a312020-08-25 08:20:111188 caller->pc()->CreateOffer(observer, RTCOfferAnswerOptions());
1189 // For this test to work, the operation has to be pending, i.e. the observer
1190 // has not yet been invoked.
1191 EXPECT_FALSE(observer->called());
1192 // Because the Operations Chain is not empty, the event is now suppressed.
1193 EXPECT_FALSE(caller->pc()->ShouldFireNegotiationNeededEvent(
1194 caller->observer()->latest_negotiation_needed_event()));
1195 caller->observer()->clear_latest_negotiation_needed_event();
1196
1197 // When the Operations Chain becomes empty again, a new negotiation needed
1198 // event will be generated that is not suppressed.
1199 EXPECT_TRUE_WAIT(observer->called(), kWaitTimeout);
1200 EXPECT_TRUE(caller->observer()->has_negotiation_needed_event());
1201 EXPECT_TRUE(caller->pc()->ShouldFireNegotiationNeededEvent(
1202 caller->observer()->latest_negotiation_needed_event()));
1203}
1204
1205TEST_F(PeerConnectionSignalingUnifiedPlanTest,
1206 SuppressNegotiationNeededWhenSignalingStateIsNotStable) {
1207 auto caller = CreatePeerConnection();
1208 auto callee = CreatePeerConnection();
1209 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
1210
1211 EXPECT_FALSE(caller->observer()->has_negotiation_needed_event());
1212 auto transceiver =
1213 callee->AddTransceiver(cricket::MEDIA_TYPE_AUDIO, RtpTransceiverInit());
1214 EXPECT_TRUE(callee->observer()->has_negotiation_needed_event());
1215
1216 // Change signaling state (to "have-remote-offer") by setting a remote offer.
1217 callee->SetRemoteDescription(std::move(offer));
1218 // Because the signaling state is not "stable", the event is now suppressed.
1219 EXPECT_FALSE(callee->pc()->ShouldFireNegotiationNeededEvent(
1220 callee->observer()->latest_negotiation_needed_event()));
1221 callee->observer()->clear_latest_negotiation_needed_event();
1222
1223 // Upon rolling back to "stable", a new negotiation needed event will be
1224 // generated that is not suppressed.
1225 callee->SetLocalDescription(CreateSessionDescription(SdpType::kRollback, ""));
1226 EXPECT_TRUE(callee->observer()->has_negotiation_needed_event());
1227 EXPECT_TRUE(callee->pc()->ShouldFireNegotiationNeededEvent(
1228 callee->observer()->latest_negotiation_needed_event()));
1229}
1230
Steve Anton8d3444d2017-10-20 22:30:511231} // namespace webrtc