diff --git a/Libraries/LibCore/Socket.cpp b/Libraries/LibCore/Socket.cpp index 1772ab0d1bb..1d1b9eb6919 100644 --- a/Libraries/LibCore/Socket.cpp +++ b/Libraries/LibCore/Socket.cpp @@ -51,7 +51,7 @@ ErrorOr Socket::create_fd(SocketDomain domain, SocketType type) #endif } -ErrorOr> Socket::resolve_host(ByteString const& host, SocketType type) +ErrorOr>> Socket::resolve_host(ByteString const& host, SocketType type) { int socket_type; switch (type) { @@ -73,22 +73,26 @@ ErrorOr> Socket::resolve_host(ByteString const auto const results = TRY(Core::System::getaddrinfo(host.characters(), nullptr, hints)); + Vector> addresses; + for (auto const& result : results.addresses()) { if (result.ai_family == AF_INET6) { auto* socket_address = bit_cast(result.ai_addr); auto address = IPv6Address { socket_address->sin6_addr.s6_addr }; - - return address; + addresses.append(address); } if (result.ai_family == AF_INET) { auto* socket_address = bit_cast(result.ai_addr); NetworkOrdered const network_ordered_address { socket_address->sin_addr.s_addr }; - return IPv4Address { network_ordered_address }; + addresses.append(IPv4Address { network_ordered_address }); } } - return Error::from_string_literal("Could not resolve to IPv4 or IPv6 address"); + if (addresses.is_empty()) + return Error::from_string_literal("Could not resolve to IPv4 or IPv6 address"); + + return addresses; } ErrorOr Socket::connect_local(int fd, ByteString const& path) @@ -214,9 +218,13 @@ void PosixSocketHelper::setup_notifier() ErrorOr> TCPSocket::connect(ByteString const& host, u16 port) { - auto ip_address = TRY(resolve_host(host, SocketType::Stream)); + auto ip_addresses = TRY(resolve_host(host, SocketType::Stream)); - return ip_address.visit([port](auto address) { return connect(SocketAddress { address, port }); }); + // It should return an error instead of an empty vector. + VERIFY(!ip_addresses.is_empty()); + + // FIXME: Support trying to connect to multiple IP addresses (e.g. if one of them doesn't seem to be working, try another one) + return ip_addresses.first().visit([port](auto address) { return connect(SocketAddress { address, port }); }); } ErrorOr> TCPSocket::connect(SocketAddress const& address) @@ -261,9 +269,13 @@ ErrorOr PosixSocketHelper::pending_bytes() const ErrorOr> UDPSocket::connect(ByteString const& host, u16 port, Optional timeout) { - auto ip_address = TRY(resolve_host(host, SocketType::Datagram)); + auto ip_addresses = TRY(resolve_host(host, SocketType::Datagram)); - return ip_address.visit([port, timeout](auto address) { return connect(SocketAddress { address, port }, timeout); }); + // It should return an error instead of an empty vector. + VERIFY(!ip_addresses.is_empty()); + + // FIXME: Support trying to connect to multiple IP addresses (e.g. if one of them doesn't seem to be working, try another one) + return ip_addresses.first().visit([port, timeout](auto address) { return connect(SocketAddress { address, port }, timeout); }); } ErrorOr> UDPSocket::connect(SocketAddress const& address, Optional timeout) diff --git a/Libraries/LibCore/Socket.h b/Libraries/LibCore/Socket.h index 0e9fd143215..094fcfa6df6 100644 --- a/Libraries/LibCore/Socket.h +++ b/Libraries/LibCore/Socket.h @@ -58,7 +58,7 @@ public: // FIXME: This will need to be updated when IPv6 socket arrives. Perhaps a // base class for all address types is appropriate. - static ErrorOr> resolve_host(ByteString const&, SocketType); + static ErrorOr>> resolve_host(ByteString const&, SocketType); Function on_ready_to_read; diff --git a/Libraries/LibDNS/Resolver.h b/Libraries/LibDNS/Resolver.h index 00f6edbedd9..e10f2a3199b 100644 --- a/Libraries/LibDNS/Resolver.h +++ b/Libraries/LibDNS/Resolver.h @@ -267,14 +267,17 @@ public: return promise; } auto result = make_ref_counted(domain_name); - auto record = record_or_error.release_value(); - record.visit( - [&](IPv4Address const& address) { - result->add_record({ .name = {}, .type = Messages::ResourceType::A, .class_ = Messages::Class::IN, .ttl = 0, .record = Messages::Records::A { address }, .raw = {} }); - }, - [&](IPv6Address const& address) { - result->add_record({ .name = {}, .type = Messages::ResourceType::AAAA, .class_ = Messages::Class::IN, .ttl = 0, .record = Messages::Records::AAAA { address }, .raw = {} }); - }); + auto records = record_or_error.release_value(); + + for (auto const& record : records) { + record.visit( + [&](IPv4Address const& address) { + result->add_record({ .name = {}, .type = Messages::ResourceType::A, .class_ = Messages::Class::IN, .ttl = 0, .record = Messages::Records::A { address }, .raw = {} }); + }, + [&](IPv6Address const& address) { + result->add_record({ .name = {}, .type = Messages::ResourceType::AAAA, .class_ = Messages::Class::IN, .ttl = 0, .record = Messages::Records::AAAA { address }, .raw = {} }); + }); + } result->finished_request(); promise->resolve(result); return promise;