diff --git a/api/transport/BUILD.gn b/api/transport/BUILD.gn index 596710ee45..c3f6f9fa83 100644 --- a/api/transport/BUILD.gn +++ b/api/transport/BUILD.gn @@ -105,6 +105,7 @@ rtc_source_set("stun_types") { "../../rtc_base:logging", "../../rtc_base:rtc_base", "../../rtc_base:socket_address", + "../../system_wrappers:metrics", ] absl_deps = [ "//third_party/abseil-cpp/absl/strings" ] } diff --git a/api/transport/stun.cc b/api/transport/stun.cc index e7cb5ed0f7..53515b17aa 100644 --- a/api/transport/stun.cc +++ b/api/transport/stun.cc @@ -24,6 +24,7 @@ #include "rtc_base/helpers.h" #include "rtc_base/logging.h" #include "rtc_base/message_digest.h" +#include "system_wrappers/include/metrics.h" using rtc::ByteBufferReader; using rtc::ByteBufferWriter; @@ -258,6 +259,71 @@ StunMessage::IntegrityStatus StunMessage::ValidateMessageIntegrity( } else { integrity_ = IntegrityStatus::kNoIntegrity; } + // Log the result of integrity checking. See crbug.com/1177125 for background. + // Convert args to integer for the benefit of the macros. + int bucket_count = static_cast(IntegrityStatus::kMaxValue) + 1; + int integrity = static_cast(integrity_); + if (IsStunRequestType(type_)) { + RTC_HISTOGRAM_ENUMERATION("WebRTC.Stun.Integrity.Request", integrity, + bucket_count); + } else if (IsStunSuccessResponseType(type_)) { + RTC_HISTOGRAM_ENUMERATION("WebRTC.Stun.Integrity.Response", integrity, + bucket_count); + } else if (IsStunIndicationType(type_)) { + RTC_HISTOGRAM_ENUMERATION("WebRTC.Stun.Integrity.Indication", integrity, + bucket_count); + } else { + RTC_DCHECK(IsStunErrorResponseType(type_)); + auto* error_attribute = GetErrorCode(); + if (!error_attribute) { + RTC_HISTOGRAM_ENUMERATION( + "WebRTC.Stun.Integrity.ErrorResponse.NoErrorAttribute", integrity, + bucket_count); + } else { + switch (error_attribute->code()) { + case STUN_ERROR_TRY_ALTERNATE: + RTC_HISTOGRAM_ENUMERATION( + "WebRTC.Stun.Integrity.ErrorResponse.TryAlternate", integrity, + bucket_count); + break; + case STUN_ERROR_BAD_REQUEST: + RTC_HISTOGRAM_ENUMERATION( + "WebRTC.Stun.Integrity.ErrorResponse.BadRequest", integrity, + bucket_count); + break; + case STUN_ERROR_UNAUTHORIZED: + RTC_HISTOGRAM_ENUMERATION( + "WebRTC.Stun.Integrity.ErrorResponse.Unauthorized", integrity, + bucket_count); + break; + case STUN_ERROR_UNKNOWN_ATTRIBUTE: + RTC_HISTOGRAM_ENUMERATION( + "WebRTC.Stun.Integrity.ErrorResponse.UnknownAttribute", integrity, + bucket_count); + break; + case STUN_ERROR_STALE_NONCE: + RTC_HISTOGRAM_ENUMERATION( + "WebRTC.Stun.Integrity.ErrorResponse.StaleNonce", integrity, + bucket_count); + break; + case STUN_ERROR_SERVER_ERROR: + RTC_HISTOGRAM_ENUMERATION( + "WebRTC.Stun.Integrity.ErrorResponse.ServerError", integrity, + bucket_count); + break; + case STUN_ERROR_GLOBAL_FAILURE: + RTC_HISTOGRAM_ENUMERATION( + "WebRTC.Stun.Integrity.ErrorResponse.GlobalFailure", integrity, + bucket_count); + break; + default: + RTC_HISTOGRAM_ENUMERATION( + "WebRTC.Stun.Integrity.ErrorResponse.ErrorOther", integrity, + bucket_count); + break; + } + } + } return integrity_; } diff --git a/api/transport/stun.h b/api/transport/stun.h index 9751ed172b..2098330f5a 100644 --- a/api/transport/stun.h +++ b/api/transport/stun.h @@ -159,11 +159,14 @@ class StunMessage { // The verification status of the message. This is checked on parsing, // or set by AddMessageIntegrity. + // These values are persisted to logs. Entries should not be renumbered and + // numeric values should never be reused. enum class IntegrityStatus { - kNotSet, - kNoIntegrity, // Message-integrity attribute missing - kIntegrityOk, // Message-integrity checked OK - kIntegrityBad, // Message-integrity verification failed + kNotSet = 0, + kNoIntegrity = 1, // Message-integrity attribute missing + kIntegrityOk = 2, // Message-integrity checked OK + kIntegrityBad = 3, // Message-integrity verification failed + kMaxValue = kIntegrityBad, }; int type() const { return type_; }