mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 05:07:45 +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;
|
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)
|
ErrorOr<void> AK::Formatter<DNS::DNSRecordType>::format(AK::FormatBuilder& builder, DNS::DNSRecordType value)
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "DNSName.h"
|
#include "DNSName.h"
|
||||||
#include <AK/Format.h>
|
#include <AK/Format.h>
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
|
#include <AK/Traits.h>
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
|
|
||||||
namespace DNS {
|
namespace DNS {
|
||||||
|
@ -33,6 +34,7 @@ enum class DNSRecordClass : u16 {
|
||||||
|
|
||||||
class DNSAnswer {
|
class DNSAnswer {
|
||||||
public:
|
public:
|
||||||
|
DNSAnswer() = default;
|
||||||
DNSAnswer(DNSName const& name, DNSRecordType type, DNSRecordClass class_code, u32 ttl, String const& record_data, bool mdns_cache_flush);
|
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; }
|
DNSName const& name() const { return m_name; }
|
||||||
|
@ -46,6 +48,9 @@ public:
|
||||||
|
|
||||||
bool has_expired() const;
|
bool has_expired() const;
|
||||||
|
|
||||||
|
unsigned hash() const;
|
||||||
|
bool operator==(DNSAnswer const&) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DNSName m_name;
|
DNSName m_name;
|
||||||
DNSRecordType m_type { 0 };
|
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<>
|
template<>
|
||||||
struct AK::Formatter<DNS::DNSRecordType> : StandardFormatter {
|
struct AK::Formatter<DNS::DNSRecordType> : StandardFormatter {
|
||||||
Formatter() = default;
|
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)
|
DNSName DNSName::parse(u8 const* data, size_t& offset, size_t max_offset, size_t recursion_level)
|
||||||
{
|
{
|
||||||
if (recursion_level > 4)
|
if (recursion_level > 4)
|
||||||
return DNSName({});
|
return {};
|
||||||
|
|
||||||
StringBuilder builder;
|
StringBuilder builder;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (offset >= max_offset)
|
if (offset >= max_offset)
|
||||||
return DNSName({});
|
return {};
|
||||||
u8 b = data[offset++];
|
u8 b = data[offset++];
|
||||||
if (b == '\0') {
|
if (b == '\0') {
|
||||||
// This terminates the name.
|
// 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) {
|
} else if ((b & 0xc0) == 0xc0) {
|
||||||
// The two bytes tell us the offset when to continue from.
|
// The two bytes tell us the offset when to continue from.
|
||||||
if (offset >= max_offset)
|
if (offset >= max_offset)
|
||||||
return DNSName({});
|
return {};
|
||||||
size_t dummy = (b & 0x3f) << 8 | data[offset++];
|
size_t dummy = (b & 0x3f) << 8 | data[offset++];
|
||||||
auto rest_of_name = parse(data, dummy, max_offset, recursion_level + 1);
|
auto rest_of_name = parse(data, dummy, max_offset, recursion_level + 1);
|
||||||
builder.append(rest_of_name.as_string());
|
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 {
|
} else {
|
||||||
// This is the length of a part.
|
// This is the length of a part.
|
||||||
if (offset + b >= max_offset)
|
if (offset + b >= max_offset)
|
||||||
return DNSName({});
|
return {};
|
||||||
builder.append((char const*)&data[offset], (size_t)b);
|
builder.append((char const*)&data[offset], (size_t)b);
|
||||||
builder.append('.');
|
builder.append('.');
|
||||||
offset += b;
|
offset += b;
|
||||||
|
|
|
@ -14,6 +14,7 @@ namespace DNS {
|
||||||
|
|
||||||
class DNSName {
|
class DNSName {
|
||||||
public:
|
public:
|
||||||
|
DNSName() = default;
|
||||||
DNSName(String const&);
|
DNSName(String const&);
|
||||||
|
|
||||||
static DNSName parse(u8 const* data, size_t& offset, size_t max_offset, size_t recursion_level = 0);
|
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