If gather_continually is set to true, keep the last port allocator session running while stopping all existing process of getting ports (when p2ptransportchannel first becomes writable).
BUG=5034
Review URL: https://codereview.webrtc.org/1359363003
Cr-Original-Commit-Position: refs/heads/master@{#10110}
Cr-Mirrored-From: https://chromium.googlesource.com/external/webrtc
Cr-Mirrored-Commit: 98db68fdaa12c5bfca8b0004eba24d034f32de71
diff --git a/p2p/base/p2ptransportchannel.cc b/p2p/base/p2ptransportchannel.cc
index 15ac006..cce20f4 100644
--- a/p2p/base/p2ptransportchannel.cc
+++ b/p2p/base/p2ptransportchannel.cc
@@ -1070,12 +1070,21 @@
// was writable, go into the writable state.
void P2PTransportChannel::HandleWritable() {
ASSERT(worker_thread_ == rtc::Thread::Current());
- if (!writable()) {
- for (uint32 i = 0; i < allocator_sessions_.size(); ++i) {
- if (allocator_sessions_[i]->IsGettingPorts()) {
- allocator_sessions_[i]->StopGettingPorts();
- }
+ if (writable()) {
+ return;
+ }
+
+ for (PortAllocatorSession* session : allocator_sessions_) {
+ if (!session->IsGettingPorts()) {
+ continue;
}
+ // If gathering continually, keep the last session running so that it
+ // will gather candidates if the networks change.
+ if (gather_continually_ && session == allocator_sessions_.back()) {
+ session->ClearGettingPorts();
+ break;
+ }
+ session->StopGettingPorts();
}
was_writable_ = true;
diff --git a/p2p/base/p2ptransportchannel_unittest.cc b/p2p/base/p2ptransportchannel_unittest.cc
index 8c25d82..4add040 100644
--- a/p2p/base/p2ptransportchannel_unittest.cc
+++ b/p2p/base/p2ptransportchannel_unittest.cc
@@ -1439,6 +1439,34 @@
DestroyChannels();
}
+// Test that if continual gathering is set to true, ICE gathering state will
+// not change to "Complete", and vice versa.
+TEST_F(P2PTransportChannelTest, TestContinualGathering) {
+ ConfigureEndpoints(OPEN, OPEN, kDefaultPortAllocatorFlags,
+ kDefaultPortAllocatorFlags);
+ SetAllocationStepDelay(0, kDefaultStepDelay);
+ SetAllocationStepDelay(1, kDefaultStepDelay);
+ CreateChannels(1);
+ cricket::IceConfig config = CreateIceConfig(1000, true);
+ ep1_ch1()->SetIceConfig(config);
+ // By default, ep2 does not gather continually.
+
+ EXPECT_TRUE_WAIT_MARGIN(ep1_ch1() != NULL && ep2_ch1() != NULL &&
+ ep1_ch1()->receiving() && ep1_ch1()->writable() &&
+ ep2_ch1()->receiving() && ep2_ch1()->writable(),
+ 1000, 1000);
+ WAIT(cricket::IceGatheringState::kIceGatheringComplete ==
+ ep1_ch1()->gathering_state(),
+ 1000);
+ EXPECT_EQ(cricket::IceGatheringState::kIceGatheringGathering,
+ ep1_ch1()->gathering_state());
+ // By now, ep2 should have completed gathering.
+ EXPECT_EQ(cricket::IceGatheringState::kIceGatheringComplete,
+ ep2_ch1()->gathering_state());
+
+ DestroyChannels();
+}
+
// Test what happens when we have 2 users behind the same NAT. This can lead
// to interesting behavior because the STUN server will only give out the
// address of the outermost NAT.
diff --git a/p2p/base/portallocator.h b/p2p/base/portallocator.h
index 6e3efa8..69b5ed0 100644
--- a/p2p/base/portallocator.h
+++ b/p2p/base/portallocator.h
@@ -91,6 +91,9 @@
// Starts gathering STUN and Relay configurations.
virtual void StartGettingPorts() = 0;
virtual void StopGettingPorts() = 0;
+ // Only stop the existing gathering process but may start new ones if needed.
+ virtual void ClearGettingPorts() = 0;
+ // Whether the process of getting ports has been stopped.
virtual bool IsGettingPorts() = 0;
sigslot::signal2<PortAllocatorSession*, PortInterface*> SignalPortReady;
diff --git a/p2p/client/basicportallocator.cc b/p2p/client/basicportallocator.cc
index 11d0cef..3c77b4f 100644
--- a/p2p/client/basicportallocator.cc
+++ b/p2p/client/basicportallocator.cc
@@ -192,10 +192,14 @@
void BasicPortAllocatorSession::StopGettingPorts() {
ASSERT(rtc::Thread::Current() == network_thread_);
running_ = false;
+ network_thread_->Post(this, MSG_CONFIG_STOP);
+ ClearGettingPorts();
+}
+
+void BasicPortAllocatorSession::ClearGettingPorts() {
network_thread_->Clear(this, MSG_ALLOCATE);
for (uint32 i = 0; i < sequences_.size(); ++i)
sequences_[i]->Stop();
- network_thread_->Post(this, MSG_CONFIG_STOP);
}
void BasicPortAllocatorSession::OnMessage(rtc::Message *message) {
diff --git a/p2p/client/basicportallocator.h b/p2p/client/basicportallocator.h
index 37ce1a0..ac2cfbf 100644
--- a/p2p/client/basicportallocator.h
+++ b/p2p/client/basicportallocator.h
@@ -112,6 +112,7 @@
virtual void StartGettingPorts();
virtual void StopGettingPorts();
+ virtual void ClearGettingPorts();
virtual bool IsGettingPorts() { return running_; }
protected:
diff --git a/p2p/client/fakeportallocator.h b/p2p/client/fakeportallocator.h
index 9e53bc0..dca86f6 100644
--- a/p2p/client/fakeportallocator.h
+++ b/p2p/client/fakeportallocator.h
@@ -63,6 +63,8 @@
virtual void StopGettingPorts() { running_ = false; }
virtual bool IsGettingPorts() { return running_; }
+ virtual void ClearGettingPorts() {}
+
int port_config_count() { return port_config_count_; }
void AddPort(cricket::Port* port) {
diff --git a/p2p/client/portallocator_unittest.cc b/p2p/client/portallocator_unittest.cc
index 2893807..92f995a 100644
--- a/p2p/client/portallocator_unittest.cc
+++ b/p2p/client/portallocator_unittest.cc
@@ -1279,3 +1279,45 @@
kClientAddr);
EXPECT_EQ(4U, candidates_.size());
}
+
+TEST_F(PortAllocatorTest, TestStopGettingPorts) {
+ AddInterface(kClientAddr);
+ allocator_->set_step_delay(cricket::kDefaultStepDelay);
+ EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP));
+ session_->StartGettingPorts();
+ ASSERT_EQ_WAIT(2U, candidates_.size(), 1000);
+ EXPECT_EQ(2U, ports_.size());
+ session_->StopGettingPorts();
+ EXPECT_TRUE_WAIT(candidate_allocation_done_, 1000);
+
+ // After stopping getting ports, adding a new interface will not start
+ // getting ports again.
+ candidates_.clear();
+ ports_.clear();
+ candidate_allocation_done_ = false;
+ network_manager_.AddInterface(kClientAddr2);
+ rtc::Thread::Current()->ProcessMessages(1000);
+ EXPECT_EQ(0U, candidates_.size());
+ EXPECT_EQ(0U, ports_.size());
+}
+
+TEST_F(PortAllocatorTest, TestClearGettingPorts) {
+ AddInterface(kClientAddr);
+ allocator_->set_step_delay(cricket::kDefaultStepDelay);
+ EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP));
+ session_->StartGettingPorts();
+ ASSERT_EQ_WAIT(2U, candidates_.size(), 1000);
+ EXPECT_EQ(2U, ports_.size());
+ session_->ClearGettingPorts();
+ WAIT(candidate_allocation_done_, 1000);
+ EXPECT_FALSE(candidate_allocation_done_);
+
+ // After clearing getting ports, adding a new interface will start getting
+ // ports again.
+ candidates_.clear();
+ ports_.clear();
+ candidate_allocation_done_ = false;
+ network_manager_.AddInterface(kClientAddr2);
+ ASSERT_EQ_WAIT(2U, candidates_.size(), 1000);
+ EXPECT_EQ(2U, ports_.size());
+}