mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-12 21:30:45 +01:00

StunServer is updated to ensure registring for receiving packet from the socket is happening on the same thread as where the packets are recevied. Bug: webrtc:15368, webrtc:11943 Change-Id: I94cc3a47278d5489de7f170c8d43015d1551c437 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/328120 Commit-Queue: Per Kjellander <perkj@webrtc.org> Reviewed-by: Jonas Oreland <jonaso@webrtc.org> Reviewed-by: Harald Alvestrand <hta@webrtc.org> Cr-Commit-Position: refs/heads/main@{#41219}
506 lines
21 KiB
C++
506 lines
21 KiB
C++
/*
|
|
* Copyright 2022 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
// This file is intended for PeerConnection integration tests that are
|
|
// slow to execute (currently defined as more than 5 seconds per test).
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <memory>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "absl/algorithm/container.h"
|
|
#include "absl/strings/string_view.h"
|
|
#include "absl/types/optional.h"
|
|
#include "api/dtmf_sender_interface.h"
|
|
#include "api/peer_connection_interface.h"
|
|
#include "api/rtp_receiver_interface.h"
|
|
#include "api/scoped_refptr.h"
|
|
#include "api/units/time_delta.h"
|
|
#include "p2p/base/port_allocator.h"
|
|
#include "p2p/base/port_interface.h"
|
|
#include "p2p/base/stun_server.h"
|
|
#include "p2p/base/test_stun_server.h"
|
|
#include "pc/test/integration_test_helpers.h"
|
|
#include "pc/test/mock_peer_connection_observers.h"
|
|
#include "rtc_base/fake_clock.h"
|
|
#include "rtc_base/fake_network.h"
|
|
#include "rtc_base/firewall_socket_server.h"
|
|
#include "rtc_base/gunit.h"
|
|
#include "rtc_base/logging.h"
|
|
#include "rtc_base/socket_address.h"
|
|
#include "rtc_base/ssl_certificate.h"
|
|
#include "rtc_base/test_certificate_verifier.h"
|
|
#include "test/gmock.h"
|
|
#include "test/gtest.h"
|
|
|
|
namespace webrtc {
|
|
|
|
namespace {
|
|
|
|
class PeerConnectionIntegrationTest
|
|
: public PeerConnectionIntegrationBaseTest,
|
|
public ::testing::WithParamInterface<SdpSemantics> {
|
|
protected:
|
|
PeerConnectionIntegrationTest()
|
|
: PeerConnectionIntegrationBaseTest(GetParam()) {}
|
|
};
|
|
|
|
// Fake clock must be set before threads are started to prevent race on
|
|
// Set/GetClockForTesting().
|
|
// To achieve that, multiple inheritance is used as a mixin pattern
|
|
// where order of construction is finely controlled.
|
|
// This also ensures peerconnection is closed before switching back to non-fake
|
|
// clock, avoiding other races and DCHECK failures such as in rtp_sender.cc.
|
|
class FakeClockForTest : public rtc::ScopedFakeClock {
|
|
protected:
|
|
FakeClockForTest() {
|
|
// Some things use a time of "0" as a special value, so we need to start out
|
|
// the fake clock at a nonzero time.
|
|
// TODO(deadbeef): Fix this.
|
|
AdvanceTime(TimeDelta::Seconds(1000));
|
|
}
|
|
|
|
// Explicit handle.
|
|
ScopedFakeClock& FakeClock() { return *this; }
|
|
};
|
|
|
|
// Ensure FakeClockForTest is constructed first (see class for rationale).
|
|
class PeerConnectionIntegrationTestWithFakeClock
|
|
: public FakeClockForTest,
|
|
public PeerConnectionIntegrationTest {};
|
|
|
|
class PeerConnectionIntegrationTestPlanB
|
|
: public PeerConnectionIntegrationBaseTest {
|
|
protected:
|
|
PeerConnectionIntegrationTestPlanB()
|
|
: PeerConnectionIntegrationBaseTest(SdpSemantics::kPlanB_DEPRECATED) {}
|
|
};
|
|
|
|
class PeerConnectionIntegrationTestUnifiedPlan
|
|
: public PeerConnectionIntegrationBaseTest {
|
|
protected:
|
|
PeerConnectionIntegrationTestUnifiedPlan()
|
|
: PeerConnectionIntegrationBaseTest(SdpSemantics::kUnifiedPlan) {}
|
|
};
|
|
|
|
// Test the OnFirstPacketReceived callback from audio/video RtpReceivers. This
|
|
// includes testing that the callback is invoked if an observer is connected
|
|
// after the first packet has already been received.
|
|
TEST_P(PeerConnectionIntegrationTest,
|
|
RtpReceiverObserverOnFirstPacketReceived) {
|
|
ASSERT_TRUE(CreatePeerConnectionWrappers());
|
|
ConnectFakeSignaling();
|
|
caller()->AddAudioVideoTracks();
|
|
callee()->AddAudioVideoTracks();
|
|
// Start offer/answer exchange and wait for it to complete.
|
|
caller()->CreateAndSetAndSignalOffer();
|
|
ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
|
|
// Should be one receiver each for audio/video.
|
|
EXPECT_EQ(2U, caller()->rtp_receiver_observers().size());
|
|
EXPECT_EQ(2U, callee()->rtp_receiver_observers().size());
|
|
// Wait for all "first packet received" callbacks to be fired.
|
|
EXPECT_TRUE_WAIT(
|
|
absl::c_all_of(caller()->rtp_receiver_observers(),
|
|
[](const std::unique_ptr<MockRtpReceiverObserver>& o) {
|
|
return o->first_packet_received();
|
|
}),
|
|
kMaxWaitForFramesMs);
|
|
EXPECT_TRUE_WAIT(
|
|
absl::c_all_of(callee()->rtp_receiver_observers(),
|
|
[](const std::unique_ptr<MockRtpReceiverObserver>& o) {
|
|
return o->first_packet_received();
|
|
}),
|
|
kMaxWaitForFramesMs);
|
|
// If new observers are set after the first packet was already received, the
|
|
// callback should still be invoked.
|
|
caller()->ResetRtpReceiverObservers();
|
|
callee()->ResetRtpReceiverObservers();
|
|
EXPECT_EQ(2U, caller()->rtp_receiver_observers().size());
|
|
EXPECT_EQ(2U, callee()->rtp_receiver_observers().size());
|
|
EXPECT_TRUE(
|
|
absl::c_all_of(caller()->rtp_receiver_observers(),
|
|
[](const std::unique_ptr<MockRtpReceiverObserver>& o) {
|
|
return o->first_packet_received();
|
|
}));
|
|
EXPECT_TRUE(
|
|
absl::c_all_of(callee()->rtp_receiver_observers(),
|
|
[](const std::unique_ptr<MockRtpReceiverObserver>& o) {
|
|
return o->first_packet_received();
|
|
}));
|
|
}
|
|
|
|
class DummyDtmfObserver : public DtmfSenderObserverInterface {
|
|
public:
|
|
DummyDtmfObserver() : completed_(false) {}
|
|
|
|
// Implements DtmfSenderObserverInterface.
|
|
void OnToneChange(const std::string& tone) override {
|
|
tones_.push_back(tone);
|
|
if (tone.empty()) {
|
|
completed_ = true;
|
|
}
|
|
}
|
|
|
|
const std::vector<std::string>& tones() const { return tones_; }
|
|
bool completed() const { return completed_; }
|
|
|
|
private:
|
|
bool completed_;
|
|
std::vector<std::string> tones_;
|
|
};
|
|
|
|
TEST_P(PeerConnectionIntegrationTest,
|
|
SSLCertificateVerifierFailureUsedForTurnConnectionsFailsConnection) {
|
|
static const rtc::SocketAddress turn_server_internal_address{"88.88.88.0",
|
|
3478};
|
|
static const rtc::SocketAddress turn_server_external_address{"88.88.88.1", 0};
|
|
|
|
// Enable TCP-TLS for the fake turn server. We need to pass in 88.88.88.0 so
|
|
// that host name verification passes on the fake certificate.
|
|
CreateTurnServer(turn_server_internal_address, turn_server_external_address,
|
|
cricket::PROTO_TLS, "88.88.88.0");
|
|
|
|
PeerConnectionInterface::IceServer ice_server;
|
|
ice_server.urls.push_back("turns:88.88.88.0:3478?transport=tcp");
|
|
ice_server.username = "test";
|
|
ice_server.password = "test";
|
|
|
|
PeerConnectionInterface::RTCConfiguration client_1_config;
|
|
client_1_config.servers.push_back(ice_server);
|
|
client_1_config.type = PeerConnectionInterface::kRelay;
|
|
|
|
PeerConnectionInterface::RTCConfiguration client_2_config;
|
|
client_2_config.servers.push_back(ice_server);
|
|
// Setting the type to kRelay forces the connection to go through a TURN
|
|
// server.
|
|
client_2_config.type = PeerConnectionInterface::kRelay;
|
|
|
|
// Get a copy to the pointer so we can verify calls later.
|
|
rtc::TestCertificateVerifier* client_1_cert_verifier =
|
|
new rtc::TestCertificateVerifier();
|
|
client_1_cert_verifier->verify_certificate_ = false;
|
|
rtc::TestCertificateVerifier* client_2_cert_verifier =
|
|
new rtc::TestCertificateVerifier();
|
|
client_2_cert_verifier->verify_certificate_ = false;
|
|
|
|
// Create the dependencies with the test certificate verifier.
|
|
PeerConnectionDependencies client_1_deps(nullptr);
|
|
client_1_deps.tls_cert_verifier =
|
|
std::unique_ptr<rtc::TestCertificateVerifier>(client_1_cert_verifier);
|
|
PeerConnectionDependencies client_2_deps(nullptr);
|
|
client_2_deps.tls_cert_verifier =
|
|
std::unique_ptr<rtc::TestCertificateVerifier>(client_2_cert_verifier);
|
|
|
|
ASSERT_TRUE(CreatePeerConnectionWrappersWithConfigAndDeps(
|
|
client_1_config, std::move(client_1_deps), client_2_config,
|
|
std::move(client_2_deps)));
|
|
ConnectFakeSignaling();
|
|
|
|
// Set "offer to receive audio/video" without adding any tracks, so we just
|
|
// set up ICE/DTLS with no media.
|
|
PeerConnectionInterface::RTCOfferAnswerOptions options;
|
|
options.offer_to_receive_audio = 1;
|
|
options.offer_to_receive_video = 1;
|
|
caller()->SetOfferAnswerOptions(options);
|
|
caller()->CreateAndSetAndSignalOffer();
|
|
bool wait_res = true;
|
|
// TODO(bugs.webrtc.org/9219): When IceConnectionState is implemented
|
|
// properly, should be able to just wait for a state of "failed" instead of
|
|
// waiting a fixed 10 seconds.
|
|
WAIT_(DtlsConnected(), kDefaultTimeout, wait_res);
|
|
ASSERT_FALSE(wait_res);
|
|
|
|
EXPECT_GT(client_1_cert_verifier->call_count_, 0u);
|
|
EXPECT_GT(client_2_cert_verifier->call_count_, 0u);
|
|
}
|
|
|
|
// Test that we can get capture start ntp time.
|
|
TEST_P(PeerConnectionIntegrationTest, GetCaptureStartNtpTimeWithOldStatsApi) {
|
|
ASSERT_TRUE(CreatePeerConnectionWrappers());
|
|
ConnectFakeSignaling();
|
|
caller()->AddAudioTrack();
|
|
|
|
callee()->AddAudioTrack();
|
|
|
|
// Do offer/answer, wait for the callee to receive some frames.
|
|
caller()->CreateAndSetAndSignalOffer();
|
|
ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
|
|
|
|
// Get the remote audio track created on the receiver, so they can be used as
|
|
// GetStats filters.
|
|
auto receivers = callee()->pc()->GetReceivers();
|
|
ASSERT_EQ(1u, receivers.size());
|
|
auto remote_audio_track = receivers[0]->track();
|
|
|
|
// Get the audio output level stats. Note that the level is not available
|
|
// until an RTCP packet has been received.
|
|
EXPECT_TRUE_WAIT(callee()->OldGetStatsForTrack(remote_audio_track.get())
|
|
->CaptureStartNtpTime() > 0,
|
|
2 * kMaxWaitForFramesMs);
|
|
}
|
|
|
|
// Test that firewalling the ICE connection causes the clients to identify the
|
|
// disconnected state and then removing the firewall causes them to reconnect.
|
|
class PeerConnectionIntegrationIceStatesTest
|
|
: public PeerConnectionIntegrationBaseTest,
|
|
public ::testing::WithParamInterface<
|
|
std::tuple<SdpSemantics, std::tuple<std::string, uint32_t>>> {
|
|
protected:
|
|
PeerConnectionIntegrationIceStatesTest()
|
|
: PeerConnectionIntegrationBaseTest(std::get<0>(GetParam())) {
|
|
port_allocator_flags_ = std::get<1>(std::get<1>(GetParam()));
|
|
}
|
|
|
|
void StartStunServer(const SocketAddress& server_address) {
|
|
stun_server_ = cricket::TestStunServer::Create(firewall(), server_address,
|
|
*network_thread());
|
|
}
|
|
|
|
bool TestIPv6() {
|
|
return (port_allocator_flags_ & cricket::PORTALLOCATOR_ENABLE_IPV6);
|
|
}
|
|
|
|
void SetPortAllocatorFlags() {
|
|
PeerConnectionIntegrationBaseTest::SetPortAllocatorFlags(
|
|
port_allocator_flags_, port_allocator_flags_);
|
|
}
|
|
|
|
std::vector<SocketAddress> CallerAddresses() {
|
|
std::vector<SocketAddress> addresses;
|
|
addresses.push_back(SocketAddress("1.1.1.1", 0));
|
|
if (TestIPv6()) {
|
|
addresses.push_back(SocketAddress("1111:0:a:b:c:d:e:f", 0));
|
|
}
|
|
return addresses;
|
|
}
|
|
|
|
std::vector<SocketAddress> CalleeAddresses() {
|
|
std::vector<SocketAddress> addresses;
|
|
addresses.push_back(SocketAddress("2.2.2.2", 0));
|
|
if (TestIPv6()) {
|
|
addresses.push_back(SocketAddress("2222:0:a:b:c:d:e:f", 0));
|
|
}
|
|
return addresses;
|
|
}
|
|
|
|
void SetUpNetworkInterfaces() {
|
|
// Remove the default interfaces added by the test infrastructure.
|
|
caller()->network_manager()->RemoveInterface(kDefaultLocalAddress);
|
|
callee()->network_manager()->RemoveInterface(kDefaultLocalAddress);
|
|
|
|
// Add network addresses for test.
|
|
for (const auto& caller_address : CallerAddresses()) {
|
|
caller()->network_manager()->AddInterface(caller_address);
|
|
}
|
|
for (const auto& callee_address : CalleeAddresses()) {
|
|
callee()->network_manager()->AddInterface(callee_address);
|
|
}
|
|
}
|
|
|
|
private:
|
|
uint32_t port_allocator_flags_;
|
|
cricket::TestStunServer::StunServerPtr stun_server_;
|
|
};
|
|
|
|
// Ensure FakeClockForTest is constructed first (see class for rationale).
|
|
class PeerConnectionIntegrationIceStatesTestWithFakeClock
|
|
: public FakeClockForTest,
|
|
public PeerConnectionIntegrationIceStatesTest {};
|
|
|
|
#if !defined(THREAD_SANITIZER)
|
|
// This test provokes TSAN errors. bugs.webrtc.org/11282
|
|
|
|
// Tests that the PeerConnection goes through all the ICE gathering/connection
|
|
// states over the duration of the call. This includes Disconnected and Failed
|
|
// states, induced by putting a firewall between the peers and waiting for them
|
|
// to time out.
|
|
TEST_P(PeerConnectionIntegrationIceStatesTestWithFakeClock, VerifyIceStates) {
|
|
const SocketAddress kStunServerAddress =
|
|
SocketAddress("99.99.99.1", cricket::STUN_SERVER_PORT);
|
|
StartStunServer(kStunServerAddress);
|
|
|
|
PeerConnectionInterface::RTCConfiguration config;
|
|
PeerConnectionInterface::IceServer ice_stun_server;
|
|
ice_stun_server.urls.push_back(
|
|
"stun:" + kStunServerAddress.HostAsURIString() + ":" +
|
|
kStunServerAddress.PortAsString());
|
|
config.servers.push_back(ice_stun_server);
|
|
|
|
ASSERT_TRUE(CreatePeerConnectionWrappersWithConfig(config, config));
|
|
ConnectFakeSignaling();
|
|
SetPortAllocatorFlags();
|
|
SetUpNetworkInterfaces();
|
|
caller()->AddAudioVideoTracks();
|
|
callee()->AddAudioVideoTracks();
|
|
|
|
// Initial state before anything happens.
|
|
ASSERT_EQ(PeerConnectionInterface::kIceGatheringNew,
|
|
caller()->ice_gathering_state());
|
|
ASSERT_EQ(PeerConnectionInterface::kIceConnectionNew,
|
|
caller()->ice_connection_state());
|
|
ASSERT_EQ(PeerConnectionInterface::kIceConnectionNew,
|
|
caller()->standardized_ice_connection_state());
|
|
|
|
// Start the call by creating the offer, setting it as the local description,
|
|
// then sending it to the peer who will respond with an answer. This happens
|
|
// asynchronously so that we can watch the states as it runs in the
|
|
// background.
|
|
caller()->CreateAndSetAndSignalOffer();
|
|
|
|
ASSERT_EQ_SIMULATED_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
|
|
caller()->ice_connection_state(), kDefaultTimeout,
|
|
FakeClock());
|
|
ASSERT_EQ_SIMULATED_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
|
|
caller()->standardized_ice_connection_state(),
|
|
kDefaultTimeout, FakeClock());
|
|
|
|
// Verify that the observer was notified of the intermediate transitions.
|
|
EXPECT_THAT(caller()->ice_connection_state_history(),
|
|
ElementsAre(PeerConnectionInterface::kIceConnectionChecking,
|
|
PeerConnectionInterface::kIceConnectionConnected,
|
|
PeerConnectionInterface::kIceConnectionCompleted));
|
|
EXPECT_THAT(caller()->standardized_ice_connection_state_history(),
|
|
ElementsAre(PeerConnectionInterface::kIceConnectionChecking,
|
|
PeerConnectionInterface::kIceConnectionConnected,
|
|
PeerConnectionInterface::kIceConnectionCompleted));
|
|
EXPECT_THAT(
|
|
caller()->peer_connection_state_history(),
|
|
ElementsAre(PeerConnectionInterface::PeerConnectionState::kConnecting,
|
|
PeerConnectionInterface::PeerConnectionState::kConnected));
|
|
EXPECT_THAT(caller()->ice_gathering_state_history(),
|
|
ElementsAre(PeerConnectionInterface::kIceGatheringGathering,
|
|
PeerConnectionInterface::kIceGatheringComplete));
|
|
|
|
// Block connections to/from the caller and wait for ICE to become
|
|
// disconnected.
|
|
for (const auto& caller_address : CallerAddresses()) {
|
|
firewall()->AddRule(false, rtc::FP_ANY, rtc::FD_ANY, caller_address);
|
|
}
|
|
RTC_LOG(LS_INFO) << "Firewall rules applied";
|
|
ASSERT_EQ_SIMULATED_WAIT(PeerConnectionInterface::kIceConnectionDisconnected,
|
|
caller()->ice_connection_state(), kDefaultTimeout,
|
|
FakeClock());
|
|
ASSERT_EQ_SIMULATED_WAIT(PeerConnectionInterface::kIceConnectionDisconnected,
|
|
caller()->standardized_ice_connection_state(),
|
|
kDefaultTimeout, FakeClock());
|
|
|
|
// Let ICE re-establish by removing the firewall rules.
|
|
firewall()->ClearRules();
|
|
RTC_LOG(LS_INFO) << "Firewall rules cleared";
|
|
ASSERT_EQ_SIMULATED_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
|
|
caller()->ice_connection_state(), kDefaultTimeout,
|
|
FakeClock());
|
|
ASSERT_EQ_SIMULATED_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
|
|
caller()->standardized_ice_connection_state(),
|
|
kDefaultTimeout, FakeClock());
|
|
|
|
// According to RFC7675, if there is no response within 30 seconds then the
|
|
// peer should consider the other side to have rejected the connection. This
|
|
// is signaled by the state transitioning to "failed".
|
|
constexpr int kConsentTimeout = 30000;
|
|
for (const auto& caller_address : CallerAddresses()) {
|
|
firewall()->AddRule(false, rtc::FP_ANY, rtc::FD_ANY, caller_address);
|
|
}
|
|
RTC_LOG(LS_INFO) << "Firewall rules applied again";
|
|
ASSERT_EQ_SIMULATED_WAIT(PeerConnectionInterface::kIceConnectionFailed,
|
|
caller()->ice_connection_state(), kConsentTimeout,
|
|
FakeClock());
|
|
ASSERT_EQ_SIMULATED_WAIT(PeerConnectionInterface::kIceConnectionFailed,
|
|
caller()->standardized_ice_connection_state(),
|
|
kConsentTimeout, FakeClock());
|
|
}
|
|
#endif
|
|
|
|
// This test sets up a call that's transferred to a new caller with a different
|
|
// DTLS fingerprint.
|
|
TEST_P(PeerConnectionIntegrationTest, CallTransferredForCallee) {
|
|
ASSERT_TRUE(CreatePeerConnectionWrappers());
|
|
ConnectFakeSignaling();
|
|
caller()->AddAudioVideoTracks();
|
|
callee()->AddAudioVideoTracks();
|
|
caller()->CreateAndSetAndSignalOffer();
|
|
ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
|
|
|
|
// Keep the original peer around which will still send packets to the
|
|
// receiving client. These SRTP packets will be dropped.
|
|
std::unique_ptr<PeerConnectionIntegrationWrapper> original_peer(
|
|
SetCallerPcWrapperAndReturnCurrent(
|
|
CreatePeerConnectionWrapperWithAlternateKey().release()));
|
|
// TODO(deadbeef): Why do we call Close here? That goes against the comment
|
|
// directly above.
|
|
original_peer->pc()->Close();
|
|
|
|
ConnectFakeSignaling();
|
|
caller()->AddAudioVideoTracks();
|
|
caller()->CreateAndSetAndSignalOffer();
|
|
ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
|
|
// Wait for some additional frames to be transmitted end-to-end.
|
|
MediaExpectations media_expectations;
|
|
media_expectations.ExpectBidirectionalAudioAndVideo();
|
|
ASSERT_TRUE(ExpectNewFrames(media_expectations));
|
|
}
|
|
|
|
// This test sets up a call that's transferred to a new callee with a different
|
|
// DTLS fingerprint.
|
|
TEST_P(PeerConnectionIntegrationTest, CallTransferredForCaller) {
|
|
ASSERT_TRUE(CreatePeerConnectionWrappers());
|
|
ConnectFakeSignaling();
|
|
caller()->AddAudioVideoTracks();
|
|
callee()->AddAudioVideoTracks();
|
|
caller()->CreateAndSetAndSignalOffer();
|
|
ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
|
|
|
|
// Keep the original peer around which will still send packets to the
|
|
// receiving client. These SRTP packets will be dropped.
|
|
std::unique_ptr<PeerConnectionIntegrationWrapper> original_peer(
|
|
SetCalleePcWrapperAndReturnCurrent(
|
|
CreatePeerConnectionWrapperWithAlternateKey().release()));
|
|
// TODO(deadbeef): Why do we call Close here? That goes against the comment
|
|
// directly above.
|
|
original_peer->pc()->Close();
|
|
|
|
ConnectFakeSignaling();
|
|
callee()->AddAudioVideoTracks();
|
|
caller()->SetOfferAnswerOptions(IceRestartOfferAnswerOptions());
|
|
caller()->CreateAndSetAndSignalOffer();
|
|
ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
|
|
// Wait for some additional frames to be transmitted end-to-end.
|
|
MediaExpectations media_expectations;
|
|
media_expectations.ExpectBidirectionalAudioAndVideo();
|
|
ASSERT_TRUE(ExpectNewFrames(media_expectations));
|
|
}
|
|
|
|
INSTANTIATE_TEST_SUITE_P(PeerConnectionIntegrationTest,
|
|
PeerConnectionIntegrationTest,
|
|
Values(SdpSemantics::kPlanB_DEPRECATED,
|
|
SdpSemantics::kUnifiedPlan));
|
|
|
|
constexpr uint32_t kFlagsIPv4NoStun = cricket::PORTALLOCATOR_DISABLE_TCP |
|
|
cricket::PORTALLOCATOR_DISABLE_STUN |
|
|
cricket::PORTALLOCATOR_DISABLE_RELAY;
|
|
constexpr uint32_t kFlagsIPv6NoStun =
|
|
cricket::PORTALLOCATOR_DISABLE_TCP | cricket::PORTALLOCATOR_DISABLE_STUN |
|
|
cricket::PORTALLOCATOR_ENABLE_IPV6 | cricket::PORTALLOCATOR_DISABLE_RELAY;
|
|
constexpr uint32_t kFlagsIPv4Stun =
|
|
cricket::PORTALLOCATOR_DISABLE_TCP | cricket::PORTALLOCATOR_DISABLE_RELAY;
|
|
|
|
INSTANTIATE_TEST_SUITE_P(
|
|
PeerConnectionIntegrationTest,
|
|
PeerConnectionIntegrationIceStatesTestWithFakeClock,
|
|
Combine(Values(SdpSemantics::kPlanB_DEPRECATED, SdpSemantics::kUnifiedPlan),
|
|
Values(std::make_pair("IPv4 no STUN", kFlagsIPv4NoStun),
|
|
std::make_pair("IPv6 no STUN", kFlagsIPv6NoStun),
|
|
std::make_pair("IPv4 with STUN", kFlagsIPv4Stun))));
|
|
|
|
} // namespace
|
|
} // namespace webrtc
|