File indexing completed on 2025-01-18 09:29:33
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_BEAST_WEBSOCKET_IMPL_HANDSHAKE_HPP
0011 #define BOOST_BEAST_WEBSOCKET_IMPL_HANDSHAKE_HPP
0012
0013 #include <boost/beast/websocket/impl/stream_impl.hpp>
0014 #include <boost/beast/websocket/detail/type_traits.hpp>
0015 #include <boost/beast/http/empty_body.hpp>
0016 #include <boost/beast/http/message.hpp>
0017 #include <boost/beast/http/read.hpp>
0018 #include <boost/beast/http/write.hpp>
0019 #include <boost/beast/core/async_base.hpp>
0020 #include <boost/beast/core/flat_buffer.hpp>
0021 #include <boost/beast/core/stream_traits.hpp>
0022 #include <boost/asio/coroutine.hpp>
0023 #include <boost/assert.hpp>
0024 #include <boost/throw_exception.hpp>
0025 #include <memory>
0026
0027 namespace boost {
0028 namespace beast {
0029 namespace websocket {
0030
0031
0032
0033
0034
0035 template<class NextLayer, bool deflateSupported>
0036 template<class Handler>
0037 class stream<NextLayer, deflateSupported>::handshake_op
0038 : public beast::stable_async_base<Handler,
0039 beast::executor_type<stream>>
0040 , public asio::coroutine
0041 {
0042 struct data
0043 {
0044
0045
0046 request_type req;
0047 http::response_parser<
0048 typename response_type::body_type> p;
0049 flat_buffer fb;
0050 bool overflow = false;
0051
0052 explicit
0053 data(request_type&& req_)
0054 : req(std::move(req_))
0055 {
0056 }
0057 };
0058
0059 boost::weak_ptr<impl_type> wp_;
0060 detail::sec_ws_key_type key_;
0061 response_type* res_p_;
0062 data& d_;
0063
0064 public:
0065 template<class Handler_>
0066 handshake_op(
0067 Handler_&& h,
0068 boost::shared_ptr<impl_type> const& sp,
0069 request_type&& req,
0070 detail::sec_ws_key_type key,
0071 response_type* res_p)
0072 : stable_async_base<Handler,
0073 beast::executor_type<stream>>(
0074 std::forward<Handler_>(h),
0075 sp->stream().get_executor())
0076 , wp_(sp)
0077 , key_(key)
0078 , res_p_(res_p)
0079 , d_(beast::allocate_stable<data>(
0080 *this, std::move(req)))
0081 {
0082 sp->reset();
0083 (*this)({}, 0, false);
0084 }
0085
0086 void
0087 operator()(
0088 error_code ec = {},
0089 std::size_t bytes_used = 0,
0090 bool cont = true)
0091 {
0092 boost::ignore_unused(bytes_used);
0093 auto sp = wp_.lock();
0094 if(! sp)
0095 {
0096 BOOST_BEAST_ASSIGN_EC(ec, net::error::operation_aborted);
0097 return this->complete(cont, ec);
0098 }
0099 auto& impl = *sp;
0100 BOOST_ASIO_CORO_REENTER(*this)
0101 {
0102 impl.change_status(status::handshake);
0103 impl.update_timer(this->get_executor());
0104
0105
0106 impl.do_pmd_config(d_.req);
0107 BOOST_ASIO_CORO_YIELD
0108 {
0109 BOOST_ASIO_HANDLER_LOCATION((
0110 __FILE__, __LINE__,
0111 "websocket::async_handshake"));
0112
0113 http::async_write(impl.stream(),
0114 d_.req, std::move(*this));
0115 }
0116 if(impl.check_stop_now(ec))
0117 goto upcall;
0118
0119
0120 BOOST_ASIO_CORO_YIELD
0121 {
0122 BOOST_ASIO_HANDLER_LOCATION((
0123 __FILE__, __LINE__,
0124 "websocket::async_handshake"));
0125
0126 http::async_read(impl.stream(),
0127 impl.rd_buf, d_.p,
0128 std::move(*this));
0129 }
0130 if(ec == http::error::buffer_overflow)
0131 {
0132
0133
0134
0135
0136 d_.fb.commit(net::buffer_copy(
0137 d_.fb.prepare(impl.rd_buf.size()),
0138 impl.rd_buf.data()));
0139 impl.rd_buf.clear();
0140
0141 BOOST_ASIO_CORO_YIELD
0142 {
0143 BOOST_ASIO_HANDLER_LOCATION((
0144 __FILE__, __LINE__,
0145 "websocket::async_handshake"));
0146
0147 http::async_read(impl.stream(),
0148 d_.fb, d_.p, std::move(*this));
0149 }
0150
0151 if(! ec)
0152 {
0153
0154
0155
0156
0157 if(d_.fb.size() <= impl.rd_buf.capacity())
0158 {
0159 impl.rd_buf.commit(net::buffer_copy(
0160 impl.rd_buf.prepare(d_.fb.size()),
0161 d_.fb.data()));
0162 }
0163 else
0164 {
0165 BOOST_BEAST_ASSIGN_EC(ec, http::error::buffer_overflow);
0166 }
0167 }
0168
0169
0170 d_.fb.clear();
0171 }
0172 if(impl.check_stop_now(ec))
0173 goto upcall;
0174
0175
0176 impl.reset_idle();
0177 impl.on_response(d_.p.get(), key_, ec);
0178 if(res_p_)
0179 swap(d_.p.get(), *res_p_);
0180
0181 upcall:
0182 this->complete(cont ,ec);
0183 }
0184 }
0185 };
0186
0187 template<class NextLayer, bool deflateSupported>
0188 struct stream<NextLayer, deflateSupported>::
0189 run_handshake_op
0190 {
0191 template<class HandshakeHandler>
0192 void operator()(
0193 HandshakeHandler&& h,
0194 boost::shared_ptr<impl_type> const& sp,
0195 request_type&& req,
0196 detail::sec_ws_key_type key,
0197 response_type* res_p)
0198 {
0199
0200
0201
0202
0203 static_assert(
0204 beast::detail::is_invocable<HandshakeHandler,
0205 void(error_code)>::value,
0206 "HandshakeHandler type requirements not met");
0207
0208 handshake_op<
0209 typename std::decay<HandshakeHandler>::type>(
0210 std::forward<HandshakeHandler>(h),
0211 sp, std::move(req), key, res_p);
0212 }
0213 };
0214
0215
0216
0217 template<class NextLayer, bool deflateSupported>
0218 template<class RequestDecorator>
0219 void
0220 stream<NextLayer, deflateSupported>::
0221 do_handshake(
0222 response_type* res_p,
0223 string_view host,
0224 string_view target,
0225 RequestDecorator const& decorator,
0226 error_code& ec)
0227 {
0228 if(res_p)
0229 res_p->result(http::status::internal_server_error);
0230
0231 auto& impl = *impl_;
0232 impl.change_status(status::handshake);
0233 impl.reset();
0234 detail::sec_ws_key_type key;
0235 {
0236 auto const req = impl.build_request(
0237 key, host, target, decorator);
0238 impl.do_pmd_config(req);
0239 http::write(impl.stream(), req, ec);
0240 }
0241 if(impl.check_stop_now(ec))
0242 return;
0243 http::response_parser<
0244 typename response_type::body_type> p;
0245 http::read(next_layer(), impl.rd_buf, p, ec);
0246 if(ec == http::error::buffer_overflow)
0247 {
0248
0249
0250
0251
0252 flat_buffer fb;
0253 fb.commit(net::buffer_copy(
0254 fb.prepare(impl.rd_buf.size()),
0255 impl.rd_buf.data()));
0256 impl.rd_buf.clear();
0257
0258 http::read(next_layer(), fb, p, ec);;
0259
0260 if(! ec)
0261 {
0262
0263
0264
0265
0266 if(fb.size() <= impl.rd_buf.capacity())
0267 {
0268 impl.rd_buf.commit(net::buffer_copy(
0269 impl.rd_buf.prepare(fb.size()),
0270 fb.data()));
0271 }
0272 else
0273 {
0274 BOOST_BEAST_ASSIGN_EC(ec, http::error::buffer_overflow);
0275 }
0276 }
0277 }
0278 if(impl.check_stop_now(ec))
0279 return;
0280
0281 if (res_p)
0282 {
0283
0284 *res_p = p.release();
0285 }
0286 else
0287 {
0288
0289 res_p = &p.get();
0290 }
0291
0292 impl.on_response(*res_p, key, ec);
0293 }
0294
0295
0296
0297 template<class NextLayer, bool deflateSupported>
0298 template<BOOST_BEAST_ASYNC_TPARAM1 HandshakeHandler>
0299 BOOST_BEAST_ASYNC_RESULT1(HandshakeHandler)
0300 stream<NextLayer, deflateSupported>::
0301 async_handshake(
0302 string_view host,
0303 string_view target,
0304 HandshakeHandler&& handler)
0305 {
0306 static_assert(is_async_stream<next_layer_type>::value,
0307 "AsyncStream type requirements not met");
0308 detail::sec_ws_key_type key;
0309 auto req = impl_->build_request(
0310 key, host, target, &default_decorate_req);
0311 return net::async_initiate<
0312 HandshakeHandler,
0313 void(error_code)>(
0314 run_handshake_op{},
0315 handler,
0316 impl_,
0317 std::move(req),
0318 key,
0319 nullptr);
0320 }
0321
0322 template<class NextLayer, bool deflateSupported>
0323 template<BOOST_BEAST_ASYNC_TPARAM1 HandshakeHandler>
0324 BOOST_BEAST_ASYNC_RESULT1(HandshakeHandler)
0325 stream<NextLayer, deflateSupported>::
0326 async_handshake(
0327 response_type& res,
0328 string_view host,
0329 string_view target,
0330 HandshakeHandler&& handler)
0331 {
0332 static_assert(is_async_stream<next_layer_type>::value,
0333 "AsyncStream type requirements not met");
0334 detail::sec_ws_key_type key;
0335 auto req = impl_->build_request(
0336 key, host, target, &default_decorate_req);
0337 res.result(http::status::internal_server_error);
0338 return net::async_initiate<
0339 HandshakeHandler,
0340 void(error_code)>(
0341 run_handshake_op{},
0342 handler,
0343 impl_,
0344 std::move(req),
0345 key,
0346 &res);
0347 }
0348
0349 template<class NextLayer, bool deflateSupported>
0350 void
0351 stream<NextLayer, deflateSupported>::
0352 handshake(string_view host,
0353 string_view target)
0354 {
0355 static_assert(is_sync_stream<next_layer_type>::value,
0356 "SyncStream type requirements not met");
0357 error_code ec;
0358 handshake(
0359 host, target, ec);
0360 if(ec)
0361 BOOST_THROW_EXCEPTION(system_error{ec});
0362 }
0363
0364 template<class NextLayer, bool deflateSupported>
0365 void
0366 stream<NextLayer, deflateSupported>::
0367 handshake(response_type& res,
0368 string_view host,
0369 string_view target)
0370 {
0371 static_assert(is_sync_stream<next_layer_type>::value,
0372 "SyncStream type requirements not met");
0373 error_code ec;
0374 handshake(res, host, target, ec);
0375 if(ec)
0376 BOOST_THROW_EXCEPTION(system_error{ec});
0377 }
0378
0379 template<class NextLayer, bool deflateSupported>
0380 void
0381 stream<NextLayer, deflateSupported>::
0382 handshake(string_view host,
0383 string_view target, error_code& ec)
0384 {
0385 static_assert(is_sync_stream<next_layer_type>::value,
0386 "SyncStream type requirements not met");
0387 do_handshake(nullptr,
0388 host, target, &default_decorate_req, ec);
0389 }
0390
0391 template<class NextLayer, bool deflateSupported>
0392 void
0393 stream<NextLayer, deflateSupported>::
0394 handshake(response_type& res,
0395 string_view host,
0396 string_view target,
0397 error_code& ec)
0398 {
0399 static_assert(is_sync_stream<next_layer_type>::value,
0400 "SyncStream type requirements not met");
0401 do_handshake(&res,
0402 host, target, &default_decorate_req, ec);
0403 }
0404
0405 }
0406 }
0407 }
0408
0409 #endif