mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-10 03:26:10 +00:00
LibDNS+dns: Avoid multi-question queries
This is not supported by much of anything (correctly), so send the requests in parallel instead.
This commit is contained in:
parent
e47b1cc1a2
commit
833617c8fe
Notes:
github-actions[bot]
2025-06-25 06:21:45 +00:00
Author: https://github.com/alimpfard
Commit: 833617c8fe
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5127
2 changed files with 60 additions and 26 deletions
|
@ -301,6 +301,37 @@ public:
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NonnullRefPtr<Core::Promise<NonnullRefPtr<LookupResult const>>> lookup(ByteString name, Messages::Class class_, Vector<Vector<Messages::ResourceType>> desired_types, LookupOptions options = LookupOptions::default_())
|
||||||
|
{
|
||||||
|
using ResultPromise = Core::Promise<NonnullRefPtr<LookupResult const>>;
|
||||||
|
Vector<NonnullRefPtr<ResultPromise>> promises;
|
||||||
|
promises.ensure_capacity(desired_types.size());
|
||||||
|
|
||||||
|
for (auto& types : desired_types)
|
||||||
|
promises.unchecked_append(lookup(name, class_, types, options));
|
||||||
|
|
||||||
|
auto result_promise = Core::Promise<NonnullRefPtr<LookupResult const>>::construct();
|
||||||
|
result_promise->add_child(Core::Promise<Empty>::after(promises)
|
||||||
|
->when_resolved([promises, result_promise = result_promise->make_weak_ptr<ResultPromise>()](auto&&) {
|
||||||
|
if (!result_promise.ptr())
|
||||||
|
return;
|
||||||
|
VERIFY(promises.first()->is_resolved());
|
||||||
|
result_promise->resolve(MUST(promises.first()->await()));
|
||||||
|
})
|
||||||
|
.when_rejected([promises, result_promise = result_promise->make_weak_ptr<ResultPromise>()](auto&& error) {
|
||||||
|
if (!result_promise.ptr())
|
||||||
|
return;
|
||||||
|
for (auto& promise : promises) {
|
||||||
|
if (promise->is_resolved()) {
|
||||||
|
result_promise->resolve(MUST(promise->await()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result_promise->reject(move(error));
|
||||||
|
}));
|
||||||
|
return result_promise;
|
||||||
|
}
|
||||||
|
|
||||||
NonnullRefPtr<Core::Promise<NonnullRefPtr<LookupResult const>>> lookup(ByteString name, Messages::Class class_ = Messages::Class::IN, LookupOptions options = LookupOptions::default_())
|
NonnullRefPtr<Core::Promise<NonnullRefPtr<LookupResult const>>> lookup(ByteString name, Messages::Class class_ = Messages::Class::IN, LookupOptions options = LookupOptions::default_())
|
||||||
{
|
{
|
||||||
return lookup(move(name), class_, { Messages::ResourceType::A, Messages::ResourceType::AAAA }, options);
|
return lookup(move(name), class_, { Messages::ResourceType::A, Messages::ResourceType::AAAA }, options);
|
||||||
|
@ -449,7 +480,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
Messages::Message query;
|
Messages::Message query;
|
||||||
if (options.repeating_lookup) {
|
if (cached_result_id.has_value()) {
|
||||||
|
query.header.id = cached_result_id.value();
|
||||||
|
} else if (options.repeating_lookup) {
|
||||||
query.header.id = options.repeating_lookup->id;
|
query.header.id = options.repeating_lookup->id;
|
||||||
options.repeating_lookup->times_repeated++;
|
options.repeating_lookup->times_repeated++;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
ErrorOr<int> serenity_main(Main::Arguments arguments)
|
ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
{
|
{
|
||||||
struct Request {
|
struct Request {
|
||||||
Vector<DNS::Messages::ResourceType> types;
|
Vector<Vector<DNS::Messages::ResourceType>> types;
|
||||||
ByteString name;
|
ByteString name;
|
||||||
};
|
};
|
||||||
Vector<Request> requests;
|
Vector<Request> requests;
|
||||||
|
@ -40,7 +40,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
return Error::from_string_literal("Invalid record/name format");
|
return Error::from_string_literal("Invalid record/name format");
|
||||||
|
|
||||||
if (parts.size() == 1) {
|
if (parts.size() == 1) {
|
||||||
current_request.types.append(DNS::Messages::ResourceType::ANY);
|
current_request.types.append({ DNS::Messages::ResourceType::ANY });
|
||||||
current_request.name = parts[0];
|
current_request.name = parts[0];
|
||||||
} else {
|
} else {
|
||||||
auto rr_parts = parts[0].split_view(',');
|
auto rr_parts = parts[0].split_view(',');
|
||||||
|
@ -49,7 +49,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
auto type = DNS::Messages::resource_type_from_string(rr_name.to_uppercase());
|
auto type = DNS::Messages::resource_type_from_string(rr_name.to_uppercase());
|
||||||
if (!type.has_value())
|
if (!type.has_value())
|
||||||
return Error::from_string_literal("Invalid resource type");
|
return Error::from_string_literal("Invalid resource type");
|
||||||
current_request.types.append(type.value());
|
current_request.types.append({ type.value() });
|
||||||
}
|
}
|
||||||
current_request.name = parts[1];
|
current_request.name = parts[1];
|
||||||
}
|
}
|
||||||
|
@ -105,8 +105,9 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
TRY(resolver.when_socket_ready()->await());
|
TRY(resolver.when_socket_ready()->await());
|
||||||
|
|
||||||
size_t pending_requests = requests.size();
|
size_t pending_requests = requests.size();
|
||||||
|
Vector<NonnullRefPtr<Core::Promise<NonnullRefPtr<DNS::LookupResult const>>>> promises;
|
||||||
for (auto& request : requests) {
|
for (auto& request : requests) {
|
||||||
resolver.lookup(request.name, DNS::Messages::Class::IN, request.types, { .validate_dnssec_locally = dnssec })
|
promises.append(resolver.lookup(request.name, DNS::Messages::Class::IN, request.types, { .validate_dnssec_locally = dnssec })
|
||||||
->when_resolved([&](auto& result) {
|
->when_resolved([&](auto& result) {
|
||||||
outln("Resolved {}:", request.name);
|
outln("Resolved {}:", request.name);
|
||||||
HashTable<DNS::Messages::ResourceType> types;
|
HashTable<DNS::Messages::ResourceType> types;
|
||||||
|
@ -128,10 +129,10 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
loop.quit(0);
|
loop.quit(0);
|
||||||
})
|
})
|
||||||
.when_rejected([&](auto& error) {
|
.when_rejected([&](auto& error) {
|
||||||
outln("Failed to resolve {} IN {}: {}", request.name, DNS::Messages::to_string(request.types.first()), error);
|
outln("Failed to resolve {} IN {}: {}", request.name, DNS::Messages::to_string(request.types.first().first()), error);
|
||||||
if (--pending_requests == 0)
|
if (--pending_requests == 0)
|
||||||
loop.quit(1);
|
loop.quit(1);
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
return loop.exec();
|
return loop.exec();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue