Coverage Report

Created: 2026-09-14 07:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/serenity/Userland/Libraries/LibDNS/Answer.cpp
Line
Count
Source
1
/*
2
 * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
3
 *
4
 * SPDX-License-Identifier: BSD-2-Clause
5
 */
6
7
#include "Answer.h"
8
#include <LibIPC/Decoder.h>
9
#include <LibIPC/Encoder.h>
10
#include <time.h>
11
12
namespace DNS {
13
14
Answer::Answer(Name const& name, RecordType type, RecordClass class_code, u32 ttl, ByteString const& record_data, bool mdns_cache_flush)
15
1.39M
    : m_name(name)
16
1.39M
    , m_type(type)
17
1.39M
    , m_class_code(class_code)
18
1.39M
    , m_ttl(ttl)
19
1.39M
    , m_record_data(record_data)
20
1.39M
    , m_mdns_cache_flush(mdns_cache_flush)
21
1.39M
{
22
1.39M
    time(&m_received_time);
23
1.39M
}
24
25
bool Answer::has_expired() const
26
0
{
27
0
    return time(nullptr) >= static_cast<time_t>(m_received_time + m_ttl);
28
0
}
29
30
unsigned Answer::hash() const
31
0
{
32
0
    auto hash = pair_int_hash(CaseInsensitiveStringTraits::hash(name().as_string()), (u32)type());
33
0
    hash = pair_int_hash(hash, pair_int_hash((u32)class_code(), ttl()));
34
0
    hash = pair_int_hash(hash, record_data().hash());
35
0
    hash = pair_int_hash(hash, (u32)mdns_cache_flush());
36
0
    return hash;
37
0
}
38
39
bool Answer::operator==(Answer const& other) const
40
0
{
41
0
    if (&other == this)
42
0
        return true;
43
0
    if (!Name::Traits::equals(name(), other.name()))
44
0
        return false;
45
0
    if (type() != other.type())
46
0
        return false;
47
0
    if (class_code() != other.class_code())
48
0
        return false;
49
0
    if (ttl() != other.ttl())
50
0
        return false;
51
0
    if (record_data() != other.record_data())
52
0
        return false;
53
0
    if (mdns_cache_flush() != other.mdns_cache_flush())
54
0
        return false;
55
0
    return true;
56
0
}
57
58
}
59
60
ErrorOr<void> AK::Formatter<DNS::RecordType>::format(AK::FormatBuilder& builder, DNS::RecordType value)
61
0
{
62
0
    switch (value) {
63
0
    case DNS::RecordType::A:
64
0
        return builder.put_string("A"sv);
65
0
    case DNS::RecordType::NS:
66
0
        return builder.put_string("NS"sv);
67
0
    case DNS::RecordType::CNAME:
68
0
        return builder.put_string("CNAME"sv);
69
0
    case DNS::RecordType::SOA:
70
0
        return builder.put_string("SOA"sv);
71
0
    case DNS::RecordType::PTR:
72
0
        return builder.put_string("PTR"sv);
73
0
    case DNS::RecordType::MX:
74
0
        return builder.put_string("MX"sv);
75
0
    case DNS::RecordType::TXT:
76
0
        return builder.put_string("TXT"sv);
77
0
    case DNS::RecordType::AAAA:
78
0
        return builder.put_string("AAAA"sv);
79
0
    case DNS::RecordType::SRV:
80
0
        return builder.put_string("SRV"sv);
81
0
    }
82
83
0
    TRY(builder.put_string("DNS record type "sv));
84
0
    TRY(builder.put_u64((u16)value));
85
0
    return {};
86
0
}
87
88
ErrorOr<void> AK::Formatter<DNS::RecordClass>::format(AK::FormatBuilder& builder, DNS::RecordClass value)
89
0
{
90
0
    switch (value) {
91
0
    case DNS::RecordClass::IN:
92
0
        return builder.put_string("IN"sv);
93
0
    }
94
95
0
    TRY(builder.put_string("DNS record class "sv));
96
0
    TRY(builder.put_u64((u16)value));
97
0
    return {};
98
0
}
99
100
namespace IPC {
101
102
template<>
103
ErrorOr<void> encode(Encoder& encoder, DNS::Answer const& answer)
104
0
{
105
0
    TRY(encoder.encode(answer.name().as_string()));
106
0
    TRY(encoder.encode(static_cast<u16>(answer.type())));
107
0
    TRY(encoder.encode(static_cast<u16>(answer.class_code())));
108
0
    TRY(encoder.encode(answer.ttl()));
109
0
    TRY(encoder.encode(answer.record_data()));
110
0
    TRY(encoder.encode(answer.mdns_cache_flush()));
111
112
0
    return {};
113
0
}
114
115
template<>
116
ErrorOr<DNS::Answer> decode(Decoder& decoder)
117
0
{
118
0
    auto name = TRY(decoder.decode<ByteString>());
119
0
    auto record_type = TRY(decoder.decode<DNS::RecordType>());
120
0
    auto class_code = TRY(decoder.decode<DNS::RecordClass>());
121
0
    auto ttl = TRY(decoder.decode<u32>());
122
0
    auto record_data = TRY(decoder.decode<ByteString>());
123
0
    auto cache_flush = TRY(decoder.decode<bool>());
124
125
0
    return DNS::Answer { name, record_type, class_code, ttl, record_data, cache_flush };
126
0
}
127
128
}