3 #include <boost/asio/any_io_executor.hpp>
4 #include <boost/asio/buffers_iterator.hpp>
6 #include <nexus/quic/detail/operation.hpp>
7 #include <nexus/quic/detail/service.hpp>
8 #include <nexus/quic/detail/stream_state.hpp>
9 #include <nexus/quic/error.hpp>
10 #include <nexus/h3/fields.hpp>
15 namespace quic::detail {
17 struct connection_impl;
20 struct stream_impl :
public boost::intrusive::list_base_hook<>,
21 public service_list_base_hook {
22 using executor_type = boost::asio::any_io_executor;
24 service<stream_impl>& svc;
25 connection_impl& conn;
26 stream_state::variant state;
28 template <
typename BufferSequence>
29 static void init_op(
const BufferSequence& buffers,
30 stream_data_operation& op) {
31 const auto end = boost::asio::buffer_sequence_end(buffers);
32 for (
auto i = boost::asio::buffer_sequence_begin(buffers);
33 i != end && op.num_iovs < op.max_iovs;
35 op.iovs[op.num_iovs].iov_base =
const_cast<void*
>(i->data());
36 op.iovs[op.num_iovs].iov_len = i->size();
40 explicit stream_impl(connection_impl& conn);
43 void service_shutdown();
45 executor_type get_executor()
const;
50 void read_headers(stream_header_read_operation& op);
52 template <
typename CompletionToken>
53 decltype(
auto) async_read_headers(h3::fields& fields,
54 CompletionToken&& token) {
55 return boost::asio::async_initiate<CompletionToken, void(error_code)>(
56 [
this, &fields] (
auto h) {
57 using Handler = std::decay_t<decltype(h)>;
58 using op_type = stream_header_read_async<Handler, executor_type>;
59 auto p = handler_allocate<op_type>(h, std::move(h),
60 get_executor(), fields);
61 auto op = handler_ptr<op_type, Handler>{p, &p->handler};
67 void read_some(stream_data_operation& op);
70 template <
typename MutableBufferSequence,
typename CompletionToken>
71 decltype(
auto) async_read_some(const MutableBufferSequence& buffers,
72 CompletionToken&& token) {
73 return boost::asio::async_initiate<CompletionToken, void(error_code, size_t)>(
74 [
this, &buffers] (
auto h) {
75 using Handler = std::decay_t<decltype(h)>;
76 using op_type = stream_data_async<Handler, executor_type>;
77 auto p = handler_allocate<op_type>(h, std::move(h), get_executor());
78 auto op = handler_ptr<op_type, Handler>{p, &p->handler};
79 init_op(buffers, *op);
85 template <
typename MutableBufferSequence>
86 std::enable_if_t<boost::asio::is_mutable_buffer_sequence<
87 MutableBufferSequence>::value,
size_t>
88 read_some(
const MutableBufferSequence& buffers, error_code& ec) {
93 ec = std::get<0>(*op.result);
94 return std::get<1>(*op.result);
97 void write_headers(stream_header_write_operation& op);
99 template <
typename CompletionToken>
100 decltype(
auto) async_write_headers(const h3::fields& fields,
101 CompletionToken&& token) {
102 return boost::asio::async_initiate<CompletionToken, void(error_code)>(
103 [
this, &fields] (
auto h) {
104 using Handler = std::decay_t<decltype(h)>;
105 using op_type = stream_header_write_async<Handler, executor_type>;
106 auto p = handler_allocate<op_type>(h, std::move(h),
107 get_executor(), fields);
108 auto op = handler_ptr<op_type, Handler>{p, &p->handler};
114 void write_some(stream_data_operation& op);
117 template <
typename ConstBufferSequence,
typename CompletionToken>
118 decltype(
auto) async_write_some(const ConstBufferSequence& buffers,
119 CompletionToken&& token) {
120 return boost::asio::async_initiate<CompletionToken, void(error_code, size_t)>(
121 [
this, &buffers] (
auto h) {
122 using Handler = std::decay_t<decltype(h)>;
123 using op_type = stream_data_async<Handler, executor_type>;
124 auto p = handler_allocate<op_type>(h, std::move(h), get_executor());
125 auto op = handler_ptr<op_type, Handler>{p, &p->handler};
126 init_op(buffers, *op);
132 template <
typename ConstBufferSequence>
133 std::enable_if_t<boost::asio::is_const_buffer_sequence<
134 ConstBufferSequence>::value,
size_t>
135 write_some(
const ConstBufferSequence& buffers, error_code& ec) {
137 init_op(buffers, op);
140 ec = std::get<0>(*op.result);
141 return std::get<1>(*op.result);
144 void flush(error_code& ec);
145 void shutdown(
int how, error_code& ec);
147 void close(stream_close_operation& op);
150 template <
typename CompletionToken>
151 decltype(
auto) async_close(CompletionToken&& token) {
152 return boost::asio::async_initiate<CompletionToken, void(error_code)>(
154 using Handler = std::decay_t<decltype(h)>;
155 using op_type = stream_close_async<Handler, executor_type>;
156 auto p = handler_allocate<op_type>(h, std::move(h), get_executor());
157 auto op = handler_ptr<op_type, Handler>{p, &p->handler};
uint64_t stream_id
stream identifier that is unique to a connection
Definition: stream_id.hpp:8
networking
Definition: error_code.hpp:8