]>
Commit | Line | Data |
---|---|---|
b32b8144 FG |
1 | // |
2 | // Copyright (c) 2016-2017 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_WEBSOCKET_IMPL_ACCEPT_IPP | |
11 | #define BOOST_BEAST_WEBSOCKET_IMPL_ACCEPT_IPP | |
12 | ||
13 | #include <boost/beast/websocket/detail/type_traits.hpp> | |
14 | #include <boost/beast/http/empty_body.hpp> | |
15 | #include <boost/beast/http/parser.hpp> | |
16 | #include <boost/beast/http/read.hpp> | |
17 | #include <boost/beast/http/string_body.hpp> | |
18 | #include <boost/beast/http/write.hpp> | |
19 | #include <boost/beast/core/buffers_prefix.hpp> | |
20 | #include <boost/beast/core/handler_ptr.hpp> | |
21 | #include <boost/beast/core/detail/type_traits.hpp> | |
22 | #include <boost/asio/coroutine.hpp> | |
23 | #include <boost/asio/associated_allocator.hpp> | |
24 | #include <boost/asio/associated_executor.hpp> | |
25 | #include <boost/asio/handler_continuation_hook.hpp> | |
11fdf7f2 | 26 | #include <boost/asio/handler_invoke_hook.hpp> |
b32b8144 FG |
27 | #include <boost/asio/post.hpp> |
28 | #include <boost/assert.hpp> | |
29 | #include <boost/throw_exception.hpp> | |
30 | #include <memory> | |
31 | #include <type_traits> | |
32 | ||
33 | namespace boost { | |
34 | namespace beast { | |
35 | namespace websocket { | |
36 | ||
37 | // Respond to an upgrade HTTP request | |
11fdf7f2 | 38 | template<class NextLayer, bool deflateSupported> |
b32b8144 | 39 | template<class Handler> |
11fdf7f2 | 40 | class stream<NextLayer, deflateSupported>::response_op |
b32b8144 FG |
41 | : public boost::asio::coroutine |
42 | { | |
43 | struct data | |
44 | { | |
11fdf7f2 TL |
45 | stream<NextLayer, deflateSupported>& ws; |
46 | error_code result; | |
b32b8144 FG |
47 | response_type res; |
48 | ||
49 | template<class Body, class Allocator, class Decorator> | |
11fdf7f2 TL |
50 | data( |
51 | Handler const&, | |
52 | stream<NextLayer, deflateSupported>& ws_, | |
53 | http::request<Body, | |
54 | http::basic_fields<Allocator>> const& req, | |
55 | Decorator const& decorator) | |
b32b8144 | 56 | : ws(ws_) |
11fdf7f2 | 57 | , res(ws_.build_response(req, decorator, result)) |
b32b8144 FG |
58 | { |
59 | } | |
60 | }; | |
61 | ||
62 | handler_ptr<data, Handler> d_; | |
63 | ||
64 | public: | |
65 | response_op(response_op&&) = default; | |
11fdf7f2 | 66 | response_op(response_op const&) = delete; |
b32b8144 FG |
67 | |
68 | template<class DeducedHandler, class... Args> | |
69 | response_op(DeducedHandler&& h, | |
11fdf7f2 | 70 | stream<NextLayer, deflateSupported>& ws, Args&&... args) |
b32b8144 FG |
71 | : d_(std::forward<DeducedHandler>(h), |
72 | ws, std::forward<Args>(args)...) | |
73 | { | |
74 | } | |
75 | ||
76 | using allocator_type = | |
77 | boost::asio::associated_allocator_t<Handler>; | |
78 | ||
79 | allocator_type | |
80 | get_allocator() const noexcept | |
81 | { | |
11fdf7f2 | 82 | return (boost::asio::get_associated_allocator)(d_.handler()); |
b32b8144 FG |
83 | } |
84 | ||
85 | using executor_type = boost::asio::associated_executor_t< | |
11fdf7f2 TL |
86 | Handler, decltype(std::declval< |
87 | stream<NextLayer, deflateSupported>&>().get_executor())>; | |
b32b8144 FG |
88 | |
89 | executor_type | |
90 | get_executor() const noexcept | |
91 | { | |
11fdf7f2 | 92 | return (boost::asio::get_associated_executor)( |
b32b8144 FG |
93 | d_.handler(), d_->ws.get_executor()); |
94 | } | |
95 | ||
96 | void operator()( | |
97 | error_code ec = {}, | |
98 | std::size_t bytes_transferred = 0); | |
99 | ||
100 | friend | |
101 | bool asio_handler_is_continuation(response_op* op) | |
102 | { | |
103 | using boost::asio::asio_handler_is_continuation; | |
104 | return asio_handler_is_continuation( | |
105 | std::addressof(op->d_.handler())); | |
106 | } | |
11fdf7f2 TL |
107 | |
108 | template<class Function> | |
109 | friend | |
110 | void asio_handler_invoke(Function&& f, response_op* op) | |
111 | { | |
112 | using boost::asio::asio_handler_invoke; | |
113 | asio_handler_invoke(f, std::addressof(op->d_.handler())); | |
114 | } | |
b32b8144 FG |
115 | }; |
116 | ||
11fdf7f2 | 117 | template<class NextLayer, bool deflateSupported> |
b32b8144 FG |
118 | template<class Handler> |
119 | void | |
11fdf7f2 | 120 | stream<NextLayer, deflateSupported>:: |
b32b8144 FG |
121 | response_op<Handler>:: |
122 | operator()( | |
123 | error_code ec, | |
124 | std::size_t) | |
125 | { | |
126 | auto& d = *d_; | |
127 | BOOST_ASIO_CORO_REENTER(*this) | |
128 | { | |
129 | // Send response | |
130 | BOOST_ASIO_CORO_YIELD | |
131 | http::async_write(d.ws.next_layer(), | |
132 | d.res, std::move(*this)); | |
11fdf7f2 TL |
133 | if(! ec) |
134 | ec = d.result; | |
b32b8144 FG |
135 | if(! ec) |
136 | { | |
11fdf7f2 | 137 | d.ws.do_pmd_config(d.res, is_deflate_supported{}); |
b32b8144 FG |
138 | d.ws.open(role_type::server); |
139 | } | |
140 | d_.invoke(ec); | |
141 | } | |
142 | } | |
143 | ||
144 | //------------------------------------------------------------------------------ | |
145 | ||
146 | // read and respond to an upgrade request | |
147 | // | |
11fdf7f2 | 148 | template<class NextLayer, bool deflateSupported> |
b32b8144 | 149 | template<class Decorator, class Handler> |
11fdf7f2 | 150 | class stream<NextLayer, deflateSupported>::accept_op |
b32b8144 FG |
151 | : public boost::asio::coroutine |
152 | { | |
153 | struct data | |
154 | { | |
11fdf7f2 | 155 | stream<NextLayer, deflateSupported>& ws; |
b32b8144 FG |
156 | Decorator decorator; |
157 | http::request_parser<http::empty_body> p; | |
11fdf7f2 TL |
158 | data( |
159 | Handler const&, | |
160 | stream<NextLayer, deflateSupported>& ws_, | |
161 | Decorator const& decorator_) | |
b32b8144 FG |
162 | : ws(ws_) |
163 | , decorator(decorator_) | |
164 | { | |
165 | } | |
166 | }; | |
167 | ||
168 | handler_ptr<data, Handler> d_; | |
169 | ||
170 | public: | |
171 | accept_op(accept_op&&) = default; | |
11fdf7f2 | 172 | accept_op(accept_op const&) = delete; |
b32b8144 FG |
173 | |
174 | template<class DeducedHandler, class... Args> | |
175 | accept_op(DeducedHandler&& h, | |
11fdf7f2 | 176 | stream<NextLayer, deflateSupported>& ws, Args&&... args) |
b32b8144 FG |
177 | : d_(std::forward<DeducedHandler>(h), |
178 | ws, std::forward<Args>(args)...) | |
179 | { | |
180 | } | |
181 | ||
182 | using allocator_type = | |
183 | boost::asio::associated_allocator_t<Handler>; | |
184 | ||
185 | allocator_type | |
186 | get_allocator() const noexcept | |
187 | { | |
11fdf7f2 | 188 | return (boost::asio::get_associated_allocator)(d_.handler()); |
b32b8144 FG |
189 | } |
190 | ||
191 | using executor_type = boost::asio::associated_executor_t< | |
11fdf7f2 | 192 | Handler, decltype(std::declval<stream<NextLayer, deflateSupported>&>().get_executor())>; |
b32b8144 FG |
193 | |
194 | executor_type | |
195 | get_executor() const noexcept | |
196 | { | |
11fdf7f2 | 197 | return (boost::asio::get_associated_executor)( |
b32b8144 FG |
198 | d_.handler(), d_->ws.get_executor()); |
199 | } | |
200 | ||
201 | template<class Buffers> | |
202 | void run(Buffers const& buffers); | |
203 | ||
204 | void operator()( | |
205 | error_code ec = {}, | |
206 | std::size_t bytes_used = 0); | |
207 | ||
208 | friend | |
209 | bool asio_handler_is_continuation(accept_op* op) | |
210 | { | |
211 | using boost::asio::asio_handler_is_continuation; | |
212 | return asio_handler_is_continuation( | |
213 | std::addressof(op->d_.handler())); | |
214 | } | |
11fdf7f2 TL |
215 | |
216 | template<class Function> | |
217 | friend | |
218 | void asio_handler_invoke(Function&& f, accept_op* op) | |
219 | { | |
220 | using boost::asio::asio_handler_invoke; | |
221 | asio_handler_invoke(f, std::addressof(op->d_.handler())); | |
222 | } | |
b32b8144 FG |
223 | }; |
224 | ||
11fdf7f2 | 225 | template<class NextLayer, bool deflateSupported> |
b32b8144 FG |
226 | template<class Decorator, class Handler> |
227 | template<class Buffers> | |
228 | void | |
11fdf7f2 | 229 | stream<NextLayer, deflateSupported>:: |
b32b8144 FG |
230 | accept_op<Decorator, Handler>:: |
231 | run(Buffers const& buffers) | |
232 | { | |
233 | using boost::asio::buffer_copy; | |
234 | using boost::asio::buffer_size; | |
235 | auto& d = *d_; | |
236 | error_code ec; | |
237 | boost::optional<typename | |
238 | static_buffer_base::mutable_buffers_type> mb; | |
239 | auto const len = buffer_size(buffers); | |
240 | try | |
241 | { | |
242 | mb.emplace(d.ws.rd_buf_.prepare(len)); | |
243 | } | |
244 | catch(std::length_error const&) | |
245 | { | |
246 | ec = error::buffer_overflow; | |
247 | return (*this)(ec); | |
248 | } | |
249 | d.ws.rd_buf_.commit( | |
250 | buffer_copy(*mb, buffers)); | |
251 | (*this)(ec); | |
252 | } | |
253 | ||
11fdf7f2 | 254 | template<class NextLayer, bool deflateSupported> |
b32b8144 FG |
255 | template<class Decorator, class Handler> |
256 | void | |
11fdf7f2 | 257 | stream<NextLayer, deflateSupported>:: |
b32b8144 FG |
258 | accept_op<Decorator, Handler>:: |
259 | operator()(error_code ec, std::size_t) | |
260 | { | |
261 | auto& d = *d_; | |
262 | BOOST_ASIO_CORO_REENTER(*this) | |
263 | { | |
264 | if(ec) | |
265 | { | |
266 | BOOST_ASIO_CORO_YIELD | |
267 | boost::asio::post( | |
268 | d.ws.get_executor(), | |
269 | bind_handler(std::move(*this), ec)); | |
270 | } | |
271 | else | |
272 | { | |
273 | BOOST_ASIO_CORO_YIELD | |
274 | http::async_read( | |
275 | d.ws.next_layer(), d.ws.rd_buf_, | |
276 | d.p, std::move(*this)); | |
277 | if(ec == http::error::end_of_stream) | |
278 | ec = error::closed; | |
279 | if(! ec) | |
280 | { | |
281 | // Arguments from our state must be | |
282 | // moved to the stack before releasing | |
283 | // the handler. | |
284 | auto& ws = d.ws; | |
285 | auto const req = d.p.release(); | |
286 | auto const decorator = d.decorator; | |
287 | #if 1 | |
288 | return response_op<Handler>{ | |
289 | d_.release_handler(), | |
290 | ws, req, decorator}(ec); | |
291 | #else | |
292 | // VFALCO This *should* work but breaks | |
293 | // coroutine invariants in the unit test. | |
294 | // Also it calls reset() when it shouldn't. | |
295 | return ws.async_accept_ex( | |
296 | req, decorator, d_.release_handler()); | |
297 | #endif | |
298 | } | |
299 | } | |
300 | d_.invoke(ec); | |
301 | } | |
302 | } | |
303 | ||
304 | //------------------------------------------------------------------------------ | |
305 | ||
11fdf7f2 | 306 | template<class NextLayer, bool deflateSupported> |
b32b8144 | 307 | void |
11fdf7f2 | 308 | stream<NextLayer, deflateSupported>:: |
b32b8144 FG |
309 | accept() |
310 | { | |
311 | static_assert(is_sync_stream<next_layer_type>::value, | |
312 | "SyncStream requirements not met"); | |
313 | error_code ec; | |
314 | accept(ec); | |
315 | if(ec) | |
316 | BOOST_THROW_EXCEPTION(system_error{ec}); | |
317 | } | |
318 | ||
11fdf7f2 | 319 | template<class NextLayer, bool deflateSupported> |
b32b8144 FG |
320 | template<class ResponseDecorator> |
321 | void | |
11fdf7f2 | 322 | stream<NextLayer, deflateSupported>:: |
b32b8144 FG |
323 | accept_ex(ResponseDecorator const& decorator) |
324 | { | |
325 | static_assert(is_sync_stream<next_layer_type>::value, | |
326 | "SyncStream requirements not met"); | |
11fdf7f2 | 327 | static_assert(detail::is_response_decorator< |
b32b8144 FG |
328 | ResponseDecorator>::value, |
329 | "ResponseDecorator requirements not met"); | |
330 | error_code ec; | |
331 | accept_ex(decorator, ec); | |
332 | if(ec) | |
333 | BOOST_THROW_EXCEPTION(system_error{ec}); | |
334 | } | |
335 | ||
11fdf7f2 | 336 | template<class NextLayer, bool deflateSupported> |
b32b8144 | 337 | void |
11fdf7f2 | 338 | stream<NextLayer, deflateSupported>:: |
b32b8144 FG |
339 | accept(error_code& ec) |
340 | { | |
341 | static_assert(is_sync_stream<next_layer_type>::value, | |
342 | "SyncStream requirements not met"); | |
343 | reset(); | |
344 | do_accept(&default_decorate_res, ec); | |
345 | } | |
346 | ||
11fdf7f2 | 347 | template<class NextLayer, bool deflateSupported> |
b32b8144 FG |
348 | template<class ResponseDecorator> |
349 | void | |
11fdf7f2 | 350 | stream<NextLayer, deflateSupported>:: |
b32b8144 FG |
351 | accept_ex(ResponseDecorator const& decorator, error_code& ec) |
352 | { | |
353 | static_assert(is_sync_stream<next_layer_type>::value, | |
354 | "SyncStream requirements not met"); | |
11fdf7f2 | 355 | static_assert(detail::is_response_decorator< |
b32b8144 FG |
356 | ResponseDecorator>::value, |
357 | "ResponseDecorator requirements not met"); | |
358 | reset(); | |
359 | do_accept(decorator, ec); | |
360 | } | |
361 | ||
11fdf7f2 | 362 | template<class NextLayer, bool deflateSupported> |
b32b8144 FG |
363 | template<class ConstBufferSequence> |
364 | typename std::enable_if<! http::detail::is_header< | |
365 | ConstBufferSequence>::value>::type | |
11fdf7f2 | 366 | stream<NextLayer, deflateSupported>:: |
b32b8144 FG |
367 | accept(ConstBufferSequence const& buffers) |
368 | { | |
369 | static_assert(is_sync_stream<next_layer_type>::value, | |
370 | "SyncStream requirements not met"); | |
371 | static_assert(boost::asio::is_const_buffer_sequence< | |
372 | ConstBufferSequence>::value, | |
373 | "ConstBufferSequence requirements not met"); | |
374 | error_code ec; | |
375 | accept(buffers, ec); | |
376 | if(ec) | |
377 | BOOST_THROW_EXCEPTION(system_error{ec}); | |
378 | } | |
379 | ||
11fdf7f2 | 380 | template<class NextLayer, bool deflateSupported> |
b32b8144 FG |
381 | template< |
382 | class ConstBufferSequence, | |
383 | class ResponseDecorator> | |
384 | typename std::enable_if<! http::detail::is_header< | |
385 | ConstBufferSequence>::value>::type | |
11fdf7f2 | 386 | stream<NextLayer, deflateSupported>:: |
b32b8144 FG |
387 | accept_ex( |
388 | ConstBufferSequence const& buffers, | |
389 | ResponseDecorator const &decorator) | |
390 | { | |
391 | static_assert(is_sync_stream<next_layer_type>::value, | |
392 | "SyncStream requirements not met"); | |
393 | static_assert(boost::asio::is_const_buffer_sequence< | |
394 | ConstBufferSequence>::value, | |
395 | "ConstBufferSequence requirements not met"); | |
11fdf7f2 | 396 | static_assert(detail::is_response_decorator< |
b32b8144 FG |
397 | ResponseDecorator>::value, |
398 | "ResponseDecorator requirements not met"); | |
399 | error_code ec; | |
400 | accept_ex(buffers, decorator, ec); | |
401 | if(ec) | |
402 | BOOST_THROW_EXCEPTION(system_error{ec}); | |
403 | } | |
404 | ||
11fdf7f2 | 405 | template<class NextLayer, bool deflateSupported> |
b32b8144 FG |
406 | template<class ConstBufferSequence> |
407 | typename std::enable_if<! http::detail::is_header< | |
408 | ConstBufferSequence>::value>::type | |
11fdf7f2 | 409 | stream<NextLayer, deflateSupported>:: |
b32b8144 FG |
410 | accept( |
411 | ConstBufferSequence const& buffers, error_code& ec) | |
412 | { | |
413 | static_assert(is_sync_stream<next_layer_type>::value, | |
414 | "SyncStream requirements not met"); | |
415 | static_assert(boost::asio::is_const_buffer_sequence< | |
416 | ConstBufferSequence>::value, | |
417 | "ConstBufferSequence requirements not met"); | |
418 | using boost::asio::buffer_copy; | |
419 | using boost::asio::buffer_size; | |
420 | reset(); | |
421 | boost::optional<typename | |
422 | static_buffer_base::mutable_buffers_type> mb; | |
423 | try | |
424 | { | |
425 | mb.emplace(rd_buf_.prepare( | |
426 | buffer_size(buffers))); | |
427 | } | |
428 | catch(std::length_error const&) | |
429 | { | |
430 | ec = error::buffer_overflow; | |
431 | return; | |
432 | } | |
433 | rd_buf_.commit( | |
434 | buffer_copy(*mb, buffers)); | |
435 | do_accept(&default_decorate_res, ec); | |
436 | } | |
437 | ||
11fdf7f2 | 438 | template<class NextLayer, bool deflateSupported> |
b32b8144 FG |
439 | template< |
440 | class ConstBufferSequence, | |
441 | class ResponseDecorator> | |
442 | typename std::enable_if<! http::detail::is_header< | |
443 | ConstBufferSequence>::value>::type | |
11fdf7f2 | 444 | stream<NextLayer, deflateSupported>:: |
b32b8144 FG |
445 | accept_ex( |
446 | ConstBufferSequence const& buffers, | |
447 | ResponseDecorator const& decorator, | |
448 | error_code& ec) | |
449 | { | |
450 | static_assert(is_sync_stream<next_layer_type>::value, | |
451 | "SyncStream requirements not met"); | |
452 | static_assert(boost::asio::is_const_buffer_sequence< | |
453 | ConstBufferSequence>::value, | |
454 | "ConstBufferSequence requirements not met"); | |
455 | static_assert(boost::asio::is_const_buffer_sequence< | |
456 | ConstBufferSequence>::value, | |
457 | "ConstBufferSequence requirements not met"); | |
458 | using boost::asio::buffer_copy; | |
459 | using boost::asio::buffer_size; | |
460 | reset(); | |
461 | boost::optional<typename | |
462 | static_buffer_base::mutable_buffers_type> mb; | |
463 | try | |
464 | { | |
465 | mb.emplace(rd_buf_.prepare( | |
466 | buffer_size(buffers))); | |
467 | } | |
468 | catch(std::length_error const&) | |
469 | { | |
470 | ec = error::buffer_overflow; | |
471 | return; | |
472 | } | |
473 | rd_buf_.commit(buffer_copy(*mb, buffers)); | |
474 | do_accept(decorator, ec); | |
475 | } | |
476 | ||
11fdf7f2 | 477 | template<class NextLayer, bool deflateSupported> |
b32b8144 FG |
478 | template<class Body, class Allocator> |
479 | void | |
11fdf7f2 | 480 | stream<NextLayer, deflateSupported>:: |
b32b8144 FG |
481 | accept( |
482 | http::request<Body, | |
483 | http::basic_fields<Allocator>> const& req) | |
484 | { | |
485 | static_assert(is_sync_stream<next_layer_type>::value, | |
486 | "SyncStream requirements not met"); | |
487 | error_code ec; | |
488 | accept(req, ec); | |
489 | if(ec) | |
490 | BOOST_THROW_EXCEPTION(system_error{ec}); | |
491 | } | |
492 | ||
11fdf7f2 | 493 | template<class NextLayer, bool deflateSupported> |
b32b8144 FG |
494 | template< |
495 | class Body, class Allocator, | |
496 | class ResponseDecorator> | |
497 | void | |
11fdf7f2 | 498 | stream<NextLayer, deflateSupported>:: |
b32b8144 FG |
499 | accept_ex( |
500 | http::request<Body, | |
501 | http::basic_fields<Allocator>> const& req, | |
502 | ResponseDecorator const& decorator) | |
503 | { | |
504 | static_assert(is_sync_stream<next_layer_type>::value, | |
505 | "SyncStream requirements not met"); | |
11fdf7f2 | 506 | static_assert(detail::is_response_decorator< |
b32b8144 FG |
507 | ResponseDecorator>::value, |
508 | "ResponseDecorator requirements not met"); | |
509 | error_code ec; | |
510 | accept_ex(req, decorator, ec); | |
511 | if(ec) | |
512 | BOOST_THROW_EXCEPTION(system_error{ec}); | |
513 | } | |
514 | ||
11fdf7f2 | 515 | template<class NextLayer, bool deflateSupported> |
b32b8144 FG |
516 | template<class Body, class Allocator> |
517 | void | |
11fdf7f2 | 518 | stream<NextLayer, deflateSupported>:: |
b32b8144 FG |
519 | accept( |
520 | http::request<Body, | |
521 | http::basic_fields<Allocator>> const& req, | |
522 | error_code& ec) | |
523 | { | |
524 | static_assert(is_sync_stream<next_layer_type>::value, | |
525 | "SyncStream requirements not met"); | |
526 | reset(); | |
527 | do_accept(req, &default_decorate_res, ec); | |
528 | } | |
529 | ||
11fdf7f2 | 530 | template<class NextLayer, bool deflateSupported> |
b32b8144 FG |
531 | template< |
532 | class Body, class Allocator, | |
533 | class ResponseDecorator> | |
534 | void | |
11fdf7f2 | 535 | stream<NextLayer, deflateSupported>:: |
b32b8144 FG |
536 | accept_ex( |
537 | http::request<Body, | |
538 | http::basic_fields<Allocator>> const& req, | |
539 | ResponseDecorator const& decorator, | |
540 | error_code& ec) | |
541 | { | |
542 | static_assert(is_sync_stream<next_layer_type>::value, | |
543 | "SyncStream requirements not met"); | |
11fdf7f2 | 544 | static_assert(detail::is_response_decorator< |
b32b8144 FG |
545 | ResponseDecorator>::value, |
546 | "ResponseDecorator requirements not met"); | |
547 | reset(); | |
548 | do_accept(req, decorator, ec); | |
549 | } | |
550 | ||
551 | //------------------------------------------------------------------------------ | |
552 | ||
11fdf7f2 | 553 | template<class NextLayer, bool deflateSupported> |
b32b8144 FG |
554 | template< |
555 | class AcceptHandler> | |
556 | BOOST_ASIO_INITFN_RESULT_TYPE( | |
557 | AcceptHandler, void(error_code)) | |
11fdf7f2 | 558 | stream<NextLayer, deflateSupported>:: |
b32b8144 FG |
559 | async_accept( |
560 | AcceptHandler&& handler) | |
561 | { | |
562 | static_assert(is_async_stream<next_layer_type>::value, | |
11fdf7f2 TL |
563 | "AsyncStream requirements not met"); |
564 | BOOST_BEAST_HANDLER_INIT( | |
565 | AcceptHandler, void(error_code)); | |
b32b8144 FG |
566 | reset(); |
567 | accept_op< | |
568 | decltype(&default_decorate_res), | |
569 | BOOST_ASIO_HANDLER_TYPE( | |
570 | AcceptHandler, void(error_code))>{ | |
11fdf7f2 | 571 | std::move(init.completion_handler), |
b32b8144 FG |
572 | *this, |
573 | &default_decorate_res}({}); | |
574 | return init.result.get(); | |
575 | } | |
576 | ||
11fdf7f2 | 577 | template<class NextLayer, bool deflateSupported> |
b32b8144 FG |
578 | template< |
579 | class ResponseDecorator, | |
580 | class AcceptHandler> | |
581 | BOOST_ASIO_INITFN_RESULT_TYPE( | |
582 | AcceptHandler, void(error_code)) | |
11fdf7f2 | 583 | stream<NextLayer, deflateSupported>:: |
b32b8144 FG |
584 | async_accept_ex( |
585 | ResponseDecorator const& decorator, | |
586 | AcceptHandler&& handler) | |
587 | { | |
588 | static_assert(is_async_stream<next_layer_type>::value, | |
11fdf7f2 TL |
589 | "AsyncStream requirements not met"); |
590 | static_assert(detail::is_response_decorator< | |
b32b8144 FG |
591 | ResponseDecorator>::value, |
592 | "ResponseDecorator requirements not met"); | |
11fdf7f2 TL |
593 | BOOST_BEAST_HANDLER_INIT( |
594 | AcceptHandler, void(error_code)); | |
b32b8144 FG |
595 | reset(); |
596 | accept_op< | |
597 | ResponseDecorator, | |
598 | BOOST_ASIO_HANDLER_TYPE( | |
599 | AcceptHandler, void(error_code))>{ | |
11fdf7f2 | 600 | std::move(init.completion_handler), |
b32b8144 FG |
601 | *this, |
602 | decorator}({}); | |
603 | return init.result.get(); | |
604 | } | |
605 | ||
11fdf7f2 | 606 | template<class NextLayer, bool deflateSupported> |
b32b8144 FG |
607 | template< |
608 | class ConstBufferSequence, | |
609 | class AcceptHandler> | |
610 | typename std::enable_if< | |
611 | ! http::detail::is_header<ConstBufferSequence>::value, | |
612 | BOOST_ASIO_INITFN_RESULT_TYPE( | |
613 | AcceptHandler, void(error_code))>::type | |
11fdf7f2 | 614 | stream<NextLayer, deflateSupported>:: |
b32b8144 FG |
615 | async_accept( |
616 | ConstBufferSequence const& buffers, | |
617 | AcceptHandler&& handler) | |
618 | { | |
619 | static_assert(is_async_stream<next_layer_type>::value, | |
11fdf7f2 | 620 | "AsyncStream requirements not met"); |
b32b8144 FG |
621 | static_assert(boost::asio::is_const_buffer_sequence< |
622 | ConstBufferSequence>::value, | |
623 | "ConstBufferSequence requirements not met"); | |
11fdf7f2 TL |
624 | BOOST_BEAST_HANDLER_INIT( |
625 | AcceptHandler, void(error_code)); | |
b32b8144 FG |
626 | reset(); |
627 | accept_op< | |
628 | decltype(&default_decorate_res), | |
629 | BOOST_ASIO_HANDLER_TYPE( | |
630 | AcceptHandler, void(error_code))>{ | |
11fdf7f2 | 631 | std::move(init.completion_handler), |
b32b8144 FG |
632 | *this, |
633 | &default_decorate_res}.run(buffers); | |
634 | return init.result.get(); | |
635 | } | |
636 | ||
11fdf7f2 | 637 | template<class NextLayer, bool deflateSupported> |
b32b8144 FG |
638 | template< |
639 | class ConstBufferSequence, | |
640 | class ResponseDecorator, | |
641 | class AcceptHandler> | |
642 | typename std::enable_if< | |
643 | ! http::detail::is_header<ConstBufferSequence>::value, | |
644 | BOOST_ASIO_INITFN_RESULT_TYPE( | |
645 | AcceptHandler, void(error_code))>::type | |
11fdf7f2 | 646 | stream<NextLayer, deflateSupported>:: |
b32b8144 FG |
647 | async_accept_ex( |
648 | ConstBufferSequence const& buffers, | |
649 | ResponseDecorator const& decorator, | |
650 | AcceptHandler&& handler) | |
651 | { | |
652 | static_assert(is_async_stream<next_layer_type>::value, | |
11fdf7f2 | 653 | "AsyncStream requirements not met"); |
b32b8144 FG |
654 | static_assert(boost::asio::is_const_buffer_sequence< |
655 | ConstBufferSequence>::value, | |
656 | "ConstBufferSequence requirements not met"); | |
11fdf7f2 | 657 | static_assert(detail::is_response_decorator< |
b32b8144 FG |
658 | ResponseDecorator>::value, |
659 | "ResponseDecorator requirements not met"); | |
11fdf7f2 TL |
660 | BOOST_BEAST_HANDLER_INIT( |
661 | AcceptHandler, void(error_code)); | |
b32b8144 FG |
662 | reset(); |
663 | accept_op< | |
664 | ResponseDecorator, | |
665 | BOOST_ASIO_HANDLER_TYPE( | |
666 | AcceptHandler, void(error_code))>{ | |
11fdf7f2 | 667 | std::move(init.completion_handler), |
b32b8144 FG |
668 | *this, |
669 | decorator}.run(buffers); | |
670 | return init.result.get(); | |
671 | } | |
672 | ||
11fdf7f2 | 673 | template<class NextLayer, bool deflateSupported> |
b32b8144 FG |
674 | template< |
675 | class Body, class Allocator, | |
676 | class AcceptHandler> | |
677 | BOOST_ASIO_INITFN_RESULT_TYPE( | |
678 | AcceptHandler, void(error_code)) | |
11fdf7f2 | 679 | stream<NextLayer, deflateSupported>:: |
b32b8144 FG |
680 | async_accept( |
681 | http::request<Body, http::basic_fields<Allocator>> const& req, | |
682 | AcceptHandler&& handler) | |
683 | { | |
684 | static_assert(is_async_stream<next_layer_type>::value, | |
11fdf7f2 TL |
685 | "AsyncStream requirements not met"); |
686 | BOOST_BEAST_HANDLER_INIT( | |
687 | AcceptHandler, void(error_code)); | |
b32b8144 FG |
688 | reset(); |
689 | using boost::asio::asio_handler_is_continuation; | |
690 | response_op< | |
691 | BOOST_ASIO_HANDLER_TYPE( | |
692 | AcceptHandler, void(error_code))>{ | |
11fdf7f2 | 693 | std::move(init.completion_handler), |
b32b8144 FG |
694 | *this, |
695 | req, | |
696 | &default_decorate_res}(); | |
697 | return init.result.get(); | |
698 | } | |
699 | ||
11fdf7f2 | 700 | template<class NextLayer, bool deflateSupported> |
b32b8144 FG |
701 | template< |
702 | class Body, class Allocator, | |
703 | class ResponseDecorator, | |
704 | class AcceptHandler> | |
705 | BOOST_ASIO_INITFN_RESULT_TYPE( | |
706 | AcceptHandler, void(error_code)) | |
11fdf7f2 | 707 | stream<NextLayer, deflateSupported>:: |
b32b8144 FG |
708 | async_accept_ex( |
709 | http::request<Body, http::basic_fields<Allocator>> const& req, | |
710 | ResponseDecorator const& decorator, | |
711 | AcceptHandler&& handler) | |
712 | { | |
713 | static_assert(is_async_stream<next_layer_type>::value, | |
11fdf7f2 TL |
714 | "AsyncStream requirements not met"); |
715 | static_assert(detail::is_response_decorator< | |
b32b8144 FG |
716 | ResponseDecorator>::value, |
717 | "ResponseDecorator requirements not met"); | |
11fdf7f2 TL |
718 | BOOST_BEAST_HANDLER_INIT( |
719 | AcceptHandler, void(error_code)); | |
b32b8144 FG |
720 | reset(); |
721 | using boost::asio::asio_handler_is_continuation; | |
722 | response_op< | |
723 | BOOST_ASIO_HANDLER_TYPE( | |
724 | AcceptHandler, void(error_code))>{ | |
11fdf7f2 | 725 | std::move(init.completion_handler), |
b32b8144 FG |
726 | *this, |
727 | req, | |
728 | decorator}(); | |
729 | return init.result.get(); | |
730 | } | |
731 | ||
732 | //------------------------------------------------------------------------------ | |
733 | ||
11fdf7f2 | 734 | template<class NextLayer, bool deflateSupported> |
b32b8144 FG |
735 | template<class Decorator> |
736 | void | |
11fdf7f2 | 737 | stream<NextLayer, deflateSupported>:: |
b32b8144 FG |
738 | do_accept( |
739 | Decorator const& decorator, | |
740 | error_code& ec) | |
741 | { | |
742 | http::request_parser<http::empty_body> p; | |
743 | http::read(next_layer(), rd_buf_, p, ec); | |
744 | if(ec == http::error::end_of_stream) | |
745 | ec = error::closed; | |
746 | if(ec) | |
747 | return; | |
748 | do_accept(p.get(), decorator, ec); | |
749 | } | |
750 | ||
11fdf7f2 | 751 | template<class NextLayer, bool deflateSupported> |
b32b8144 FG |
752 | template<class Body, class Allocator, |
753 | class Decorator> | |
754 | void | |
11fdf7f2 | 755 | stream<NextLayer, deflateSupported>:: |
b32b8144 | 756 | do_accept( |
11fdf7f2 TL |
757 | http::request<Body, |
758 | http::basic_fields<Allocator>> const& req, | |
b32b8144 FG |
759 | Decorator const& decorator, |
760 | error_code& ec) | |
761 | { | |
11fdf7f2 TL |
762 | error_code result; |
763 | auto const res = build_response(req, decorator, result); | |
b32b8144 FG |
764 | http::write(stream_, res, ec); |
765 | if(ec) | |
766 | return; | |
11fdf7f2 TL |
767 | ec = result; |
768 | if(ec) | |
b32b8144 | 769 | { |
b32b8144 FG |
770 | // VFALCO TODO Respect keep alive setting, perform |
771 | // teardown if Connection: close. | |
772 | return; | |
773 | } | |
11fdf7f2 | 774 | do_pmd_config(res, is_deflate_supported{}); |
b32b8144 FG |
775 | open(role_type::server); |
776 | } | |
777 | ||
778 | } // websocket | |
779 | } // beast | |
780 | } // boost | |
781 | ||
782 | #endif |