Imported Upstream version 1.72.0
[platform/upstream/boost.git] / boost / beast / websocket / impl / accept.hpp
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_WEBSOCKET_IMPL_ACCEPT_IPP
11 #define BOOST_BEAST_WEBSOCKET_IMPL_ACCEPT_IPP
12
13 #include <boost/beast/websocket/impl/stream_impl.hpp>
14 #include <boost/beast/websocket/detail/type_traits.hpp>
15 #include <boost/beast/http/empty_body.hpp>
16 #include <boost/beast/http/parser.hpp>
17 #include <boost/beast/http/read.hpp>
18 #include <boost/beast/http/string_body.hpp>
19 #include <boost/beast/http/write.hpp>
20 #include <boost/beast/core/async_base.hpp>
21 #include <boost/beast/core/buffer_traits.hpp>
22 #include <boost/beast/core/stream_traits.hpp>
23 #include <boost/beast/core/detail/buffer.hpp>
24 #include <boost/beast/version.hpp>
25 #include <boost/asio/coroutine.hpp>
26 #include <boost/asio/post.hpp>
27 #include <boost/assert.hpp>
28 #include <boost/throw_exception.hpp>
29 #include <memory>
30 #include <type_traits>
31
32 namespace boost {
33 namespace beast {
34 namespace websocket {
35
36 //------------------------------------------------------------------------------
37
38 namespace detail {
39
40 template<class Body, class Allocator>
41 void
42 impl_base<true>::
43 build_response_pmd(
44     http::response<http::string_body>& res,
45     http::request<Body,
46         http::basic_fields<Allocator>> const& req)
47 {
48     pmd_offer offer;
49     pmd_offer unused;
50     pmd_read(offer, req);
51     pmd_negotiate(res, unused, offer, pmd_opts_);
52 }
53
54 template<class Body, class Allocator>
55 void
56 impl_base<false>::
57 build_response_pmd(
58     http::response<http::string_body>&,
59     http::request<Body,
60         http::basic_fields<Allocator>> const&)
61 {
62 }
63
64 } // detail
65
66 template<class NextLayer, bool deflateSupported>
67 template<class Body, class Allocator, class Decorator>
68 response_type
69 stream<NextLayer, deflateSupported>::impl_type::
70 build_response(
71     http::request<Body,
72         http::basic_fields<Allocator>> const& req,
73     Decorator const& decorator,
74     error_code& result)
75 {
76     auto const decorate =
77         [this, &decorator](response_type& res)
78         {
79             decorator_opt(res);
80             decorator(res);
81             if(! res.count(http::field::server))
82                 res.set(http::field::server,
83                     string_view(BOOST_BEAST_VERSION_STRING));
84         };
85     auto err =
86         [&](error e)
87         {
88             result = e;
89             response_type res;
90             res.version(req.version());
91             res.result(http::status::bad_request);
92             res.body() = result.message();
93             res.prepare_payload();
94             decorate(res);
95             return res;
96         };
97     if(req.version() != 11)
98         return err(error::bad_http_version);
99     if(req.method() != http::verb::get)
100         return err(error::bad_method);
101     if(! req.count(http::field::host))
102         return err(error::no_host);
103     {
104         auto const it = req.find(http::field::connection);
105         if(it == req.end())
106             return err(error::no_connection);
107         if(! http::token_list{it->value()}.exists("upgrade"))
108             return err(error::no_connection_upgrade);
109     }
110     {
111         auto const it = req.find(http::field::upgrade);
112         if(it == req.end())
113             return err(error::no_upgrade);
114         if(! http::token_list{it->value()}.exists("websocket"))
115             return err(error::no_upgrade_websocket);
116     }
117     string_view key;
118     {
119         auto const it = req.find(http::field::sec_websocket_key);
120         if(it == req.end())
121             return err(error::no_sec_key);
122         key = it->value();
123         if(key.size() > detail::sec_ws_key_type::max_size_n)
124             return err(error::bad_sec_key);
125     }
126     {
127         auto const it = req.find(http::field::sec_websocket_version);
128         if(it == req.end())
129             return err(error::no_sec_version);
130         if(it->value() != "13")
131         {
132             response_type res;
133             res.result(http::status::upgrade_required);
134             res.version(req.version());
135             res.set(http::field::sec_websocket_version, "13");
136             result = error::bad_sec_version;
137             res.body() = result.message();
138             res.prepare_payload();
139             decorate(res);
140             return res;
141         }
142     }
143
144     response_type res;
145     res.result(http::status::switching_protocols);
146     res.version(req.version());
147     res.set(http::field::upgrade, "websocket");
148     res.set(http::field::connection, "upgrade");
149     {
150         detail::sec_ws_accept_type acc;
151         detail::make_sec_ws_accept(acc, key);
152         res.set(http::field::sec_websocket_accept, acc);
153     }
154     this->build_response_pmd(res, req);
155     decorate(res);
156     result = {};
157     return res;
158 }
159
160 //------------------------------------------------------------------------------
161
162 /** Respond to an HTTP request
163 */
164 template<class NextLayer, bool deflateSupported>
165 template<class Handler>
166 class stream<NextLayer, deflateSupported>::response_op
167     : public beast::stable_async_base<
168         Handler, beast::executor_type<stream>>
169     , public asio::coroutine
170 {
171     boost::weak_ptr<impl_type> wp_;
172     error_code result_; // must come before res_
173     response_type& res_;
174
175 public:
176     template<
177         class Handler_,
178         class Body, class Allocator,
179         class Decorator>
180     response_op(
181         Handler_&& h,
182         boost::shared_ptr<impl_type> const& sp,
183         http::request<Body,
184             http::basic_fields<Allocator>> const& req,
185         Decorator const& decorator,
186         bool cont = false)
187         : stable_async_base<Handler,
188             beast::executor_type<stream>>(
189                 std::forward<Handler_>(h),
190                     sp->stream().get_executor())
191         , wp_(sp)
192         , res_(beast::allocate_stable<response_type>(*this,
193             sp->build_response(req, decorator, result_)))
194     {
195         (*this)({}, 0, cont);
196     }
197
198     void operator()(
199         error_code ec = {},
200         std::size_t bytes_transferred = 0,
201         bool cont = true)
202     {
203         boost::ignore_unused(bytes_transferred);
204         auto sp = wp_.lock();
205         if(! sp)
206         {
207             ec = net::error::operation_aborted;
208             return this->complete(cont, ec);
209         }
210         auto& impl = *sp;
211         BOOST_ASIO_CORO_REENTER(*this)
212         {
213             impl.change_status(status::handshake);
214             impl.update_timer(this->get_executor());
215
216             // Send response
217             BOOST_ASIO_CORO_YIELD
218             http::async_write(
219                 impl.stream(), res_, std::move(*this));
220             if(impl.check_stop_now(ec))
221                 goto upcall;
222             if(! ec)
223                 ec = result_;
224             if(! ec)
225             {
226                 impl.do_pmd_config(res_);
227                 impl.open(role_type::server);
228             }
229         upcall:
230             this->complete(cont, ec);
231         }
232     }
233 };
234
235 //------------------------------------------------------------------------------
236
237 // read and respond to an upgrade request
238 //
239 template<class NextLayer, bool deflateSupported>
240 template<class Handler, class Decorator>
241 class stream<NextLayer, deflateSupported>::accept_op
242     : public beast::stable_async_base<
243         Handler, beast::executor_type<stream>>
244     , public asio::coroutine
245 {
246     boost::weak_ptr<impl_type> wp_;
247     http::request_parser<http::empty_body>& p_;
248     Decorator d_;
249
250 public:
251     template<class Handler_, class Buffers>
252     accept_op(
253         Handler_&& h,
254         boost::shared_ptr<impl_type> const& sp,
255         Decorator const& decorator,
256         Buffers const& buffers)
257         : stable_async_base<Handler,
258             beast::executor_type<stream>>(
259                 std::forward<Handler_>(h),
260                     sp->stream().get_executor())
261         , wp_(sp)
262         , p_(beast::allocate_stable<
263             http::request_parser<http::empty_body>>(*this))
264         , d_(decorator)
265     {
266         auto& impl = *sp;
267         error_code ec;
268         auto const mb =
269             beast::detail::dynamic_buffer_prepare(
270             impl.rd_buf, buffer_bytes(buffers),
271                 ec, error::buffer_overflow);
272         if(! ec)
273             impl.rd_buf.commit(
274                 net::buffer_copy(*mb, buffers));
275         (*this)(ec);
276     }
277
278     void operator()(
279         error_code ec = {},
280         std::size_t bytes_transferred = 0,
281         bool cont = true)
282     {
283         boost::ignore_unused(bytes_transferred);
284         auto sp = wp_.lock();
285         if(! sp)
286         {
287             ec = net::error::operation_aborted;
288             return this->complete(cont, ec);
289         }
290         auto& impl = *sp;
291         BOOST_ASIO_CORO_REENTER(*this)
292         {
293             impl.change_status(status::handshake);
294             impl.update_timer(this->get_executor());
295
296             // The constructor could have set ec
297             if(ec)
298                 goto upcall;
299
300             BOOST_ASIO_CORO_YIELD
301             http::async_read(impl.stream(),
302                 impl.rd_buf, p_, std::move(*this));
303             if(ec == http::error::end_of_stream)
304                 ec = error::closed;
305             if(impl.check_stop_now(ec))
306                 goto upcall;
307
308             {
309                 // Arguments from our state must be
310                 // moved to the stack before releasing
311                 // the handler.
312                 auto const req = p_.release();
313                 auto const decorator = d_;
314                 response_op<Handler>(
315                     this->release_handler(),
316                         sp, req, decorator, true);
317                 return;
318             }
319
320         upcall:
321             this->complete(cont, ec);
322         }
323     }
324 };
325
326 template<class NextLayer, bool deflateSupported>
327 struct stream<NextLayer, deflateSupported>::
328     run_response_op
329 {
330     template<
331         class AcceptHandler,
332         class Body, class Allocator,
333         class Decorator>
334     void
335     operator()(
336         AcceptHandler&& h,
337         boost::shared_ptr<impl_type> const& sp,
338         http::request<Body,
339             http::basic_fields<Allocator>> const* m,
340         Decorator const& d)
341     {
342         // If you get an error on the following line it means
343         // that your handler does not meet the documented type
344         // requirements for the handler.
345
346         static_assert(
347             beast::detail::is_invocable<AcceptHandler,
348                 void(error_code)>::value,
349             "AcceptHandler type requirements not met");
350
351         response_op<
352             typename std::decay<AcceptHandler>::type>(
353                 std::forward<AcceptHandler>(h), sp, *m, d);
354     }
355 };
356
357 template<class NextLayer, bool deflateSupported>
358 struct stream<NextLayer, deflateSupported>::
359     run_accept_op
360 {
361     template<
362         class AcceptHandler,
363         class Decorator,
364         class Buffers>
365     void
366     operator()(
367         AcceptHandler&& h,
368         boost::shared_ptr<impl_type> const& sp,
369         Decorator const& d,
370         Buffers const& b)
371     {
372         // If you get an error on the following line it means
373         // that your handler does not meet the documented type
374         // requirements for the handler.
375
376         static_assert(
377             beast::detail::is_invocable<AcceptHandler,
378                 void(error_code)>::value,
379             "AcceptHandler type requirements not met");
380
381         accept_op<
382             typename std::decay<AcceptHandler>::type,
383             Decorator>(
384                 std::forward<AcceptHandler>(h),
385                 sp,
386                 d,
387                 b);
388     }
389 };
390
391 //------------------------------------------------------------------------------
392
393 template<class NextLayer, bool deflateSupported>
394 template<class Body, class Allocator,
395     class Decorator>
396 void
397 stream<NextLayer, deflateSupported>::
398 do_accept(
399     http::request<Body,
400         http::basic_fields<Allocator>> const& req,
401     Decorator const& decorator,
402     error_code& ec)
403 {
404     impl_->change_status(status::handshake);
405
406     error_code result;
407     auto const res = impl_->build_response(req, decorator, result);
408     http::write(impl_->stream(), res, ec);
409     if(ec)
410         return;
411     ec = result;
412     if(ec)
413     {
414         // VFALCO TODO Respect keep alive setting, perform
415         //             teardown if Connection: close.
416         return;
417     }
418     impl_->do_pmd_config(res);
419     impl_->open(role_type::server);
420 }
421
422 template<class NextLayer, bool deflateSupported>
423 template<class Buffers, class Decorator>
424 void
425 stream<NextLayer, deflateSupported>::
426 do_accept(
427     Buffers const& buffers,
428     Decorator const& decorator,
429     error_code& ec)
430 {
431     impl_->reset();
432     auto const mb =
433         beast::detail::dynamic_buffer_prepare(
434         impl_->rd_buf, buffer_bytes(buffers), ec,
435             error::buffer_overflow);
436     if(ec)
437         return;
438     impl_->rd_buf.commit(net::buffer_copy(*mb, buffers));
439
440     http::request_parser<http::empty_body> p;
441     http::read(next_layer(), impl_->rd_buf, p, ec);
442     if(ec == http::error::end_of_stream)
443         ec = error::closed;
444     if(ec)
445         return;
446     do_accept(p.get(), decorator, ec);
447 }
448
449 //------------------------------------------------------------------------------
450
451 template<class NextLayer, bool deflateSupported>
452 void
453 stream<NextLayer, deflateSupported>::
454 accept()
455 {
456     static_assert(is_sync_stream<next_layer_type>::value,
457         "SyncStream type requirements not met");
458     error_code ec;
459     accept(ec);
460     if(ec)
461         BOOST_THROW_EXCEPTION(system_error{ec});
462 }
463
464 template<class NextLayer, bool deflateSupported>
465 void
466 stream<NextLayer, deflateSupported>::
467 accept(error_code& ec)
468 {
469     static_assert(is_sync_stream<next_layer_type>::value,
470         "SyncStream type requirements not met");
471     do_accept(
472         net::const_buffer{},
473         &default_decorate_res, ec);
474 }
475
476 template<class NextLayer, bool deflateSupported>
477 template<class ConstBufferSequence>
478 typename std::enable_if<! http::detail::is_header<
479     ConstBufferSequence>::value>::type
480 stream<NextLayer, deflateSupported>::
481 accept(ConstBufferSequence const& buffers)
482 {
483     static_assert(is_sync_stream<next_layer_type>::value,
484         "SyncStream type requirements not met");
485     static_assert(net::is_const_buffer_sequence<
486         ConstBufferSequence>::value,
487             "ConstBufferSequence type requirements not met");
488     error_code ec;
489     accept(buffers, ec);
490     if(ec)
491         BOOST_THROW_EXCEPTION(system_error{ec});
492 }
493 template<class NextLayer, bool deflateSupported>
494 template<class ConstBufferSequence>
495 typename std::enable_if<! http::detail::is_header<
496     ConstBufferSequence>::value>::type
497 stream<NextLayer, deflateSupported>::
498 accept(
499     ConstBufferSequence const& buffers, error_code& ec)
500 {
501     static_assert(is_sync_stream<next_layer_type>::value,
502         "SyncStream type requirements not met");
503     static_assert(net::is_const_buffer_sequence<
504         ConstBufferSequence>::value,
505             "ConstBufferSequence type requirements not met");
506     do_accept(buffers, &default_decorate_res, ec);
507 }
508
509
510 template<class NextLayer, bool deflateSupported>
511 template<class Body, class Allocator>
512 void
513 stream<NextLayer, deflateSupported>::
514 accept(
515     http::request<Body,
516         http::basic_fields<Allocator>> const& req)
517 {
518     static_assert(is_sync_stream<next_layer_type>::value,
519         "SyncStream type requirements not met");
520     error_code ec;
521     accept(req, ec);
522     if(ec)
523         BOOST_THROW_EXCEPTION(system_error{ec});
524 }
525
526 template<class NextLayer, bool deflateSupported>
527 template<class Body, class Allocator>
528 void
529 stream<NextLayer, deflateSupported>::
530 accept(
531     http::request<Body,
532         http::basic_fields<Allocator>> const& req,
533     error_code& ec)
534 {
535     static_assert(is_sync_stream<next_layer_type>::value,
536         "SyncStream type requirements not met");
537     impl_->reset();
538     do_accept(req, &default_decorate_res, ec);
539 }
540
541 //------------------------------------------------------------------------------
542
543 template<class NextLayer, bool deflateSupported>
544 template<
545     class AcceptHandler>
546 BOOST_BEAST_ASYNC_RESULT1(AcceptHandler)
547 stream<NextLayer, deflateSupported>::
548 async_accept(
549     AcceptHandler&& handler)
550 {
551     static_assert(is_async_stream<next_layer_type>::value,
552         "AsyncStream type requirements not met");
553     impl_->reset();
554     return net::async_initiate<
555         AcceptHandler,
556         void(error_code)>(
557             run_accept_op{},
558             handler,
559             impl_,
560             &default_decorate_res,
561             net::const_buffer{});
562 }
563
564 template<class NextLayer, bool deflateSupported>
565 template<
566     class ResponseDecorator,
567     class AcceptHandler>
568 BOOST_BEAST_ASYNC_RESULT1(AcceptHandler)
569 stream<NextLayer, deflateSupported>::
570 async_accept_ex(
571     ResponseDecorator const& decorator,
572     AcceptHandler&& handler)
573 {
574     static_assert(is_async_stream<next_layer_type>::value,
575         "AsyncStream type requirements not met");
576     static_assert(detail::is_response_decorator<
577         ResponseDecorator>::value,
578             "ResponseDecorator requirements not met");
579     impl_->reset();
580     return net::async_initiate<
581         AcceptHandler,
582         void(error_code)>(
583             run_accept_op{},
584             handler,
585             impl_,
586             decorator,
587             net::const_buffer{});
588 }
589
590 template<class NextLayer, bool deflateSupported>
591 template<
592     class ConstBufferSequence,
593     class AcceptHandler>
594 BOOST_BEAST_ASYNC_RESULT1(AcceptHandler)
595 stream<NextLayer, deflateSupported>::
596 async_accept(
597     ConstBufferSequence const& buffers,
598     AcceptHandler&& handler,
599     typename std::enable_if<
600         ! http::detail::is_header<
601         ConstBufferSequence>::value>::type*
602 )
603 {
604     static_assert(is_async_stream<next_layer_type>::value,
605         "AsyncStream type requirements not met");
606     static_assert(net::is_const_buffer_sequence<
607         ConstBufferSequence>::value,
608             "ConstBufferSequence type requirements not met");
609     impl_->reset();
610     return net::async_initiate<
611         AcceptHandler,
612         void(error_code)>(
613             run_accept_op{},
614             handler,
615             impl_,
616             &default_decorate_res,
617             buffers);
618 }
619
620 template<class NextLayer, bool deflateSupported>
621 template<
622     class ConstBufferSequence,
623     class ResponseDecorator,
624     class AcceptHandler>
625 BOOST_BEAST_ASYNC_RESULT1(AcceptHandler)
626 stream<NextLayer, deflateSupported>::
627 async_accept_ex(
628     ConstBufferSequence const& buffers,
629     ResponseDecorator const& decorator,
630     AcceptHandler&& handler,
631     typename std::enable_if<
632         ! http::detail::is_header<
633         ConstBufferSequence>::value>::type*)
634 {
635     static_assert(is_async_stream<next_layer_type>::value,
636         "AsyncStream type requirements not met");
637     static_assert(net::is_const_buffer_sequence<
638         ConstBufferSequence>::value,
639             "ConstBufferSequence type requirements not met");
640     static_assert(detail::is_response_decorator<
641         ResponseDecorator>::value,
642             "ResponseDecorator requirements not met");
643     impl_->reset();
644     return net::async_initiate<
645         AcceptHandler,
646         void(error_code)>(
647             run_accept_op{},
648             handler,
649             impl_,
650             decorator,
651             buffers);
652 }
653
654 template<class NextLayer, bool deflateSupported>
655 template<
656     class Body, class Allocator,
657     class AcceptHandler>
658 BOOST_BEAST_ASYNC_RESULT1(AcceptHandler)
659 stream<NextLayer, deflateSupported>::
660 async_accept(
661     http::request<Body, http::basic_fields<Allocator>> const& req,
662     AcceptHandler&& handler)
663 {
664     static_assert(is_async_stream<next_layer_type>::value,
665         "AsyncStream type requirements not met");
666     impl_->reset();
667     return net::async_initiate<
668         AcceptHandler,
669         void(error_code)>(
670             run_response_op{},
671             handler,
672             impl_,
673             &req,
674             &default_decorate_res);
675 }
676
677 template<class NextLayer, bool deflateSupported>
678 template<
679     class Body, class Allocator,
680     class ResponseDecorator,
681     class AcceptHandler>
682 BOOST_BEAST_ASYNC_RESULT1(AcceptHandler)
683 stream<NextLayer, deflateSupported>::
684 async_accept_ex(
685     http::request<Body, http::basic_fields<Allocator>> const& req,
686     ResponseDecorator const& decorator,
687     AcceptHandler&& handler)
688 {
689     static_assert(is_async_stream<next_layer_type>::value,
690         "AsyncStream type requirements not met");
691     static_assert(detail::is_response_decorator<
692         ResponseDecorator>::value,
693             "ResponseDecorator requirements not met");
694     impl_->reset();
695     return net::async_initiate<
696         AcceptHandler,
697         void(error_code)>(
698             run_response_op{},
699             handler,
700             impl_,
701             &req,
702             decorator);
703 }
704
705 //------------------------------------------------------------------------------
706
707 template<class NextLayer, bool deflateSupported>
708 template<class ResponseDecorator>
709 void
710 stream<NextLayer, deflateSupported>::
711 accept_ex(ResponseDecorator const& decorator)
712 {
713 #ifndef BOOST_BEAST_ALLOW_DEPRECATED
714     static_assert(sizeof(ResponseDecorator) == 0,
715         BOOST_BEAST_DEPRECATION_STRING);
716 #endif
717     static_assert(is_sync_stream<next_layer_type>::value,
718         "SyncStream type requirements not met");
719     static_assert(detail::is_response_decorator<
720         ResponseDecorator>::value,
721             "ResponseDecorator requirements not met");
722     error_code ec;
723     accept_ex(decorator, ec);
724     if(ec)
725         BOOST_THROW_EXCEPTION(system_error{ec});
726 }
727
728 template<class NextLayer, bool deflateSupported>
729 template<class ResponseDecorator>
730 void
731 stream<NextLayer, deflateSupported>::
732 accept_ex(ResponseDecorator const& decorator, error_code& ec)
733 {
734 #ifndef BOOST_BEAST_ALLOW_DEPRECATED
735     static_assert(sizeof(ResponseDecorator) == 0,
736         BOOST_BEAST_DEPRECATION_STRING);
737 #endif
738     static_assert(is_sync_stream<next_layer_type>::value,
739         "SyncStream type requirements not met");
740     static_assert(detail::is_response_decorator<
741         ResponseDecorator>::value,
742             "ResponseDecorator requirements not met");
743     do_accept(
744         net::const_buffer{},
745         decorator, ec);
746 }
747
748 template<class NextLayer, bool deflateSupported>
749 template<
750     class ConstBufferSequence,
751     class ResponseDecorator>
752 typename std::enable_if<! http::detail::is_header<
753     ConstBufferSequence>::value>::type
754 stream<NextLayer, deflateSupported>::
755 accept_ex(
756     ConstBufferSequence const& buffers,
757     ResponseDecorator const &decorator)
758 {
759 #ifndef BOOST_BEAST_ALLOW_DEPRECATED
760     static_assert(sizeof(ResponseDecorator) == 0,
761         BOOST_BEAST_DEPRECATION_STRING);
762 #endif
763     static_assert(is_sync_stream<next_layer_type>::value,
764         "SyncStream type requirements not met");
765     static_assert(net::is_const_buffer_sequence<
766         ConstBufferSequence>::value,
767             "ConstBufferSequence type requirements not met");
768     static_assert(detail::is_response_decorator<
769         ResponseDecorator>::value,
770             "ResponseDecorator requirements not met");
771     error_code ec;
772     accept_ex(buffers, decorator, ec);
773     if(ec)
774         BOOST_THROW_EXCEPTION(system_error{ec});
775 }
776
777 template<class NextLayer, bool deflateSupported>
778 template<
779     class ConstBufferSequence,
780     class ResponseDecorator>
781 typename std::enable_if<! http::detail::is_header<
782     ConstBufferSequence>::value>::type
783 stream<NextLayer, deflateSupported>::
784 accept_ex(
785     ConstBufferSequence const& buffers,
786     ResponseDecorator const& decorator,
787     error_code& ec)
788 {
789 #ifndef BOOST_BEAST_ALLOW_DEPRECATED
790     static_assert(sizeof(ResponseDecorator) == 0,
791         BOOST_BEAST_DEPRECATION_STRING);
792 #endif
793     static_assert(is_sync_stream<next_layer_type>::value,
794         "SyncStream type requirements not met");
795     static_assert(net::is_const_buffer_sequence<
796         ConstBufferSequence>::value,
797             "ConstBufferSequence type requirements not met");
798     static_assert(net::is_const_buffer_sequence<
799         ConstBufferSequence>::value,
800             "ConstBufferSequence type requirements not met");
801     do_accept(buffers, decorator, ec);
802 }
803
804 template<class NextLayer, bool deflateSupported>
805 template<
806     class Body, class Allocator,
807     class ResponseDecorator>
808 void
809 stream<NextLayer, deflateSupported>::
810 accept_ex(
811     http::request<Body,
812         http::basic_fields<Allocator>> const& req,
813     ResponseDecorator const& decorator)
814 {
815 #ifndef BOOST_BEAST_ALLOW_DEPRECATED
816     static_assert(sizeof(ResponseDecorator) == 0,
817         BOOST_BEAST_DEPRECATION_STRING);
818 #endif
819     static_assert(is_sync_stream<next_layer_type>::value,
820         "SyncStream type requirements not met");
821     static_assert(detail::is_response_decorator<
822         ResponseDecorator>::value,
823             "ResponseDecorator requirements not met");
824     error_code ec;
825     accept_ex(req, decorator, ec);
826     if(ec)
827         BOOST_THROW_EXCEPTION(system_error{ec});
828 }
829
830 template<class NextLayer, bool deflateSupported>
831 template<
832     class Body, class Allocator,
833     class ResponseDecorator>
834 void
835 stream<NextLayer, deflateSupported>::
836 accept_ex(
837     http::request<Body,
838         http::basic_fields<Allocator>> const& req,
839     ResponseDecorator const& decorator,
840     error_code& ec)
841 {
842 #ifndef BOOST_BEAST_ALLOW_DEPRECATED
843     static_assert(sizeof(ResponseDecorator) == 0,
844         BOOST_BEAST_DEPRECATION_STRING);
845 #endif
846     static_assert(is_sync_stream<next_layer_type>::value,
847         "SyncStream type requirements not met");
848     static_assert(detail::is_response_decorator<
849         ResponseDecorator>::value,
850             "ResponseDecorator requirements not met");
851     impl_->reset();
852     do_accept(req, decorator, ec);
853 }
854
855 } // websocket
856 } // beast
857 } // boost
858
859 #endif