[Connection] Construct ping/connection requests in one step.

This moves the construction of StunMessage instances for
ConnectionRequest, outside of the Prepare() method.

Following this, removing Construct()+Prepare() is relatively
straight forward.

Bug: none
Change-Id: Ibcf0510cef30a6e648005b43602c7ae1fb06729e
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/264558
Reviewed-by: Niels Moller <nisse@webrtc.org>
Reviewed-by: Jonas Oreland <jonaso@webrtc.org>
Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#37122}
This commit is contained in:
Tommi 2022-06-03 14:28:59 +02:00 committed by WebRTC LUCI CQ
parent 0ba10283fb
commit e83500e17b
13 changed files with 195 additions and 188 deletions

View File

@ -362,22 +362,19 @@ bool StunMessage::ValidateMessageIntegrityOfType(int mi_attr_type,
mi_attr_size) == 0; mi_attr_size) == 0;
} }
bool StunMessage::AddMessageIntegrity(const std::string& password) { bool StunMessage::AddMessageIntegrity(absl::string_view password) {
return AddMessageIntegrityOfType(STUN_ATTR_MESSAGE_INTEGRITY, return AddMessageIntegrityOfType(STUN_ATTR_MESSAGE_INTEGRITY,
kStunMessageIntegritySize, password.c_str(), kStunMessageIntegritySize, password);
password.size());
} }
bool StunMessage::AddMessageIntegrity32(absl::string_view password) { bool StunMessage::AddMessageIntegrity32(absl::string_view password) {
return AddMessageIntegrityOfType(STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32, return AddMessageIntegrityOfType(STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32,
kStunMessageIntegrity32Size, password.data(), kStunMessageIntegrity32Size, password);
password.length());
} }
bool StunMessage::AddMessageIntegrityOfType(int attr_type, bool StunMessage::AddMessageIntegrityOfType(int attr_type,
size_t attr_size, size_t attr_size,
const char* key, absl::string_view key) {
size_t keylen) {
// Add the attribute with a dummy value. Since this is a known attribute, it // Add the attribute with a dummy value. Since this is a known attribute, it
// can't fail. // can't fail.
RTC_DCHECK(attr_size <= kStunMessageIntegritySize); RTC_DCHECK(attr_size <= kStunMessageIntegritySize);
@ -394,7 +391,8 @@ bool StunMessage::AddMessageIntegrityOfType(int attr_type,
int msg_len_for_hmac = static_cast<int>( int msg_len_for_hmac = static_cast<int>(
buf.Length() - kStunAttributeHeaderSize - msg_integrity_attr->length()); buf.Length() - kStunAttributeHeaderSize - msg_integrity_attr->length());
char hmac[kStunMessageIntegritySize]; char hmac[kStunMessageIntegritySize];
size_t ret = rtc::ComputeHmac(rtc::DIGEST_SHA_1, key, keylen, buf.Data(), size_t ret =
rtc::ComputeHmac(rtc::DIGEST_SHA_1, key.data(), key.size(), buf.Data(),
msg_len_for_hmac, hmac, sizeof(hmac)); msg_len_for_hmac, hmac, sizeof(hmac));
RTC_DCHECK(ret == sizeof(hmac)); RTC_DCHECK(ret == sizeof(hmac));
if (ret != sizeof(hmac)) { if (ret != sizeof(hmac)) {
@ -405,7 +403,7 @@ bool StunMessage::AddMessageIntegrityOfType(int attr_type,
// Insert correct HMAC into the attribute. // Insert correct HMAC into the attribute.
msg_integrity_attr->CopyBytes(hmac, attr_size); msg_integrity_attr->CopyBytes(hmac, attr_size);
password_.assign(key, keylen); password_ = std::string(key);
integrity_ = IntegrityStatus::kIntegrityOk; integrity_ = IntegrityStatus::kIntegrityOk;
return true; return true;
} }
@ -1006,9 +1004,9 @@ StunByteStringAttribute::StunByteStringAttribute(uint16_t type)
: StunAttribute(type, 0), bytes_(NULL) {} : StunAttribute(type, 0), bytes_(NULL) {}
StunByteStringAttribute::StunByteStringAttribute(uint16_t type, StunByteStringAttribute::StunByteStringAttribute(uint16_t type,
const std::string& str) absl::string_view str)
: StunAttribute(type, 0), bytes_(NULL) { : StunAttribute(type, 0), bytes_(NULL) {
CopyBytes(str.c_str(), str.size()); CopyBytes(str);
} }
StunByteStringAttribute::StunByteStringAttribute(uint16_t type, StunByteStringAttribute::StunByteStringAttribute(uint16_t type,
@ -1029,8 +1027,10 @@ StunAttributeValueType StunByteStringAttribute::value_type() const {
return STUN_VALUE_BYTE_STRING; return STUN_VALUE_BYTE_STRING;
} }
void StunByteStringAttribute::CopyBytes(const char* bytes) { void StunByteStringAttribute::CopyBytes(absl::string_view bytes) {
CopyBytes(bytes, strlen(bytes)); char* new_bytes = new char[bytes.size()];
memcpy(new_bytes, bytes.data(), bytes.size());
SetBytes(new_bytes, bytes.size());
} }
void StunByteStringAttribute::CopyBytes(const void* bytes, size_t length) { void StunByteStringAttribute::CopyBytes(const void* bytes, size_t length) {

View File

@ -233,7 +233,7 @@ class StunMessage {
} }
// Adds a MESSAGE-INTEGRITY attribute that is valid for the current message. // Adds a MESSAGE-INTEGRITY attribute that is valid for the current message.
bool AddMessageIntegrity(const std::string& password); bool AddMessageIntegrity(absl::string_view password);
// Adds a STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32 attribute that is valid for the // Adds a STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32 attribute that is valid for the
// current message. // current message.
@ -316,8 +316,7 @@ class StunMessage {
static bool IsValidTransactionId(absl::string_view transaction_id); static bool IsValidTransactionId(absl::string_view transaction_id);
bool AddMessageIntegrityOfType(int mi_attr_type, bool AddMessageIntegrityOfType(int mi_attr_type,
size_t mi_attr_size, size_t mi_attr_size,
const char* key, absl::string_view key);
size_t keylen);
static bool ValidateMessageIntegrityOfType(int mi_attr_type, static bool ValidateMessageIntegrityOfType(int mi_attr_type,
size_t mi_attr_size, size_t mi_attr_size,
const char* data, const char* data,
@ -507,7 +506,7 @@ class StunUInt64Attribute : public StunAttribute {
class StunByteStringAttribute : public StunAttribute { class StunByteStringAttribute : public StunAttribute {
public: public:
explicit StunByteStringAttribute(uint16_t type); explicit StunByteStringAttribute(uint16_t type);
StunByteStringAttribute(uint16_t type, const std::string& str); StunByteStringAttribute(uint16_t type, absl::string_view str);
StunByteStringAttribute(uint16_t type, const void* bytes, size_t length); StunByteStringAttribute(uint16_t type, const void* bytes, size_t length);
StunByteStringAttribute(uint16_t type, uint16_t length); StunByteStringAttribute(uint16_t type, uint16_t length);
~StunByteStringAttribute() override; ~StunByteStringAttribute() override;
@ -515,10 +514,16 @@ class StunByteStringAttribute : public StunAttribute {
StunAttributeValueType value_type() const override; StunAttributeValueType value_type() const override;
const char* bytes() const { return bytes_; } const char* bytes() const { return bytes_; }
std::string GetString() const { return std::string(bytes_, length()); } absl::string_view string_view() const {
return absl::string_view(bytes_, length());
}
[[deprecated]] std::string GetString() const {
return std::string(bytes_, length());
}
void CopyBytes(const char* bytes); // uses strlen
void CopyBytes(const void* bytes, size_t length); void CopyBytes(const void* bytes, size_t length);
void CopyBytes(absl::string_view bytes);
uint8_t GetByte(size_t index) const; uint8_t GetByte(size_t index) const;
void SetByte(size_t index, uint8_t value); void SetByte(size_t index, uint8_t value);

View File

@ -650,12 +650,12 @@ TEST_F(StunTest, ReadRfc5769RequestMessage) {
const StunByteStringAttribute* software = const StunByteStringAttribute* software =
msg.GetByteString(STUN_ATTR_SOFTWARE); msg.GetByteString(STUN_ATTR_SOFTWARE);
ASSERT_TRUE(software != NULL); ASSERT_TRUE(software != NULL);
EXPECT_EQ(kRfc5769SampleMsgClientSoftware, software->GetString()); EXPECT_EQ(kRfc5769SampleMsgClientSoftware, software->string_view());
const StunByteStringAttribute* username = const StunByteStringAttribute* username =
msg.GetByteString(STUN_ATTR_USERNAME); msg.GetByteString(STUN_ATTR_USERNAME);
ASSERT_TRUE(username != NULL); ASSERT_TRUE(username != NULL);
EXPECT_EQ(kRfc5769SampleMsgUsername, username->GetString()); EXPECT_EQ(kRfc5769SampleMsgUsername, username->string_view());
// Actual M-I value checked in a later test. // Actual M-I value checked in a later test.
ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL); ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
@ -677,7 +677,7 @@ TEST_F(StunTest, ReadRfc5769ResponseMessage) {
const StunByteStringAttribute* software = const StunByteStringAttribute* software =
msg.GetByteString(STUN_ATTR_SOFTWARE); msg.GetByteString(STUN_ATTR_SOFTWARE);
ASSERT_TRUE(software != NULL); ASSERT_TRUE(software != NULL);
EXPECT_EQ(kRfc5769SampleMsgServerSoftware, software->GetString()); EXPECT_EQ(kRfc5769SampleMsgServerSoftware, software->string_view());
const StunAddressAttribute* mapped_address = const StunAddressAttribute* mapped_address =
msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS); msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
@ -700,7 +700,7 @@ TEST_F(StunTest, ReadRfc5769ResponseMessageIPv6) {
const StunByteStringAttribute* software = const StunByteStringAttribute* software =
msg.GetByteString(STUN_ATTR_SOFTWARE); msg.GetByteString(STUN_ATTR_SOFTWARE);
ASSERT_TRUE(software != NULL); ASSERT_TRUE(software != NULL);
EXPECT_EQ(kRfc5769SampleMsgServerSoftware, software->GetString()); EXPECT_EQ(kRfc5769SampleMsgServerSoftware, software->string_view());
const StunAddressAttribute* mapped_address = const StunAddressAttribute* mapped_address =
msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS); msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
@ -723,15 +723,15 @@ TEST_F(StunTest, ReadRfc5769RequestMessageLongTermAuth) {
const StunByteStringAttribute* username = const StunByteStringAttribute* username =
msg.GetByteString(STUN_ATTR_USERNAME); msg.GetByteString(STUN_ATTR_USERNAME);
ASSERT_TRUE(username != NULL); ASSERT_TRUE(username != NULL);
EXPECT_EQ(kRfc5769SampleMsgWithAuthUsername, username->GetString()); EXPECT_EQ(kRfc5769SampleMsgWithAuthUsername, username->string_view());
const StunByteStringAttribute* nonce = msg.GetByteString(STUN_ATTR_NONCE); const StunByteStringAttribute* nonce = msg.GetByteString(STUN_ATTR_NONCE);
ASSERT_TRUE(nonce != NULL); ASSERT_TRUE(nonce != NULL);
EXPECT_EQ(kRfc5769SampleMsgWithAuthNonce, nonce->GetString()); EXPECT_EQ(kRfc5769SampleMsgWithAuthNonce, nonce->string_view());
const StunByteStringAttribute* realm = msg.GetByteString(STUN_ATTR_REALM); const StunByteStringAttribute* realm = msg.GetByteString(STUN_ATTR_REALM);
ASSERT_TRUE(realm != NULL); ASSERT_TRUE(realm != NULL);
EXPECT_EQ(kRfc5769SampleMsgWithAuthRealm, realm->GetString()); EXPECT_EQ(kRfc5769SampleMsgWithAuthRealm, realm->string_view());
// No fingerprint, actual M-I checked in later tests. // No fingerprint, actual M-I checked in later tests.
ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL); ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
@ -1013,7 +1013,7 @@ TEST_F(StunTest, ReadByteStringAttribute) {
const StunByteStringAttribute* username = const StunByteStringAttribute* username =
msg.GetByteString(STUN_ATTR_USERNAME); msg.GetByteString(STUN_ATTR_USERNAME);
ASSERT_TRUE(username != NULL); ASSERT_TRUE(username != NULL);
EXPECT_EQ(kTestUserName1, username->GetString()); EXPECT_EQ(kTestUserName1, username->string_view());
} }
TEST_F(StunTest, ReadPaddedByteStringAttribute) { TEST_F(StunTest, ReadPaddedByteStringAttribute) {
@ -1026,7 +1026,7 @@ TEST_F(StunTest, ReadPaddedByteStringAttribute) {
const StunByteStringAttribute* username = const StunByteStringAttribute* username =
msg.GetByteString(STUN_ATTR_USERNAME); msg.GetByteString(STUN_ATTR_USERNAME);
ASSERT_TRUE(username != NULL); ASSERT_TRUE(username != NULL);
EXPECT_EQ(kTestUserName2, username->GetString()); EXPECT_EQ(kTestUserName2, username->string_view());
} }
TEST_F(StunTest, ReadErrorCodeAttribute) { TEST_F(StunTest, ReadErrorCodeAttribute) {
@ -1073,7 +1073,7 @@ TEST_F(StunTest, ReadMessageWithAnUnknownAttribute) {
const StunByteStringAttribute* username = const StunByteStringAttribute* username =
msg.GetByteString(STUN_ATTR_USERNAME); msg.GetByteString(STUN_ATTR_USERNAME);
ASSERT_TRUE(username != NULL); ASSERT_TRUE(username != NULL);
EXPECT_EQ(kTestUserName2, username->GetString()); EXPECT_EQ(kTestUserName2, username->string_view());
} }
TEST_F(StunTest, WriteMessageWithAnErrorCodeAttribute) { TEST_F(StunTest, WriteMessageWithAnErrorCodeAttribute) {
@ -1498,7 +1498,7 @@ TEST_F(StunTest, ReadRelayMessage) {
const StunByteStringAttribute* bytes = msg.GetByteString(STUN_ATTR_USERNAME); const StunByteStringAttribute* bytes = msg.GetByteString(STUN_ATTR_USERNAME);
ASSERT_TRUE(bytes != NULL); ASSERT_TRUE(bytes != NULL);
EXPECT_EQ(12U, bytes->length()); EXPECT_EQ(12U, bytes->length());
EXPECT_EQ("abcdefghijkl", bytes->GetString()); EXPECT_EQ("abcdefghijkl", bytes->string_view());
auto bytes2 = StunAttribute::CreateByteString(STUN_ATTR_USERNAME); auto bytes2 = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
bytes2->CopyBytes("abcdefghijkl"); bytes2->CopyBytes("abcdefghijkl");
@ -1556,7 +1556,7 @@ TEST_F(StunTest, ReadRelayMessage) {
bytes = msg.GetByteString(STUN_ATTR_DATA); bytes = msg.GetByteString(STUN_ATTR_DATA);
ASSERT_TRUE(bytes != NULL); ASSERT_TRUE(bytes != NULL);
EXPECT_EQ(7U, bytes->length()); EXPECT_EQ(7U, bytes->length());
EXPECT_EQ("abcdefg", bytes->GetString()); EXPECT_EQ("abcdefg", bytes->string_view());
bytes2 = StunAttribute::CreateByteString(STUN_ATTR_DATA); bytes2 = StunAttribute::CreateByteString(STUN_ATTR_DATA);
bytes2->CopyBytes("abcdefg"); bytes2->CopyBytes("abcdefg");

View File

@ -34,12 +34,13 @@
#include "rtc_base/strings/string_builder.h" #include "rtc_base/strings/string_builder.h"
#include "rtc_base/third_party/base64/base64.h" #include "rtc_base/third_party/base64/base64.h"
namespace cricket {
namespace { namespace {
// Determines whether we have seen at least the given maximum number of // Determines whether we have seen at least the given maximum number of
// pings fail to have a response. // pings fail to have a response.
inline bool TooManyFailures( inline bool TooManyFailures(
const std::vector<cricket::Connection::SentPing>& pings_since_last_response, const std::vector<Connection::SentPing>& pings_since_last_response,
uint32_t maximum_failures, uint32_t maximum_failures,
int rtt_estimate, int rtt_estimate,
int64_t now) { int64_t now) {
@ -56,7 +57,7 @@ inline bool TooManyFailures(
// Determines whether we have gone too long without seeing any response. // Determines whether we have gone too long without seeing any response.
inline bool TooLongWithoutResponse( inline bool TooLongWithoutResponse(
const std::vector<cricket::Connection::SentPing>& pings_since_last_response, const std::vector<Connection::SentPing>& pings_since_last_response,
int64_t maximum_time, int64_t maximum_time,
int64_t now) { int64_t now) {
if (pings_since_last_response.size() == 0) if (pings_since_last_response.size() == 0)
@ -69,13 +70,13 @@ inline bool TooLongWithoutResponse(
// Helper methods for converting string values of log description fields to // Helper methods for converting string values of log description fields to
// enum. // enum.
webrtc::IceCandidateType GetCandidateTypeByString(const std::string& type) { webrtc::IceCandidateType GetCandidateTypeByString(const std::string& type) {
if (type == cricket::LOCAL_PORT_TYPE) { if (type == LOCAL_PORT_TYPE) {
return webrtc::IceCandidateType::kLocal; return webrtc::IceCandidateType::kLocal;
} else if (type == cricket::STUN_PORT_TYPE) { } else if (type == STUN_PORT_TYPE) {
return webrtc::IceCandidateType::kStun; return webrtc::IceCandidateType::kStun;
} else if (type == cricket::PRFLX_PORT_TYPE) { } else if (type == PRFLX_PORT_TYPE) {
return webrtc::IceCandidateType::kPrflx; return webrtc::IceCandidateType::kPrflx;
} else if (type == cricket::RELAY_PORT_TYPE) { } else if (type == RELAY_PORT_TYPE) {
return webrtc::IceCandidateType::kRelay; return webrtc::IceCandidateType::kRelay;
} }
return webrtc::IceCandidateType::kUnknown; return webrtc::IceCandidateType::kUnknown;
@ -83,13 +84,13 @@ webrtc::IceCandidateType GetCandidateTypeByString(const std::string& type) {
webrtc::IceCandidatePairProtocol GetProtocolByString( webrtc::IceCandidatePairProtocol GetProtocolByString(
const std::string& protocol) { const std::string& protocol) {
if (protocol == cricket::UDP_PROTOCOL_NAME) { if (protocol == UDP_PROTOCOL_NAME) {
return webrtc::IceCandidatePairProtocol::kUdp; return webrtc::IceCandidatePairProtocol::kUdp;
} else if (protocol == cricket::TCP_PROTOCOL_NAME) { } else if (protocol == TCP_PROTOCOL_NAME) {
return webrtc::IceCandidatePairProtocol::kTcp; return webrtc::IceCandidatePairProtocol::kTcp;
} else if (protocol == cricket::SSLTCP_PROTOCOL_NAME) { } else if (protocol == SSLTCP_PROTOCOL_NAME) {
return webrtc::IceCandidatePairProtocol::kSsltcp; return webrtc::IceCandidatePairProtocol::kSsltcp;
} else if (protocol == cricket::TLS_PROTOCOL_NAME) { } else if (protocol == TLS_PROTOCOL_NAME) {
return webrtc::IceCandidatePairProtocol::kTls; return webrtc::IceCandidatePairProtocol::kTls;
} }
return webrtc::IceCandidatePairProtocol::kUnknown; return webrtc::IceCandidatePairProtocol::kUnknown;
@ -148,24 +149,22 @@ const int RTT_RATIO = 3; // 3 : 1
constexpr int64_t kMinExtraPingDelayMs = 100; constexpr int64_t kMinExtraPingDelayMs = 100;
// Default field trials. // Default field trials.
const cricket::IceFieldTrials kDefaultFieldTrials; const IceFieldTrials kDefaultFieldTrials;
constexpr int kSupportGoogPingVersionRequestIndex = constexpr int kSupportGoogPingVersionRequestIndex = static_cast<int>(
static_cast<int>(cricket::IceGoogMiscInfoBindingRequestAttributeIndex:: IceGoogMiscInfoBindingRequestAttributeIndex::SUPPORT_GOOG_PING_VERSION);
SUPPORT_GOOG_PING_VERSION);
constexpr int kSupportGoogPingVersionResponseIndex = constexpr int kSupportGoogPingVersionResponseIndex = static_cast<int>(
static_cast<int>(cricket::IceGoogMiscInfoBindingResponseAttributeIndex:: IceGoogMiscInfoBindingResponseAttributeIndex::SUPPORT_GOOG_PING_VERSION);
SUPPORT_GOOG_PING_VERSION);
} // namespace } // namespace
namespace cricket { // A ConnectionRequest is a STUN binding used to determine writability.
class Connection::ConnectionRequest : public StunRequest { class Connection::ConnectionRequest : public StunRequest {
public: public:
ConnectionRequest(StunRequestManager& manager, Connection* connection); ConnectionRequest(StunRequestManager& manager,
void Prepare(StunMessage* message) override; Connection* connection,
std::unique_ptr<IceMessage> message);
void OnResponse(StunMessage* response) override; void OnResponse(StunMessage* response) override;
void OnErrorResponse(StunMessage* response) override; void OnErrorResponse(StunMessage* response) override;
void OnTimeout() override; void OnTimeout() override;
@ -176,101 +175,11 @@ class Connection::ConnectionRequest : public StunRequest {
Connection* const connection_; Connection* const connection_;
}; };
// A ConnectionRequest is a STUN binding used to determine writability. Connection::ConnectionRequest::ConnectionRequest(
Connection::ConnectionRequest::ConnectionRequest(StunRequestManager& manager, StunRequestManager& manager,
Connection* connection) Connection* connection,
: StunRequest(manager, std::make_unique<IceMessage>(STUN_BINDING_REQUEST)), std::unique_ptr<IceMessage> message)
connection_(connection) {} : StunRequest(manager, std::move(message)), connection_(connection) {}
void Connection::ConnectionRequest::Prepare(StunMessage* message) {
RTC_DCHECK_RUN_ON(connection_->network_thread_);
RTC_DCHECK_EQ(message->type(), STUN_BINDING_REQUEST);
std::string username;
connection_->port()->CreateStunUsername(
connection_->remote_candidate().username(), &username);
// Note that the order of attributes does not impact the parsing on the
// receiver side. The attribute is retrieved then by iterating and matching
// over all parsed attributes. See StunMessage::GetAttribute.
message->AddAttribute(
std::make_unique<StunByteStringAttribute>(STUN_ATTR_USERNAME, username));
// connection_ already holds this ping, so subtract one from count.
if (connection_->port()->send_retransmit_count_attribute()) {
message->AddAttribute(std::make_unique<StunUInt32Attribute>(
STUN_ATTR_RETRANSMIT_COUNT,
static_cast<uint32_t>(connection_->pings_since_last_response_.size() -
1)));
}
uint32_t network_info = connection_->port()->Network()->id();
network_info = (network_info << 16) | connection_->port()->network_cost();
message->AddAttribute(std::make_unique<StunUInt32Attribute>(
STUN_ATTR_GOOG_NETWORK_INFO, network_info));
if (connection_->field_trials_->piggyback_ice_check_acknowledgement &&
connection_->last_ping_id_received()) {
message->AddAttribute(std::make_unique<StunByteStringAttribute>(
STUN_ATTR_GOOG_LAST_ICE_CHECK_RECEIVED,
connection_->last_ping_id_received().value()));
}
// Adding ICE_CONTROLLED or ICE_CONTROLLING attribute based on the role.
if (connection_->port()->GetIceRole() == ICEROLE_CONTROLLING) {
message->AddAttribute(std::make_unique<StunUInt64Attribute>(
STUN_ATTR_ICE_CONTROLLING, connection_->port()->IceTiebreaker()));
// We should have either USE_CANDIDATE attribute or ICE_NOMINATION
// attribute but not both. That was enforced in p2ptransportchannel.
if (connection_->use_candidate_attr()) {
message->AddAttribute(
std::make_unique<StunByteStringAttribute>(STUN_ATTR_USE_CANDIDATE));
}
if (connection_->nomination_ &&
connection_->nomination_ != connection_->acked_nomination()) {
message->AddAttribute(std::make_unique<StunUInt32Attribute>(
STUN_ATTR_NOMINATION, connection_->nomination_));
}
} else if (connection_->port()->GetIceRole() == ICEROLE_CONTROLLED) {
message->AddAttribute(std::make_unique<StunUInt64Attribute>(
STUN_ATTR_ICE_CONTROLLED, connection_->port()->IceTiebreaker()));
} else {
RTC_DCHECK_NOTREACHED();
}
// Adding PRIORITY Attribute.
// Changing the type preference to Peer Reflexive and local preference
// and component id information is unchanged from the original priority.
// priority = (2^24)*(type preference) +
// (2^8)*(local preference) +
// (2^0)*(256 - component ID)
uint32_t type_preference =
(connection_->local_candidate().protocol() == TCP_PROTOCOL_NAME)
? ICE_TYPE_PREFERENCE_PRFLX_TCP
: ICE_TYPE_PREFERENCE_PRFLX;
uint32_t prflx_priority =
type_preference << 24 |
(connection_->local_candidate().priority() & 0x00FFFFFF);
message->AddAttribute(std::make_unique<StunUInt32Attribute>(
STUN_ATTR_PRIORITY, prflx_priority));
if (connection_->field_trials_->enable_goog_ping &&
!connection_->remote_support_goog_ping_.has_value()) {
// Check if remote supports GOOG PING by announcing which version we
// support. This is sent on all STUN_BINDING_REQUEST until we get a
// STUN_BINDING_RESPONSE.
auto list =
StunAttribute::CreateUInt16ListAttribute(STUN_ATTR_GOOG_MISC_INFO);
list->AddTypeAtIndex(kSupportGoogPingVersionRequestIndex, kGoogPingVersion);
message->AddAttribute(std::move(list));
}
if (connection_->ShouldSendGoogPing(message)) {
message->SetType(GOOG_PING_REQUEST);
message->ClearAttributes();
message->AddMessageIntegrity32(connection_->remote_candidate().password());
} else {
message->AddMessageIntegrity(connection_->remote_candidate().password());
message->AddFingerprint();
}
}
void Connection::ConnectionRequest::OnResponse(StunMessage* response) { void Connection::ConnectionRequest::OnResponse(StunMessage* response) {
RTC_DCHECK_RUN_ON(connection_->network_thread_); RTC_DCHECK_RUN_ON(connection_->network_thread_);
@ -997,7 +906,7 @@ int64_t Connection::last_ping_sent() const {
void Connection::Ping(int64_t now) { void Connection::Ping(int64_t now) {
RTC_DCHECK_RUN_ON(network_thread_); RTC_DCHECK_RUN_ON(network_thread_);
last_ping_sent_ = now; last_ping_sent_ = now;
ConnectionRequest* req = new ConnectionRequest(requests_, this);
// If not using renomination, we use "1" to mean "nominated" and "0" to mean // If not using renomination, we use "1" to mean "nominated" and "0" to mean
// "not nominated". If using renomination, values greater than 1 are used for // "not nominated". If using renomination, values greater than 1 are used for
// re-nominated pairs. // re-nominated pairs.
@ -1005,15 +914,87 @@ void Connection::Ping(int64_t now) {
if (nomination_ > 0) { if (nomination_ > 0) {
nomination = nomination_; nomination = nomination_;
} }
auto req =
std::make_unique<ConnectionRequest>(requests_, this, BuildPingRequest());
if (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)));
}
pings_since_last_response_.push_back(SentPing(req->id(), now, nomination)); pings_since_last_response_.push_back(SentPing(req->id(), now, nomination));
RTC_LOG(LS_VERBOSE) << ToString() << ": Sending STUN ping, id=" RTC_LOG(LS_VERBOSE) << ToString() << ": Sending STUN ping, id="
<< rtc::hex_encode(req->id()) << rtc::hex_encode(req->id())
<< ", nomination=" << nomination_; << ", nomination=" << nomination_;
requests_.Send(req); requests_.Send(req.release());
state_ = IceCandidatePairState::IN_PROGRESS; state_ = IceCandidatePairState::IN_PROGRESS;
num_pings_sent_++; num_pings_sent_++;
} }
std::unique_ptr<IceMessage> Connection::BuildPingRequest() {
auto message = std::make_unique<IceMessage>(STUN_BINDING_REQUEST);
// Note that the order of attributes does not impact the parsing on the
// receiver side. The attribute is retrieved then by iterating and matching
// over all parsed attributes. See StunMessage::GetAttribute.
message->AddAttribute(std::make_unique<StunByteStringAttribute>(
STUN_ATTR_USERNAME,
port()->CreateStunUsername(remote_candidate_.username())));
message->AddAttribute(std::make_unique<StunUInt32Attribute>(
STUN_ATTR_GOOG_NETWORK_INFO,
(port_->Network()->id() << 16) | port_->network_cost()));
if (field_trials_->piggyback_ice_check_acknowledgement &&
last_ping_id_received_) {
message->AddAttribute(std::make_unique<StunByteStringAttribute>(
STUN_ATTR_GOOG_LAST_ICE_CHECK_RECEIVED, *last_ping_id_received_));
}
// Adding ICE_CONTROLLED or ICE_CONTROLLING attribute based on the role.
IceRole ice_role = port_->GetIceRole();
RTC_DCHECK(ice_role == ICEROLE_CONTROLLING || ice_role == ICEROLE_CONTROLLED);
message->AddAttribute(std::make_unique<StunUInt64Attribute>(
ice_role == ICEROLE_CONTROLLING ? STUN_ATTR_ICE_CONTROLLING
: STUN_ATTR_ICE_CONTROLLED,
port_->IceTiebreaker()));
if (ice_role == ICEROLE_CONTROLLING) {
// We should have either USE_CANDIDATE attribute or ICE_NOMINATION
// attribute but not both. That was enforced in p2ptransportchannel.
if (use_candidate_attr()) {
message->AddAttribute(
std::make_unique<StunByteStringAttribute>(STUN_ATTR_USE_CANDIDATE));
}
if (nomination_ && nomination_ != acked_nomination()) {
message->AddAttribute(std::make_unique<StunUInt32Attribute>(
STUN_ATTR_NOMINATION, nomination_));
}
}
message->AddAttribute(std::make_unique<StunUInt32Attribute>(
STUN_ATTR_PRIORITY, prflx_priority()));
if (port()->send_retransmit_count_attribute()) {
message->AddAttribute(std::make_unique<StunUInt32Attribute>(
STUN_ATTR_RETRANSMIT_COUNT, pings_since_last_response_.size()));
}
if (field_trials_->enable_goog_ping &&
!remote_support_goog_ping_.has_value()) {
// Check if remote supports GOOG PING by announcing which version we
// support. This is sent on all STUN_BINDING_REQUEST until we get a
// STUN_BINDING_RESPONSE.
auto list =
StunAttribute::CreateUInt16ListAttribute(STUN_ATTR_GOOG_MISC_INFO);
list->AddTypeAtIndex(kSupportGoogPingVersionRequestIndex, kGoogPingVersion);
message->AddAttribute(std::move(list));
}
message->AddMessageIntegrity(remote_candidate_.password());
message->AddFingerprint();
return message;
}
int64_t Connection::last_ping_response_received() const { int64_t Connection::last_ping_response_received() const {
RTC_DCHECK_RUN_ON(network_thread_); RTC_DCHECK_RUN_ON(network_thread_);
return last_ping_response_received_; return last_ping_response_received_;
@ -1051,7 +1032,8 @@ void Connection::HandlePiggybackCheckAcknowledgementIfAny(StunMessage* msg) {
const StunByteStringAttribute* last_ice_check_received_attr = const StunByteStringAttribute* last_ice_check_received_attr =
msg->GetByteString(STUN_ATTR_GOOG_LAST_ICE_CHECK_RECEIVED); msg->GetByteString(STUN_ATTR_GOOG_LAST_ICE_CHECK_RECEIVED);
if (last_ice_check_received_attr) { if (last_ice_check_received_attr) {
const std::string request_id = last_ice_check_received_attr->GetString(); const absl::string_view request_id =
last_ice_check_received_attr->string_view();
auto iter = absl::c_find_if( auto iter = absl::c_find_if(
pings_since_last_response_, pings_since_last_response_,
[&request_id](const SentPing& ping) { return ping.id == request_id; }); [&request_id](const SentPing& ping) { return ping.id == request_id; });
@ -1078,7 +1060,7 @@ int64_t Connection::last_data_received() const {
void Connection::ReceivedPingResponse( void Connection::ReceivedPingResponse(
int rtt, int rtt,
const std::string& request_id, absl::string_view request_id,
const absl::optional<uint32_t>& nomination) { const absl::optional<uint32_t>& nomination) {
RTC_DCHECK_RUN_ON(network_thread_); RTC_DCHECK_RUN_ON(network_thread_);
RTC_DCHECK_GE(rtt, 0); RTC_DCHECK_GE(rtt, 0);
@ -1487,6 +1469,21 @@ int64_t Connection::receiving_unchanged_since() const {
return receiving_unchanged_since_; return receiving_unchanged_since_;
} }
uint32_t Connection::prflx_priority() const {
RTC_DCHECK_RUN_ON(network_thread_);
// PRIORITY Attribute.
// Changing the type preference to Peer Reflexive and local preference
// and component id information is unchanged from the original priority.
// priority = (2^24)*(type preference) +
// (2^8)*(local preference) +
// (2^0)*(256 - component ID)
IcePriorityValue type_preference =
(local_candidate_.protocol() == TCP_PROTOCOL_NAME)
? ICE_TYPE_PREFERENCE_PRFLX_TCP
: ICE_TYPE_PREFERENCE_PRFLX;
return type_preference << 24 | (local_candidate_.priority() & 0x00FFFFFF);
}
ConnectionInfo Connection::stats() { ConnectionInfo Connection::stats() {
RTC_DCHECK_RUN_ON(network_thread_); RTC_DCHECK_RUN_ON(network_thread_);
stats_.recv_bytes_second = round(recv_rate_tracker_.ComputeRate()); stats_.recv_bytes_second = round(recv_rate_tracker_.ComputeRate());

View File

@ -202,8 +202,9 @@ class Connection : public CandidatePairInterface {
void Ping(int64_t now); void Ping(int64_t now);
void ReceivedPingResponse( void ReceivedPingResponse(
int rtt, int rtt,
const std::string& request_id, absl::string_view request_id,
const absl::optional<uint32_t>& nomination = absl::nullopt); const absl::optional<uint32_t>& nomination = absl::nullopt);
std::unique_ptr<IceMessage> BuildPingRequest() RTC_RUN_ON(network_thread_);
int64_t last_ping_response_received() const; int64_t last_ping_response_received() const;
const absl::optional<std::string>& last_ping_id_received() const; const absl::optional<std::string>& last_ping_id_received() const;
@ -274,6 +275,10 @@ class Connection : public CandidatePairInterface {
// Returns the last time when the connection changed its receiving state. // Returns the last time when the connection changed its receiving state.
int64_t receiving_unchanged_since() const; int64_t receiving_unchanged_since() const;
// Constructs the prflx priority as described in
// https://datatracker.ietf.org/doc/html/rfc5245#section-4.1.2.1
uint32_t prflx_priority() const;
bool stable(int64_t now) const; bool stable(int64_t now) const;
// Check if we sent `val` pings without receving a response. // Check if we sent `val` pings without receving a response.

View File

@ -653,14 +653,14 @@ bool Port::ParseStunUsername(const StunMessage* stun_msg,
return false; return false;
// RFRAG:LFRAG // RFRAG:LFRAG
const std::string username = username_attr->GetString(); const absl::string_view username = username_attr->string_view();
size_t colon_pos = username.find(':'); size_t colon_pos = username.find(':');
if (colon_pos == std::string::npos) { if (colon_pos == absl::string_view::npos) {
return false; return false;
} }
*local_ufrag = username.substr(0, colon_pos); *local_ufrag = std::string(username.substr(0, colon_pos));
*remote_ufrag = username.substr(colon_pos + 1, username.size()); *remote_ufrag = std::string(username.substr(colon_pos + 1, username.size()));
return true; return true;
} }
@ -725,12 +725,8 @@ bool Port::MaybeIceRoleConflict(const rtc::SocketAddress& addr,
return ret; return ret;
} }
void Port::CreateStunUsername(const std::string& remote_username, std::string Port::CreateStunUsername(const std::string& remote_username) const {
std::string* stun_username_attr_str) const { return remote_username + ":" + username_fragment();
stun_username_attr_str->clear();
*stun_username_attr_str = remote_username;
stun_username_attr_str->append(":");
stun_username_attr_str->append(username_fragment());
} }
bool Port::HandleIncomingPacket(rtc::AsyncPacketSocket* socket, bool Port::HandleIncomingPacket(rtc::AsyncPacketSocket* socket,

View File

@ -62,7 +62,9 @@ extern const char TCPTYPE_ACTIVE_STR[];
extern const char TCPTYPE_PASSIVE_STR[]; extern const char TCPTYPE_PASSIVE_STR[];
extern const char TCPTYPE_SIMOPEN_STR[]; extern const char TCPTYPE_SIMOPEN_STR[];
enum IcePriorityValue { // The type preference MUST be an integer from 0 to 126 inclusive.
// https://datatracker.ietf.org/doc/html/rfc5245#section-4.1.2.1
enum IcePriorityValue : uint8_t {
ICE_TYPE_PREFERENCE_RELAY_TLS = 0, ICE_TYPE_PREFERENCE_RELAY_TLS = 0,
ICE_TYPE_PREFERENCE_RELAY_TCP = 1, ICE_TYPE_PREFERENCE_RELAY_TCP = 1,
ICE_TYPE_PREFERENCE_RELAY_UDP = 2, ICE_TYPE_PREFERENCE_RELAY_UDP = 2,
@ -346,8 +348,7 @@ class Port : public PortInterface,
bool ParseStunUsername(const StunMessage* stun_msg, bool ParseStunUsername(const StunMessage* stun_msg,
std::string* local_username, std::string* local_username,
std::string* remote_username) const; std::string* remote_username) const;
void CreateStunUsername(const std::string& remote_username, std::string CreateStunUsername(const std::string& remote_username) const;
std::string* stun_username_attr_str) const;
bool MaybeIceRoleConflict(const rtc::SocketAddress& addr, bool MaybeIceRoleConflict(const rtc::SocketAddress& addr,
IceMessage* stun_msg, IceMessage* stun_msg,

View File

@ -1472,7 +1472,7 @@ TEST_F(PortTest, TestLoopbackCall) {
const StunByteStringAttribute* username_attr = const StunByteStringAttribute* username_attr =
msg->GetByteString(STUN_ATTR_USERNAME); msg->GetByteString(STUN_ATTR_USERNAME);
modified_req->AddAttribute(std::make_unique<StunByteStringAttribute>( modified_req->AddAttribute(std::make_unique<StunByteStringAttribute>(
STUN_ATTR_USERNAME, username_attr->GetString())); STUN_ATTR_USERNAME, username_attr->string_view()));
// To make sure we receive error response, adding tiebreaker less than // To make sure we receive error response, adding tiebreaker less than
// what's present in request. // what's present in request.
modified_req->AddAttribute(std::make_unique<StunUInt64Attribute>( modified_req->AddAttribute(std::make_unique<StunUInt64Attribute>(
@ -1792,7 +1792,7 @@ TEST_F(PortTest, TestSendStunMessage) {
const StunUInt32Attribute* priority_attr = msg->GetUInt32(STUN_ATTR_PRIORITY); const StunUInt32Attribute* priority_attr = msg->GetUInt32(STUN_ATTR_PRIORITY);
ASSERT_TRUE(priority_attr != NULL); ASSERT_TRUE(priority_attr != NULL);
EXPECT_EQ(kDefaultPrflxPriority, priority_attr->value()); EXPECT_EQ(kDefaultPrflxPriority, priority_attr->value());
EXPECT_EQ("rfrag:lfrag", username_attr->GetString()); EXPECT_EQ("rfrag:lfrag", username_attr->string_view());
EXPECT_TRUE(msg->GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL); EXPECT_TRUE(msg->GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
EXPECT_EQ(StunMessage::IntegrityStatus::kIntegrityOk, EXPECT_EQ(StunMessage::IntegrityStatus::kIntegrityOk,
msg->ValidateMessageIntegrity("rpass")); msg->ValidateMessageIntegrity("rpass"));

View File

@ -1185,7 +1185,7 @@ bool TurnPort::UpdateNonce(StunMessage* response) {
"stale nonce error response."; "stale nonce error response.";
return false; return false;
} }
set_realm(realm_attr->GetString()); set_realm(realm_attr->string_view());
const StunByteStringAttribute* nonce_attr = const StunByteStringAttribute* nonce_attr =
response->GetByteString(STUN_ATTR_NONCE); response->GetByteString(STUN_ATTR_NONCE);
@ -1194,7 +1194,7 @@ bool TurnPort::UpdateNonce(StunMessage* response) {
"stale nonce error response."; "stale nonce error response.";
return false; return false;
} }
set_nonce(nonce_attr->GetString()); set_nonce(nonce_attr->string_view());
return true; return true;
} }
@ -1499,7 +1499,7 @@ void TurnAllocateRequest::OnAuthChallenge(StunMessage* response, int code) {
"allocate unauthorized response."; "allocate unauthorized response.";
return; return;
} }
port_->set_realm(realm_attr->GetString()); port_->set_realm(realm_attr->string_view());
const StunByteStringAttribute* nonce_attr = const StunByteStringAttribute* nonce_attr =
response->GetByteString(STUN_ATTR_NONCE); response->GetByteString(STUN_ATTR_NONCE);
@ -1509,7 +1509,7 @@ void TurnAllocateRequest::OnAuthChallenge(StunMessage* response, int code) {
"allocate unauthorized response."; "allocate unauthorized response.";
return; return;
} }
port_->set_nonce(nonce_attr->GetString()); port_->set_nonce(nonce_attr->string_view());
// Send another allocate request, with the received realm and nonce values. // Send another allocate request, with the received realm and nonce values.
port_->SendRequest(new TurnAllocateRequest(port_), 0); port_->SendRequest(new TurnAllocateRequest(port_), 0);
@ -1544,7 +1544,7 @@ void TurnAllocateRequest::OnTryAlternate(StunMessage* response, int code) {
RTC_LOG(LS_INFO) << port_->ToString() RTC_LOG(LS_INFO) << port_->ToString()
<< ": Applying STUN_ATTR_REALM attribute in " << ": Applying STUN_ATTR_REALM attribute in "
"try alternate error response."; "try alternate error response.";
port_->set_realm(realm_attr->GetString()); port_->set_realm(realm_attr->string_view());
} }
const StunByteStringAttribute* nonce_attr = const StunByteStringAttribute* nonce_attr =
@ -1553,7 +1553,7 @@ void TurnAllocateRequest::OnTryAlternate(StunMessage* response, int code) {
RTC_LOG(LS_INFO) << port_->ToString() RTC_LOG(LS_INFO) << port_->ToString()
<< ": Applying STUN_ATTR_NONCE attribute in " << ": Applying STUN_ATTR_NONCE attribute in "
"try alternate error response."; "try alternate error response.";
port_->set_nonce(nonce_attr->GetString()); port_->set_nonce(nonce_attr->string_view());
} }
// For TCP, we can't close the original Tcp socket during handling a 300 as // For TCP, we can't close the original Tcp socket during handling a 300 as

View File

@ -268,10 +268,10 @@ class TurnPort : public Port {
bool CreateTurnClientSocket(); bool CreateTurnClientSocket();
void set_nonce(const std::string& nonce) { nonce_ = nonce; } void set_nonce(absl::string_view nonce) { nonce_ = std::string(nonce); }
void set_realm(const std::string& realm) { void set_realm(absl::string_view realm) {
if (realm != realm_) { if (realm != realm_) {
realm_ = realm; realm_ = std::string(realm);
UpdateHash(); UpdateHash();
} }
} }

View File

@ -876,7 +876,7 @@ class TurnLoggingIdValidator : public StunMessageObserver {
msg->GetByteString(cricket::STUN_ATTR_TURN_LOGGING_ID); msg->GetByteString(cricket::STUN_ATTR_TURN_LOGGING_ID);
if (expect_val_) { if (expect_val_) {
ASSERT_NE(nullptr, attr); ASSERT_NE(nullptr, attr);
ASSERT_EQ(expect_val_, attr->GetString()); ASSERT_EQ(expect_val_, attr->string_view());
} else { } else {
EXPECT_EQ(nullptr, attr); EXPECT_EQ(nullptr, attr);
} }

View File

@ -286,7 +286,7 @@ void TurnServer::HandleStunMessage(TurnServerConnection* conn,
// This is a non-allocate request, or a retransmit of an allocate. // This is a non-allocate request, or a retransmit of an allocate.
// Check that the username matches the previous username used. // Check that the username matches the previous username used.
if (IsStunRequestType(msg.type()) && if (IsStunRequestType(msg.type()) &&
msg.GetByteString(STUN_ATTR_USERNAME)->GetString() != msg.GetByteString(STUN_ATTR_USERNAME)->string_view() !=
allocation->username()) { allocation->username()) {
SendErrorResponse(conn, &msg, STUN_ERROR_WRONG_CREDENTIALS, SendErrorResponse(conn, &msg, STUN_ERROR_WRONG_CREDENTIALS,
STUN_ERROR_REASON_WRONG_CREDENTIALS); STUN_ERROR_REASON_WRONG_CREDENTIALS);
@ -307,8 +307,9 @@ bool TurnServer::GetKey(const StunMessage* msg, std::string* key) {
return false; return false;
} }
std::string username = username_attr->GetString(); return (auth_hook_ != NULL &&
return (auth_hook_ != NULL && auth_hook_->GetKey(username, realm_, key)); auth_hook_->GetKey(std::string(username_attr->string_view()), realm_,
key));
} }
bool TurnServer::CheckAuthorization(TurnServerConnection* conn, bool TurnServer::CheckAuthorization(TurnServerConnection* conn,
@ -342,7 +343,7 @@ bool TurnServer::CheckAuthorization(TurnServerConnection* conn,
} }
// Fail if bad nonce. // Fail if bad nonce.
if (!ValidateNonce(nonce_attr->GetString())) { if (!ValidateNonce(nonce_attr->string_view())) {
SendErrorResponseWithRealmAndNonce(conn, msg, STUN_ERROR_STALE_NONCE, SendErrorResponseWithRealmAndNonce(conn, msg, STUN_ERROR_STALE_NONCE,
STUN_ERROR_REASON_STALE_NONCE); STUN_ERROR_REASON_STALE_NONCE);
return false; return false;
@ -359,14 +360,14 @@ bool TurnServer::CheckAuthorization(TurnServerConnection* conn,
// Fail if one-time-use nonce feature is enabled. // Fail if one-time-use nonce feature is enabled.
TurnServerAllocation* allocation = FindAllocation(conn); TurnServerAllocation* allocation = FindAllocation(conn);
if (enable_otu_nonce_ && allocation && if (enable_otu_nonce_ && allocation &&
allocation->last_nonce() == nonce_attr->GetString()) { allocation->last_nonce() == nonce_attr->string_view()) {
SendErrorResponseWithRealmAndNonce(conn, msg, STUN_ERROR_STALE_NONCE, SendErrorResponseWithRealmAndNonce(conn, msg, STUN_ERROR_STALE_NONCE,
STUN_ERROR_REASON_STALE_NONCE); STUN_ERROR_REASON_STALE_NONCE);
return false; return false;
} }
if (allocation) { if (allocation) {
allocation->set_last_nonce(nonce_attr->GetString()); allocation->set_last_nonce(nonce_attr->string_view());
} }
// Success. // Success.
return true; return true;
@ -425,7 +426,7 @@ std::string TurnServer::GenerateNonce(int64_t now) const {
return nonce; return nonce;
} }
bool TurnServer::ValidateNonce(const std::string& nonce) const { bool TurnServer::ValidateNonce(absl::string_view nonce) const {
// Check the size. // Check the size.
if (nonce.size() != kNonceSize) { if (nonce.size() != kNonceSize) {
return false; return false;
@ -662,7 +663,7 @@ void TurnServerAllocation::HandleAllocateRequest(const TurnMessage* msg) {
const StunByteStringAttribute* username_attr = const StunByteStringAttribute* username_attr =
msg->GetByteString(STUN_ATTR_USERNAME); msg->GetByteString(STUN_ATTR_USERNAME);
RTC_DCHECK(username_attr != NULL); RTC_DCHECK(username_attr != NULL);
username_ = username_attr->GetString(); username_ = std::string(username_attr->string_view());
// Figure out the lifetime and start the allocation timer. // Figure out the lifetime and start the allocation timer.
int lifetime_secs = ComputeLifetime(*msg); int lifetime_secs = ComputeLifetime(*msg);

View File

@ -81,7 +81,9 @@ class TurnServerAllocation : public rtc::MessageHandlerAutoCleanup,
const std::string& transaction_id() const { return transaction_id_; } const std::string& transaction_id() const { return transaction_id_; }
const std::string& username() const { return username_; } const std::string& username() const { return username_; }
const std::string& last_nonce() const { return last_nonce_; } const std::string& last_nonce() const { return last_nonce_; }
void set_last_nonce(const std::string& nonce) { last_nonce_ = nonce; } void set_last_nonce(absl::string_view nonce) {
last_nonce_ = std::string(nonce);
}
std::string ToString() const; std::string ToString() const;
@ -288,7 +290,7 @@ class TurnServer : public sigslot::has_slots<> {
const char* data, const char* data,
size_t size, size_t size,
const std::string& key) RTC_RUN_ON(thread_); const std::string& key) RTC_RUN_ON(thread_);
bool ValidateNonce(const std::string& nonce) const RTC_RUN_ON(thread_); bool ValidateNonce(absl::string_view nonce) const RTC_RUN_ON(thread_);
TurnServerAllocation* FindAllocation(TurnServerConnection* conn) TurnServerAllocation* FindAllocation(TurnServerConnection* conn)
RTC_RUN_ON(thread_); RTC_RUN_ON(thread_);