206 lines
4.5 KiB
C++
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
|