breadcast/breadcast-caststream-sys/vendor/openscreen/util/uuid.cc
Breadway 8c745d18e0
Some checks failed
dev release / build (push) Failing after 12s
Implement Cast Streaming mirroring, DLNA casting, daemon+GUI, and breadd integration
Builds out the full v1 scope: a vendored+patched openscreen subset for
low-latency Cast Streaming (Mirroring receiver 0F5096E8) alongside the
existing Cast V2/HLS and new DLNA/AVTransport casting paths, breadcastd's
Idle/Casting state machine with a private IPC socket, the breadcast GTK4
popup as a thin IPC client, and bread.cast.*/bread.command.cast.* breadd
integration (device discovery, start/stop, mirroring lifecycle events).
Also adds bakery/systemd/Forgejo CI packaging.

Validated end-to-end against a real Chromecast/Google TV: negotiated
Cast Streaming session, live pipeline playback, and daemon+GUI click-to-cast/
stop through the actual popup.
2026-08-03 09:07:21 +08:00

127 lines
3.5 KiB
C++

// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "util/uuid.h"
#include <stddef.h>
#include <stdint.h>
#include <ostream>
#include "util/big_endian.h"
#include "util/crypto/random_bytes.h"
#include "util/hashing.h"
#include "util/osp_logging.h"
#include "util/string_util.h"
#include "util/stringprintf.h"
namespace openscreen {
namespace {
constexpr bool IsHyphenPosition(size_t i) {
return i == 8 || i == 13 || i == 18 || i == 23;
}
// Returns a canonical Uuid string given that `input` is validly formatted
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, such that x is a hexadecimal digit.
// If `strict`, x must be a lower-case hexadecimal digit.
std::string GetCanonicalUuidInternal(std::string_view input, bool strict) {
constexpr size_t kUuidLength = 36;
if (input.length() != kUuidLength) {
return {};
}
std::string lowercase;
lowercase.resize(kUuidLength);
for (size_t i = 0; i < input.length(); ++i) {
auto current = input[i];
if (IsHyphenPosition(i)) {
if (current != '-') {
return {};
}
lowercase[i] = '-';
} else {
if (strict ? !string_util::ascii_islowerhex(current)
: !string_util::ascii_ishex(current)) {
return {};
}
lowercase[i] = static_cast<char>(string_util::ascii_tolower(current));
}
}
return lowercase;
}
} // namespace
// static
Uuid Uuid::GenerateRandomV4() {
return FormatRandomDataAsV4Impl(GenerateRandomBytes16());
}
// static
Uuid Uuid::FormatRandomDataAsV4Impl(ByteView input) {
OSP_CHECK_EQ(input.size(), kGuidV4InputLength);
auto first_u64 = ReadBigEndian<uint64_t>(input.first(8).data());
auto second_u64 = ReadBigEndian<uint64_t>(input.last(8).data());
// Set the Uuid to version 4 as described in RFC 4122, section 4.4.
// The format of Uuid version 4 must be xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx,
// where y is one of [8, 9, a, b].
// Clear the version bits and set the version to 4:
first_u64 &= 0xffffffff'ffff0fffULL;
first_u64 |= 0x00000000'00004000ULL;
// Clear bit 65 and set bit 64, to set the 'var' field to 0b10 per RFC 9562
// section 5.4.
second_u64 &= 0x3fffffff'ffffffffULL;
second_u64 |= 0x80000000'00000000ULL;
Uuid uuid;
uuid.lowercase_ =
StringFormat("{:08x}-{:04x}-{:04x}-{:04x}-{:012x}",
static_cast<uint32_t>(first_u64 >> 32),
static_cast<uint32_t>((first_u64 >> 16) & 0x0000'ffff),
static_cast<uint32_t>(first_u64 & 0x0000'ffff),
static_cast<uint32_t>(second_u64 >> 48),
second_u64 & 0x0000'ffff'ffff'ffffULL);
return uuid;
}
// static
Uuid Uuid::ParseCaseInsensitive(std::string_view input) {
Uuid uuid;
uuid.lowercase_ = GetCanonicalUuidInternal(input, /*strict=*/false);
return uuid;
}
// static
Uuid Uuid::ParseLowercase(std::string_view input) {
Uuid uuid;
uuid.lowercase_ = GetCanonicalUuidInternal(input, /*strict=*/true);
return uuid;
}
Uuid::Uuid() = default;
Uuid::Uuid(const Uuid& other) = default;
Uuid::Uuid(Uuid&& other) noexcept = default;
Uuid& Uuid::operator=(const Uuid& other) = default;
Uuid& Uuid::operator=(Uuid&& other) = default;
const std::string& Uuid::AsLowercaseString() const {
return lowercase_;
}
std::ostream& operator<<(std::ostream& out, const Uuid& uuid) {
return out << uuid.AsLowercaseString();
}
size_t UuidHash::operator()(const Uuid& uuid) const {
return ComputeAggregateHash(uuid.AsLowercaseString());
}
} // namespace openscreen