]> git.proxmox.com Git - ceph.git/blob - ceph/src/Beast/include/beast/websocket/impl/teardown.ipp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / Beast / include / beast / websocket / impl / teardown.ipp
1 //
2 // Copyright (c) 2013-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
8 #ifndef BEAST_WEBSOCKET_IMPL_TEARDOWN_IPP
9 #define BEAST_WEBSOCKET_IMPL_TEARDOWN_IPP
10
11 #include <beast/core/async_completion.hpp>
12 #include <beast/core/handler_concepts.hpp>
13 #include <beast/core/handler_helpers.hpp>
14 #include <beast/core/handler_ptr.hpp>
15 #include <memory>
16
17 namespace beast {
18 namespace websocket {
19
20 namespace detail {
21
22 template<class Handler>
23 class teardown_tcp_op
24 {
25 using socket_type =
26 boost::asio::ip::tcp::socket;
27
28 struct data
29 {
30 bool cont;
31 socket_type& socket;
32 char buf[2048];
33 int state = 0;
34
35 data(Handler& handler, socket_type& socket_)
36 : cont(beast_asio_helpers::
37 is_continuation(handler))
38 , socket(socket_)
39 {
40 }
41 };
42
43 handler_ptr<data, Handler> d_;
44
45 public:
46 template<class DeducedHandler>
47 teardown_tcp_op(
48 DeducedHandler&& h,
49 socket_type& socket)
50 : d_(std::forward<DeducedHandler>(h), socket)
51 {
52 (*this)(error_code{}, 0, false);
53 }
54
55 void
56 operator()(error_code ec, std::size_t, bool again = true);
57
58 friend
59 void* asio_handler_allocate(std::size_t size,
60 teardown_tcp_op* op)
61 {
62 return beast_asio_helpers::
63 allocate(size, op->d_.handler());
64 }
65
66 friend
67 void asio_handler_deallocate(void* p,
68 std::size_t size, teardown_tcp_op* op)
69 {
70 return beast_asio_helpers::
71 deallocate(p, size, op->d_.handler());
72 }
73
74 friend
75 bool asio_handler_is_continuation(teardown_tcp_op* op)
76 {
77 return op->d_->cont;
78 }
79
80 template<class Function>
81 friend
82 void asio_handler_invoke(Function&& f,
83 teardown_tcp_op* op)
84 {
85 return beast_asio_helpers::
86 invoke(f, op->d_.handler());
87 }
88 };
89
90 template<class Handler>
91 void
92 teardown_tcp_op<Handler>::
93 operator()(error_code ec, std::size_t, bool again)
94 {
95 using boost::asio::buffer;
96 auto& d = *d_;
97 d.cont = d.cont || again;
98 while(! ec)
99 {
100 switch(d.state)
101 {
102 case 0:
103 d.state = 1;
104 d.socket.shutdown(
105 boost::asio::ip::tcp::socket::shutdown_send, ec);
106 break;
107
108 case 1:
109 d.socket.async_read_some(
110 buffer(d.buf), std::move(*this));
111 return;
112 }
113 }
114 if(ec == boost::asio::error::eof)
115 {
116 d.socket.close(ec);
117 ec = error_code{};
118 }
119 d_.invoke(ec);
120 }
121
122 } // detail
123
124 //------------------------------------------------------------------------------
125
126 inline
127 void
128 teardown(teardown_tag,
129 boost::asio::ip::tcp::socket& socket,
130 error_code& ec)
131 {
132 using boost::asio::buffer;
133 socket.shutdown(
134 boost::asio::ip::tcp::socket::shutdown_send, ec);
135 while(! ec)
136 {
137 char buf[8192];
138 auto const n = socket.read_some(
139 buffer(buf), ec);
140 if(! n)
141 break;
142 }
143 if(ec == boost::asio::error::eof)
144 ec = error_code{};
145 socket.close(ec);
146 }
147
148 template<class TeardownHandler>
149 inline
150 void
151 async_teardown(teardown_tag,
152 boost::asio::ip::tcp::socket& socket,
153 TeardownHandler&& handler)
154 {
155 static_assert(beast::is_CompletionHandler<
156 TeardownHandler, void(error_code)>::value,
157 "TeardownHandler requirements not met");
158 detail::teardown_tcp_op<typename std::decay<
159 TeardownHandler>::type>{std::forward<
160 TeardownHandler>(handler), socket};
161 }
162
163 } // websocket
164 } // beast
165
166 #endif