summaryrefslogtreecommitdiff
path: root/modules/io_codec/c++/io_peer.hpp
blob: bd0af69379308ed345881575dca7ce429db90e04 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#pragma once

#include <forstio/async/async.hpp>
#include <forstio/buffer.hpp>
#include <forstio/io/io.hpp>
#include <forstio/codec/data.hpp>
#include <forstio/codec/transport.hpp>

namespace saw {

template <typename Incoming, typename Outgoing,
		  typename TransportEncoding, typename ContentEncoding,
		  typename BufferT = chain_array_buffer>
class streaming_io_peer {
private:
	static_assert(not std::is_same_v<ContentEncoding, encode::Native>, "The native encoding by definition is not fit for transport.");
public:
	/**
	 * Constructor with the option to provide a custom codec, in and out buffer
	 */
	streaming_io_peer(
		own<conveyor_feeder<data<Incoming, ContentEncoding>>> feed,
		own<async_io_stream> stream, transport<TransportEncoding> in_codec);

	/**
	 * Constructor with mostly default assignements
	 */
	streaming_io_peer(
		own<conveyor_feeder<data<Incoming, ContentEncoding>>> feed,
		own<async_io_stream> stream);

	/**
	 * Deleted copy and move constructors
	 */
	SAW_FORBID_COPY(streaming_io_peer);
	SAW_FORBID_MOVE(streaming_io_peer);

	/**
	 * Send a message to the remote peer
	 */
	error_or<void> send(data<Outgoing, ContentEncoding> builder);

	/**
	 * A phantom conveyor feeder. Meant for interfacing with other components
	 */
	conveyor_feeder<data<Outgoing, ContentEncoding>> &feeder();

	conveyor<void> on_disconnected();

private:
	/// @unimplemented
	/// This will be a mechanic which allows connecting the outbound connection natively to a pure conveyor setup.
	class peer_conveyor_feeder final
		: public conveyor_feeder<data<Outgoing, ContentEncoding>> {
	public:
		peer_conveyor_feeder(
			streaming_io_peer<Incoming, Outgoing, TransportEncoding, ContentEncoding, BufferT> &peer_)
			: peer_{peer_} {}

		void feed(data<Outgoing, ContentEncoding> &&data_) override {
			(void)data_;
		}

		void fail(error &&err) override { (void)err; }

		size_t space() const override { return 0; }

		size_t queued() const override { return 0; }
	
		error_or<void> swap(conveyor<data<Outgoing, ContentEncoding>> &&) noexcept override { return make_error<err::not_implemented>();}
	private:
		streaming_io_peer<Incoming, Outgoing, TransportEncoding, ContentEncoding,
						  BufferT> &peer_;
	};

private:
	own<conveyor_feeder<data<Incoming, ContentEncoding>>>
		incoming_feeder_ = nullptr;

	own<async_io_stream> io_stream_;

	transport<TransportEncoding> in_codec_;

	BufferT in_buffer_;
	BufferT out_buffer_;

	conveyor_sink sink_read_;
	conveyor_sink sink_write_;

	peer_conveyor_feeder conveyor_feeder_;

	conveyor_sink io_read_disconnected_;
	own<conveyor_feeder<void>> disconnect_feeder_ = nullptr;
};

/**
 * Setup new streaming io peer with the provided network protocols.
 * This is a convenience wrapper intended for a faster setup of this class
 */
template <typename Incoming, typename Outgoing,
		  typename TransportEncoding, typename ContentEncoding,
		  typename BufferT = ring_buffer>
std::pair<own<streaming_io_peer<Incoming, Outgoing, TransportEncoding, ContentEncoding, BufferT>>,
		  conveyor<data<Incoming, ContentEncoding>>>
new_streaming_io_peer(own<async_io_stream> stream);

} // namespace saw

#include "io_peer.tmpl.hpp"