mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 07:47:37 +00:00
LibDNS: Implement Traits for DNSAnswer class
This enables DNSAnswer instances being used e.g. in a HashTable for caching purposes.
This commit is contained in:
parent
be4a4144f2
commit
f3af82585d
4 changed files with 45 additions and 4 deletions
|
@ -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<void> AK::Formatter<DNS::DNSRecordType>::format(AK::FormatBuilder& builder, DNS::DNSRecordType value)
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "DNSName.h"
|
||||
#include <AK/Format.h>
|
||||
#include <AK/String.h>
|
||||
#include <AK/Traits.h>
|
||||
#include <AK/Types.h>
|
||||
|
||||
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<DNS::DNSAnswer> : public GenericTraits<DNS::DNSAnswer> {
|
||||
static constexpr bool is_trivial() { return false; }
|
||||
static unsigned hash(DNS::DNSAnswer a) { return a.hash(); }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct AK::Formatter<DNS::DNSRecordType> : StandardFormatter {
|
||||
Formatter() = default;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue