]>
Commit | Line | Data |
---|---|---|
92f5a8d4 TL |
1 | // |
2 | // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) | |
3 | // | |
4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
6 | // | |
7 | // Official repository: https://github.com/boostorg/beast | |
8 | // | |
9 | ||
10 | #ifndef BOOST_BEAST_CORE_IMPL_FLAT_STREAM_HPP | |
11 | #define BOOST_BEAST_CORE_IMPL_FLAT_STREAM_HPP | |
12 | ||
13 | #include <boost/beast/core/async_base.hpp> | |
14 | #include <boost/beast/core/buffers_prefix.hpp> | |
15 | #include <boost/beast/core/static_buffer.hpp> | |
16 | #include <boost/beast/core/stream_traits.hpp> | |
17 | #include <boost/beast/websocket/teardown.hpp> | |
18 | #include <boost/asio/buffer.hpp> | |
19 | #include <memory> | |
20 | ||
21 | namespace boost { | |
22 | namespace beast { | |
23 | ||
24 | template<class NextLayer> | |
25 | struct flat_stream<NextLayer>::ops | |
26 | { | |
27 | ||
28 | template<class Handler> | |
29 | class write_op | |
30 | : public async_base<Handler, | |
31 | beast::executor_type<flat_stream>> | |
32 | { | |
33 | public: | |
34 | template< | |
35 | class ConstBufferSequence, | |
36 | class Handler_> | |
37 | write_op( | |
38 | Handler_&& h, | |
39 | flat_stream<NextLayer>& s, | |
40 | ConstBufferSequence const& b) | |
41 | : async_base<Handler, | |
42 | beast::executor_type<flat_stream>>( | |
43 | std::forward<Handler_>(h), | |
44 | s.get_executor()) | |
45 | { | |
46 | auto const result = | |
47 | flatten(b, max_size); | |
48 | if(result.flatten) | |
49 | { | |
50 | s.buffer_.clear(); | |
51 | s.buffer_.commit(net::buffer_copy( | |
52 | s.buffer_.prepare(result.size), | |
53 | b, result.size)); | |
20effc67 TL |
54 | |
55 | BOOST_ASIO_HANDLER_LOCATION(( | |
56 | __FILE__, __LINE__, | |
57 | "flat_stream::async_write_some")); | |
58 | ||
92f5a8d4 TL |
59 | s.stream_.async_write_some( |
60 | s.buffer_.data(), std::move(*this)); | |
61 | } | |
62 | else | |
63 | { | |
64 | s.buffer_.clear(); | |
65 | s.buffer_.shrink_to_fit(); | |
20effc67 TL |
66 | |
67 | BOOST_ASIO_HANDLER_LOCATION(( | |
68 | __FILE__, __LINE__, | |
69 | "flat_stream::async_write_some")); | |
70 | ||
92f5a8d4 TL |
71 | s.stream_.async_write_some( |
72 | beast::buffers_prefix( | |
73 | result.size, b), std::move(*this)); | |
74 | } | |
75 | } | |
76 | ||
77 | void | |
78 | operator()( | |
79 | boost::system::error_code ec, | |
80 | std::size_t bytes_transferred) | |
81 | { | |
82 | this->complete_now(ec, bytes_transferred); | |
83 | } | |
84 | }; | |
85 | ||
86 | struct run_write_op | |
87 | { | |
88 | template<class WriteHandler, class Buffers> | |
89 | void | |
90 | operator()( | |
91 | WriteHandler&& h, | |
92 | flat_stream* s, | |
93 | Buffers const& b) | |
94 | { | |
95 | // If you get an error on the following line it means | |
96 | // that your handler does not meet the documented type | |
97 | // requirements for the handler. | |
98 | ||
99 | static_assert( | |
100 | beast::detail::is_invocable<WriteHandler, | |
101 | void(error_code, std::size_t)>::value, | |
102 | "WriteHandler type requirements not met"); | |
103 | ||
104 | write_op< | |
105 | typename std::decay<WriteHandler>::type>( | |
106 | std::forward<WriteHandler>(h), *s, b); | |
107 | } | |
108 | }; | |
109 | ||
110 | }; | |
111 | ||
112 | //------------------------------------------------------------------------------ | |
113 | ||
114 | template<class NextLayer> | |
115 | template<class... Args> | |
116 | flat_stream<NextLayer>:: | |
117 | flat_stream(Args&&... args) | |
118 | : stream_(std::forward<Args>(args)...) | |
119 | { | |
120 | } | |
121 | ||
122 | template<class NextLayer> | |
123 | template<class MutableBufferSequence> | |
124 | std::size_t | |
125 | flat_stream<NextLayer>:: | |
126 | read_some(MutableBufferSequence const& buffers) | |
127 | { | |
128 | static_assert(boost::beast::is_sync_read_stream<next_layer_type>::value, | |
129 | "SyncReadStream type requirements not met"); | |
130 | static_assert(net::is_mutable_buffer_sequence< | |
131 | MutableBufferSequence>::value, | |
132 | "MutableBufferSequence type requirements not met"); | |
133 | error_code ec; | |
134 | auto n = read_some(buffers, ec); | |
135 | if(ec) | |
136 | BOOST_THROW_EXCEPTION(boost::system::system_error{ec}); | |
137 | return n; | |
138 | } | |
139 | ||
140 | template<class NextLayer> | |
141 | template<class MutableBufferSequence> | |
142 | std::size_t | |
143 | flat_stream<NextLayer>:: | |
144 | read_some(MutableBufferSequence const& buffers, error_code& ec) | |
145 | { | |
146 | static_assert(boost::beast::is_sync_read_stream<next_layer_type>::value, | |
147 | "SyncReadStream type requirements not met"); | |
148 | static_assert(net::is_mutable_buffer_sequence< | |
149 | MutableBufferSequence>::value, | |
150 | "MutableBufferSequence type requirements not met"); | |
151 | return stream_.read_some(buffers, ec); | |
152 | } | |
153 | ||
154 | template<class NextLayer> | |
155 | template< | |
156 | class MutableBufferSequence, | |
20effc67 | 157 | BOOST_BEAST_ASYNC_TPARAM2 ReadHandler> |
92f5a8d4 TL |
158 | BOOST_BEAST_ASYNC_RESULT2(ReadHandler) |
159 | flat_stream<NextLayer>:: | |
160 | async_read_some( | |
161 | MutableBufferSequence const& buffers, | |
162 | ReadHandler&& handler) | |
163 | { | |
164 | static_assert(boost::beast::is_async_read_stream<next_layer_type>::value, | |
165 | "AsyncReadStream type requirements not met"); | |
166 | static_assert(net::is_mutable_buffer_sequence< | |
167 | MutableBufferSequence >::value, | |
168 | "MutableBufferSequence type requirements not met"); | |
169 | return stream_.async_read_some( | |
170 | buffers, std::forward<ReadHandler>(handler)); | |
171 | } | |
172 | ||
173 | template<class NextLayer> | |
174 | template<class ConstBufferSequence> | |
175 | std::size_t | |
176 | flat_stream<NextLayer>:: | |
177 | write_some(ConstBufferSequence const& buffers) | |
178 | { | |
179 | static_assert(boost::beast::is_sync_write_stream<next_layer_type>::value, | |
180 | "SyncWriteStream type requirements not met"); | |
181 | static_assert(net::is_const_buffer_sequence< | |
182 | ConstBufferSequence>::value, | |
183 | "ConstBufferSequence type requirements not met"); | |
184 | error_code ec; | |
185 | auto n = write_some(buffers, ec); | |
186 | if(ec) | |
187 | BOOST_THROW_EXCEPTION(boost::system::system_error{ec}); | |
188 | return n; | |
189 | } | |
190 | ||
191 | template<class NextLayer> | |
192 | template<class ConstBufferSequence> | |
193 | std::size_t | |
194 | flat_stream<NextLayer>:: | |
195 | stack_write_some( | |
196 | std::size_t size, | |
197 | ConstBufferSequence const& buffers, | |
198 | error_code& ec) | |
199 | { | |
200 | static_buffer<max_stack> b; | |
201 | b.commit(net::buffer_copy( | |
202 | b.prepare(size), buffers)); | |
203 | return stream_.write_some(b.data(), ec); | |
204 | } | |
205 | ||
206 | template<class NextLayer> | |
207 | template<class ConstBufferSequence> | |
208 | std::size_t | |
209 | flat_stream<NextLayer>:: | |
210 | write_some(ConstBufferSequence const& buffers, error_code& ec) | |
211 | { | |
212 | static_assert(boost::beast::is_sync_write_stream<next_layer_type>::value, | |
213 | "SyncWriteStream type requirements not met"); | |
214 | static_assert(net::is_const_buffer_sequence< | |
215 | ConstBufferSequence>::value, | |
216 | "ConstBufferSequence type requirements not met"); | |
217 | auto const result = flatten(buffers, max_size); | |
218 | if(result.flatten) | |
219 | { | |
220 | if(result.size <= max_stack) | |
221 | return stack_write_some(result.size, buffers, ec); | |
222 | ||
223 | buffer_.clear(); | |
224 | buffer_.commit(net::buffer_copy( | |
225 | buffer_.prepare(result.size), | |
226 | buffers)); | |
227 | return stream_.write_some(buffer_.data(), ec); | |
228 | } | |
229 | buffer_.clear(); | |
230 | buffer_.shrink_to_fit(); | |
231 | return stream_.write_some( | |
232 | boost::beast::buffers_prefix(result.size, buffers), ec); | |
233 | } | |
234 | ||
235 | template<class NextLayer> | |
236 | template< | |
237 | class ConstBufferSequence, | |
20effc67 | 238 | BOOST_BEAST_ASYNC_TPARAM2 WriteHandler> |
92f5a8d4 TL |
239 | BOOST_BEAST_ASYNC_RESULT2(WriteHandler) |
240 | flat_stream<NextLayer>:: | |
241 | async_write_some( | |
242 | ConstBufferSequence const& buffers, | |
243 | WriteHandler&& handler) | |
244 | { | |
245 | static_assert(boost::beast::is_async_write_stream<next_layer_type>::value, | |
246 | "AsyncWriteStream type requirements not met"); | |
247 | static_assert(net::is_const_buffer_sequence< | |
248 | ConstBufferSequence>::value, | |
249 | "ConstBufferSequence type requirements not met"); | |
250 | return net::async_initiate< | |
251 | WriteHandler, | |
252 | void(error_code, std::size_t)>( | |
253 | typename ops::run_write_op{}, | |
254 | handler, | |
255 | this, | |
256 | buffers); | |
257 | } | |
258 | ||
259 | template<class NextLayer> | |
260 | void | |
261 | teardown( | |
262 | boost::beast::role_type role, | |
263 | flat_stream<NextLayer>& s, | |
264 | error_code& ec) | |
265 | { | |
266 | using boost::beast::websocket::teardown; | |
267 | teardown(role, s.next_layer(), ec); | |
268 | } | |
269 | ||
270 | template<class NextLayer, class TeardownHandler> | |
271 | void | |
272 | async_teardown( | |
273 | boost::beast::role_type role, | |
274 | flat_stream<NextLayer>& s, | |
275 | TeardownHandler&& handler) | |
276 | { | |
277 | using boost::beast::websocket::async_teardown; | |
278 | async_teardown(role, s.next_layer(), std::move(handler)); | |
279 | } | |
280 | ||
281 | } // beast | |
282 | } // boost | |
283 | ||
284 | #endif |