p2p: separate ICE tie breaker and foundation seed
BUG=webrtc:14626 Change-Id: I189a708192c9cef0b50c3fcbe798b30376d3b547 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/338982 Reviewed-by: Tomas Gunnarsson <tommi@webrtc.org> Commit-Queue: Philipp Hancke <phancke@microsoft.com> Reviewed-by: Harald Alvestrand <hta@webrtc.org> Cr-Commit-Position: refs/heads/main@{#41806}
This commit is contained in:
parent
7c5f9cf47f
commit
d99499abba
@ -263,7 +263,7 @@ Candidate Candidate::ToSanitizedCopy(bool use_hostname_address,
|
||||
}
|
||||
|
||||
void Candidate::ComputeFoundation(const rtc::SocketAddress& base_address,
|
||||
uint64_t tie_breaker) {
|
||||
uint64_t seed) {
|
||||
// https://www.rfc-editor.org/rfc/rfc5245#section-4.1.1.3
|
||||
// The foundation is an identifier, scoped within a session. Two candidates
|
||||
// MUST have the same foundation ID when all of the following are true:
|
||||
@ -282,14 +282,9 @@ void Candidate::ComputeFoundation(const rtc::SocketAddress& base_address,
|
||||
rtc::StringBuilder sb;
|
||||
sb << type_name() << base_address.ipaddr().ToString() << protocol_
|
||||
<< relay_protocol_;
|
||||
|
||||
// https://www.rfc-editor.org/rfc/rfc5245#section-5.2
|
||||
// [...] it is possible for both agents to mistakenly believe they are
|
||||
// controlled or controlling. To resolve this, each agent MUST select a random
|
||||
// number, called the tie-breaker, uniformly distributed between 0 and (2**64)
|
||||
// - 1 (that is, a 64-bit positive integer). This number is used in
|
||||
// connectivity checks to detect and repair this case [...]
|
||||
sb << rtc::ToString(tie_breaker);
|
||||
// The random seed is passed to prevent a reverse CRC32 lookup of the address
|
||||
// based on the foundation.
|
||||
sb << rtc::ToString(seed);
|
||||
foundation_ = rtc::ToString(rtc::ComputeCrc32(sb.Release()));
|
||||
}
|
||||
|
||||
|
||||
@ -254,10 +254,9 @@ class RTC_EXPORT Candidate {
|
||||
// then the foundation will be different. Two candidate pairs with
|
||||
// the same foundation pairs are likely to have similar network
|
||||
// characteristics. Foundations are used in the frozen algorithm.
|
||||
// A session wide (peerconnection) tie-breaker is applied to the foundation,
|
||||
// A session wide (peerconnection) seed is applied to the foundation,
|
||||
// adds additional randomness and must be the same for all candidates.
|
||||
void ComputeFoundation(const rtc::SocketAddress& base_address,
|
||||
uint64_t tie_breaker);
|
||||
void ComputeFoundation(const rtc::SocketAddress& base_address, uint64_t seed);
|
||||
|
||||
// https://www.rfc-editor.org/rfc/rfc5245#section-7.2.1.3
|
||||
// Call to populate the foundation field for a new peer reflexive remote
|
||||
|
||||
@ -128,6 +128,7 @@ class FakePortAllocatorSession : public PortAllocatorSession {
|
||||
field_trials_));
|
||||
RTC_DCHECK(port_);
|
||||
port_->SetIceTiebreaker(allocator_->ice_tiebreaker());
|
||||
port_->SetFoundationSeed(allocator_->foundation_seed());
|
||||
port_->SubscribePortDestroyed(
|
||||
[this](PortInterface* port) { OnPortDestroyed(port); });
|
||||
AddPort(port_.get());
|
||||
|
||||
@ -199,6 +199,14 @@ uint64_t Port::IceTiebreaker() const {
|
||||
return tiebreaker_;
|
||||
}
|
||||
|
||||
void Port::SetFoundationSeed(uint64_t foundation_seed) {
|
||||
foundation_seed_ = foundation_seed;
|
||||
}
|
||||
|
||||
uint64_t Port::FoundationSeed() const {
|
||||
return foundation_seed_;
|
||||
}
|
||||
|
||||
bool Port::SharedSocket() const {
|
||||
return shared_socket_;
|
||||
}
|
||||
@ -255,8 +263,8 @@ void Port::AddAddress(const rtc::SocketAddress& address,
|
||||
type, generation_, "", network_->id(), network_cost_);
|
||||
// Set the relay protocol before computing the foundation field.
|
||||
c.set_relay_protocol(relay_protocol);
|
||||
// TODO(bugs.webrtc.org/14605): ensure IceTiebreaker() is set.
|
||||
c.ComputeFoundation(base_address, tiebreaker_);
|
||||
// TODO(bugs.webrtc.org/14605): ensure FoundationSeed() is set.
|
||||
c.ComputeFoundation(base_address, foundation_seed_);
|
||||
|
||||
c.set_priority(
|
||||
c.GetPriority(type_preference, network_->preference(), relay_preference,
|
||||
|
||||
@ -211,6 +211,9 @@ class RTC_EXPORT Port : public PortInterface, public sigslot::has_slots<> {
|
||||
void SetIceTiebreaker(uint64_t tiebreaker) override;
|
||||
uint64_t IceTiebreaker() const override;
|
||||
|
||||
void SetFoundationSeed(uint64_t foundation_seed) override;
|
||||
uint64_t FoundationSeed() const override;
|
||||
|
||||
bool SharedSocket() const override;
|
||||
void ResetSharedSocket() { shared_socket_ = false; }
|
||||
|
||||
@ -494,6 +497,7 @@ class RTC_EXPORT Port : public PortInterface, public sigslot::has_slots<> {
|
||||
bool enable_port_packets_;
|
||||
IceRole ice_role_;
|
||||
uint64_t tiebreaker_;
|
||||
uint64_t foundation_seed_;
|
||||
bool shared_socket_;
|
||||
// Information to use when going through a proxy.
|
||||
std::string user_agent_;
|
||||
|
||||
@ -100,7 +100,8 @@ PortAllocator::PortAllocator()
|
||||
step_delay_(kDefaultStepDelay),
|
||||
allow_tcp_listen_(true),
|
||||
candidate_filter_(CF_ALL),
|
||||
tiebreaker_(rtc::CreateRandomId64()) {
|
||||
tiebreaker_(rtc::CreateRandomId64()),
|
||||
foundation_seed_(rtc::CreateRandomId64()) {
|
||||
// The allocator will be attached to a thread in Initialize.
|
||||
thread_checker_.Detach();
|
||||
}
|
||||
|
||||
@ -452,6 +452,7 @@ class RTC_EXPORT PortAllocator : public sigslot::has_slots<> {
|
||||
Candidate SanitizeCandidate(const Candidate& c) const;
|
||||
|
||||
uint64_t ice_tiebreaker() const { return tiebreaker_; }
|
||||
uint64_t foundation_seed() const { return foundation_seed_; }
|
||||
|
||||
uint32_t flags() const {
|
||||
CheckRunOnValidThreadIfInitialized();
|
||||
@ -664,8 +665,14 @@ class RTC_EXPORT PortAllocator : public sigslot::has_slots<> {
|
||||
std::vector<std::unique_ptr<PortAllocatorSession>>::const_iterator
|
||||
FindPooledSession(const IceParameters* ice_credentials = nullptr) const;
|
||||
|
||||
// ICE tie breaker.
|
||||
// ICE Tie-breaker as described in
|
||||
// https://www.rfc-editor.org/rfc/rfc5245#section-5.2
|
||||
uint64_t tiebreaker_;
|
||||
// A random value that is included in the foundation of all ICE candidates
|
||||
// generated by ports derived from this allocator. See
|
||||
// https://www.rfc-editor.org/rfc/rfc5245#section-4.1.1.3
|
||||
// Never sent over the network.
|
||||
uint64_t foundation_seed_;
|
||||
};
|
||||
|
||||
} // namespace cricket
|
||||
|
||||
@ -62,6 +62,11 @@ class PortInterface {
|
||||
virtual void SetIceTiebreaker(uint64_t tiebreaker) = 0;
|
||||
virtual uint64_t IceTiebreaker() const = 0;
|
||||
|
||||
// Methods to set/get the PortAllocator random value which is used to seed the
|
||||
// foundation.
|
||||
virtual void SetFoundationSeed(uint64_t foundation_seed) = 0;
|
||||
virtual uint64_t FoundationSeed() const = 0;
|
||||
|
||||
virtual bool SharedSocket() const = 0;
|
||||
|
||||
virtual bool SupportsProtocol(absl::string_view protocol) const = 0;
|
||||
|
||||
@ -109,6 +109,7 @@ const uint32_t kDefaultPrflxPriority = ICE_TYPE_PREFERENCE_PRFLX << 24 |
|
||||
constexpr int kTiebreaker1 = 11111;
|
||||
constexpr int kTiebreaker2 = 22222;
|
||||
constexpr int kTiebreakerDefault = 44444;
|
||||
constexpr int kFoundationSeed = 42;
|
||||
|
||||
const char* data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
|
||||
|
||||
@ -555,6 +556,7 @@ class PortTest : public ::testing::Test, public sigslot::has_slots<> {
|
||||
username_, password_, true, absl::nullopt,
|
||||
&field_trials_);
|
||||
port->SetIceTiebreaker(kTiebreakerDefault);
|
||||
port->SetFoundationSeed(kFoundationSeed);
|
||||
return port;
|
||||
}
|
||||
|
||||
@ -567,6 +569,7 @@ class PortTest : public ::testing::Test, public sigslot::has_slots<> {
|
||||
MakeNetworkMultipleAddrs(global_addr, link_local_addr), 0, 0, username_,
|
||||
password_, true, absl::nullopt, &field_trials_);
|
||||
port->SetIceTiebreaker(kTiebreakerDefault);
|
||||
port->SetFoundationSeed(kFoundationSeed);
|
||||
return port;
|
||||
}
|
||||
std::unique_ptr<TCPPort> CreateTcpPort(const SocketAddress& addr) {
|
||||
@ -577,6 +580,7 @@ class PortTest : public ::testing::Test, public sigslot::has_slots<> {
|
||||
auto port = TCPPort::Create(&main_, socket_factory, MakeNetwork(addr), 0, 0,
|
||||
username_, password_, true, &field_trials_);
|
||||
port->SetIceTiebreaker(kTiebreakerDefault);
|
||||
port->SetFoundationSeed(kFoundationSeed);
|
||||
return port;
|
||||
}
|
||||
std::unique_ptr<StunPort> CreateStunPort(const SocketAddress& addr,
|
||||
@ -587,6 +591,7 @@ class PortTest : public ::testing::Test, public sigslot::has_slots<> {
|
||||
username_, password_, stun_servers,
|
||||
absl::nullopt, &field_trials_);
|
||||
port->SetIceTiebreaker(kTiebreakerDefault);
|
||||
port->SetFoundationSeed(kFoundationSeed);
|
||||
return port;
|
||||
}
|
||||
std::unique_ptr<Port> CreateRelayPort(const SocketAddress& addr,
|
||||
|
||||
@ -1484,6 +1484,7 @@ void AllocationSequence::CreateUDPPorts() {
|
||||
|
||||
if (port) {
|
||||
port->SetIceTiebreaker(session_->allocator()->ice_tiebreaker());
|
||||
port->SetFoundationSeed(session_->allocator()->foundation_seed());
|
||||
// If shared socket is enabled, STUN candidate will be allocated by the
|
||||
// UDPPort.
|
||||
if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET)) {
|
||||
@ -1520,6 +1521,7 @@ void AllocationSequence::CreateTCPPorts() {
|
||||
session_->allocator()->field_trials());
|
||||
if (port) {
|
||||
port->SetIceTiebreaker(session_->allocator()->ice_tiebreaker());
|
||||
port->SetFoundationSeed(session_->allocator()->foundation_seed());
|
||||
session_->AddAllocatedPort(port.release(), this);
|
||||
// Since TCPPort is not created using shared socket, `port` will not be
|
||||
// added to the dequeue.
|
||||
@ -1550,6 +1552,7 @@ void AllocationSequence::CreateStunPorts() {
|
||||
session_->allocator()->field_trials());
|
||||
if (port) {
|
||||
port->SetIceTiebreaker(session_->allocator()->ice_tiebreaker());
|
||||
port->SetFoundationSeed(session_->allocator()->foundation_seed());
|
||||
session_->AddAllocatedPort(port.release(), this);
|
||||
// Since StunPort is not created using shared socket, `port` will not be
|
||||
// added to the dequeue.
|
||||
@ -1653,6 +1656,7 @@ void AllocationSequence::CreateTurnPort(const RelayServerConfig& config,
|
||||
}
|
||||
RTC_DCHECK(port != NULL);
|
||||
port->SetIceTiebreaker(session_->allocator()->ice_tiebreaker());
|
||||
port->SetFoundationSeed(session_->allocator()->foundation_seed());
|
||||
session_->AddAllocatedPort(port.release(), this);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user