diff --git a/Servers/LookupServer/DNSAnswer.cpp b/Servers/LookupServer/DNSAnswer.cpp new file mode 100644 index 0000000000..775c23784e --- /dev/null +++ b/Servers/LookupServer/DNSAnswer.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020, Andreas Kling + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "DNSAnswer.h" +#include + +DNSAnswer::DNSAnswer(const String& name, u16 type, u16 class_code, u32 ttl, const String& record_data) + : m_name(name) + , m_type(type) + , m_class_code(class_code) + , m_ttl(ttl) + , m_record_data(record_data) +{ + auto now = time(nullptr); + m_expiration_time = now + m_ttl; + if (m_expiration_time < now) + m_expiration_time = 0; +} + +bool DNSAnswer::has_expired() const +{ + return time(nullptr) >= m_expiration_time; +} diff --git a/Servers/LookupServer/DNSAnswer.h b/Servers/LookupServer/DNSAnswer.h index 9776371f0d..794603dd30 100644 --- a/Servers/LookupServer/DNSAnswer.h +++ b/Servers/LookupServer/DNSAnswer.h @@ -31,14 +31,7 @@ class DNSAnswer { public: - DNSAnswer(const String& name, u16 type, u16 class_code, u32 ttl, const String& record_data) - : m_name(name) - , m_type(type) - , m_class_code(class_code) - , m_ttl(ttl) - , m_record_data(record_data) - { - } + DNSAnswer(const String& name, u16 type, u16 class_code, u32 ttl, const String& record_data); const String& name() const { return m_name; } u16 type() const { return m_type; } @@ -46,10 +39,13 @@ public: u32 ttl() const { return m_ttl; } const String& record_data() const { return m_record_data; } + bool has_expired() const; + private: String m_name; u16 m_type { 0 }; u16 m_class_code { 0 }; u32 m_ttl { 0 }; + time_t m_expiration_time { 0 }; String m_record_data; }; diff --git a/Servers/LookupServer/LookupServer.cpp b/Servers/LookupServer/LookupServer.cpp index 2fba96b888..cb36c1cc5f 100644 --- a/Servers/LookupServer/LookupServer.cpp +++ b/Servers/LookupServer/LookupServer.cpp @@ -157,8 +157,16 @@ Vector LookupServer::lookup(const String& hostname, bool& did_timeout, u { if (auto it = m_lookup_cache.find(hostname); it != m_lookup_cache.end()) { auto& cached_lookup = it->value; - if (cached_lookup.record_type == record_type && cached_lookup.timestamp < (time(nullptr) + 60)) { - return it->value.responses; + if (cached_lookup.question.record_type() == record_type) { + Vector responses; + for (auto& cached_answer : cached_lookup.answers) { + dbg() << "Cache hit: " << hostname << " -> " << cached_answer.record_data() << ", expired: " << cached_answer.has_expired(); + if (!cached_answer.has_expired()) { + responses.append(cached_answer.record_data()); + } + } + if (!responses.is_empty()) + return responses; } m_lookup_cache.remove(it); } @@ -232,11 +240,13 @@ Vector LookupServer::lookup(const String& hostname, bool& did_timeout, u return {}; } - Vector addresses; + Vector responses; for (auto& answer : response.answers()) { - addresses.append(answer.record_data()); + responses.append(answer.record_data()); } - m_lookup_cache.set(hostname, { time(nullptr), record_type, addresses }); - return addresses; + if (m_lookup_cache.size() >= 256) + m_lookup_cache.remove(m_lookup_cache.begin()); + m_lookup_cache.set(hostname, { request.questions()[0], response.answers() }); + return responses; } diff --git a/Servers/LookupServer/LookupServer.h b/Servers/LookupServer/LookupServer.h index d7048931d6..c36f60a044 100644 --- a/Servers/LookupServer/LookupServer.h +++ b/Servers/LookupServer/LookupServer.h @@ -27,11 +27,13 @@ #pragma once #include "DNSRequest.h" +#include "DNSResponse.h" #include #include class CLocalSocket; class CLocalServer; +class DNSAnswer; class LookupServer final : public CObject { C_OBJECT(LookupServer) @@ -45,9 +47,8 @@ private: Vector lookup(const String& hostname, bool& did_timeout, unsigned short record_type, ShouldRandomizeCase = ShouldRandomizeCase::Yes); struct CachedLookup { - time_t timestamp { 0 }; - unsigned short record_type { 0 }; - Vector responses; + DNSQuestion question; + Vector answers; }; RefPtr m_local_server; diff --git a/Servers/LookupServer/Makefile b/Servers/LookupServer/Makefile index f7735a3758..42a4e1930b 100644 --- a/Servers/LookupServer/Makefile +++ b/Servers/LookupServer/Makefile @@ -2,6 +2,7 @@ OBJS = \ LookupServer.o \ DNSRequest.o \ DNSResponse.o \ + DNSAnswer.o \ main.o PROGRAM = LookupServer