LibCore: Make UDPServer::receive() return ErrorOr<ByteBuffer>

This is a first step towards handling OOM errors instead of just
crashing the program.

Now UDPServer's method `receive()` return memory allocation
errors explicitly with help of ErrorOr.

This removes one FIXME and make a bunch of new ones. :(
This commit is contained in:
Alexander Narsudinov 2022-12-18 00:15:54 +03:00 committed by Andreas Kling
parent 9ae9d82a03
commit 767529ebf5
6 changed files with 19 additions and 17 deletions

View file

@ -291,7 +291,9 @@ TEST_CASE(udp_socket_read_write)
usleep(100000); usleep(100000);
struct sockaddr_in client_address; struct sockaddr_in client_address;
auto server_receive_buffer = udp_server->receive(64, client_address); auto server_receive_buffer_or_error = udp_server->receive(64, client_address);
EXPECT(!server_receive_buffer_or_error.is_error());
auto server_receive_buffer = server_receive_buffer_or_error.release_value();
EXPECT(!server_receive_buffer.is_empty()); EXPECT(!server_receive_buffer.is_empty());
StringView server_received_data { server_receive_buffer.bytes() }; StringView server_received_data { server_receive_buffer.bytes() };

View file

@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org> * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2022, Alexander Narsudinov <a.narsudinov@gmail.com>
* *
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
@ -7,6 +8,7 @@
#include <AK/IPv4Address.h> #include <AK/IPv4Address.h>
#include <AK/Types.h> #include <AK/Types.h>
#include <LibCore/Notifier.h> #include <LibCore/Notifier.h>
#include <LibCore/System.h>
#include <LibCore/UDPServer.h> #include <LibCore/UDPServer.h>
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
@ -61,18 +63,12 @@ bool UDPServer::bind(IPv4Address const& address, u16 port)
return true; return true;
} }
ByteBuffer UDPServer::receive(size_t size, sockaddr_in& in) ErrorOr<ByteBuffer> UDPServer::receive(size_t size, sockaddr_in& in)
{ {
// FIXME: Handle possible OOM situation. auto buf = TRY(ByteBuffer::create_uninitialized(size));
auto buf = ByteBuffer::create_uninitialized(size).release_value_but_fixme_should_propagate_errors();
socklen_t in_len = sizeof(in); socklen_t in_len = sizeof(in);
ssize_t rlen = ::recvfrom(m_fd, buf.data(), size, 0, (sockaddr*)&in, &in_len); auto bytes_received = TRY(Core::System::recvfrom(m_fd, buf.data(), size, 0, (sockaddr*)&in, &in_len));
if (rlen < 0) { buf.resize(bytes_received);
dbgln("recvfrom: {}", strerror(errno));
return {};
}
buf.resize(rlen);
return buf; return buf;
} }

View file

@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org> * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2022, Alexander Narsudinov <a.narsudinov@gmail.com>
* *
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
@ -23,8 +24,8 @@ public:
bool is_bound() const { return m_bound; } bool is_bound() const { return m_bound; }
bool bind(IPv4Address const& address, u16 port); bool bind(IPv4Address const& address, u16 port);
ByteBuffer receive(size_t size, sockaddr_in& from); ErrorOr<ByteBuffer> receive(size_t size, sockaddr_in& from);
ByteBuffer receive(size_t size) ErrorOr<ByteBuffer> receive(size_t size)
{ {
struct sockaddr_in saddr; struct sockaddr_in saddr;
return receive(size, saddr); return receive(size, saddr);

View file

@ -122,7 +122,8 @@ DHCPv4Client::DHCPv4Client(Vector<DeprecatedString> interfaces_with_dhcp_enabled
{ {
m_server = Core::UDPServer::construct(this); m_server = Core::UDPServer::construct(this);
m_server->on_ready_to_receive = [this] { m_server->on_ready_to_receive = [this] {
auto buffer = m_server->receive(sizeof(DHCPv4Packet)); // TODO: we need to handle possible errors here somehow
auto buffer = MUST(m_server->receive(sizeof(DHCPv4Packet)));
dbgln_if(DHCPV4CLIENT_DEBUG, "Received {} bytes", buffer.size()); dbgln_if(DHCPV4CLIENT_DEBUG, "Received {} bytes", buffer.size());
if (buffer.size() < sizeof(DHCPv4Packet) - DHCPV4_OPTION_FIELD_MAX_LENGTH + 1 || buffer.size() > sizeof(DHCPv4Packet)) { if (buffer.size() < sizeof(DHCPv4Packet) - DHCPV4_OPTION_FIELD_MAX_LENGTH + 1 || buffer.size() > sizeof(DHCPv4Packet)) {
dbgln("we expected {}-{} bytes, this is a bad packet", sizeof(DHCPv4Packet) - DHCPV4_OPTION_FIELD_MAX_LENGTH + 1, sizeof(DHCPv4Packet)); dbgln("we expected {}-{} bytes, this is a bad packet", sizeof(DHCPv4Packet) - DHCPV4_OPTION_FIELD_MAX_LENGTH + 1, sizeof(DHCPv4Packet));

View file

@ -28,7 +28,7 @@ DNSServer::DNSServer(Object* parent)
ErrorOr<void> DNSServer::handle_client() ErrorOr<void> DNSServer::handle_client()
{ {
sockaddr_in client_address; sockaddr_in client_address;
auto buffer = receive(1024, client_address); auto buffer = TRY(receive(1024, client_address));
auto optional_request = Packet::from_raw_packet(buffer.data(), buffer.size()); auto optional_request = Packet::from_raw_packet(buffer.data(), buffer.size());
if (!optional_request.has_value()) { if (!optional_request.has_value()) {
dbgln("Got an invalid DNS packet"); dbgln("Got an invalid DNS packet");

View file

@ -51,7 +51,8 @@ MulticastDNS::MulticastDNS(Object* parent)
void MulticastDNS::handle_packet() void MulticastDNS::handle_packet()
{ {
auto buffer = receive(1024); // TODO: propagate the error somehow
auto buffer = MUST(receive(1024));
auto optional_packet = Packet::from_raw_packet(buffer.data(), buffer.size()); auto optional_packet = Packet::from_raw_packet(buffer.data(), buffer.size());
if (!optional_packet.has_value()) { if (!optional_packet.has_value()) {
dbgln("Got an invalid mDNS packet"); dbgln("Got an invalid mDNS packet");
@ -167,7 +168,8 @@ Vector<Answer> MulticastDNS::lookup(Name const& name, RecordType record_type)
return {}; return {};
} }
auto buffer = receive(1024); // TODO: propagate the error somehow
auto buffer = MUST(receive(1024));
if (buffer.is_empty()) if (buffer.is_empty())
return {}; return {};
auto optional_packet = Packet::from_raw_packet(buffer.data(), buffer.size()); auto optional_packet = Packet::from_raw_packet(buffer.data(), buffer.size());