forstio/source/forstio/io.h

206 lines
4.5 KiB
C++

#pragma once
#include "async.h"
#include "common.h"
#include "io_helpers.h"
#include <string>
#include <variant>
namespace saw {
/*
* Input stream
*/
class input_stream {
public:
virtual ~input_stream() = default;
virtual error_or<size_t> read(void *buffer, size_t length) = 0;
virtual conveyor<void> read_ready() = 0;
virtual conveyor<void> on_read_disconnected() = 0;
};
/*
* Output stream
*/
class output_stream {
public:
virtual ~output_stream() = default;
virtual error_or<size_t> write(const void *buffer, size_t length) = 0;
virtual conveyor<void> write_ready() = 0;
};
/*
* Io stream
*/
class io_stream : public input_stream, public output_stream {
public:
virtual ~io_stream() = default;
};
class async_input_stream {
public:
virtual ~async_input_stream() = default;
virtual void read(void *buffer, size_t min_length, size_t max_length) = 0;
virtual conveyor<size_t> read_done() = 0;
virtual conveyor<void> on_read_disconnected() = 0;
};
class async_output_stream {
public:
virtual ~async_output_stream() = default;
virtual void write(const void *buffer, size_t length) = 0;
virtual conveyor<size_t> write_done() = 0;
};
class async_io_stream final : public async_input_stream,
public async_output_stream {
private:
own<io_stream> stream_;
conveyor_sink read_ready_;
conveyor_sink write_ready_;
conveyor_sink read_disconnected_;
read_task_and_step_helper read_stepper_;
write_task_and_step_helper write_stepper_;
public:
async_io_stream(own<io_stream> str);
SAW_FORBID_COPY(async_io_stream);
SAW_FORBID_MOVE(async_io_stream);
void read(void *buffer, size_t length, size_t max_length) override;
conveyor<size_t> read_done() override;
conveyor<void> on_read_disconnected() override;
void write(const void *buffer, size_t length) override;
conveyor<size_t> write_done() override;
};
class server {
public:
virtual ~server() = default;
virtual conveyor<own<io_stream>> accept() = 0;
};
class network_address;
/**
* Datagram class. Bound to a local address it is able to receive inbound
* datagram messages and send them as well as long as an address is provided as
* well
*/
class datagram {
public:
virtual ~datagram() = default;
virtual error_or<size_t> read(void *buffer, size_t length) = 0;
virtual conveyor<void> read_ready() = 0;
virtual error_or<size_t> write(const void *buffer, size_t length,
network_address &dest) = 0;
virtual conveyor<void> write_ready() = 0;
};
class os_network_address;
class string_network_address;
class network_address {
public:
using child_variant =
std::variant<os_network_address *, string_network_address *>;
virtual ~network_address() = default;
virtual network_address::child_variant representation() = 0;
virtual const std::string &address() const = 0;
virtual uint16_t port() const = 0;
};
class os_network_address : public network_address {
public:
virtual ~os_network_address() = default;
network_address::child_variant representation() override { return this; }
};
class string_network_address final : public network_address {
private:
std::string address_value_;
uint16_t port_value_;
public:
string_network_address(const std::string &address, uint16_t port);
const std::string &address() const override;
uint16_t port() const override;
network_address::child_variant representation() override { return this; }
};
class network {
public:
virtual ~network() = default;
/**
* Resolve the provided string and uint16 to the preferred storage method
*/
virtual conveyor<own<network_address>>
resolve_address(const std::string &addr, uint16_t port_hint = 0) = 0;
/**
* Parse the provided string and uint16 to the preferred storage method
* Since no dns request is made here, no async conveyors have to be used.
*/
/// @todo implement
// virtual Own<NetworkAddress> parseAddress(const std::string& addr,
// uint16_t port_hint = 0) = 0;
/**
* Set up a listener on this address
*/
virtual own<server> listen(network_address &bind_addr) = 0;
/**
* Connect to a remote address
*/
virtual conveyor<own<io_stream>> connect(network_address &address) = 0;
/**
* Bind a datagram socket at this address.
*/
virtual own<datagram> datagram(network_address &address) = 0;
};
class io_provider {
public:
virtual ~io_provider() = default;
virtual own<input_stream> wrap_input_fd(int fd) = 0;
virtual network &network() = 0;
};
struct async_io_context {
own<io_provider> io;
event_loop &event_loop;
event_port &event_port;
};
error_or<async_io_context> setup_async_io();
} // namespace saw