2025-03-07 22:15:49 +01:00

172 lines
4.0 KiB
C++

#include <seafire/protocol/read.hxx>
#include <seafire/protocol/match.hxx>
#include <seafire/protocol/rfc7230/content-length.hxx>
#include <seafire/common/io/read-until.hxx>
#include <asio.hpp>
namespace seafire::protocol
{
/// Read a request message from buffer \a b, reading more content from
/// stream \a s as required.
///
/// The read request message is placed in \a r.
///
/// If the buffer \a b contains a full request message, no I/O operations
/// will be performed.
///
/// \throws std::system_error Thrown on error.
/// \relatesalso request_t
///
void
read(common::io::stream_t& s,
asio::streambuf& b,
request_t& r)
{
std::error_code ec;
read(s, b, r, ec);
if (ec) {
throw std::system_error{ec};
}
}
/// Read a request message from buffer \a b, reading more content from
/// stream \a s as required.
///
/// The read request message is placed in \a r.
///
/// If the buffer \a b contains a full request message, no I/O operations
/// will be performed.
///
/// Errors are reported through \a ec.
///
/// \relatesalso request_t
///
void
read(common::io::stream_t& s,
asio::streambuf& b,
request_t& r,
std::error_code& ec)
{
auto bytes_consumed = common::io::read_until(s, b, match_request_t{r}, ec);
if (ec) {
return;
}
b.consume(bytes_consumed);
}
/// Initialize an asynchronous read of a request message from buffer \a b,
/// reading more content from \a s as required.
///
/// The read request message is placed in \a r.
///
/// If the buffer \a b contains a full request message, no I/O operations
/// will be performed.
///
/// \a r must be valid until the completion-handler \a h is called.
///
void
async_read(common::io::stream_t& s,
asio::streambuf& b,
request_t& r,
std::function<void(std::error_code)> h)
{
auto bound = [&b, h](std::error_code const& ec, std::size_t n)
{
if (!ec) {
b.consume(n);
}
h(ec);
};
common::io::async_read_until(s, b, match_request_t{r}, bound);
}
/// Read a response message from buffer \a b, reading more content from
/// stream \a s as required.
///
/// The read response message is placed in \a r.
///
/// If the buffer \a b contains a full response message, no I/O operations
/// will be performed.
///
/// \throws std::system_error Thrown on error.
/// \relatesalso response_t
///
void
read(common::io::stream_t& s,
asio::streambuf& b,
response_t& r)
{
std::error_code ec;
read(s, b, r, ec);
if (ec) {
throw std::system_error{ec};
}
}
/// Read a response message from buffer \a b, reading more content from
/// stream \a s as required.
///
/// The read response message is placed in \a r.
///
/// If the buffer \a b contains a full response message, no I/O operations
/// will be performed.
///
/// Errors are reported through \a ec.
///
/// \relatesalso response_t
///
void
read(common::io::stream_t& s,
asio::streambuf& b,
response_t& r,
std::error_code& ec)
{
auto bytes_consumed = common::io::read_until(s, b, match_response_t{r}, ec);
if (ec) {
return;
}
b.consume(bytes_consumed);
}
/// Initialize an asynchronous read of a response message from buffer \a b,
/// reading more content from \a s as required.
///
/// The read response message is placed in \a r.
///
/// If the buffer \a b contains a full response message, no I/O operations
/// will be performed.
///
/// \a r must be valid until the completion-handler \a h is called.
///
void
async_read(common::io::stream_t& s,
asio::streambuf& b,
response_t& r,
std::function<void(std::error_code)> h)
{
auto bound = [&b, h](std::error_code const& ec, std::size_t n)
{
if (!ec) {
b.consume(n);
}
h(ec);
};
common::io::async_read_until(s, b, match_response_t{r}, bound);
}
} // namespace seafire::protocol