]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/beast/websocket/impl/handshake.ipp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / beast / websocket / impl / handshake.ipp
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_HANDSHAKE_IPP
11 #define BOOST_BEAST_WEBSOCKET_IMPL_HANDSHAKE_IPP
12
13 #include <boost/beast/websocket/detail/type_traits.hpp>
14 #include <boost/beast/http/empty_body.hpp>
15 #include <boost/beast/http/message.hpp>
16 #include <boost/beast/http/read.hpp>
17 #include <boost/beast/http/write.hpp>
18 #include <boost/beast/core/handler_ptr.hpp>
19 #include <boost/beast/core/type_traits.hpp>
20 #include <boost/asio/associated_allocator.hpp>
21 #include <boost/asio/associated_executor.hpp>
22 #include <boost/asio/coroutine.hpp>
23 #include <boost/asio/handler_continuation_hook.hpp>
24 #include <boost/assert.hpp>
25 #include <boost/throw_exception.hpp>
26 #include <memory>
27
28 namespace boost {
29 namespace beast {
30 namespace websocket {
31
32 //------------------------------------------------------------------------------
33
34 // send the upgrade request and process the response
35 //
36 template<class NextLayer>
37 template<class Handler>
38 class stream<NextLayer>::handshake_op
39 : public boost::asio::coroutine
40 {
41 struct data
42 {
43 stream<NextLayer>& ws;
44 response_type* res_p;
45 detail::sec_ws_key_type key;
46 http::request<http::empty_body> req;
47 response_type res;
48
49 template<class Decorator>
50 data(Handler&, stream<NextLayer>& ws_,
51 response_type* res_p_,
52 string_view host,
53 string_view target,
54 Decorator const& decorator)
55 : ws(ws_)
56 , res_p(res_p_)
57 , req(ws.build_request(key,
58 host, target, decorator))
59 {
60 ws.reset();
61 }
62 };
63
64 handler_ptr<data, Handler> d_;
65
66 public:
67 handshake_op(handshake_op&&) = default;
68 handshake_op(handshake_op const&) = default;
69
70 template<class DeducedHandler, class... Args>
71 handshake_op(DeducedHandler&& h,
72 stream<NextLayer>& ws, Args&&... args)
73 : d_(std::forward<DeducedHandler>(h),
74 ws, std::forward<Args>(args)...)
75 {
76 }
77
78 using allocator_type =
79 boost::asio::associated_allocator_t<Handler>;
80
81 allocator_type
82 get_allocator() const noexcept
83 {
84 return boost::asio::get_associated_allocator(d_.handler());
85 }
86
87 using executor_type = boost::asio::associated_executor_t<
88 Handler, decltype(std::declval<stream<NextLayer>&>().get_executor())>;
89
90 executor_type
91 get_executor() const noexcept
92 {
93 return boost::asio::get_associated_executor(
94 d_.handler(), d_->ws.get_executor());
95 }
96
97 void
98 operator()(
99 error_code ec = {},
100 std::size_t bytes_used = 0);
101
102 friend
103 bool asio_handler_is_continuation(handshake_op* op)
104 {
105 using boost::asio::asio_handler_is_continuation;
106 return asio_handler_is_continuation(
107 std::addressof(op->d_.handler()));
108 }
109 };
110
111 template<class NextLayer>
112 template<class Handler>
113 void
114 stream<NextLayer>::handshake_op<Handler>::
115 operator()(error_code ec, std::size_t)
116 {
117 auto& d = *d_;
118 BOOST_ASIO_CORO_REENTER(*this)
119 {
120 // Send HTTP Upgrade
121 pmd_read(d.ws.pmd_config_, d.req);
122 BOOST_ASIO_CORO_YIELD
123 http::async_write(d.ws.stream_,
124 d.req, std::move(*this));
125 if(ec)
126 goto upcall;
127
128 // VFALCO We could pre-serialize the request to
129 // a single buffer, send that instead,
130 // and delete the buffer here. The buffer
131 // could be a variable block at the end
132 // of handler_ptr's allocation.
133
134 // Read HTTP response
135 BOOST_ASIO_CORO_YIELD
136 http::async_read(d.ws.next_layer(),
137 d.ws.rd_buf_, d.res,
138 std::move(*this));
139 if(ec)
140 goto upcall;
141 d.ws.on_response(d.res, d.key, ec);
142 if(d.res_p)
143 swap(d.res, *d.res_p);
144 upcall:
145 d_.invoke(ec);
146 }
147 }
148
149 template<class NextLayer>
150 template<class HandshakeHandler>
151 BOOST_ASIO_INITFN_RESULT_TYPE(
152 HandshakeHandler, void(error_code))
153 stream<NextLayer>::
154 async_handshake(string_view host,
155 string_view target,
156 HandshakeHandler&& handler)
157 {
158 static_assert(is_async_stream<next_layer_type>::value,
159 "AsyncStream requirements not met");
160 boost::asio::async_completion<HandshakeHandler,
161 void(error_code)> init{handler};
162 handshake_op<BOOST_ASIO_HANDLER_TYPE(
163 HandshakeHandler, void(error_code))>{
164 init.completion_handler, *this, nullptr, host,
165 target, &default_decorate_req}();
166 return init.result.get();
167 }
168
169 template<class NextLayer>
170 template<class HandshakeHandler>
171 BOOST_ASIO_INITFN_RESULT_TYPE(
172 HandshakeHandler, void(error_code))
173 stream<NextLayer>::
174 async_handshake(response_type& res,
175 string_view host,
176 string_view target,
177 HandshakeHandler&& handler)
178 {
179 static_assert(is_async_stream<next_layer_type>::value,
180 "AsyncStream requirements not met");
181 boost::asio::async_completion<HandshakeHandler,
182 void(error_code)> init{handler};
183 handshake_op<BOOST_ASIO_HANDLER_TYPE(
184 HandshakeHandler, void(error_code))>{
185 init.completion_handler, *this, &res, host,
186 target, &default_decorate_req}();
187 return init.result.get();
188 }
189
190 template<class NextLayer>
191 template<class RequestDecorator, class HandshakeHandler>
192 BOOST_ASIO_INITFN_RESULT_TYPE(
193 HandshakeHandler, void(error_code))
194 stream<NextLayer>::
195 async_handshake_ex(string_view host,
196 string_view target,
197 RequestDecorator const& decorator,
198 HandshakeHandler&& handler)
199 {
200 static_assert(is_async_stream<next_layer_type>::value,
201 "AsyncStream requirements not met");
202 static_assert(detail::is_RequestDecorator<
203 RequestDecorator>::value,
204 "RequestDecorator requirements not met");
205 boost::asio::async_completion<HandshakeHandler,
206 void(error_code)> init{handler};
207 handshake_op<BOOST_ASIO_HANDLER_TYPE(
208 HandshakeHandler, void(error_code))>{
209 init.completion_handler, *this, nullptr, host,
210 target, decorator}();
211 return init.result.get();
212 }
213
214 template<class NextLayer>
215 template<class RequestDecorator, class HandshakeHandler>
216 BOOST_ASIO_INITFN_RESULT_TYPE(
217 HandshakeHandler, void(error_code))
218 stream<NextLayer>::
219 async_handshake_ex(response_type& res,
220 string_view host,
221 string_view target,
222 RequestDecorator const& decorator,
223 HandshakeHandler&& handler)
224 {
225 static_assert(is_async_stream<next_layer_type>::value,
226 "AsyncStream requirements not met");
227 static_assert(detail::is_RequestDecorator<
228 RequestDecorator>::value,
229 "RequestDecorator requirements not met");
230 boost::asio::async_completion<HandshakeHandler,
231 void(error_code)> init{handler};
232 handshake_op<BOOST_ASIO_HANDLER_TYPE(
233 HandshakeHandler, void(error_code))>{
234 init.completion_handler, *this, &res, host,
235 target, decorator}();
236 return init.result.get();
237 }
238
239 template<class NextLayer>
240 void
241 stream<NextLayer>::
242 handshake(string_view host,
243 string_view target)
244 {
245 static_assert(is_sync_stream<next_layer_type>::value,
246 "SyncStream requirements not met");
247 error_code ec;
248 handshake(
249 host, target, ec);
250 if(ec)
251 BOOST_THROW_EXCEPTION(system_error{ec});
252 }
253
254 template<class NextLayer>
255 void
256 stream<NextLayer>::
257 handshake(response_type& res,
258 string_view host,
259 string_view target)
260 {
261 static_assert(is_sync_stream<next_layer_type>::value,
262 "SyncStream requirements not met");
263 error_code ec;
264 handshake(res, host, target, ec);
265 if(ec)
266 BOOST_THROW_EXCEPTION(system_error{ec});
267 }
268
269 template<class NextLayer>
270 template<class RequestDecorator>
271 void
272 stream<NextLayer>::
273 handshake_ex(string_view host,
274 string_view target,
275 RequestDecorator const& decorator)
276 {
277 static_assert(is_sync_stream<next_layer_type>::value,
278 "SyncStream requirements not met");
279 static_assert(detail::is_RequestDecorator<
280 RequestDecorator>::value,
281 "RequestDecorator requirements not met");
282 error_code ec;
283 handshake_ex(host, target, decorator, ec);
284 if(ec)
285 BOOST_THROW_EXCEPTION(system_error{ec});
286 }
287
288 template<class NextLayer>
289 template<class RequestDecorator>
290 void
291 stream<NextLayer>::
292 handshake_ex(response_type& res,
293 string_view host,
294 string_view target,
295 RequestDecorator const& decorator)
296 {
297 static_assert(is_sync_stream<next_layer_type>::value,
298 "SyncStream requirements not met");
299 static_assert(detail::is_RequestDecorator<
300 RequestDecorator>::value,
301 "RequestDecorator requirements not met");
302 error_code ec;
303 handshake_ex(res, host, target, decorator, ec);
304 if(ec)
305 BOOST_THROW_EXCEPTION(system_error{ec});
306 }
307
308 template<class NextLayer>
309 void
310 stream<NextLayer>::
311 handshake(string_view host,
312 string_view target, error_code& ec)
313 {
314 static_assert(is_sync_stream<next_layer_type>::value,
315 "SyncStream requirements not met");
316 do_handshake(nullptr,
317 host, target, &default_decorate_req, ec);
318 }
319
320 template<class NextLayer>
321 void
322 stream<NextLayer>::
323 handshake(response_type& res,
324 string_view host,
325 string_view target,
326 error_code& ec)
327 {
328 static_assert(is_sync_stream<next_layer_type>::value,
329 "SyncStream requirements not met");
330 do_handshake(&res,
331 host, target, &default_decorate_req, ec);
332 }
333
334 template<class NextLayer>
335 template<class RequestDecorator>
336 void
337 stream<NextLayer>::
338 handshake_ex(string_view host,
339 string_view target,
340 RequestDecorator const& decorator,
341 error_code& ec)
342 {
343 static_assert(is_sync_stream<next_layer_type>::value,
344 "SyncStream requirements not met");
345 static_assert(detail::is_RequestDecorator<
346 RequestDecorator>::value,
347 "RequestDecorator requirements not met");
348 do_handshake(nullptr,
349 host, target, decorator, ec);
350 }
351
352 template<class NextLayer>
353 template<class RequestDecorator>
354 void
355 stream<NextLayer>::
356 handshake_ex(response_type& res,
357 string_view host,
358 string_view target,
359 RequestDecorator const& decorator,
360 error_code& ec)
361 {
362 static_assert(is_sync_stream<next_layer_type>::value,
363 "SyncStream requirements not met");
364 static_assert(detail::is_RequestDecorator<
365 RequestDecorator>::value,
366 "RequestDecorator requirements not met");
367 do_handshake(&res,
368 host, target, decorator, ec);
369 }
370
371 //------------------------------------------------------------------------------
372
373 template<class NextLayer>
374 template<class RequestDecorator>
375 void
376 stream<NextLayer>::
377 do_handshake(
378 response_type* res_p,
379 string_view host,
380 string_view target,
381 RequestDecorator const& decorator,
382 error_code& ec)
383 {
384 response_type res;
385 reset();
386 detail::sec_ws_key_type key;
387 {
388 auto const req = build_request(
389 key, host, target, decorator);
390 pmd_read(pmd_config_, req);
391 http::write(stream_, req, ec);
392 }
393 if(ec)
394 return;
395 http::read(next_layer(), rd_buf_, res, ec);
396 if(ec)
397 return;
398 on_response(res, key, ec);
399 if(res_p)
400 *res_p = std::move(res);
401 }
402
403 } // websocket
404 } // beast
405 } // boost
406
407 #endif