2 // Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
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)
8 #ifndef BEAST_WEBSOCKET_IMPL_HANDSHAKE_IPP
9 #define BEAST_WEBSOCKET_IMPL_HANDSHAKE_IPP
11 #include <beast/http/message.hpp>
12 #include <beast/http/read.hpp>
13 #include <beast/http/streambuf_body.hpp>
14 #include <beast/http/write.hpp>
15 #include <beast/core/handler_helpers.hpp>
16 #include <beast/core/handler_ptr.hpp>
17 #include <beast/core/stream_concepts.hpp>
18 #include <boost/assert.hpp>
24 //------------------------------------------------------------------------------
26 // send the upgrade request and process the response
28 template<class NextLayer>
29 template<class Handler>
30 class stream<NextLayer>::handshake_op
35 stream<NextLayer>& ws;
37 http::request_header req;
38 http::response<http::streambuf_body> res;
41 data(Handler& handler, stream<NextLayer>& ws_,
42 boost::string_ref const& host,
43 boost::string_ref const& resource)
44 : cont(beast_asio_helpers::
45 is_continuation(handler))
47 , req(ws.build_request(host, resource, key))
53 handler_ptr<data, Handler> d_;
56 handshake_op(handshake_op&&) = default;
57 handshake_op(handshake_op const&) = default;
59 template<class DeducedHandler, class... Args>
60 handshake_op(DeducedHandler&& h,
61 stream<NextLayer>& ws, Args&&... args)
62 : d_(std::forward<DeducedHandler>(h),
63 ws, std::forward<Args>(args)...)
65 (*this)(error_code{}, false);
69 operator()(error_code ec, bool again = true);
72 void* asio_handler_allocate(
73 std::size_t size, handshake_op* op)
75 return beast_asio_helpers::
76 allocate(size, op->d_.handler());
80 void asio_handler_deallocate(
81 void* p, std::size_t size, handshake_op* op)
83 return beast_asio_helpers::
84 deallocate(p, size, op->d_.handler());
88 bool asio_handler_is_continuation(handshake_op* op)
93 template<class Function>
95 void asio_handler_invoke(Function&& f, handshake_op* op)
97 return beast_asio_helpers::
98 invoke(f, op->d_.handler());
102 template<class NextLayer>
103 template<class Handler>
105 stream<NextLayer>::handshake_op<Handler>::
106 operator()(error_code ec, bool again)
109 d.cont = d.cont || again;
110 while(! ec && d.state != 99)
118 // VFALCO Do we need the ability to move
119 // a message on the async_write?
121 d.ws.pmd_config_, d.req.fields);
122 http::async_write(d.ws.stream_,
123 d.req, std::move(*this));
129 // read http response
131 http::async_read(d.ws.next_layer(),
132 d.ws.stream_.buffer(), d.res,
139 d.ws.do_response(d.res, d.key, ec);
149 template<class NextLayer>
150 template<class HandshakeHandler>
151 typename async_completion<
152 HandshakeHandler, void(error_code)>::result_type
154 async_handshake(boost::string_ref const& host,
155 boost::string_ref const& resource, HandshakeHandler&& handler)
157 static_assert(is_AsyncStream<next_layer_type>::value,
158 "AsyncStream requirements not met");
159 beast::async_completion<
160 HandshakeHandler, void(error_code)
161 > completion{handler};
162 handshake_op<decltype(completion.handler)>{
163 completion.handler, *this, host, resource};
164 return completion.result.get();
167 template<class NextLayer>
170 handshake(boost::string_ref const& host,
171 boost::string_ref const& resource)
173 static_assert(is_SyncStream<next_layer_type>::value,
174 "SyncStream requirements not met");
176 handshake(host, resource, ec);
178 throw system_error{ec};
181 template<class NextLayer>
184 handshake(boost::string_ref const& host,
185 boost::string_ref const& resource, error_code& ec)
187 static_assert(is_SyncStream<next_layer_type>::value,
188 "SyncStream requirements not met");
193 build_request(host, resource, key);
194 pmd_read(pmd_config_, req.fields);
195 http::write(stream_, req, ec);
199 http::response<http::streambuf_body> res;
200 http::read(next_layer(), stream_.buffer(), res, ec);
203 do_response(res, key, ec);
206 //------------------------------------------------------------------------------