forked from boostorg/beast
fix #80, #212, fix #303, fix #314, fix #317 websocket::stream now provides the following families of functions for performing handshakes: When operating in the server role: * stream::accept * stream::accept_ex * stream::async_accept * stream::async_accept_ex When operating in the client role: * stream::handshake * stream::handshake_ex * stream::async_handshake * stream::async_handshake_ex Member functions ending with "_ex" allow an additional RequestDecorator parameter (for the accept family of functions) or ResponseDecorator parameter (for the handshake family of functions). The decorator is called to optionally modify the contents of the HTTP request or HTTP response object generated by the implementation, before the message is sent. This permits callers to set the User-Agent or Server fields, add or modify HTTP fields related to subprotocols, or perform any required transformation of the HTTP message for application-specific needs. The handshake() family of functions now have an additional set of overloads accepting a parameter of type response_type&, allowing the caller to receive the HTTP Response to the Upgrade handshake. This permits inspection of the response to handle things like subprotocols, authentication, or other application-specific needs. The new implementation does not require any state to be stored in the stream object. Therefore, websocket::stream objects are now smaller in size. The overload of set_option for setting a decorator on the stream is removed. The only way to set decorators now is with a suitable overload of accept or handshake.
141 lines
3.5 KiB
C++
141 lines
3.5 KiB
C++
//
|
|
// Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
|
|
//
|
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
//
|
|
|
|
#ifndef BEAST_TEST_STRING_OSTREAM_HPP
|
|
#define BEAST_TEST_STRING_OSTREAM_HPP
|
|
|
|
#include <beast/core/async_completion.hpp>
|
|
#include <beast/core/bind_handler.hpp>
|
|
#include <beast/core/error.hpp>
|
|
#include <beast/websocket/teardown.hpp>
|
|
#include <boost/asio/buffer.hpp>
|
|
#include <boost/asio/io_service.hpp>
|
|
#include <string>
|
|
|
|
namespace beast {
|
|
namespace test {
|
|
|
|
class string_ostream
|
|
{
|
|
boost::asio::io_service& ios_;
|
|
|
|
public:
|
|
std::string str;
|
|
|
|
explicit
|
|
string_ostream(boost::asio::io_service& ios)
|
|
: ios_(ios)
|
|
{
|
|
}
|
|
|
|
boost::asio::io_service&
|
|
get_io_service()
|
|
{
|
|
return ios_;
|
|
}
|
|
|
|
template<class MutableBufferSequence>
|
|
std::size_t
|
|
read_some(MutableBufferSequence const& buffers)
|
|
{
|
|
error_code ec;
|
|
auto const n = read_some(buffers, ec);
|
|
if(ec)
|
|
throw system_error{ec};
|
|
return n;
|
|
}
|
|
|
|
template<class MutableBufferSequence>
|
|
std::size_t
|
|
read_some(MutableBufferSequence const& buffers,
|
|
error_code& ec)
|
|
{
|
|
ec = boost::asio::error::eof;
|
|
return 0;
|
|
}
|
|
|
|
template<class MutableBufferSequence, class ReadHandler>
|
|
typename async_completion<ReadHandler,
|
|
void(error_code, std::size_t)>::result_type
|
|
async_read_some(MutableBufferSequence const& buffers,
|
|
ReadHandler&& handler)
|
|
{
|
|
async_completion<ReadHandler,
|
|
void(error_code, std::size_t)> completion{handler};
|
|
ios_.post(bind_handler(completion.handler,
|
|
boost::asio::error::eof, 0));
|
|
return completion.result.get();
|
|
}
|
|
|
|
template<class ConstBufferSequence>
|
|
std::size_t
|
|
write_some(ConstBufferSequence const& buffers)
|
|
{
|
|
error_code ec;
|
|
auto const n = write_some(buffers, ec);
|
|
if(ec)
|
|
throw system_error{ec};
|
|
return n;
|
|
}
|
|
|
|
template<class ConstBufferSequence>
|
|
std::size_t
|
|
write_some(
|
|
ConstBufferSequence const& buffers, error_code&)
|
|
{
|
|
auto const n = buffer_size(buffers);
|
|
using boost::asio::buffer_size;
|
|
using boost::asio::buffer_cast;
|
|
str.reserve(str.size() + n);
|
|
for(auto const& buffer : buffers)
|
|
str.append(buffer_cast<char const*>(buffer),
|
|
buffer_size(buffer));
|
|
return n;
|
|
}
|
|
|
|
template<class ConstBufferSequence, class WriteHandler>
|
|
typename async_completion<
|
|
WriteHandler, void(error_code)>::result_type
|
|
async_write_some(ConstBufferSequence const& buffers,
|
|
WriteHandler&& handler)
|
|
{
|
|
error_code ec;
|
|
auto const bytes_transferred = write_some(buffers, ec);
|
|
async_completion<
|
|
WriteHandler, void(error_code, std::size_t)
|
|
> completion{handler};
|
|
get_io_service().post(
|
|
bind_handler(completion.handler, ec, bytes_transferred));
|
|
return completion.result.get();
|
|
}
|
|
|
|
friend
|
|
void
|
|
teardown(websocket::teardown_tag,
|
|
string_ostream& stream,
|
|
boost::system::error_code& ec)
|
|
{
|
|
}
|
|
|
|
template<class TeardownHandler>
|
|
friend
|
|
void
|
|
async_teardown(websocket::teardown_tag,
|
|
string_ostream& stream,
|
|
TeardownHandler&& handler)
|
|
{
|
|
stream.get_io_service().post(
|
|
bind_handler(std::move(handler),
|
|
error_code{}));
|
|
}
|
|
};
|
|
|
|
} // test
|
|
} // beast
|
|
|
|
#endif
|