diff --git a/Userland/Libraries/LibDNS/DNSAnswer.cpp b/Userland/Libraries/LibDNS/DNSAnswer.cpp index 2997027a33..9dce5f4877 100644 --- a/Userland/Libraries/LibDNS/DNSAnswer.cpp +++ b/Userland/Libraries/LibDNS/DNSAnswer.cpp @@ -26,6 +26,34 @@ bool DNSAnswer::has_expired() const return time(nullptr) >= m_received_time + m_ttl; } +unsigned DNSAnswer::hash() const +{ + auto hash = pair_int_hash(CaseInsensitiveStringTraits::hash(name().as_string()), (u32)type()); + hash = pair_int_hash(hash, pair_int_hash((u32)class_code(), ttl())); + hash = pair_int_hash(hash, record_data().hash()); + hash = pair_int_hash(hash, (u32)mdns_cache_flush()); + return hash; +} + +bool DNSAnswer::operator==(DNSAnswer const& other) const +{ + if (&other == this) + return true; + if (!DNSName::Traits::equals(name(), other.name())) + return false; + if (type() != other.type()) + return false; + if (class_code() != other.class_code()) + return false; + if (ttl() != other.ttl()) + return false; + if (record_data() != other.record_data()) + return false; + if (mdns_cache_flush() != other.mdns_cache_flush()) + return false; + return true; +} + } ErrorOr AK::Formatter::format(AK::FormatBuilder& builder, DNS::DNSRecordType value) diff --git a/Userland/Libraries/LibDNS/DNSAnswer.h b/Userland/Libraries/LibDNS/DNSAnswer.h index 714804aaf8..459028dc7a 100644 --- a/Userland/Libraries/LibDNS/DNSAnswer.h +++ b/Userland/Libraries/LibDNS/DNSAnswer.h @@ -9,6 +9,7 @@ #include "DNSName.h" #include #include +#include #include namespace DNS { @@ -33,6 +34,7 @@ enum class DNSRecordClass : u16 { class DNSAnswer { public: + DNSAnswer() = default; DNSAnswer(DNSName const& name, DNSRecordType type, DNSRecordClass class_code, u32 ttl, String const& record_data, bool mdns_cache_flush); DNSName const& name() const { return m_name; } @@ -46,6 +48,9 @@ public: bool has_expired() const; + unsigned hash() const; + bool operator==(DNSAnswer const&) const; + private: DNSName m_name; DNSRecordType m_type { 0 }; @@ -57,6 +62,13 @@ private: }; } + +template<> +struct AK::Traits : public GenericTraits { + static constexpr bool is_trivial() { return false; } + static unsigned hash(DNS::DNSAnswer a) { return a.hash(); } +}; + template<> struct AK::Formatter : StandardFormatter { Formatter() = default; diff --git a/Userland/Libraries/LibDNS/DNSName.cpp b/Userland/Libraries/LibDNS/DNSName.cpp index 281ee41646..01787a492c 100644 --- a/Userland/Libraries/LibDNS/DNSName.cpp +++ b/Userland/Libraries/LibDNS/DNSName.cpp @@ -23,12 +23,12 @@ DNSName::DNSName(String const& name) DNSName DNSName::parse(u8 const* data, size_t& offset, size_t max_offset, size_t recursion_level) { if (recursion_level > 4) - return DNSName({}); + return {}; StringBuilder builder; while (true) { if (offset >= max_offset) - return DNSName({}); + return {}; u8 b = data[offset++]; if (b == '\0') { // This terminates the name. @@ -36,7 +36,7 @@ DNSName DNSName::parse(u8 const* data, size_t& offset, size_t max_offset, size_t } else if ((b & 0xc0) == 0xc0) { // The two bytes tell us the offset when to continue from. if (offset >= max_offset) - return DNSName({}); + return {}; size_t dummy = (b & 0x3f) << 8 | data[offset++]; auto rest_of_name = parse(data, dummy, max_offset, recursion_level + 1); builder.append(rest_of_name.as_string()); @@ -44,7 +44,7 @@ DNSName DNSName::parse(u8 const* data, size_t& offset, size_t max_offset, size_t } else { // This is the length of a part. if (offset + b >= max_offset) - return DNSName({}); + return {}; builder.append((char const*)&data[offset], (size_t)b); builder.append('.'); offset += b; diff --git a/Userland/Libraries/LibDNS/DNSName.h b/Userland/Libraries/LibDNS/DNSName.h index 74aeb447fc..993f3c145b 100644 --- a/Userland/Libraries/LibDNS/DNSName.h +++ b/Userland/Libraries/LibDNS/DNSName.h @@ -14,6 +14,7 @@ namespace DNS { class DNSName { public: + DNSName() = default; DNSName(String const&); static DNSName parse(u8 const* data, size_t& offset, size_t max_offset, size_t recursion_level = 0);