Some checks failed
dev release / build (push) Failing after 12s
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.
209 lines
7 KiB
C++
209 lines
7 KiB
C++
// Copyright 2018 The Chromium Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#ifndef PLATFORM_BASE_IP_ADDRESS_H_
|
|
#define PLATFORM_BASE_IP_ADDRESS_H_
|
|
|
|
#include <algorithm>
|
|
#include <array>
|
|
#include <cstdint>
|
|
#include <ostream>
|
|
#include <span>
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <type_traits>
|
|
|
|
#include "platform/base/error.h"
|
|
|
|
namespace openscreen {
|
|
|
|
class IPAddress {
|
|
public:
|
|
enum class Version {
|
|
kV4,
|
|
kV6,
|
|
};
|
|
|
|
static constexpr IPAddress kAnyV4() { return IPAddress{0, 0, 0, 0}; }
|
|
static constexpr IPAddress kAnyV6() {
|
|
return IPAddress{0, 0, 0, 0, 0, 0, 0, 0};
|
|
}
|
|
static constexpr IPAddress kV4LoopbackAddress() {
|
|
return IPAddress{127, 0, 0, 1};
|
|
}
|
|
static constexpr IPAddress kV6LoopbackAddress() {
|
|
return IPAddress{0, 0, 0, 0, 0, 0, 0, 1};
|
|
}
|
|
static constexpr size_t kV4Size = 4;
|
|
static constexpr size_t kV6Size = 16;
|
|
|
|
constexpr IPAddress() : version_(Version::kV4), bytes_({}) {}
|
|
|
|
// `bytes` contains 4 octets for IPv4, or 8 hextets (16 bytes of big-endian
|
|
// shorts) for IPv6.
|
|
// TODO(jophba): delete once usage is removed in Chromium's network_util.cc.
|
|
inline IPAddress(Version version, const uint8_t* bytes) : version_(version) {
|
|
std::copy_n(bytes, size(), bytes_.begin());
|
|
}
|
|
|
|
IPAddress(Version version, std::span<const uint8_t> bytes);
|
|
|
|
// IPv4 constructors (IPAddress from 4 octets).
|
|
explicit constexpr IPAddress(std::span<const uint8_t, 4> bytes)
|
|
: version_(Version::kV4),
|
|
bytes_{{bytes[0], bytes[1], bytes[2], bytes[3]}} {}
|
|
|
|
constexpr IPAddress(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4)
|
|
: version_(Version::kV4), bytes_{{b1, b2, b3, b4}} {}
|
|
|
|
// IPv6 constructors (IPAddress from 8 hextets).
|
|
explicit constexpr IPAddress(std::span<const uint16_t, 8> hextets)
|
|
: IPAddress(hextets[0],
|
|
hextets[1],
|
|
hextets[2],
|
|
hextets[3],
|
|
hextets[4],
|
|
hextets[5],
|
|
hextets[6],
|
|
hextets[7]) {}
|
|
|
|
constexpr IPAddress(uint16_t h0,
|
|
uint16_t h1,
|
|
uint16_t h2,
|
|
uint16_t h3,
|
|
uint16_t h4,
|
|
uint16_t h5,
|
|
uint16_t h6,
|
|
uint16_t h7)
|
|
: version_(Version::kV6),
|
|
bytes_{{
|
|
static_cast<uint8_t>(h0 >> 8),
|
|
static_cast<uint8_t>(h0),
|
|
static_cast<uint8_t>(h1 >> 8),
|
|
static_cast<uint8_t>(h1),
|
|
static_cast<uint8_t>(h2 >> 8),
|
|
static_cast<uint8_t>(h2),
|
|
static_cast<uint8_t>(h3 >> 8),
|
|
static_cast<uint8_t>(h3),
|
|
static_cast<uint8_t>(h4 >> 8),
|
|
static_cast<uint8_t>(h4),
|
|
static_cast<uint8_t>(h5 >> 8),
|
|
static_cast<uint8_t>(h5),
|
|
static_cast<uint8_t>(h6 >> 8),
|
|
static_cast<uint8_t>(h6),
|
|
static_cast<uint8_t>(h7 >> 8),
|
|
static_cast<uint8_t>(h7),
|
|
}} {}
|
|
|
|
// IPv6 constructor with scope ID.
|
|
explicit constexpr IPAddress(std::span<const uint8_t, 16> bytes,
|
|
uint32_t scope_id)
|
|
: version_(Version::kV6), scope_id_(scope_id) {
|
|
for (size_t i = 0; i < 16; ++i) {
|
|
bytes_[i] = bytes[i];
|
|
}
|
|
}
|
|
|
|
constexpr IPAddress(const IPAddress& o) noexcept = default;
|
|
constexpr IPAddress(IPAddress&& o) noexcept = default;
|
|
~IPAddress() = default;
|
|
|
|
constexpr IPAddress& operator=(const IPAddress& o) noexcept = default;
|
|
constexpr IPAddress& operator=(IPAddress&& o) noexcept = default;
|
|
|
|
bool operator==(const IPAddress& o) const;
|
|
bool operator!=(const IPAddress& o) const;
|
|
|
|
// IP address comparison rules are based on the following two principles:
|
|
// 1. newer versions are greater, e.g. IPv6 > IPv4
|
|
// 2. higher numerical values are greater, e.g. 192.168.0.1 > 10.0.0.1
|
|
bool operator<(const IPAddress& other) const;
|
|
bool operator>(const IPAddress& other) const { return other < *this; }
|
|
bool operator<=(const IPAddress& other) const { return !(other < *this); }
|
|
bool operator>=(const IPAddress& other) const { return !(*this < other); }
|
|
explicit operator bool() const;
|
|
|
|
Version version() const { return version_; }
|
|
size_t size() const { return (version_ == Version::kV4) ? kV4Size : kV6Size; }
|
|
bool IsV4() const { return version_ == Version::kV4; }
|
|
bool IsV6() const { return version_ == Version::kV6; }
|
|
|
|
// Returns true if the address is an IPv6 link-local address.
|
|
bool IsLinkLocal() const;
|
|
|
|
// Returns the scope ID for link-local IPv6 addresses. Returns 0 for
|
|
// non-link-local addresses.
|
|
uint32_t GetScopeId() const { return scope_id_; }
|
|
|
|
// These methods assume `x` is the appropriate size, but due to various
|
|
// callers' casting needs we can't check them like the constructors above.
|
|
// Callers should instead make any necessary checks themselves.
|
|
void CopyTo(std::span<uint8_t> bytes) const;
|
|
|
|
// TODO(jophba): delete once usage is removed in Chromium's network_util.cc.
|
|
inline void CopyToV4(uint8_t* x) const { CopyTo(std::span(x, kV4Size)); }
|
|
inline void CopyToV6(uint8_t* x) const { CopyTo(std::span(x, kV6Size)); }
|
|
|
|
// In some instances, we want direct access to the underlying byte storage,
|
|
// in order to avoid making multiple copies.
|
|
std::span<const uint8_t> bytes() const {
|
|
return {bytes_.data(), (version_ == Version::kV4) ? kV4Size : kV6Size};
|
|
}
|
|
|
|
// Parses a text representation of an IPv4 address (e.g. "192.168.0.1") or an
|
|
// IPv6 address (e.g. "abcd::1234").
|
|
static ErrorOr<IPAddress> Parse(std::string_view s);
|
|
|
|
private:
|
|
friend ErrorOr<IPAddress> ParseV6(std::string_view s);
|
|
|
|
Version version_;
|
|
std::array<uint8_t, 16> bytes_;
|
|
uint32_t scope_id_ = 0;
|
|
};
|
|
|
|
struct IPEndpoint {
|
|
public:
|
|
IPAddress address;
|
|
uint16_t port = 0;
|
|
|
|
// Used with various socket types to indicate "any" address.
|
|
static const IPEndpoint kAnyV4();
|
|
static const IPEndpoint kAnyV6();
|
|
explicit operator bool() const;
|
|
|
|
// Parses a text representation of an IPv4/IPv6 address and port (e.g.
|
|
// "192.168.0.1:8080" or "[abcd::1234]:8080").
|
|
static ErrorOr<IPEndpoint> Parse(std::string_view s);
|
|
|
|
std::string ToString() const;
|
|
};
|
|
|
|
bool operator==(const IPEndpoint& a, const IPEndpoint& b);
|
|
bool operator!=(const IPEndpoint& a, const IPEndpoint& b);
|
|
|
|
bool operator<(const IPEndpoint& a, const IPEndpoint& b);
|
|
inline bool operator>(const IPEndpoint& a, const IPEndpoint& b) {
|
|
return b < a;
|
|
}
|
|
inline bool operator<=(const IPEndpoint& a, const IPEndpoint& b) {
|
|
return !(a > b);
|
|
}
|
|
inline bool operator>=(const IPEndpoint& a, const IPEndpoint& b) {
|
|
return !(a < b);
|
|
}
|
|
|
|
// Outputs a string of the form:
|
|
// 123.234.34.56
|
|
// or fe80:0000:0000:0000:1234:5678:9abc:def0
|
|
std::ostream& operator<<(std::ostream& out, const IPAddress& address);
|
|
|
|
// Outputs a string of the form:
|
|
// 123.234.34.56:443
|
|
// or [fe80:0000:0000:0000:1234:5678:9abc:def0]:8080
|
|
std::ostream& operator<<(std::ostream& out, const IPEndpoint& endpoint);
|
|
|
|
} // namespace openscreen
|
|
|
|
#endif // PLATFORM_BASE_IP_ADDRESS_H_
|