1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-14 07:04:57 +00:00
serenity/Userland/Libraries/LibProtocol/Request.cpp
Tim Schumacher d5871f5717 AK: Rename Stream::{read,write} to Stream::{read_some,write_some}
Similar to POSIX read, the basic read and write functions of AK::Stream
do not have a lower limit of how much data they read or write (apart
from "none at all").

Rename the functions to "read some [data]" and "write some [data]" (with
"data" being omitted, since everything here is reading and writing data)
to make them sufficiently distinct from the functions that ensure to
use the entire buffer (which should be the go-to function for most
usages).

No functional changes, just a lot of new FIXMEs.
2023-03-13 15:16:20 +00:00

134 lines
4.6 KiB
C++

/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibProtocol/Request.h>
#include <LibProtocol/RequestClient.h>
namespace Protocol {
Request::Request(RequestClient& client, i32 request_id)
: m_client(client)
, m_request_id(request_id)
{
}
bool Request::stop()
{
return m_client->stop_request({}, *this);
}
void Request::stream_into(Stream& stream)
{
VERIFY(!m_internal_stream_data);
m_internal_stream_data = make<InternalStreamData>(MUST(Core::File::adopt_fd(fd(), Core::File::OpenMode::Read)));
m_internal_stream_data->read_notifier = Core::Notifier::construct(fd(), Core::Notifier::Read);
auto user_on_finish = move(on_finish);
on_finish = [this](auto success, auto total_size) {
m_internal_stream_data->success = success;
m_internal_stream_data->total_size = total_size;
m_internal_stream_data->request_done = true;
m_internal_stream_data->on_finish();
};
m_internal_stream_data->on_finish = [this, user_on_finish = move(user_on_finish)] {
if (!m_internal_stream_data->user_finish_called && m_internal_stream_data->read_stream->is_eof()) {
m_internal_stream_data->user_finish_called = true;
user_on_finish(m_internal_stream_data->success, m_internal_stream_data->total_size);
}
};
m_internal_stream_data->read_notifier->on_ready_to_read = [this, &stream] {
constexpr size_t buffer_size = 256 * KiB;
static char buf[buffer_size];
do {
auto result = m_internal_stream_data->read_stream->read_some({ buf, buffer_size });
if (result.is_error() && (!result.error().is_errno() || (result.error().is_errno() && result.error().code() != EINTR)))
break;
if (result.is_error())
continue;
auto read_bytes = result.release_value();
if (read_bytes.is_empty())
break;
// FIXME: What do we do if this fails?
stream.write_entire_buffer(read_bytes).release_value_but_fixme_should_propagate_errors();
break;
} while (true);
if (m_internal_stream_data->read_stream->is_eof())
m_internal_stream_data->read_notifier->close();
if (m_internal_stream_data->request_done)
m_internal_stream_data->on_finish();
};
}
void Request::set_should_buffer_all_input(bool value)
{
if (m_should_buffer_all_input == value)
return;
if (m_internal_buffered_data && !value) {
m_internal_buffered_data = nullptr;
m_should_buffer_all_input = false;
return;
}
VERIFY(!m_internal_stream_data);
VERIFY(!m_internal_buffered_data);
VERIFY(on_buffered_request_finish); // Not having this set makes no sense.
m_internal_buffered_data = make<InternalBufferedData>();
m_should_buffer_all_input = true;
on_headers_received = [this](auto& headers, auto response_code) {
m_internal_buffered_data->response_headers = headers;
m_internal_buffered_data->response_code = move(response_code);
};
on_finish = [this](auto success, u32 total_size) {
auto output_buffer = ByteBuffer::create_uninitialized(m_internal_buffered_data->payload_stream.used_buffer_size()).release_value_but_fixme_should_propagate_errors();
m_internal_buffered_data->payload_stream.read_entire_buffer(output_buffer).release_value_but_fixme_should_propagate_errors();
on_buffered_request_finish(
success,
total_size,
m_internal_buffered_data->response_headers,
m_internal_buffered_data->response_code,
output_buffer);
};
stream_into(m_internal_buffered_data->payload_stream);
}
void Request::did_finish(Badge<RequestClient>, bool success, u32 total_size)
{
if (!on_finish)
return;
on_finish(success, total_size);
}
void Request::did_progress(Badge<RequestClient>, Optional<u32> total_size, u32 downloaded_size)
{
if (on_progress)
on_progress(total_size, downloaded_size);
}
void Request::did_receive_headers(Badge<RequestClient>, HashMap<DeprecatedString, DeprecatedString, CaseInsensitiveStringTraits> const& response_headers, Optional<u32> response_code)
{
if (on_headers_received)
on_headers_received(response_headers, response_code);
}
void Request::did_request_certificates(Badge<RequestClient>)
{
if (on_certificate_requested) {
auto result = on_certificate_requested();
if (!m_client->set_certificate({}, *this, result.certificate, result.key)) {
dbgln("Request: set_certificate failed");
}
}
}
}