]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/beast/test/beast/websocket/test.hpp
b4c90d2b738ccedc399bb564161beaae594b6de2
[ceph.git] / ceph / src / boost / libs / beast / test / beast / websocket / test.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 BEAST_TEST_WEBSOCKET_TEST_HPP
11 #define BEAST_TEST_WEBSOCKET_TEST_HPP
12
13 #include <boost/beast/core/bind_handler.hpp>
14 #include <boost/beast/core/buffer_traits.hpp>
15 #include <boost/beast/core/buffers_to_string.hpp>
16 #include <boost/beast/core/ostream.hpp>
17 #include <boost/beast/core/multi_buffer.hpp>
18 #include <boost/beast/websocket/stream.hpp>
19 #include <boost/beast/_experimental/test/stream.hpp>
20 #include <boost/beast/test/yield_to.hpp>
21 #include <boost/beast/_experimental/unit_test/suite.hpp>
22 #include <boost/asio/executor_work_guard.hpp>
23 #include <boost/asio/io_context.hpp>
24 #include <boost/optional.hpp>
25 #include <cstdlib>
26 #include <memory>
27 #include <random>
28 #include <string>
29
30 namespace boost {
31 namespace beast {
32 namespace websocket {
33
34 class websocket_test_suite
35 : public beast::unit_test::suite
36 , public test::enable_yield_to
37 {
38 public:
39 template<bool deflateSupported>
40 using ws_type_t =
41 websocket::stream<test::stream&, deflateSupported>;
42
43 using ws_type =
44 websocket::stream<test::stream&>;
45
46 struct move_only_handler
47 {
48 move_only_handler() = default;
49 move_only_handler(move_only_handler&&) = default;
50 move_only_handler(move_only_handler const&) = delete;
51
52 template<class... Args>
53 void
54 operator()(Args&&...) const
55 {
56 }
57 };
58
59 enum class kind
60 {
61 sync,
62 async,
63 async_client
64 };
65
66 class echo_server
67 {
68 enum
69 {
70 buf_size = 20000
71 };
72
73 std::ostream& log_;
74 net::io_context ioc_;
75 net::executor_work_guard<
76 net::io_context::executor_type> work_;
77 static_buffer<buf_size> buffer_;
78 test::stream ts_;
79 std::thread t_;
80 websocket::stream<test::stream&> ws_;
81 bool close_ = false;
82
83 public:
84 explicit
85 echo_server(
86 std::ostream& log,
87 kind k = kind::sync)
88 : log_(log)
89 , work_(ioc_.get_executor())
90 , ts_(ioc_)
91 , ws_(ts_)
92 {
93 permessage_deflate pmd;
94 pmd.server_enable = true;
95 pmd.server_max_window_bits = 9;
96 pmd.compLevel = 1;
97 ws_.set_option(pmd);
98
99 switch(k)
100 {
101 case kind::sync:
102 t_ = std::thread{[&]{ do_sync(); }};
103 break;
104
105 case kind::async:
106 t_ = std::thread{[&]{ ioc_.run(); }};
107 do_accept();
108 break;
109
110 case kind::async_client:
111 t_ = std::thread{[&]{ ioc_.run(); }};
112 break;
113 }
114 }
115
116 ~echo_server()
117 {
118 work_.reset();
119 t_.join();
120 }
121
122 test::stream&
123 stream()
124 {
125 return ts_;
126 }
127
128 void
129 async_handshake()
130 {
131 ws_.async_handshake("localhost", "/",
132 bind_front_handler(
133 &echo_server::on_handshake,
134 this));
135 }
136
137 void
138 async_close()
139 {
140 net::post(ioc_,
141 [&]
142 {
143 if(ws_.is_open())
144 {
145 ws_.async_close({},
146 bind_front_handler(
147 &echo_server::on_close,
148 this));
149 }
150 else
151 {
152 close_ = true;
153 }
154 });
155 }
156
157 private:
158 void
159 do_sync()
160 {
161 try
162 {
163 ws_.accept();
164 for(;;)
165 {
166 ws_.read(buffer_);
167 ws_.text(ws_.got_text());
168 ws_.write(buffer_.data());
169 buffer_.consume(buffer_.size());
170 }
171 }
172 catch(system_error const& se)
173 {
174 boost::ignore_unused(se);
175 #if 0
176 if( se.code() != error::closed &&
177 se.code() != error::failed &&
178 se.code() != net::error::eof)
179 log_ << "echo_server: " << se.code().message() << std::endl;
180 #endif
181 }
182 catch(std::exception const& e)
183 {
184 log_ << "echo_server: " << e.what() << std::endl;
185 }
186 }
187
188 void
189 do_accept()
190 {
191 ws_.async_accept(
192 bind_front_handler(
193 &echo_server::on_accept,
194 this));
195 }
196
197 void
198 on_handshake(error_code ec)
199 {
200 if(ec)
201 return fail(ec);
202
203 do_read();
204 }
205
206 void
207 on_accept(error_code ec)
208 {
209 if(ec)
210 return fail(ec);
211
212 if(close_)
213 {
214 return ws_.async_close({},
215 bind_front_handler(
216 &echo_server::on_close,
217 this));
218 }
219
220 do_read();
221 }
222
223 void
224 do_read()
225 {
226 ws_.async_read(buffer_,
227 beast::bind_front_handler(
228 &echo_server::on_read,
229 this));
230 }
231
232 void
233 on_read(error_code ec, std::size_t)
234 {
235 if(ec)
236 return fail(ec);
237 ws_.text(ws_.got_text());
238 ws_.async_write(buffer_.data(),
239 beast::bind_front_handler(
240 &echo_server::on_write,
241 this));
242 }
243
244 void
245 on_write(error_code ec, std::size_t)
246 {
247 if(ec)
248 return fail(ec);
249 buffer_.consume(buffer_.size());
250 do_read();
251 }
252
253 void
254 on_close(error_code ec)
255 {
256 if(ec)
257 return fail(ec);
258 }
259
260 void
261 fail(error_code ec)
262 {
263 boost::ignore_unused(ec);
264 #if 0
265 if( ec != error::closed &&
266 ec != error::failed &&
267 ec != net::error::eof)
268 log_ <<
269 "echo_server_async: " <<
270 ec.message() <<
271 std::endl;
272 #endif
273 }
274 };
275
276 template<class Test>
277 void
278 doFailLoop(
279 Test const& f, std::size_t limit = 200)
280 {
281 std::size_t n;
282 for(n = 0; n < limit; ++n)
283 {
284 test::fail_count fc{n};
285 try
286 {
287 f(fc);
288 break;
289 }
290 catch(system_error const& se)
291 {
292 BEAST_EXPECTS(
293 se.code() == test::error::test_failure,
294 se.code().message());
295 }
296 }
297 BEAST_EXPECT(n < limit);
298 }
299
300 template<class Test>
301 void
302 doStreamLoop(Test const& f)
303 {
304 // This number has to be high for the
305 // test that writes the large buffer.
306 static std::size_t constexpr limit = 200;
307
308 doFailLoop(
309 [&](test::fail_count& fc)
310 {
311 test::stream ts{ioc_, fc};
312 f(ts);
313 ts.close();
314 }
315 , limit);
316 }
317
318 template<bool deflateSupported = true, class Test>
319 void
320 doTest(
321 permessage_deflate const& pmd,
322 Test const& f)
323 {
324 // This number has to be high for the
325 // test that writes the large buffer.
326 static std::size_t constexpr limit = 200;
327
328 for(int i = 0; i < 2; ++i)
329 {
330 std::size_t n;
331 for(n = 0; n < limit; ++n)
332 {
333 test::fail_count fc{n};
334 test::stream ts{ioc_, fc};
335 ws_type_t<deflateSupported> ws{ts};
336 ws.set_option(pmd);
337
338 echo_server es{log, i==1 ?
339 kind::async : kind::sync};
340 error_code ec;
341 ws.next_layer().connect(es.stream());
342 ws.handshake("localhost", "/", ec);
343 if(ec)
344 {
345 ts.close();
346 if( ! BEAST_EXPECTS(
347 ec == test::error::test_failure,
348 ec.message()))
349 BOOST_THROW_EXCEPTION(system_error{ec});
350 continue;
351 }
352 try
353 {
354 f(ws);
355 ts.close();
356 break;
357 }
358 catch(system_error const& se)
359 {
360 BEAST_EXPECTS(
361 se.code() == test::error::test_failure,
362 se.code().message());
363 }
364 catch(std::exception const& e)
365 {
366 fail(e.what(), __FILE__, __LINE__);
367 }
368 ts.close();
369 continue;
370 }
371 BEAST_EXPECT(n < limit);
372 }
373 }
374
375 //--------------------------------------------------------------------------
376
377 net::const_buffer cbuf(std::initializer_list<std::uint8_t> bytes)
378 {
379 return {bytes.begin(), bytes.size()};
380 }
381
382 template<std::size_t N>
383 static
384 net::const_buffer
385 sbuf(const char (&s)[N])
386 {
387 return net::const_buffer(&s[0], N-1);
388 }
389
390 template<
391 class DynamicBuffer,
392 class ConstBufferSequence>
393 void
394 put(
395 DynamicBuffer& buffer,
396 ConstBufferSequence const& buffers)
397 {
398 buffer.commit(net::buffer_copy(
399 buffer.prepare(buffer_bytes(buffers)),
400 buffers));
401 }
402
403 template<class Pred>
404 bool
405 run_until(net::io_context& ioc,
406 std::size_t limit, Pred&& pred)
407 {
408 for(std::size_t i = 0; i < limit; ++i)
409 {
410 if(pred())
411 return true;
412 ioc.run_one();
413 }
414 return false;
415 }
416
417 template<class Pred>
418 bool
419 run_until(
420 net::io_context& ioc, Pred&& pred)
421 {
422 return run_until(ioc, 100, pred);
423 }
424
425 inline
426 std::string const&
427 random_string()
428 {
429 static std::string const s = []
430 {
431 std::size_t constexpr N = 16384;
432 std::mt19937 mt{1};
433 std::string tmp;
434 tmp.reserve(N);
435 for(std::size_t i = 0; i < N; ++ i)
436 tmp.push_back(static_cast<char>(
437 std::uniform_int_distribution<
438 unsigned>{0, 255}(mt)));
439 return tmp;
440 }();
441 return s;
442 }
443
444 //--------------------------------------------------------------------------
445
446 struct SyncClient
447 {
448 template<class NextLayer, bool deflateSupported>
449 void
450 accept(
451 stream<NextLayer, deflateSupported>& ws) const
452 {
453 ws.accept();
454 }
455
456 template<
457 class NextLayer, bool deflateSupported,
458 class Buffers>
459 typename std::enable_if<
460 ! http::detail::is_header<Buffers>::value>::type
461 accept(stream<NextLayer, deflateSupported>& ws,
462 Buffers const& buffers) const
463 {
464 ws.accept(buffers);
465 }
466
467 template<class NextLayer, bool deflateSupported>
468 void
469 accept(
470 stream<NextLayer, deflateSupported>& ws,
471 http::request<http::empty_body> const& req) const
472 {
473 ws.accept(req);
474 }
475
476 template<
477 class NextLayer, bool deflateSupported,
478 class Decorator>
479 void
480 accept_ex(
481 stream<NextLayer, deflateSupported>& ws,
482 Decorator const& d) const
483 {
484 ws.accept_ex(d);
485 }
486
487 template<
488 class NextLayer, bool deflateSupported,
489 class Buffers, class Decorator>
490 typename std::enable_if<
491 ! http::detail::is_header<Buffers>::value>::type
492 accept_ex(
493 stream<NextLayer, deflateSupported>& ws,
494 Buffers const& buffers,
495 Decorator const& d) const
496 {
497 ws.accept_ex(buffers, d);
498 }
499
500 template<
501 class NextLayer, bool deflateSupported,
502 class Decorator>
503 void
504 accept_ex(
505 stream<NextLayer, deflateSupported>& ws,
506 http::request<http::empty_body> const& req,
507 Decorator const& d) const
508 {
509 ws.accept_ex(req, d);
510 }
511
512 template<
513 class NextLayer, bool deflateSupported,
514 class Buffers, class Decorator>
515 void
516 accept_ex(
517 stream<NextLayer, deflateSupported>& ws,
518 http::request<http::empty_body> const& req,
519 Buffers const& buffers,
520 Decorator const& d) const
521 {
522 ws.accept_ex(req, buffers, d);
523 }
524
525 template<class NextLayer, bool deflateSupported>
526 void
527 handshake(
528 stream<NextLayer, deflateSupported>& ws,
529 string_view uri,
530 string_view path) const
531 {
532 ws.handshake(uri, path);
533 }
534
535 template<class NextLayer, bool deflateSupported>
536 void
537 handshake(
538 stream<NextLayer, deflateSupported>& ws,
539 response_type& res,
540 string_view uri,
541 string_view path) const
542 {
543 ws.handshake(res, uri, path);
544 }
545
546 template<
547 class NextLayer, bool deflateSupported,
548 class Decorator>
549 void
550 handshake_ex(
551 stream<NextLayer, deflateSupported>& ws,
552 string_view uri,
553 string_view path,
554 Decorator const& d) const
555 {
556 ws.handshake_ex(uri, path, d);
557 }
558
559 template<
560 class NextLayer, bool deflateSupported,
561 class Decorator>
562 void
563 handshake_ex(
564 stream<NextLayer, deflateSupported>& ws,
565 response_type& res,
566 string_view uri,
567 string_view path,
568 Decorator const& d) const
569 {
570 ws.handshake_ex(res, uri, path, d);
571 }
572
573 template<class NextLayer, bool deflateSupported>
574 void
575 ping(stream<NextLayer, deflateSupported>& ws,
576 ping_data const& payload) const
577 {
578 ws.ping(payload);
579 }
580
581 template<class NextLayer, bool deflateSupported>
582 void
583 pong(stream<NextLayer, deflateSupported>& ws,
584 ping_data const& payload) const
585 {
586 ws.pong(payload);
587 }
588
589 template<class NextLayer, bool deflateSupported>
590 void
591 close(stream<NextLayer, deflateSupported>& ws,
592 close_reason const& cr) const
593 {
594 ws.close(cr);
595 }
596
597 template<
598 class NextLayer, bool deflateSupported,
599 class DynamicBuffer>
600 std::size_t
601 read(stream<NextLayer, deflateSupported>& ws,
602 DynamicBuffer& buffer) const
603 {
604 return ws.read(buffer);
605 }
606
607 template<
608 class NextLayer, bool deflateSupported,
609 class DynamicBuffer>
610 std::size_t
611 read_some(
612 stream<NextLayer, deflateSupported>& ws,
613 std::size_t limit,
614 DynamicBuffer& buffer) const
615 {
616 return ws.read_some(buffer, limit);
617 }
618
619 template<
620 class NextLayer, bool deflateSupported,
621 class MutableBufferSequence>
622 std::size_t
623 read_some(
624 stream<NextLayer, deflateSupported>& ws,
625 MutableBufferSequence const& buffers) const
626 {
627 return ws.read_some(buffers);
628 }
629
630 template<
631 class NextLayer, bool deflateSupported,
632 class ConstBufferSequence>
633 std::size_t
634 write(
635 stream<NextLayer, deflateSupported>& ws,
636 ConstBufferSequence const& buffers) const
637 {
638 return ws.write(buffers);
639 }
640
641 template<
642 class NextLayer, bool deflateSupported,
643 class ConstBufferSequence>
644 std::size_t
645 write_some(
646 stream<NextLayer, deflateSupported>& ws,
647 bool fin,
648 ConstBufferSequence const& buffers) const
649 {
650 return ws.write_some(fin, buffers);
651 }
652
653 template<
654 class NextLayer, bool deflateSupported,
655 class ConstBufferSequence>
656 std::size_t
657 write_raw(
658 stream<NextLayer, deflateSupported>& ws,
659 ConstBufferSequence const& buffers) const
660 {
661 return net::write(
662 ws.next_layer(), buffers);
663 }
664 };
665
666 //--------------------------------------------------------------------------
667
668 class AsyncClient
669 {
670 net::yield_context& yield_;
671
672 public:
673 explicit
674 AsyncClient(net::yield_context& yield)
675 : yield_(yield)
676 {
677 }
678
679 template<class NextLayer, bool deflateSupported>
680 void
681 accept(stream<NextLayer, deflateSupported>& ws) const
682 {
683 error_code ec;
684 ws.async_accept(yield_[ec]);
685 if(ec)
686 throw system_error{ec};
687 }
688
689 template<
690 class NextLayer, bool deflateSupported,
691 class Buffers>
692 typename std::enable_if<
693 ! http::detail::is_header<Buffers>::value>::type
694 accept(
695 stream<NextLayer, deflateSupported>& ws,
696 Buffers const& buffers) const
697 {
698 error_code ec;
699 ws.async_accept(buffers, yield_[ec]);
700 if(ec)
701 throw system_error{ec};
702 }
703
704 template<class NextLayer, bool deflateSupported>
705 void
706 accept(
707 stream<NextLayer, deflateSupported>& ws,
708 http::request<http::empty_body> const& req) const
709 {
710 error_code ec;
711 ws.async_accept(req, yield_[ec]);
712 if(ec)
713 throw system_error{ec};
714 }
715
716 template<
717 class NextLayer, bool deflateSupported,
718 class Decorator>
719 void
720 accept_ex(
721 stream<NextLayer, deflateSupported>& ws,
722 Decorator const& d) const
723 {
724 error_code ec;
725 ws.async_accept_ex(d, yield_[ec]);
726 if(ec)
727 throw system_error{ec};
728 }
729
730 template<
731 class NextLayer, bool deflateSupported,
732 class Buffers, class Decorator>
733 typename std::enable_if<
734 ! http::detail::is_header<Buffers>::value>::type
735 accept_ex(
736 stream<NextLayer, deflateSupported>& ws,
737 Buffers const& buffers,
738 Decorator const& d) const
739 {
740 error_code ec;
741 ws.async_accept_ex(buffers, d, yield_[ec]);
742 if(ec)
743 throw system_error{ec};
744 }
745
746 template<
747 class NextLayer, bool deflateSupported,
748 class Decorator>
749 void
750 accept_ex(
751 stream<NextLayer, deflateSupported>& ws,
752 http::request<http::empty_body> const& req,
753 Decorator const& d) const
754 {
755 error_code ec;
756 ws.async_accept_ex(req, d, yield_[ec]);
757 if(ec)
758 throw system_error{ec};
759 }
760
761 template<
762 class NextLayer, bool deflateSupported,
763 class Buffers, class Decorator>
764 void
765 accept_ex(
766 stream<NextLayer, deflateSupported>& ws,
767 http::request<http::empty_body> const& req,
768 Buffers const& buffers,
769 Decorator const& d) const
770 {
771 error_code ec;
772 ws.async_accept_ex(
773 req, buffers, d, yield_[ec]);
774 if(ec)
775 throw system_error{ec};
776 }
777
778 template<
779 class NextLayer, bool deflateSupported>
780 void
781 handshake(
782 stream<NextLayer, deflateSupported>& ws,
783 string_view uri,
784 string_view path) const
785 {
786 error_code ec;
787 ws.async_handshake(
788 uri, path, yield_[ec]);
789 if(ec)
790 throw system_error{ec};
791 }
792
793 template<class NextLayer, bool deflateSupported>
794 void
795 handshake(
796 stream<NextLayer, deflateSupported>& ws,
797 response_type& res,
798 string_view uri,
799 string_view path) const
800 {
801 error_code ec;
802 ws.async_handshake(
803 res, uri, path, yield_[ec]);
804 if(ec)
805 throw system_error{ec};
806 }
807
808 template<
809 class NextLayer, bool deflateSupported,
810 class Decorator>
811 void
812 handshake_ex(
813 stream<NextLayer, deflateSupported>& ws,
814 string_view uri,
815 string_view path,
816 Decorator const &d) const
817 {
818 error_code ec;
819 ws.async_handshake_ex(
820 uri, path, d, yield_[ec]);
821 if(ec)
822 throw system_error{ec};
823 }
824
825 template<
826 class NextLayer, bool deflateSupported,
827 class Decorator>
828 void
829 handshake_ex(
830 stream<NextLayer, deflateSupported>& ws,
831 response_type& res,
832 string_view uri,
833 string_view path,
834 Decorator const &d) const
835 {
836 error_code ec;
837 ws.async_handshake_ex(
838 res, uri, path, d, yield_[ec]);
839 if(ec)
840 throw system_error{ec};
841 }
842
843 template<class NextLayer, bool deflateSupported>
844 void
845 ping(
846 stream<NextLayer, deflateSupported>& ws,
847 ping_data const& payload) const
848 {
849 error_code ec;
850 ws.async_ping(payload, yield_[ec]);
851 if(ec)
852 throw system_error{ec};
853 }
854
855 template<class NextLayer, bool deflateSupported>
856 void
857 pong(
858 stream<NextLayer, deflateSupported>& ws,
859 ping_data const& payload) const
860 {
861 error_code ec;
862 ws.async_pong(payload, yield_[ec]);
863 if(ec)
864 throw system_error{ec};
865 }
866
867 template<class NextLayer, bool deflateSupported>
868 void
869 close(
870 stream<NextLayer, deflateSupported>& ws,
871 close_reason const& cr) const
872 {
873 error_code ec;
874 ws.async_close(cr, yield_[ec]);
875 if(ec)
876 throw system_error{ec};
877 }
878
879 template<
880 class NextLayer, bool deflateSupported,
881 class DynamicBuffer>
882 std::size_t
883 read(
884 stream<NextLayer, deflateSupported>& ws,
885 DynamicBuffer& buffer) const
886 {
887 error_code ec;
888 auto const bytes_written =
889 ws.async_read(buffer, yield_[ec]);
890 if(ec)
891 throw system_error{ec};
892 return bytes_written;
893 }
894
895 template<
896 class NextLayer, bool deflateSupported,
897 class DynamicBuffer>
898 std::size_t
899 read_some(
900 stream<NextLayer, deflateSupported>& ws,
901 std::size_t limit,
902 DynamicBuffer& buffer) const
903 {
904 error_code ec;
905 auto const bytes_written =
906 ws.async_read_some(buffer, limit, yield_[ec]);
907 if(ec)
908 throw system_error{ec};
909 return bytes_written;
910 }
911
912 template<
913 class NextLayer, bool deflateSupported,
914 class MutableBufferSequence>
915 std::size_t
916 read_some(
917 stream<NextLayer, deflateSupported>& ws,
918 MutableBufferSequence const& buffers) const
919 {
920 error_code ec;
921 auto const bytes_written =
922 ws.async_read_some(buffers, yield_[ec]);
923 if(ec)
924 throw system_error{ec};
925 return bytes_written;
926 }
927
928 template<
929 class NextLayer, bool deflateSupported,
930 class ConstBufferSequence>
931 std::size_t
932 write(
933 stream<NextLayer, deflateSupported>& ws,
934 ConstBufferSequence const& buffers) const
935 {
936 error_code ec;
937 auto const bytes_transferred =
938 ws.async_write(buffers, yield_[ec]);
939 if(ec)
940 throw system_error{ec};
941 return bytes_transferred;
942 }
943
944 template<
945 class NextLayer, bool deflateSupported,
946 class ConstBufferSequence>
947 std::size_t
948 write_some(
949 stream<NextLayer, deflateSupported>& ws,
950 bool fin,
951 ConstBufferSequence const& buffers) const
952 {
953 error_code ec;
954 auto const bytes_transferred =
955 ws.async_write_some(fin, buffers, yield_[ec]);
956 if(ec)
957 throw system_error{ec};
958 return bytes_transferred;
959 }
960
961 template<
962 class NextLayer, bool deflateSupported,
963 class ConstBufferSequence>
964 std::size_t
965 write_raw(
966 stream<NextLayer, deflateSupported>& ws,
967 ConstBufferSequence const& buffers) const
968 {
969 error_code ec;
970 auto const bytes_transferred =
971 net::async_write(
972 ws.next_layer(), buffers, yield_[ec]);
973 if(ec)
974 throw system_error{ec};
975 return bytes_transferred;
976 }
977 };
978 };
979
980 struct test_sync_api
981 {
982 template<class NextLayer, bool deflateSupported>
983 void
984 accept(
985 stream<NextLayer, deflateSupported>& ws) const
986 {
987 ws.accept();
988 }
989
990 template<
991 class NextLayer, bool deflateSupported,
992 class Buffers>
993 typename std::enable_if<
994 ! http::detail::is_header<Buffers>::value>::type
995 accept(stream<NextLayer, deflateSupported>& ws,
996 Buffers const& buffers) const
997 {
998 ws.accept(buffers);
999 }
1000
1001 template<class NextLayer, bool deflateSupported>
1002 void
1003 accept(
1004 stream<NextLayer, deflateSupported>& ws,
1005 http::request<http::empty_body> const& req) const
1006 {
1007 ws.accept(req);
1008 }
1009
1010 template<
1011 class NextLayer, bool deflateSupported,
1012 class Decorator>
1013 void
1014 accept_ex(
1015 stream<NextLayer, deflateSupported>& ws,
1016 Decorator const& d) const
1017 {
1018 ws.accept_ex(d);
1019 }
1020
1021 template<
1022 class NextLayer, bool deflateSupported,
1023 class Buffers, class Decorator>
1024 typename std::enable_if<
1025 ! http::detail::is_header<Buffers>::value>::type
1026 accept_ex(
1027 stream<NextLayer, deflateSupported>& ws,
1028 Buffers const& buffers,
1029 Decorator const& d) const
1030 {
1031 ws.accept_ex(buffers, d);
1032 }
1033
1034 template<
1035 class NextLayer, bool deflateSupported,
1036 class Decorator>
1037 void
1038 accept_ex(
1039 stream<NextLayer, deflateSupported>& ws,
1040 http::request<http::empty_body> const& req,
1041 Decorator const& d) const
1042 {
1043 ws.accept_ex(req, d);
1044 }
1045
1046 template<
1047 class NextLayer, bool deflateSupported,
1048 class Buffers, class Decorator>
1049 void
1050 accept_ex(
1051 stream<NextLayer, deflateSupported>& ws,
1052 http::request<http::empty_body> const& req,
1053 Buffers const& buffers,
1054 Decorator const& d) const
1055 {
1056 ws.accept_ex(req, buffers, d);
1057 }
1058
1059 template<class NextLayer, bool deflateSupported>
1060 void
1061 handshake(
1062 stream<NextLayer, deflateSupported>& ws,
1063 response_type& res,
1064 string_view uri,
1065 string_view path) const
1066 {
1067 ws.handshake(res, uri, path);
1068 }
1069
1070 template<
1071 class NextLayer, bool deflateSupported,
1072 class Decorator>
1073 void
1074 handshake_ex(
1075 stream<NextLayer, deflateSupported>& ws,
1076 string_view uri,
1077 string_view path,
1078 Decorator const& d) const
1079 {
1080 ws.handshake_ex(uri, path, d);
1081 }
1082
1083 template<
1084 class NextLayer, bool deflateSupported,
1085 class Decorator>
1086 void
1087 handshake_ex(
1088 stream<NextLayer, deflateSupported>& ws,
1089 response_type& res,
1090 string_view uri,
1091 string_view path,
1092 Decorator const& d) const
1093 {
1094 ws.handshake_ex(res, uri, path, d);
1095 }
1096
1097 template<class NextLayer, bool deflateSupported>
1098 void
1099 ping(stream<NextLayer, deflateSupported>& ws,
1100 ping_data const& payload) const
1101 {
1102 ws.ping(payload);
1103 }
1104
1105 template<class NextLayer, bool deflateSupported>
1106 void
1107 pong(stream<NextLayer, deflateSupported>& ws,
1108 ping_data const& payload) const
1109 {
1110 ws.pong(payload);
1111 }
1112
1113 template<class NextLayer, bool deflateSupported>
1114 void
1115 close(stream<NextLayer, deflateSupported>& ws,
1116 close_reason const& cr) const
1117 {
1118 ws.close(cr);
1119 }
1120
1121 template<
1122 class NextLayer, bool deflateSupported,
1123 class DynamicBuffer>
1124 std::size_t
1125 read(stream<NextLayer, deflateSupported>& ws,
1126 DynamicBuffer& buffer) const
1127 {
1128 return ws.read(buffer);
1129 }
1130
1131 template<
1132 class NextLayer, bool deflateSupported,
1133 class DynamicBuffer>
1134 std::size_t
1135 read_some(
1136 stream<NextLayer, deflateSupported>& ws,
1137 std::size_t limit,
1138 DynamicBuffer& buffer) const
1139 {
1140 return ws.read_some(buffer, limit);
1141 }
1142
1143 template<
1144 class NextLayer, bool deflateSupported,
1145 class MutableBufferSequence>
1146 std::size_t
1147 read_some(
1148 stream<NextLayer, deflateSupported>& ws,
1149 MutableBufferSequence const& buffers) const
1150 {
1151 return ws.read_some(buffers);
1152 }
1153
1154 template<
1155 class NextLayer, bool deflateSupported,
1156 class ConstBufferSequence>
1157 std::size_t
1158 write(
1159 stream<NextLayer, deflateSupported>& ws,
1160 ConstBufferSequence const& buffers) const
1161 {
1162 return ws.write(buffers);
1163 }
1164
1165 template<
1166 class NextLayer, bool deflateSupported,
1167 class ConstBufferSequence>
1168 std::size_t
1169 write_some(
1170 stream<NextLayer, deflateSupported>& ws,
1171 bool fin,
1172 ConstBufferSequence const& buffers) const
1173 {
1174 return ws.write_some(fin, buffers);
1175 }
1176
1177 template<
1178 class NextLayer, bool deflateSupported,
1179 class ConstBufferSequence>
1180 std::size_t
1181 write_raw(
1182 stream<NextLayer, deflateSupported>& ws,
1183 ConstBufferSequence const& buffers) const
1184 {
1185 return net::write(
1186 ws.next_layer(), buffers);
1187 }
1188 };
1189
1190 //--------------------------------------------------------------------------
1191
1192 class test_async_api
1193 {
1194 struct handler
1195 {
1196 error_code& ec_;
1197 std::size_t* n_ = 0;
1198 bool pass_ = false;
1199
1200 explicit
1201 handler(error_code& ec)
1202 : ec_(ec)
1203 {
1204 }
1205
1206 explicit
1207 handler(error_code& ec, std::size_t& n)
1208 : ec_(ec)
1209 , n_(&n)
1210 {
1211 *n_ = 0;
1212 }
1213
1214 handler(handler&& other)
1215 : ec_(other.ec_)
1216 , pass_(boost::exchange(other.pass_, true))
1217 {
1218 }
1219
1220 ~handler()
1221 {
1222 BEAST_EXPECT(pass_);
1223 }
1224
1225 void
1226 operator()(error_code ec)
1227 {
1228 BEAST_EXPECT(! pass_);
1229 pass_ = true;
1230 ec_ = ec;
1231 }
1232
1233 void
1234 operator()(error_code ec, std::size_t n)
1235 {
1236 BEAST_EXPECT(! pass_);
1237 pass_ = true;
1238 ec_ = ec;
1239 if(n_)
1240 *n_ = n;
1241 }
1242 };
1243
1244 public:
1245 template<class NextLayer, bool deflateSupported>
1246 void
1247 accept(
1248 stream<NextLayer, deflateSupported>& ws) const
1249 {
1250 error_code ec;
1251 ws.async_accept(handler(ec));
1252 ws.get_executor().context().run();
1253 ws.get_executor().context().restart();
1254 if(ec)
1255 throw system_error{ec};
1256 }
1257
1258 template<
1259 class NextLayer, bool deflateSupported,
1260 class Buffers>
1261 typename std::enable_if<
1262 ! http::detail::is_header<Buffers>::value>::type
1263 accept(
1264 stream<NextLayer, deflateSupported>& ws,
1265 Buffers const& buffers) const
1266 {
1267 error_code ec;
1268 ws.async_accept(buffers, handler(ec));
1269 ws.get_executor().context().run();
1270 ws.get_executor().context().restart();
1271 if(ec)
1272 throw system_error{ec};
1273 }
1274
1275 template<class NextLayer, bool deflateSupported>
1276 void
1277 accept(
1278 stream<NextLayer, deflateSupported>& ws,
1279 http::request<http::empty_body> const& req) const
1280 {
1281 error_code ec;
1282 ws.async_accept(req, handler(ec));
1283 ws.get_executor().context().run();
1284 ws.get_executor().context().restart();
1285 if(ec)
1286 throw system_error{ec};
1287 }
1288
1289 template<
1290 class NextLayer, bool deflateSupported,
1291 class Decorator>
1292 void
1293 accept_ex(
1294 stream<NextLayer, deflateSupported>& ws,
1295 Decorator const& d) const
1296 {
1297 error_code ec;
1298 ws.async_accept_ex(d, handler(ec));
1299 ws.get_executor().context().run();
1300 ws.get_executor().context().restart();
1301 if(ec)
1302 throw system_error{ec};
1303 }
1304
1305 template<
1306 class NextLayer, bool deflateSupported,
1307 class Buffers, class Decorator>
1308 typename std::enable_if<
1309 ! http::detail::is_header<Buffers>::value>::type
1310 accept_ex(
1311 stream<NextLayer, deflateSupported>& ws,
1312 Buffers const& buffers,
1313 Decorator const& d) const
1314 {
1315 error_code ec;
1316 ws.async_accept_ex(buffers, d, handler(ec));
1317 ws.get_executor().context().run();
1318 ws.get_executor().context().restart();
1319 if(ec)
1320 throw system_error{ec};
1321 }
1322
1323 template<
1324 class NextLayer, bool deflateSupported,
1325 class Decorator>
1326 void
1327 accept_ex(
1328 stream<NextLayer, deflateSupported>& ws,
1329 http::request<http::empty_body> const& req,
1330 Decorator const& d) const
1331 {
1332 error_code ec;
1333 ws.async_accept_ex(req, d, handler(ec));
1334 ws.get_executor().context().run();
1335 ws.get_executor().context().restart();
1336 if(ec)
1337 throw system_error{ec};
1338 }
1339
1340 template<
1341 class NextLayer, bool deflateSupported,
1342 class Buffers, class Decorator>
1343 void
1344 accept_ex(
1345 stream<NextLayer, deflateSupported>& ws,
1346 http::request<http::empty_body> const& req,
1347 Buffers const& buffers,
1348 Decorator const& d) const
1349 {
1350 error_code ec;
1351 ws.async_accept_ex(
1352 req, buffers, d, handler(ec));
1353 ws.get_executor().context().run();
1354 ws.get_executor().context().restart();
1355 if(ec)
1356 throw system_error{ec};
1357 }
1358
1359 template<
1360 class NextLayer, bool deflateSupported>
1361 void
1362 handshake(
1363 stream<NextLayer, deflateSupported>& ws,
1364 string_view uri,
1365 string_view path) const
1366 {
1367 error_code ec;
1368 ws.async_handshake(
1369 uri, path, handler(ec));
1370 ws.get_executor().context().run();
1371 ws.get_executor().context().restart();
1372 if(ec)
1373 throw system_error{ec};
1374 }
1375
1376 template<class NextLayer, bool deflateSupported>
1377 void
1378 handshake(
1379 stream<NextLayer, deflateSupported>& ws,
1380 response_type& res,
1381 string_view uri,
1382 string_view path) const
1383 {
1384 error_code ec;
1385 ws.async_handshake(
1386 res, uri, path, handler(ec));
1387 ws.get_executor().context().run();
1388 ws.get_executor().context().restart();
1389 if(ec)
1390 throw system_error{ec};
1391 }
1392
1393 template<
1394 class NextLayer, bool deflateSupported,
1395 class Decorator>
1396 void
1397 handshake_ex(
1398 stream<NextLayer, deflateSupported>& ws,
1399 string_view uri,
1400 string_view path,
1401 Decorator const &d) const
1402 {
1403 error_code ec;
1404 ws.async_handshake_ex(
1405 uri, path, d, handler(ec));
1406 ws.get_executor().context().run();
1407 ws.get_executor().context().restart();
1408 if(ec)
1409 throw system_error{ec};
1410 }
1411
1412 template<
1413 class NextLayer, bool deflateSupported,
1414 class Decorator>
1415 void
1416 handshake_ex(
1417 stream<NextLayer, deflateSupported>& ws,
1418 response_type& res,
1419 string_view uri,
1420 string_view path,
1421 Decorator const &d) const
1422 {
1423 error_code ec;
1424 ws.async_handshake_ex(
1425 res, uri, path, d, handler(ec));
1426 ws.get_executor().context().run();
1427 ws.get_executor().context().restart();
1428 if(ec)
1429 throw system_error{ec};
1430 }
1431
1432 template<class NextLayer, bool deflateSupported>
1433 void
1434 ping(
1435 stream<NextLayer, deflateSupported>& ws,
1436 ping_data const& payload) const
1437 {
1438 error_code ec;
1439 ws.async_ping(payload, handler(ec));
1440 ws.get_executor().context().run();
1441 ws.get_executor().context().restart();
1442 if(ec)
1443 throw system_error{ec};
1444 }
1445
1446 template<class NextLayer, bool deflateSupported>
1447 void
1448 pong(
1449 stream<NextLayer, deflateSupported>& ws,
1450 ping_data const& payload) const
1451 {
1452 error_code ec;
1453 ws.async_pong(payload, handler(ec));
1454 ws.get_executor().context().run();
1455 ws.get_executor().context().restart();
1456 if(ec)
1457 throw system_error{ec};
1458 }
1459
1460 template<class NextLayer, bool deflateSupported>
1461 void
1462 close(
1463 stream<NextLayer, deflateSupported>& ws,
1464 close_reason const& cr) const
1465 {
1466 error_code ec;
1467 ws.async_close(cr, handler(ec));
1468 ws.get_executor().context().run();
1469 ws.get_executor().context().restart();
1470 if(ec)
1471 throw system_error{ec};
1472 }
1473
1474 template<
1475 class NextLayer, bool deflateSupported,
1476 class DynamicBuffer>
1477 std::size_t
1478 read(
1479 stream<NextLayer, deflateSupported>& ws,
1480 DynamicBuffer& buffer) const
1481 {
1482 error_code ec;
1483 std::size_t n;
1484 ws.async_read(buffer, handler(ec, n));
1485 ws.get_executor().context().run();
1486 ws.get_executor().context().restart();
1487 if(ec)
1488 throw system_error{ec};
1489 return n;
1490 }
1491
1492 template<
1493 class NextLayer, bool deflateSupported,
1494 class DynamicBuffer>
1495 std::size_t
1496 read_some(
1497 stream<NextLayer, deflateSupported>& ws,
1498 std::size_t limit,
1499 DynamicBuffer& buffer) const
1500 {
1501 error_code ec;
1502 std::size_t n;
1503 ws.async_read_some(buffer, limit, handler(ec, n));
1504 ws.get_executor().context().run();
1505 ws.get_executor().context().restart();
1506 if(ec)
1507 throw system_error{ec};
1508 return n;
1509 }
1510
1511 template<
1512 class NextLayer, bool deflateSupported,
1513 class MutableBufferSequence>
1514 std::size_t
1515 read_some(
1516 stream<NextLayer, deflateSupported>& ws,
1517 MutableBufferSequence const& buffers) const
1518 {
1519 error_code ec;
1520 std::size_t n;
1521 ws.async_read_some(buffers, handler(ec, n));
1522 ws.get_executor().context().run();
1523 ws.get_executor().context().restart();
1524 if(ec)
1525 throw system_error{ec};
1526 return n;
1527 }
1528
1529 template<
1530 class NextLayer, bool deflateSupported,
1531 class ConstBufferSequence>
1532 std::size_t
1533 write(
1534 stream<NextLayer, deflateSupported>& ws,
1535 ConstBufferSequence const& buffers) const
1536 {
1537 error_code ec;
1538 std::size_t n;
1539 ws.async_write(buffers, handler(ec, n));
1540 ws.get_executor().context().run();
1541 ws.get_executor().context().restart();
1542 if(ec)
1543 throw system_error{ec};
1544 return n;
1545 }
1546
1547 template<
1548 class NextLayer, bool deflateSupported,
1549 class ConstBufferSequence>
1550 std::size_t
1551 write_some(
1552 stream<NextLayer, deflateSupported>& ws,
1553 bool fin,
1554 ConstBufferSequence const& buffers) const
1555 {
1556 error_code ec;
1557 std::size_t n;
1558 ws.async_write_some(fin, buffers, handler(ec, n));
1559 ws.get_executor().context().run();
1560 ws.get_executor().context().restart();
1561 if(ec)
1562 throw system_error{ec};
1563 return n;
1564 }
1565
1566 template<
1567 class NextLayer, bool deflateSupported,
1568 class ConstBufferSequence>
1569 std::size_t
1570 write_raw(
1571 stream<NextLayer, deflateSupported>& ws,
1572 ConstBufferSequence const& buffers) const
1573 {
1574 error_code ec;
1575 std::size_t n;
1576 net::async_write(ws.next_layer(),
1577 buffers, handler(ec, n));
1578 ws.get_executor().context().run();
1579 ws.get_executor().context().restart();
1580 if(ec)
1581 throw system_error{ec};
1582 return n;
1583 }
1584 };
1585
1586 } // websocket
1587 } // beast
1588 } // boost
1589
1590 #endif