#ifndef NET_TRAFFIC_ANNOTATION_NETWORK_TRAFFIC_ANNOTATION_H_
#define NET_TRAFFIC_ANNOTATION_NETWORK_TRAFFIC_ANNOTATION_H_
#include <cstdint>
#include "base/check.h"
#include "base/compiler_specific.h"
#include "base/notreached.h"
#include "build/build_config.h"
#if BUILDFLAG(IS_ANDROID)
#include "base/android/scoped_java_ref.h"
#endif
namespace net::internal {
template <size_t N>
consteval int32_t ComputeAnnotationHash(const char (&str)[N]) {
uint32_t ret = 0;
for (size_t i = 0; i < N - 1; ++i) {
ret = (ret * 31u + static_cast<uint32_t>(UNSAFE_TODO(str[i]))) % 138003713u;
}
return static_cast<int32_t>(ret);
}
struct StringLiteralToHash {
int32_t hash_value;
template <size_t N>
consteval StringLiteralToHash(const char (&str)[N]) {
hash_value = ComputeAnnotationHash(str);
}
};
constexpr int TRAFFIC_ANNOTATION_UNINITIALIZED = -1;
constexpr int32_t TEST_PARTIAL_HASH = ComputeAnnotationHash("test_partial");
constexpr int32_t UNDEFINED_HASH = ComputeAnnotationHash("undefined");
}
namespace net {
struct PartialNetworkTrafficAnnotationTag;
struct NetworkTrafficAnnotationTag {
const int32_t unique_id_hash_code;
bool operator==(const NetworkTrafficAnnotationTag& other) const {
return unique_id_hash_code == other.unique_id_hash_code;
}
static NetworkTrafficAnnotationTag NotReached() { NOTREACHED(); }
friend constexpr NetworkTrafficAnnotationTag DefineNetworkTrafficAnnotation(
internal::StringLiteralToHash unique_id,
const char* proto);
friend NetworkTrafficAnnotationTag CompleteNetworkTrafficAnnotation(
internal::StringLiteralToHash unique_id,
const PartialNetworkTrafficAnnotationTag& partial_annotation,
const char* proto);
friend constexpr NetworkTrafficAnnotationTag
BranchedCompleteNetworkTrafficAnnotation(
internal::StringLiteralToHash unique_id,
internal::StringLiteralToHash group_id,
const PartialNetworkTrafficAnnotationTag& partial_annotation,
const char* proto);
#if BUILDFLAG(IS_ANDROID)
static NetworkTrafficAnnotationTag FromJavaAnnotation(
int32_t unique_id_hash_code);
#endif
friend struct MutableNetworkTrafficAnnotationTag;
private:
constexpr explicit NetworkTrafficAnnotationTag(int32_t unique_id_hash_code_)
: unique_id_hash_code(unique_id_hash_code_) {}
};
struct PartialNetworkTrafficAnnotationTag {
const int32_t unique_id_hash_code;
#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
const int32_t completing_id_hash_code;
#endif
friend constexpr PartialNetworkTrafficAnnotationTag
DefinePartialNetworkTrafficAnnotation(
internal::StringLiteralToHash unique_id,
internal::StringLiteralToHash completing_id,
const char* proto);
friend struct MutablePartialNetworkTrafficAnnotationTag;
private:
#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
constexpr PartialNetworkTrafficAnnotationTag(int32_t unique_id_hash_code_,
int32_t completing_id_hash_code_)
: unique_id_hash_code(unique_id_hash_code_),
completing_id_hash_code(completing_id_hash_code_) {}
#else
constexpr explicit PartialNetworkTrafficAnnotationTag(
int32_t unique_id_hash_code_)
: unique_id_hash_code(unique_id_hash_code_) {}
#endif
};
inline constexpr NetworkTrafficAnnotationTag DefineNetworkTrafficAnnotation(
internal::StringLiteralToHash unique_id,
const char* proto) {
return NetworkTrafficAnnotationTag(unique_id.hash_value);
}
constexpr PartialNetworkTrafficAnnotationTag
DefinePartialNetworkTrafficAnnotation(
internal::StringLiteralToHash unique_id,
internal::StringLiteralToHash completing_id,
const char* proto) {
#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
return PartialNetworkTrafficAnnotationTag(unique_id.hash_value,
completing_id.hash_value);
#else
return PartialNetworkTrafficAnnotationTag(unique_id.hash_value);
#endif
}
inline NetworkTrafficAnnotationTag CompleteNetworkTrafficAnnotation(
internal::StringLiteralToHash unique_id,
const PartialNetworkTrafficAnnotationTag& partial_annotation,
const char* proto) {
#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
DCHECK(partial_annotation.completing_id_hash_code == unique_id.hash_value ||
partial_annotation.unique_id_hash_code ==
internal::TEST_PARTIAL_HASH ||
partial_annotation.unique_id_hash_code == internal::UNDEFINED_HASH);
#endif
return NetworkTrafficAnnotationTag(partial_annotation.unique_id_hash_code);
}
constexpr inline NetworkTrafficAnnotationTag
BranchedCompleteNetworkTrafficAnnotation(
internal::StringLiteralToHash unique_id,
internal::StringLiteralToHash group_id,
const PartialNetworkTrafficAnnotationTag& partial_annotation,
const char* proto) {
#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
DCHECK(partial_annotation.completing_id_hash_code == group_id.hash_value ||
partial_annotation.unique_id_hash_code ==
internal::TEST_PARTIAL_HASH ||
partial_annotation.unique_id_hash_code == internal::UNDEFINED_HASH);
#endif
return NetworkTrafficAnnotationTag(unique_id.hash_value);
}
struct MutableNetworkTrafficAnnotationTag {
MutableNetworkTrafficAnnotationTag()
: unique_id_hash_code(internal::TRAFFIC_ANNOTATION_UNINITIALIZED) {}
explicit MutableNetworkTrafficAnnotationTag(
const NetworkTrafficAnnotationTag& traffic_annotation)
: unique_id_hash_code(traffic_annotation.unique_id_hash_code) {}
int32_t unique_id_hash_code;
bool operator==(const MutableNetworkTrafficAnnotationTag& other) const {
return unique_id_hash_code == other.unique_id_hash_code;
}
explicit operator NetworkTrafficAnnotationTag() const {
DCHECK(is_valid());
return NetworkTrafficAnnotationTag(unique_id_hash_code);
}
bool is_valid() const {
return unique_id_hash_code != internal::TRAFFIC_ANNOTATION_UNINITIALIZED;
}
void reset() {
unique_id_hash_code = internal::TRAFFIC_ANNOTATION_UNINITIALIZED;
}
friend MutableNetworkTrafficAnnotationTag
CreateMutableNetworkTrafficAnnotationTag(int32_t unique_id_hash_code);
private:
explicit MutableNetworkTrafficAnnotationTag(int32_t unique_id_hash_code_)
: unique_id_hash_code(unique_id_hash_code_) {}
};
inline MutableNetworkTrafficAnnotationTag
CreateMutableNetworkTrafficAnnotationTag(int32_t unique_id_hash_code) {
return MutableNetworkTrafficAnnotationTag(unique_id_hash_code);
}
struct MutablePartialNetworkTrafficAnnotationTag {
#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
MutablePartialNetworkTrafficAnnotationTag()
: unique_id_hash_code(internal::TRAFFIC_ANNOTATION_UNINITIALIZED),
completing_id_hash_code(internal::TRAFFIC_ANNOTATION_UNINITIALIZED) {}
explicit MutablePartialNetworkTrafficAnnotationTag(
const PartialNetworkTrafficAnnotationTag& partial_traffic_annotation)
: unique_id_hash_code(partial_traffic_annotation.unique_id_hash_code),
completing_id_hash_code(
partial_traffic_annotation.completing_id_hash_code) {}
int32_t unique_id_hash_code;
int32_t completing_id_hash_code;
explicit operator PartialNetworkTrafficAnnotationTag() const {
DCHECK(is_valid());
return PartialNetworkTrafficAnnotationTag(unique_id_hash_code,
completing_id_hash_code);
}
bool is_valid() const {
return unique_id_hash_code != internal::TRAFFIC_ANNOTATION_UNINITIALIZED &&
completing_id_hash_code !=
internal::TRAFFIC_ANNOTATION_UNINITIALIZED;
}
void reset() {
unique_id_hash_code = internal::TRAFFIC_ANNOTATION_UNINITIALIZED;
completing_id_hash_code = internal::TRAFFIC_ANNOTATION_UNINITIALIZED;
}
#else
MutablePartialNetworkTrafficAnnotationTag()
: unique_id_hash_code(internal::TRAFFIC_ANNOTATION_UNINITIALIZED) {}
explicit MutablePartialNetworkTrafficAnnotationTag(
const PartialNetworkTrafficAnnotationTag& partial_traffic_annotation)
: unique_id_hash_code(partial_traffic_annotation.unique_id_hash_code) {}
int32_t unique_id_hash_code;
explicit operator PartialNetworkTrafficAnnotationTag() const {
return PartialNetworkTrafficAnnotationTag(unique_id_hash_code);
}
bool is_valid() const {
return unique_id_hash_code != internal::TRAFFIC_ANNOTATION_UNINITIALIZED;
}
void reset() {
unique_id_hash_code = internal::TRAFFIC_ANNOTATION_UNINITIALIZED;
}
#endif
};
}
#if !BUILDFLAG(IS_WIN) && !BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS)
#define TRAFFIC_ANNOTATION_WITHOUT_PROTO(ANNOTATION_ID) \
net::DefineNetworkTrafficAnnotation(ANNOTATION_ID, "No proto yet.")
#endif
#if !BUILDFLAG(IS_WIN) && !BUILDFLAG(IS_LINUX)
#define NO_TRAFFIC_ANNOTATION_YET \
net::DefineNetworkTrafficAnnotation("undefined", "Nothing here yet.")
#endif
#define MISSING_TRAFFIC_ANNOTATION \
net::DefineNetworkTrafficAnnotation( \
"missing", "Function called without traffic annotation.")
#endif