summaryrefslogtreecommitdiff
path: root/src/io/io.h
diff options
context:
space:
mode:
authorClaudius Holeksa <mail@keldu.de>2023-05-03 20:34:02 +0200
committerClaudius Holeksa <mail@keldu.de>2023-05-03 20:34:02 +0200
commit2aa2af0007b7e969845642027c635cd3fd9c8aea (patch)
treee72a05a3c2bfe58442b160c0c8e98ce1d095f36f /src/io/io.h
parent9b81a2585142260f89d47cbe1e592cec9e1f778f (diff)
Moved dirs and added codec-json dir
Diffstat (limited to 'src/io/io.h')
-rw-r--r--src/io/io.h214
1 files changed, 214 insertions, 0 deletions
diff --git a/src/io/io.h b/src/io/io.h
new file mode 100644
index 0000000..bcc59fd
--- /dev/null
+++ b/src/io/io.h
@@ -0,0 +1,214 @@
+#pragma once
+
+#include <forstio/async/async.h>
+#include <forstio/core/common.h>
+#include "io_helpers.h"
+
+#include <string>
+#include <variant>
+
+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<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