Implement Connection::ForgetLearnedState()
This patch adds a new ForgetLearnedState() method on a Connection. The method, puts the connection into a state similar to when it was just created. - write_state = STATE_WRITE_INIT - receving = false - throw away all pending request - reset RttEstimate All other state is kept unchanged. Note: It does not trigger SignalStateChange A subsequent patch will expose the method to the IceController. BUG: webrtc:11463 Change-Id: I055e8cd067e1bc4fd5ad64dd10f458554dbc87e3 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/171805 Reviewed-by: Harald Alvestrand <hta@webrtc.org> Commit-Queue: Jonas Oreland <jonaso@webrtc.org> Cr-Commit-Position: refs/heads/master@{#30916}
This commit is contained in:
parent
749dff12b5
commit
ef60c2b0ad
@ -1334,6 +1334,15 @@ bool Connection::ShouldSendGoogPing(const StunMessage* message) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void Connection::ForgetLearnedState() {
|
||||
RTC_LOG(LS_INFO) << ToString() << ": Connection forget learned state";
|
||||
requests_.Clear();
|
||||
receiving_ = false;
|
||||
write_state_ = STATE_WRITE_INIT;
|
||||
rtt_estimate_.Reset();
|
||||
pings_since_last_response_.clear();
|
||||
}
|
||||
|
||||
ProxyConnection::ProxyConnection(Port* port,
|
||||
size_t index,
|
||||
const Candidate& remote_candidate)
|
||||
|
||||
@ -303,6 +303,20 @@ class Connection : public CandidatePairInterface,
|
||||
return rtt_estimate_;
|
||||
}
|
||||
|
||||
// Reset the connection to a state of a newly connected.
|
||||
// - STATE_WRITE_INIT
|
||||
// - receving = false
|
||||
// - throw away all pending request
|
||||
// - reset RttEstimate
|
||||
//
|
||||
// Keep the following unchanged:
|
||||
// - connected
|
||||
// - remote_candidate
|
||||
// - statistics
|
||||
//
|
||||
// Does not trigger SignalStateChange
|
||||
void ForgetLearnedState();
|
||||
|
||||
void SendStunBindingResponse(const StunMessage* request);
|
||||
void SendGoogPingResponse(const StunMessage* request);
|
||||
void SendResponseMessage(const StunMessage& response);
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@ -3363,4 +3364,158 @@ TEST_F(PortTest, TestAddConnectionWithSameAddress) {
|
||||
EXPECT_TRUE(port->GetConnection(address) != nullptr);
|
||||
}
|
||||
|
||||
// TODO(webrtc:11463) : Move Connection tests into separate unit test
|
||||
// splitting out shared test code as needed.
|
||||
|
||||
class ConnectionTest : public PortTest {
|
||||
public:
|
||||
ConnectionTest() {
|
||||
lport_ = CreateTestPort(kLocalAddr1, "lfrag", "lpass");
|
||||
rport_ = CreateTestPort(kLocalAddr2, "rfrag", "rpass");
|
||||
lport_->SetIceRole(cricket::ICEROLE_CONTROLLING);
|
||||
lport_->SetIceTiebreaker(kTiebreaker1);
|
||||
rport_->SetIceRole(cricket::ICEROLE_CONTROLLED);
|
||||
rport_->SetIceTiebreaker(kTiebreaker2);
|
||||
|
||||
lport_->PrepareAddress();
|
||||
rport_->PrepareAddress();
|
||||
}
|
||||
|
||||
rtc::ScopedFakeClock clock_;
|
||||
int num_state_changes_ = 0;
|
||||
|
||||
Connection* CreateConnection(IceRole role) {
|
||||
Connection* conn;
|
||||
if (role == cricket::ICEROLE_CONTROLLING) {
|
||||
conn = lport_->CreateConnection(rport_->Candidates()[0],
|
||||
Port::ORIGIN_MESSAGE);
|
||||
} else {
|
||||
conn = rport_->CreateConnection(lport_->Candidates()[0],
|
||||
Port::ORIGIN_MESSAGE);
|
||||
}
|
||||
conn->SignalStateChange.connect(this,
|
||||
&ConnectionTest::OnConnectionStateChange);
|
||||
return conn;
|
||||
}
|
||||
|
||||
void SendPingAndCaptureReply(Connection* lconn,
|
||||
Connection* rconn,
|
||||
int64_t ms,
|
||||
rtc::BufferT<uint8_t>* reply) {
|
||||
TestPort* lport =
|
||||
lconn->PortForTest() == lport_.get() ? lport_.get() : rport_.get();
|
||||
TestPort* rport =
|
||||
rconn->PortForTest() == rport_.get() ? rport_.get() : lport_.get();
|
||||
lconn->Ping(rtc::TimeMillis());
|
||||
ASSERT_TRUE_WAIT(lport->last_stun_msg(), kDefaultTimeout);
|
||||
ASSERT_TRUE(lport->last_stun_buf());
|
||||
rconn->OnReadPacket(lport->last_stun_buf()->data<char>(),
|
||||
lport->last_stun_buf()->size(),
|
||||
/* packet_time_us */ -1);
|
||||
clock_.AdvanceTime(webrtc::TimeDelta::Millis(ms));
|
||||
ASSERT_TRUE_WAIT(rport->last_stun_msg(), kDefaultTimeout);
|
||||
ASSERT_TRUE(rport->last_stun_buf());
|
||||
*reply = std::move(*rport->last_stun_buf());
|
||||
}
|
||||
|
||||
void SendPingAndReceiveResponse(Connection* lconn,
|
||||
Connection* rconn,
|
||||
int64_t ms) {
|
||||
rtc::BufferT<uint8_t> reply;
|
||||
SendPingAndCaptureReply(lconn, rconn, ms, &reply);
|
||||
lconn->OnReadPacket(reply.data<char>(), reply.size(),
|
||||
/* packet_time_us */ -1);
|
||||
}
|
||||
|
||||
void OnConnectionStateChange(Connection* connection) { num_state_changes_++; }
|
||||
|
||||
private:
|
||||
std::unique_ptr<TestPort> lport_;
|
||||
std::unique_ptr<TestPort> rport_;
|
||||
};
|
||||
|
||||
TEST_F(ConnectionTest, ConnectionForgetLearnedState) {
|
||||
Connection* lconn = CreateConnection(ICEROLE_CONTROLLING);
|
||||
Connection* rconn = CreateConnection(ICEROLE_CONTROLLED);
|
||||
|
||||
EXPECT_FALSE(lconn->writable());
|
||||
EXPECT_FALSE(lconn->receiving());
|
||||
EXPECT_TRUE(std::isnan(lconn->GetRttEstimate().GetAverage()));
|
||||
EXPECT_EQ(lconn->GetRttEstimate().GetVariance(),
|
||||
std::numeric_limits<double>::infinity());
|
||||
|
||||
SendPingAndReceiveResponse(lconn, rconn, 10);
|
||||
|
||||
EXPECT_TRUE(lconn->writable());
|
||||
EXPECT_TRUE(lconn->receiving());
|
||||
EXPECT_EQ(lconn->GetRttEstimate().GetAverage(), 10);
|
||||
EXPECT_EQ(lconn->GetRttEstimate().GetVariance(),
|
||||
std::numeric_limits<double>::infinity());
|
||||
|
||||
SendPingAndReceiveResponse(lconn, rconn, 11);
|
||||
|
||||
EXPECT_TRUE(lconn->writable());
|
||||
EXPECT_TRUE(lconn->receiving());
|
||||
EXPECT_NEAR(lconn->GetRttEstimate().GetAverage(), 10, 0.5);
|
||||
EXPECT_LT(lconn->GetRttEstimate().GetVariance(),
|
||||
std::numeric_limits<double>::infinity());
|
||||
|
||||
lconn->ForgetLearnedState();
|
||||
|
||||
EXPECT_FALSE(lconn->writable());
|
||||
EXPECT_FALSE(lconn->receiving());
|
||||
EXPECT_TRUE(std::isnan(lconn->GetRttEstimate().GetAverage()));
|
||||
EXPECT_EQ(lconn->GetRttEstimate().GetVariance(),
|
||||
std::numeric_limits<double>::infinity());
|
||||
}
|
||||
|
||||
TEST_F(ConnectionTest, ConnectionForgetLearnedStateDiscardsPendingPings) {
|
||||
Connection* lconn = CreateConnection(ICEROLE_CONTROLLING);
|
||||
Connection* rconn = CreateConnection(ICEROLE_CONTROLLED);
|
||||
|
||||
SendPingAndReceiveResponse(lconn, rconn, 10);
|
||||
|
||||
EXPECT_TRUE(lconn->writable());
|
||||
EXPECT_TRUE(lconn->receiving());
|
||||
|
||||
rtc::BufferT<uint8_t> reply;
|
||||
SendPingAndCaptureReply(lconn, rconn, 10, &reply);
|
||||
|
||||
lconn->ForgetLearnedState();
|
||||
|
||||
EXPECT_FALSE(lconn->writable());
|
||||
EXPECT_FALSE(lconn->receiving());
|
||||
|
||||
lconn->OnReadPacket(reply.data<char>(), reply.size(),
|
||||
/* packet_time_us */ -1);
|
||||
|
||||
// That reply was discarded due to the ForgetLearnedState() while it was
|
||||
// outstanding.
|
||||
EXPECT_FALSE(lconn->writable());
|
||||
EXPECT_FALSE(lconn->receiving());
|
||||
|
||||
// But sending a new ping and getting a reply works.
|
||||
SendPingAndReceiveResponse(lconn, rconn, 11);
|
||||
EXPECT_TRUE(lconn->writable());
|
||||
EXPECT_TRUE(lconn->receiving());
|
||||
}
|
||||
|
||||
TEST_F(ConnectionTest, ConnectionForgetLearnedStateDoesNotTriggerStateChange) {
|
||||
Connection* lconn = CreateConnection(ICEROLE_CONTROLLING);
|
||||
Connection* rconn = CreateConnection(ICEROLE_CONTROLLED);
|
||||
|
||||
EXPECT_EQ(num_state_changes_, 0);
|
||||
SendPingAndReceiveResponse(lconn, rconn, 10);
|
||||
|
||||
EXPECT_TRUE(lconn->writable());
|
||||
EXPECT_TRUE(lconn->receiving());
|
||||
EXPECT_EQ(num_state_changes_, 2);
|
||||
|
||||
lconn->ForgetLearnedState();
|
||||
|
||||
EXPECT_FALSE(lconn->writable());
|
||||
EXPECT_FALSE(lconn->receiving());
|
||||
EXPECT_EQ(num_state_changes_, 2);
|
||||
}
|
||||
|
||||
} // namespace cricket
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user