#pragma once #include #include #include "io_helpers.h" #include #include namespace saw { /** * Set of error common in io */ namespace err { struct disconnected { static constexpr std::string_view description = "Disconnected"; static constexpr bool is_critical = true; }; } /* * Input stream */ class input_stream { public: virtual ~input_stream() = default; virtual error_or read(void *buffer, size_t length) = 0; virtual conveyor read_ready() = 0; virtual conveyor on_read_disconnected() = 0; }; /* * Output stream */ class output_stream { public: virtual ~output_stream() = default; virtual error_or write(const void *buffer, size_t length) = 0; virtual conveyor 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 read_done() = 0; virtual conveyor 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 write_done() = 0; }; class async_io_stream final : public async_input_stream, public async_output_stream { private: own 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 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 read_done() override; conveyor on_read_disconnected() override; void write(const void *buffer, size_t length) override; conveyor write_done() override; }; class server { public: virtual ~server() = default; virtual conveyor> 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 read(void *buffer, size_t length) = 0; virtual conveyor read_ready() = 0; virtual error_or write(const void *buffer, size_t length, network_address &dest) = 0; virtual conveyor write_ready() = 0; }; class os_network_address; class string_network_address; class network_address { public: using child_variant = std::variant; 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> 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 parseAddress(const std::string& addr, // uint16_t port_hint = 0) = 0; /** * Set up a listener on this address */ virtual own listen(network_address &bind_addr) = 0; /** * Connect to a remote address */ virtual conveyor> connect(network_address &address) = 0; /** * Bind a datagram socket at this address. */ virtual own datagram(network_address &address) = 0; }; class io_provider { public: virtual ~io_provider() = default; virtual own wrap_input_fd(int fd) = 0; virtual network &network() = 0; }; struct async_io_context { own io; event_loop &event_loop; event_port &event_port; }; error_or setup_async_io(); } // namespace saw