Propagate clock into StunRequest
While at it migrate some integers to strong time types
Update Send function signature to use unique_ptr to communicate request
is passed with ownership
Bug: webrtc:42223992
Change-Id: I177dc20ce1d40d5dec9efaf9f37b46ee4f994ea1
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/407080
Reviewed-by: Per Kjellander <perkj@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#45510}
diff --git a/p2p/BUILD.gn b/p2p/BUILD.gn
index 2baa0e2..281a0d0 100644
--- a/p2p/BUILD.gn
+++ b/p2p/BUILD.gn
@@ -758,6 +758,8 @@
"../api:local_network_access_permission",
"../api:packet_socket_factory",
"../api/transport:stun_types",
+ "../api/units:time_delta",
+ "../api/units:timestamp",
"../rtc_base:async_packet_socket",
"../rtc_base:checks",
"../rtc_base:dscp",
@@ -787,10 +789,12 @@
deps = [
"../api:array_view",
"../api:sequence_checker",
+ "../api/environment",
"../api/task_queue",
"../api/task_queue:pending_task_safety_flag",
"../api/transport:stun_types",
"../api/units:time_delta",
+ "../api/units:timestamp",
"../rtc_base:byte_buffer",
"../rtc_base:checks",
"../rtc_base:crypto_random",
@@ -920,6 +924,7 @@
"../rtc_base:logging",
"../rtc_base:net_helper",
"../rtc_base:network",
+ "../rtc_base:platform_thread_types",
"../rtc_base:socket",
"../rtc_base:socket_address",
"../rtc_base:ssl",
diff --git a/p2p/base/connection.cc b/p2p/base/connection.cc
index 5bdf070..1afd41b 100644
--- a/p2p/base/connection.cc
+++ b/p2p/base/connection.cc
@@ -180,7 +180,8 @@
// A ConnectionRequest is a STUN binding used to determine writability.
class Connection::ConnectionRequest : public StunRequest {
public:
- ConnectionRequest(StunRequestManager& manager,
+ ConnectionRequest(const Environment& env,
+ StunRequestManager& manager,
Connection* connection,
std::unique_ptr<IceMessage> message);
void OnResponse(StunMessage* response) override;
@@ -194,10 +195,11 @@
};
Connection::ConnectionRequest::ConnectionRequest(
+ const Environment& env,
StunRequestManager& manager,
Connection* connection,
std::unique_ptr<IceMessage> message)
- : StunRequest(manager, std::move(message)), connection_(connection) {}
+ : StunRequest(env, manager, std::move(message)), connection_(connection) {}
void Connection::ConnectionRequest::OnResponse(StunMessage* response) {
RTC_DCHECK_RUN_ON(connection_->network_thread_);
@@ -1103,19 +1105,20 @@
bool has_delta = delta != nullptr;
auto req = std::make_unique<ConnectionRequest>(
- requests_, this, BuildPingRequest(std::move(delta)));
+ env_, requests_, this, BuildPingRequest(std::move(delta)));
if (!has_delta && ShouldSendGoogPing(req->msg())) {
auto message = std::make_unique<IceMessage>(GOOG_PING_REQUEST, req->id());
message->AddMessageIntegrity32(remote_candidate_.password());
- req.reset(new ConnectionRequest(requests_, this, std::move(message)));
+ req = std::make_unique<ConnectionRequest>(env_, requests_, this,
+ std::move(message));
}
pings_since_last_response_.push_back(SentPing(req->id(), now, nomination));
RTC_LOG(LS_VERBOSE) << ToString()
<< ": Sending STUN ping, id=" << hex_encode(req->id())
<< ", nomination=" << nomination_;
- requests_.Send(req.release());
+ requests_.Send(std::move(req));
state_ = IceCandidatePairState::IN_PROGRESS;
num_pings_sent_++;
}
@@ -1513,7 +1516,7 @@
// connection.
LoggingSeverity sev = !writable() ? LS_INFO : LS_VERBOSE;
- TimeDelta rtt = TimeDelta::Millis(request->Elapsed());
+ TimeDelta rtt = request->Elapsed();
if (RTC_LOG_CHECK_LEVEL_V(sev)) {
std::string pings;
diff --git a/p2p/base/stun_port.cc b/p2p/base/stun_port.cc
index b6b2c53..9903a16 100644
--- a/p2p/base/stun_port.cc
+++ b/p2p/base/stun_port.cc
@@ -26,6 +26,8 @@
#include "api/local_network_access_permission.h"
#include "api/packet_socket_factory.h"
#include "api/transport/stun.h"
+#include "api/units/time_delta.h"
+#include "api/units/timestamp.h"
#include "p2p/base/connection.h"
#include "p2p/base/p2p_constants.h"
#include "p2p/base/port.h"
@@ -43,25 +45,27 @@
#include "rtc_base/socket.h"
#include "rtc_base/socket_address.h"
#include "rtc_base/strings/string_builder.h"
-#include "rtc_base/time_utils.h"
#include "system_wrappers/include/metrics.h"
namespace webrtc {
-
+namespace {
// TODO(?): Move these to a common place (used in relayport too)
-const int RETRY_TIMEOUT = 50 * 1000; // 50 seconds
+constexpr TimeDelta kRetryTimeout = TimeDelta::Seconds(50);
// Stop logging errors in UDPPort::SendTo after we have logged
// `kSendErrorLogLimit` messages. Start again after a successful send.
-const int kSendErrorLogLimit = 5;
+constexpr int kSendErrorLogLimit = 5;
+
+} // namespace
// Handles a binding request sent to the STUN server.
class StunBindingRequest : public StunRequest {
public:
StunBindingRequest(UDPPort* port,
const SocketAddress& addr,
- int64_t start_time)
- : StunRequest(port->request_manager(),
+ Timestamp start_time)
+ : StunRequest(port->env(),
+ port->request_manager(),
std::make_unique<StunMessage>(STUN_BINDING_REQUEST)),
port_(port),
server_addr_(addr),
@@ -85,10 +89,10 @@
}
// The keep-alive requests will be stopped after its lifetime has passed.
- if (WithinLifetime(TimeMillis())) {
- port_->request_manager_.SendDelayed(
- new StunBindingRequest(port_, server_addr_, start_time_),
- port_->stun_keepalive_delay());
+ if (WithinLifetime(Connection::AlignTime(env().clock().CurrentTime()))) {
+ port_->request_manager_.Send(std::make_unique<StunBindingRequest>(
+ port_, server_addr_, start_time_),
+ /*delay=*/port_->stun_keepalive_delay());
}
}
@@ -108,11 +112,11 @@
attr ? attr->reason()
: "STUN binding response with no error code attribute.");
- int64_t now = TimeMillis();
- if (WithinLifetime(now) && TimeDiff(now, start_time_) < RETRY_TIMEOUT) {
- port_->request_manager_.SendDelayed(
- new StunBindingRequest(port_, server_addr_, start_time_),
- port_->stun_keepalive_delay());
+ Timestamp now = Connection::AlignTime(env().clock().CurrentTime());
+ if (WithinLifetime(now) && now - start_time_ < kRetryTimeout) {
+ port_->request_manager_.Send(std::make_unique<StunBindingRequest>(
+ port_, server_addr_, start_time_),
+ /*delay=*/port_->stun_keepalive_delay());
}
}
void OnTimeout() override {
@@ -125,17 +129,15 @@
}
private:
- // Returns true if `now` is within the lifetime of the request (a negative
- // lifetime means infinite).
- bool WithinLifetime(int64_t now) const {
- int lifetime = port_->stun_keepalive_lifetime();
- return lifetime < 0 || TimeDiff(now, start_time_) <= lifetime;
+ // Returns true if `now` is within the lifetime of the request.
+ bool WithinLifetime(Timestamp now) const {
+ return now - start_time_ <= port_->stun_keepalive_lifetime();
}
UDPPort* port_;
const SocketAddress server_addr_;
- int64_t start_time_;
+ Timestamp start_time_;
};
UDPPort::AddressResolver::AddressResolver(
@@ -508,8 +510,9 @@
return;
}
- request_manager_.Send(
- new StunBindingRequest(this, stun_addr, TimeMillis()));
+ request_manager_.Send(std::make_unique<StunBindingRequest>(
+ this, stun_addr,
+ Connection::AlignTime(env().clock().CurrentTime())));
});
}
@@ -531,9 +534,10 @@
}
void UDPPort::OnStunBindingRequestSucceeded(
- int rtt_ms,
+ TimeDelta rtt,
const SocketAddress& stun_server_addr,
const SocketAddress& stun_reflected_addr) {
+ int rtt_ms = rtt.ms();
RTC_DCHECK(stats_.stun_binding_responses_received <
stats_.stun_binding_requests_sent);
stats_.stun_binding_responses_received++;
diff --git a/p2p/base/stun_port.h b/p2p/base/stun_port.h
index 1dc4da7..171e232 100644
--- a/p2p/base/stun_port.h
+++ b/p2p/base/stun_port.h
@@ -24,6 +24,7 @@
#include "api/candidate.h"
#include "api/field_trials_view.h"
#include "api/packet_socket_factory.h"
+#include "api/units/time_delta.h"
#include "p2p/base/connection.h"
#include "p2p/base/port.h"
#include "p2p/base/port_interface.h"
@@ -39,10 +40,9 @@
namespace webrtc {
-// Lifetime chosen for STUN ports on low-cost networks.
-static const int INFINITE_LIFETIME = -1;
// Lifetime for STUN ports on high-cost networks: 2 minutes
-static const int HIGH_COST_PORT_KEEPALIVE_LIFETIME = 2 * 60 * 1000;
+inline constexpr TimeDelta kHighCostPortKeepaliveLifetime =
+ TimeDelta::Seconds(2 * 60);
// Communicates using the address on the outside of a NAT.
class RTC_EXPORT UDPPort : public Port {
@@ -105,11 +105,13 @@
void GetStunStats(std::optional<StunStats>* stats) override;
void set_stun_keepalive_delay(const std::optional<int>& delay);
- int stun_keepalive_delay() const { return stun_keepalive_delay_; }
+ TimeDelta stun_keepalive_delay() const {
+ return TimeDelta::Millis(stun_keepalive_delay_);
+ }
// Visible for testing.
- int stun_keepalive_lifetime() const { return stun_keepalive_lifetime_; }
- void set_stun_keepalive_lifetime(int lifetime) {
+ TimeDelta stun_keepalive_lifetime() const { return stun_keepalive_lifetime_; }
+ void set_stun_keepalive_lifetime(TimeDelta lifetime) {
stun_keepalive_lifetime_ = lifetime;
}
@@ -201,7 +203,7 @@
void SendStunBindingRequest(const SocketAddress& stun_addr);
// Below methods handles binding request responses.
- void OnStunBindingRequestSucceeded(int rtt_ms,
+ void OnStunBindingRequestSucceeded(TimeDelta rtt,
const SocketAddress& stun_server_addr,
const SocketAddress& stun_reflected_addr);
void OnStunBindingOrResolveRequestFailed(
@@ -220,11 +222,10 @@
// If this is a low-cost network, it will keep on sending STUN binding
// requests indefinitely to keep the NAT binding alive. Otherwise, stop
- // sending STUN binding requests after HIGH_COST_PORT_KEEPALIVE_LIFETIME.
- int GetStunKeepaliveLifetime() {
- return (network_cost() >= kNetworkCostHigh)
- ? HIGH_COST_PORT_KEEPALIVE_LIFETIME
- : INFINITE_LIFETIME;
+ // sending STUN binding requests after kHighCostPortKeepaliveLifetime.
+ TimeDelta GetStunKeepaliveLifetime() {
+ return (network_cost() >= kNetworkCostHigh) ? kHighCostPortKeepaliveLifetime
+ : TimeDelta::PlusInfinity();
}
ServerAddresses server_addresses_;
@@ -237,7 +238,7 @@
std::unique_ptr<AddressResolver> resolver_;
bool ready_;
int stun_keepalive_delay_;
- int stun_keepalive_lifetime_ = INFINITE_LIFETIME;
+ TimeDelta stun_keepalive_lifetime_ = TimeDelta::PlusInfinity();
DiffServCodePoint dscp_;
StunStats stats_;
diff --git a/p2p/base/stun_port_unittest.cc b/p2p/base/stun_port_unittest.cc
index 6fa8096..99e2e86 100644
--- a/p2p/base/stun_port_unittest.cc
+++ b/p2p/base/stun_port_unittest.cc
@@ -98,9 +98,6 @@
// stun prio = 100 (srflx) << 24 | 40 (IPv6) << 8 | 256 - 1 (component)
constexpr uint32_t kIPv6StunCandidatePriority =
(100 << 24) | (40 << 8) | (256 - 1);
-constexpr int kInfiniteLifetime = -1;
-constexpr int kHighCostPortKeepaliveLifetimeMs = 2 * 60 * 1000;
-
constexpr uint64_t kTiebreakerDefault = 44444;
struct IPAddressTypeTestConfig {
@@ -156,8 +153,7 @@
nat_server_(CreateNatServer(nat_server_address, webrtc::NAT_OPEN_CONE)),
done_(false),
error_(false),
- stun_keepalive_delay_(1),
- stun_keepalive_lifetime_(-1) {
+ stun_keepalive_delay_(1) {
network_ = MakeNetwork(address);
RTC_CHECK(address.family() == nat_server_address.family());
for (const auto& addr : stun_server_addresses) {
@@ -210,10 +206,10 @@
0, 0, stun_servers, std::nullopt);
stun_port_->SetIceTiebreaker(kTiebreakerDefault);
stun_port_->set_stun_keepalive_delay(stun_keepalive_delay_);
- // If `stun_keepalive_lifetime_` is negative, let the stun port
- // choose its lifetime from the network type.
- if (stun_keepalive_lifetime_ >= 0) {
- stun_port_->set_stun_keepalive_lifetime(stun_keepalive_lifetime_);
+ // If `stun_keepalive_lifetime_` is not set, let the stun port choose its
+ // lifetime from the network type.
+ if (stun_keepalive_lifetime_.has_value()) {
+ stun_port_->set_stun_keepalive_lifetime(*stun_keepalive_lifetime_);
}
stun_port_->SignalPortComplete.connect(this,
&StunPortTestBase::OnPortComplete);
@@ -292,7 +288,7 @@
}
void SetKeepaliveDelay(int delay) { stun_keepalive_delay_ = delay; }
- void SetKeepaliveLifetime(int lifetime) {
+ void SetKeepaliveLifetime(TimeDelta lifetime) {
stun_keepalive_lifetime_ = lifetime;
}
@@ -324,7 +320,7 @@
bool done_;
bool error_;
int stun_keepalive_delay_;
- int stun_keepalive_lifetime_;
+ std::optional<TimeDelta> stun_keepalive_lifetime_;
protected:
webrtc::IceCandidateErrorEvent error_event_;
@@ -653,43 +649,41 @@
// type on a STUN port. Also test that it will be updated if the network type
// changes.
TEST_F(StunPortTest, TestStunPortGetStunKeepaliveLifetime) {
- // Lifetime for the default (unknown) network type is `kInfiniteLifetime`.
+ // Lifetime for the default (unknown) network type is infinite.
CreateStunPort(kStunServerAddr1);
- EXPECT_EQ(kInfiniteLifetime, port()->stun_keepalive_lifetime());
- // Lifetime for the cellular network is `kHighCostPortKeepaliveLifetimeMs`
+ EXPECT_EQ(port()->stun_keepalive_lifetime(), TimeDelta::PlusInfinity());
+ // Lifetime for the cellular network is `kHighCostPortKeepaliveLifetime`
SetNetworkType(webrtc::ADAPTER_TYPE_CELLULAR);
- EXPECT_EQ(kHighCostPortKeepaliveLifetimeMs,
- port()->stun_keepalive_lifetime());
+ EXPECT_EQ(port()->stun_keepalive_lifetime(), kHighCostPortKeepaliveLifetime);
- // Lifetime for the wifi network is `kInfiniteLifetime`.
+ // Lifetime for the wifi network is infinite.
SetNetworkType(webrtc::ADAPTER_TYPE_WIFI);
CreateStunPort(kStunServerAddr2);
- EXPECT_EQ(kInfiniteLifetime, port()->stun_keepalive_lifetime());
+ EXPECT_EQ(port()->stun_keepalive_lifetime(), TimeDelta::PlusInfinity());
}
// Test that the stun_keepalive_lifetime is set correctly based on the network
// type on a shared STUN port (UDPPort). Also test that it will be updated
// if the network type changes.
TEST_F(StunPortTest, TestUdpPortGetStunKeepaliveLifetime) {
- // Lifetime for the default (unknown) network type is `kInfiniteLifetime`.
+ // Lifetime for the default (unknown) network type is infinite.
CreateSharedUdpPort(kStunServerAddr1, nullptr);
- EXPECT_EQ(kInfiniteLifetime, port()->stun_keepalive_lifetime());
- // Lifetime for the cellular network is `kHighCostPortKeepaliveLifetimeMs`.
+ EXPECT_EQ(port()->stun_keepalive_lifetime(), TimeDelta::PlusInfinity());
+ // Lifetime for the cellular network is `kHighCostPortKeepaliveLifetime`.
SetNetworkType(webrtc::ADAPTER_TYPE_CELLULAR);
- EXPECT_EQ(kHighCostPortKeepaliveLifetimeMs,
- port()->stun_keepalive_lifetime());
+ EXPECT_EQ(port()->stun_keepalive_lifetime(), kHighCostPortKeepaliveLifetime);
- // Lifetime for the wifi network type is `kInfiniteLifetime`.
+ // Lifetime for the wifi network type is infinite.
SetNetworkType(webrtc::ADAPTER_TYPE_WIFI);
CreateSharedUdpPort(kStunServerAddr2, nullptr);
- EXPECT_EQ(kInfiniteLifetime, port()->stun_keepalive_lifetime());
+ EXPECT_EQ(port()->stun_keepalive_lifetime(), TimeDelta::PlusInfinity());
}
// Test that STUN binding requests will be stopped shortly if the keep-alive
// lifetime is short.
TEST_F(StunPortTest, TestStunBindingRequestShortLifetime) {
SetKeepaliveDelay(101);
- SetKeepaliveLifetime(100);
+ SetKeepaliveLifetime(TimeDelta::Millis(100));
CreateStunPort(kStunServerAddr1);
PrepareAddress();
EXPECT_THAT(
diff --git a/p2p/base/stun_request.cc b/p2p/base/stun_request.cc
index 1a31df5..874da79 100644
--- a/p2p/base/stun_request.cc
+++ b/p2p/base/stun_request.cc
@@ -19,18 +19,18 @@
#include <utility>
#include <vector>
-#include "absl/memory/memory.h"
#include "api/array_view.h"
+#include "api/environment/environment.h"
#include "api/sequence_checker.h"
#include "api/task_queue/pending_task_safety_flag.h"
#include "api/task_queue/task_queue_base.h"
#include "api/transport/stun.h"
#include "api/units/time_delta.h"
+#include "api/units/timestamp.h"
#include "rtc_base/byte_buffer.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/string_encode.h"
-#include "rtc_base/time_utils.h" // For TimeMillis
namespace webrtc {
@@ -58,11 +58,8 @@
StunRequestManager::~StunRequestManager() = default;
-void StunRequestManager::Send(StunRequest* request) {
- SendDelayed(request, 0);
-}
-
-void StunRequestManager::SendDelayed(StunRequest* request, int delay) {
+void StunRequestManager::Send(std::unique_ptr<StunRequest> request,
+ TimeDelta delay) {
RTC_DCHECK_RUN_ON(thread_);
RTC_DCHECK_EQ(this, request->manager());
RTC_DCHECK(!request->AuthenticationRequired() ||
@@ -70,9 +67,9 @@
StunMessage::IntegrityStatus::kNotSet)
<< "Sending request w/o integrity!";
auto [iter, was_inserted] =
- requests_.emplace(request->id(), absl::WrapUnique(request));
+ requests_.emplace(request->id(), std::move(request));
RTC_DCHECK(was_inserted);
- request->Send(TimeDelta::Millis(delay));
+ iter->second->Send(delay);
}
void StunRequestManager::FlushForTest(int msg_type) {
@@ -233,20 +230,23 @@
send_packet_(data, size, request);
}
-StunRequest::StunRequest(StunRequestManager& manager)
- : manager_(manager),
- msg_(new StunMessage(STUN_INVALID_MESSAGE_TYPE)),
- tstamp_(0),
+StunRequest::StunRequest(const Environment& env, StunRequestManager& manager)
+ : env_(env),
+ manager_(manager),
+ msg_(std::make_unique<StunMessage>(STUN_INVALID_MESSAGE_TYPE)),
+ tstamp_(Timestamp::Zero()),
count_(0),
timeout_(false) {
RTC_DCHECK_RUN_ON(network_thread());
}
-StunRequest::StunRequest(StunRequestManager& manager,
+StunRequest::StunRequest(const Environment& env,
+ StunRequestManager& manager,
std::unique_ptr<StunMessage> message)
- : manager_(manager),
+ : env_(env),
+ manager_(manager),
msg_(std::move(message)),
- tstamp_(0),
+ tstamp_(Timestamp::Zero()),
count_(0),
timeout_(false) {
RTC_DCHECK_RUN_ON(network_thread());
@@ -264,9 +264,9 @@
return msg_.get();
}
-int StunRequest::Elapsed() const {
+TimeDelta StunRequest::Elapsed() const {
RTC_DCHECK_RUN_ON(network_thread());
- return static_cast<int>(TimeMillis() - tstamp_);
+ return env_.clock().CurrentTime() - tstamp_;
}
void StunRequest::SendInternal() {
@@ -277,7 +277,7 @@
return;
}
- tstamp_ = TimeMillis();
+ tstamp_ = env_.clock().CurrentTime();
ByteBufferWriter buf;
msg_->Write(&buf);
diff --git a/p2p/base/stun_request.h b/p2p/base/stun_request.h
index 8d6a7f5..b7f2025 100644
--- a/p2p/base/stun_request.h
+++ b/p2p/base/stun_request.h
@@ -18,10 +18,12 @@
#include <memory>
#include <string>
+#include "api/environment/environment.h"
#include "api/task_queue/pending_task_safety_flag.h"
#include "api/task_queue/task_queue_base.h"
#include "api/transport/stun.h"
#include "api/units/time_delta.h"
+#include "api/units/timestamp.h"
#include "rtc_base/thread_annotations.h"
namespace webrtc {
@@ -45,8 +47,8 @@
~StunRequestManager();
// Starts sending the given request (perhaps after a delay).
- void Send(StunRequest* request);
- void SendDelayed(StunRequest* request, int delay);
+ void Send(std::unique_ptr<StunRequest> request,
+ TimeDelta delay = TimeDelta::Zero());
// If `msg_type` is kAllRequestsForTest, sends all pending requests right
// away. Otherwise, sends those that have a matching type right away. Only for
@@ -90,8 +92,9 @@
// constructed beforehand or built on demand.
class StunRequest {
public:
- explicit StunRequest(StunRequestManager& manager);
- StunRequest(StunRequestManager& manager,
+ StunRequest(const Environment& env, StunRequestManager& manager);
+ StunRequest(const Environment& env,
+ StunRequestManager& manager,
std::unique_ptr<StunMessage> message);
virtual ~StunRequest();
@@ -112,8 +115,8 @@
// Returns a const pointer to `msg_`.
const StunMessage* msg() const;
- // Time elapsed since last send (in ms)
- int Elapsed() const;
+ // Time elapsed since last send.
+ TimeDelta Elapsed() const;
// Add method to explitly allow requests w/o password.
// - STUN_BINDINGs from StunPort to a stun server
@@ -124,6 +127,8 @@
protected:
friend class StunRequestManager;
+ const Environment& env() { return env_; }
+
// Called by StunRequestManager.
void Send(TimeDelta delay);
@@ -152,9 +157,10 @@
// specified timeout.
void SendDelayed(TimeDelta delay);
+ const Environment env_;
StunRequestManager& manager_;
const std::unique_ptr<StunMessage> msg_;
- int64_t tstamp_ RTC_GUARDED_BY(network_thread());
+ Timestamp tstamp_ RTC_GUARDED_BY(network_thread());
int count_ RTC_GUARDED_BY(network_thread());
bool timeout_ RTC_GUARDED_BY(network_thread());
ScopedTaskSafety task_safety_{
diff --git a/p2p/base/stun_request_unittest.cc b/p2p/base/stun_request_unittest.cc
index ec3bb74..2055a16 100644
--- a/p2p/base/stun_request_unittest.cc
+++ b/p2p/base/stun_request_unittest.cc
@@ -13,8 +13,11 @@
#include <cstddef>
#include <cstdint>
#include <memory>
+#include <string>
+#include <utility>
#include <vector>
+#include "api/environment/environment.h"
#include "api/test/rtc_error_matchers.h"
#include "api/transport/stun.h"
#include "api/units/time_delta.h"
@@ -23,6 +26,7 @@
#include "rtc_base/logging.h"
#include "rtc_base/thread.h"
#include "rtc_base/time_utils.h"
+#include "test/create_test_environment.h"
#include "test/gmock.h"
#include "test/gtest.h"
#include "test/wait_until.h"
@@ -47,10 +51,13 @@
}
} // namespace
+class StunRequestThunker;
+
class StunRequestTest : public ::testing::Test {
public:
StunRequestTest()
- : manager_(Thread::Current(),
+ : env_(CreateTestEnvironment()),
+ manager_(Thread::Current(),
[this](const void* data, size_t size, StunRequest* request) {
OnSendPacket(data, size, request);
}),
@@ -60,6 +67,8 @@
failure_(false),
timeout_(false) {}
+ std::unique_ptr<StunRequestThunker> CreateStunRequest();
+
void OnSendPacket(const void* data, size_t size, StunRequest* req) {
request_count_++;
}
@@ -76,6 +85,7 @@
protected:
AutoThread main_thread_;
+ const Environment env_;
StunRequestManager manager_;
int request_count_;
StunMessage* response_;
@@ -87,8 +97,10 @@
// Forwards results to the test class.
class StunRequestThunker : public StunRequest {
public:
- StunRequestThunker(StunRequestManager& manager, StunRequestTest* test)
- : StunRequest(manager, CreateStunMessage(STUN_BINDING_REQUEST)),
+ StunRequestThunker(const Environment& env,
+ StunRequestManager& manager,
+ StunRequestTest* test)
+ : StunRequest(env, manager, CreateStunMessage(STUN_BINDING_REQUEST)),
test_(test) {
SetAuthenticationRequired(false);
}
@@ -107,12 +119,16 @@
StunRequestTest* test_;
};
+std::unique_ptr<StunRequestThunker> StunRequestTest::CreateStunRequest() {
+ return std::make_unique<StunRequestThunker>(env_, manager_, this);
+}
+
// Test handling of a normal binding response.
TEST_F(StunRequestTest, TestSuccess) {
- auto* request = new StunRequestThunker(manager_, this);
+ std::unique_ptr<StunRequestThunker> request = CreateStunRequest();
std::unique_ptr<StunMessage> res =
request->CreateResponseMessage(STUN_BINDING_RESPONSE);
- manager_.Send(request);
+ manager_.Send(std::move(request));
EXPECT_TRUE(manager_.CheckResponse(res.get()));
EXPECT_TRUE(response_ == res.get());
@@ -123,10 +139,10 @@
// Test handling of an error binding response.
TEST_F(StunRequestTest, TestError) {
- auto* request = new StunRequestThunker(manager_, this);
+ std::unique_ptr<StunRequestThunker> request = CreateStunRequest();
std::unique_ptr<StunMessage> res =
request->CreateResponseMessage(STUN_BINDING_ERROR_RESPONSE);
- manager_.Send(request);
+ manager_.Send(std::move(request));
EXPECT_TRUE(manager_.CheckResponse(res.get()));
EXPECT_TRUE(response_ == res.get());
@@ -137,10 +153,10 @@
// Test handling of a binding response with the wrong transaction id.
TEST_F(StunRequestTest, TestUnexpected) {
- auto* request = new StunRequestThunker(manager_, this);
+ std::unique_ptr<StunRequestThunker> request = CreateStunRequest();
std::unique_ptr<StunMessage> res = CreateStunMessage(STUN_BINDING_RESPONSE);
- manager_.Send(request);
+ manager_.Send(std::move(request));
EXPECT_FALSE(manager_.CheckResponse(res.get()));
EXPECT_TRUE(response_ == nullptr);
@@ -152,12 +168,12 @@
// Test that requests are sent at the right times.
TEST_F(StunRequestTest, TestBackoff) {
ScopedFakeClock fake_clock;
- auto* request = new StunRequestThunker(manager_, this);
+ std::unique_ptr<StunRequestThunker> request = CreateStunRequest();
std::unique_ptr<StunMessage> res =
request->CreateResponseMessage(STUN_BINDING_RESPONSE);
int64_t start = TimeMillis();
- manager_.Send(request);
+ manager_.Send(std::move(request));
for (int i = 0; i < 9; ++i) {
EXPECT_THAT(WaitUntil([&] { return request_count_; }, Ne(i),
{.timeout = TimeDelta::Millis(STUN_TOTAL_TIMEOUT),
@@ -179,11 +195,11 @@
// Test that we timeout properly if no response is received.
TEST_F(StunRequestTest, TestTimeout) {
ScopedFakeClock fake_clock;
- auto* request = new StunRequestThunker(manager_, this);
+ std::unique_ptr<StunRequestThunker> request = CreateStunRequest();
std::unique_ptr<StunMessage> res =
request->CreateResponseMessage(STUN_BINDING_RESPONSE);
- manager_.Send(request);
+ manager_.Send(std::move(request));
SIMULATED_WAIT(false, STUN_TOTAL_TIMEOUT, fake_clock);
EXPECT_FALSE(manager_.CheckResponse(res.get()));
@@ -196,11 +212,12 @@
// Regression test for specific crash where we receive a response with the
// same id as a request that doesn't have an underlying StunMessage yet.
TEST_F(StunRequestTest, TestNoEmptyRequest) {
- StunRequestThunker* request = new StunRequestThunker(manager_, this);
+ std::unique_ptr<StunRequestThunker> request = CreateStunRequest();
+ std::string request_id = request->id();
- manager_.SendDelayed(request, 100);
+ manager_.Send(std::move(request), /*delay=*/TimeDelta::Millis(100));
- StunMessage dummy_req(0, request->id());
+ StunMessage dummy_req(0, request_id);
std::unique_ptr<StunMessage> res =
CreateStunMessage(STUN_BINDING_RESPONSE, &dummy_req);
@@ -216,11 +233,11 @@
// which is not recognized, the transaction should be considered a failure and
// the response should be ignored.
TEST_F(StunRequestTest, TestUnrecognizedComprehensionRequiredAttribute) {
- auto* request = new StunRequestThunker(manager_, this);
+ std::unique_ptr<StunRequestThunker> request = CreateStunRequest();
std::unique_ptr<StunMessage> res =
request->CreateResponseMessage(STUN_BINDING_ERROR_RESPONSE);
- manager_.Send(request);
+ manager_.Send(std::move(request));
res->AddAttribute(StunAttribute::CreateUInt32(0x7777));
EXPECT_FALSE(manager_.CheckResponse(res.get()));
@@ -243,10 +260,10 @@
};
TEST_F(StunRequestReentranceTest, TestSuccess) {
- auto* request = new StunRequestThunker(manager_, this);
+ std::unique_ptr<StunRequestThunker> request = CreateStunRequest();
std::unique_ptr<StunMessage> res =
request->CreateResponseMessage(STUN_BINDING_RESPONSE);
- manager_.Send(request);
+ manager_.Send(std::move(request));
EXPECT_TRUE(manager_.CheckResponse(res.get()));
EXPECT_TRUE(response_ == res.get());
@@ -256,10 +273,10 @@
}
TEST_F(StunRequestReentranceTest, TestError) {
- auto* request = new StunRequestThunker(manager_, this);
+ std::unique_ptr<StunRequestThunker> request = CreateStunRequest();
std::unique_ptr<StunMessage> res =
request->CreateResponseMessage(STUN_BINDING_ERROR_RESPONSE);
- manager_.Send(request);
+ manager_.Send(std::move(request));
EXPECT_TRUE(manager_.CheckResponse(res.get()));
EXPECT_TRUE(response_ == res.get());
diff --git a/p2p/base/turn_port.cc b/p2p/base/turn_port.cc
index cff27b0..fe18fa6 100644
--- a/p2p/base/turn_port.cc
+++ b/p2p/base/turn_port.cc
@@ -21,6 +21,7 @@
#include <vector>
#include "absl/algorithm/container.h"
+#include "absl/memory/memory.h"
#include "absl/strings/match.h"
#include "absl/strings/string_view.h"
#include "api/array_view.h"
@@ -51,6 +52,7 @@
#include "rtc_base/network.h"
#include "rtc_base/network/received_packet.h"
#include "rtc_base/network/sent_packet.h"
+#include "rtc_base/platform_thread_types.h"
#include "rtc_base/socket.h"
#include "rtc_base/socket_address.h"
#include "rtc_base/ssl_certificate.h"
@@ -1162,7 +1164,7 @@
}
void TurnPort::SendRequest(StunRequest* req, int delay) {
- request_manager_.SendDelayed(req, delay);
+ request_manager_.Send(absl::WrapUnique(req), TimeDelta::Millis(delay));
}
void TurnPort::AddRequestAuthInfo(StunMessage* msg) {
@@ -1338,7 +1340,8 @@
}
TurnAllocateRequest::TurnAllocateRequest(TurnPort* port)
- : StunRequest(port->request_manager(),
+ : StunRequest(port->env(),
+ port->request_manager(),
std::make_unique<TurnMessage>(TURN_ALLOCATE_REQUEST)),
port_(port) {
StunMessage* message = mutable_msg();
@@ -1536,7 +1539,8 @@
}
TurnRefreshRequest::TurnRefreshRequest(TurnPort* port, int lifetime /*= -1*/)
- : StunRequest(port->request_manager(),
+ : StunRequest(port->env(),
+ port->request_manager(),
std::make_unique<TurnMessage>(TURN_REFRESH_REQUEST)),
port_(port) {
StunMessage* message = mutable_msg();
@@ -1623,6 +1627,7 @@
TurnEntry* entry,
const SocketAddress& ext_addr)
: StunRequest(
+ port->env(),
port->request_manager(),
std::make_unique<TurnMessage>(TURN_CREATE_PERMISSION_REQUEST)),
port_(port),
@@ -1692,7 +1697,8 @@
TurnEntry* entry,
uint16_t channel_id,
const SocketAddress& ext_addr)
- : StunRequest(port->request_manager(),
+ : StunRequest(port->env(),
+ port->request_manager(),
std::make_unique<TurnMessage>(TURN_CHANNEL_BIND_REQUEST)),
port_(port),
entry_(entry),
diff --git a/p2p/client/basic_port_allocator_unittest.cc b/p2p/client/basic_port_allocator_unittest.cc
index 2d543ee..48eaff1 100644
--- a/p2p/client/basic_port_allocator_unittest.cc
+++ b/p2p/client/basic_port_allocator_unittest.cc
@@ -145,7 +145,7 @@
port->GetProtocol() == webrtc::PROTO_UDP)) {
EXPECT_EQ(
static_cast<const webrtc::UDPPort*>(port)->stun_keepalive_delay(),
- expected);
+ webrtc::TimeDelta::Millis(expected));
}
}
}