Merge commit '2f9a8440c2432d8a196571d6300404cb76314125' into develop

This commit is contained in:
Vinnie Falco
2016-09-15 14:21:55 -04:00
134 changed files with 2838 additions and 2670 deletions

View File

@@ -47,7 +47,7 @@ namespace beast {
@note See <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3896.pdf">
Library Foundations For Asynchronous Operations</a>
*/
template <class CompletionHandler, class Signature>
template<class CompletionHandler, class Signature>
struct async_completion
{
/** The type of the final handler called by the asynchronous initiation function.

View File

@@ -14,10 +14,10 @@
namespace beast {
/** Adapts a @b `MutableBufferSequence` into a @b `Streambuf`.
/** Adapts a @b `MutableBufferSequence` into a @b `DynamicBuffer`.
This class wraps a @b `MutableBufferSequence` to meet the requirements
of @b `Streambuf`. Upon construction the input and output sequences are
of @b `DynamicBuffer`. Upon construction the input and output sequences are
empty. A copy of the mutable buffer sequence object is stored; however,
ownership of the underlying memory is not transferred. The caller is
responsible for making sure that referenced memory remains valid

View File

@@ -44,7 +44,7 @@ namespace detail {
*/
template <class = void>
template<class = void>
std::string const&
base64_alphabet()
{
@@ -62,7 +62,7 @@ is_base64(unsigned char c)
return (std::isalnum(c) || (c == '+') || (c == '/'));
}
template <class = void>
template<class = void>
std::string
base64_encode (std::uint8_t const* data,
std::size_t in_len)
@@ -112,7 +112,7 @@ base64_encode (std::uint8_t const* data,
}
template <class = void>
template<class = void>
std::string
base64_encode (std::string const& s)
{
@@ -120,11 +120,11 @@ base64_encode (std::string const& s)
std::uint8_t const*> (s.data()), s.size());
}
template <class = void>
template<class = void>
std::string
base64_decode(std::string const& data)
{
int in_len = data.size();
auto in_len = data.size();
unsigned char c3[3], c4[4];
int i = 0;
int j = 0;

View File

@@ -54,14 +54,14 @@ public:
operator()()
{
invoke(h_, args_,
index_sequence_for<Args...> ());
index_sequence_for<Args...>());
}
void
operator()() const
{
invoke(h_, args_,
index_sequence_for<Args...> ());
index_sequence_for<Args...>());
}
friend

View File

@@ -14,7 +14,7 @@
namespace beast {
namespace detail {
template <class T>
template<class T>
struct empty_base_optimization_decide
: std::integral_constant <bool,
std::is_empty <T>::value
@@ -25,7 +25,7 @@ struct empty_base_optimization_decide
{
};
template <
template<
class T,
int UniqueID = 0,
bool ShouldDeriveFrom =
@@ -57,7 +57,7 @@ public:
//------------------------------------------------------------------------------
template <
template<
class T,
int UniqueID
>

View File

@@ -13,7 +13,7 @@
namespace beast {
namespace detail {
template <class R, class C, class ...A>
template<class R, class C, class ...A>
auto
is_call_possible_test(C&& c, int, A&& ...a)
-> decltype(std::is_convertible<
@@ -21,7 +21,7 @@ is_call_possible_test(C&& c, int, A&& ...a)
std::is_same<R, void>::value,
std::true_type());
template <class R, class C, class ...A>
template<class R, class C, class ...A>
std::false_type
is_call_possible_test(C&& c, long, A&& ...a);
@@ -30,13 +30,13 @@ is_call_possible_test(C&& c, long, A&& ...a);
is_call_possible<T, void(std::string)>
*/
/** @{ */
template <class C, class F>
template<class C, class F>
struct is_call_possible
: std::false_type
{
};
template <class C, class R, class ...A>
template<class C, class R, class ...A>
struct is_call_possible<C, R(A...)>
: decltype(is_call_possible_test<R>(
std::declval<C>(), 1, std::declval<A>()...))

View File

@@ -281,10 +281,10 @@ finish(sha1_context& ctx, void* digest) noexcept
ctx.buf[ctx.buflen++] = 0x00;
std::uint32_t block[BLOCK_INTS];
sha1::make_block(ctx.buf, block);
if (buflen > BLOCK_BYTES - 8)
if(buflen > BLOCK_BYTES - 8)
{
sha1::transform(ctx.digest, block);
for (size_t i = 0; i < BLOCK_INTS - 2; i++)
for(size_t i = 0; i < BLOCK_INTS - 2; i++)
block[i] = 0;
}

View File

@@ -34,7 +34,7 @@ class has_get_io_service
decltype(std::declval<U>().get_io_service()),
boost::asio::io_service&>>
static R check(int);
template <class>
template<class>
static std::false_type check(...);
public:
using type = decltype(check<T>(0));

View File

@@ -227,7 +227,7 @@ public:
/// Write the given data to the stream. Returns the number of bytes written,
/// or 0 if an error occurred.
template <class ConstBufferSequence>
template<class ConstBufferSequence>
std::size_t
write_some(ConstBufferSequence const& buffers,
error_code& ec)

View File

@@ -34,10 +34,10 @@ namespace beast {
caller is still responsible for freeing memory.
*/
#if GENERATING_DOCS
template <class T, class CompletionHandler>
template<class T, class CompletionHandler>
class handler_alloc;
#else
template <class T, class CompletionHandler>
template<class T, class CompletionHandler>
class handler_alloc
{
private:
@@ -46,7 +46,7 @@ private:
// should produce a compile error if CompletionHandler is not
// constructible from H.
//
template <class U, class H>
template<class U, class H>
friend class handler_alloc;
CompletionHandler h_;

View File

@@ -85,7 +85,7 @@ public:
is_continuation(op->d_->h);
}
template <class Function>
template<class Function>
friend
void asio_handler_invoke(Function&& f, read_some_op* op)
{

View File

@@ -129,7 +129,7 @@ protected:
//------------------------------------------------------------------------------
/** A `Streambuf` with a fixed size internal buffer.
/** A `DynamicBuffer` with a fixed size internal buffer.
@tparam N The number of bytes in the internal buffer.

View File

@@ -12,14 +12,14 @@
namespace beast {
/** A @b `Streambuf` that uses multiple buffers internally.
/** A @b `DynamicBuffer` that uses multiple buffers internally.
The implementation uses a sequence of one or more character arrays
of varying sizes. Additional character array objects are appended to
the sequence to accommodate changes in the size of the character
sequence.
@note Meets the requirements of @b `Streambuf`.
@note Meets the requirements of @b `DynamicBuffer`.
*/
using streambuf = basic_streambuf<std::allocator<char>>;

View File

@@ -105,7 +105,7 @@ protected:
using list_t = typename boost::intrusive::make_list<
element, boost::intrusive::constant_time_size<false>>::type;
using set_t = typename boost::intrusive::make_set<
using set_t = typename boost::intrusive::make_multiset<
element, boost::intrusive::constant_time_size<true>,
boost::intrusive::compare<less>>::type;
@@ -117,7 +117,6 @@ protected:
: set_(std::move(set))
, list_(std::move(list))
{
}
public:
@@ -244,9 +243,10 @@ public:
value.
Field names are stored as-is, but comparison are case-insensitive.
The container preserves the order of insertion of fields with
different names. For fields with the same name, the implementation
concatenates values inserted with duplicate names as per rfc7230.
When the container is iterated, the fields are presented in the order
of insertion. For fields with the same name, the container behaves
as a std::multiset; there will be a separate value for each occurrence
of the field name.
@note Meets the requirements of @b `FieldSequence`.
*/
@@ -359,27 +359,44 @@ public:
return set_.size();
}
/** Returns `true` if the specified field exists. */
/// Returns `true` if the specified field exists.
bool
exists(boost::string_ref const& name) const
{
return set_.find(name, less{}) != set_.end();
}
/** Returns an iterator to the case-insensitive matching header. */
/// Returns the number of values for the specified field.
std::size_t
count(boost::string_ref const& name) const;
/** Returns an iterator to the case-insensitive matching field name.
If more than one field with the specified name exists, the
first field defined by insertion order is returned.
*/
iterator
find(boost::string_ref const& name) const;
/** Returns the value for a case-insensitive matching header, or "" */
/** Returns the value for a case-insensitive matching header, or `""`.
If more than one field with the specified name exists, the
first field defined by insertion order is returned.
*/
boost::string_ref
operator[](boost::string_ref const& name) const;
/** Clear the contents of the basic_headers. */
/// Clear the contents of the basic_headers.
void
clear() noexcept;
/** Remove a field.
If more than one field with the specified name exists, all
matching fields will be removed.
@param name The name of the field(s) to remove.
@return The number of fields removed.
*/
std::size_t
@@ -387,39 +404,57 @@ public:
/** Insert a field value.
If a field value already exists the new value will be
extended as per RFC2616 Section 4.2.
If a field with the same name already exists, the
existing field is untouched and a new field value pair
is inserted into the container.
@param name The name of the field.
@param value A string holding the value of the field.
*/
// VFALCO TODO Consider allowing rvalue references for std::move?
void
insert(boost::string_ref const& name, boost::string_ref value);
/** Insert a field value.
If a field value already exists the new value will be
extended as per RFC2616 Section 4.2.
If a field with the same name already exists, the
existing field is untouched and a new field value pair
is inserted into the container.
@param name The name of the field
@param value The value of the field. The object will be
converted to a string using `boost::lexical_cast`.
*/
template<class T>
typename std::enable_if<
! std::is_constructible<boost::string_ref, T>::value>::type
insert(boost::string_ref name, T const& value)
{
insert(name,
boost::lexical_cast<std::string>(value));
insert(name, boost::lexical_cast<std::string>(value));
}
/** Replace a field value.
The current field value, if any, is removed. Then the
specified value is inserted as if by `insert(field, value)`.
First removes any values with matching field names, then
inserts the new field value.
@param name The name of the field.
@param value A string holding the value of the field.
*/
void
replace(boost::string_ref const& name, boost::string_ref value);
/** Replace a field value.
The current field value, if any, is removed. Then the
specified value is inserted as if by `insert(field, value)`.
First removes any values with matching field names, then
inserts the new field value.
@param name The name of the field
@param value The value of the field. The object will be
converted to a string using `boost::lexical_cast`.
*/
template<class T>
typename std::enable_if<

View File

@@ -482,7 +482,7 @@ private:
std::declval<error_code&>()),
std::true_type{})>
static R check(int);
template <class>
template<class>
static std::false_type check(...);
using type = decltype(check<C>(0));
public:
@@ -501,7 +501,7 @@ private:
std::declval<error_code&>()),
std::true_type{})>
static R check(int);
template <class>
template<class>
static std::false_type check(...);
using type = decltype(check<C>(0));
public:
@@ -520,7 +520,7 @@ private:
std::declval<error_code&>()),
std::true_type{})>
static R check(int);
template <class>
template<class>
static std::false_type check(...);
using type = decltype(check<C>(0));
public:
@@ -539,7 +539,7 @@ private:
std::declval<error_code&>()),
std::true_type{})>
static R check(int);
template <class>
template<class>
static std::false_type check(...);
using type = decltype(check<C>(0));
public:
@@ -557,7 +557,7 @@ private:
std::declval<error_code&>()),
std::true_type{})>
static R check(int);
template <class>
template<class>
static std::false_type check(...);
using type = decltype(check<C>(0));
public:
@@ -575,7 +575,7 @@ private:
std::declval<error_code&>()),
std::true_type{})>
static R check(int);
template <class>
template<class>
static std::false_type check(...);
using type = decltype(check<C>(0));
public:
@@ -594,7 +594,7 @@ private:
std::declval<error_code&>()),
std::true_type{})>
static R check(int);
template <class>
template<class>
static std::false_type check(...);
using type = decltype(check<C>(0));
public:
@@ -613,7 +613,7 @@ private:
std::declval<error_code&>()),
std::true_type{})>
static R check(int);
template <class>
template<class>
static std::false_type check(...);
using type = decltype(check<C>(0));
public:
@@ -630,7 +630,7 @@ private:
decltype(std::declval<T>().on_headers(
std::declval<std::uint64_t>(), std::declval<error_code&>()))>>
static R check(int);
template <class>
template<class>
static std::false_type check(...);
using type = decltype(check<C>(0));
public:
@@ -649,7 +649,7 @@ private:
std::declval<error_code&>()),
std::true_type{})>
static R check(int);
template <class>
template<class>
static std::false_type check(...);
using type = decltype(check<C>(0));
public:
@@ -667,7 +667,7 @@ private:
std::declval<error_code&>()),
std::true_type{})>
static R check(int);
template <class>
template<class>
static std::false_type check(...);
using type = decltype(check<C>(0));
public:

View File

@@ -29,7 +29,7 @@ class chunk_encode_text
// Storage for the longest hex string we might need, plus delimiters.
std::array<char, 2 * sizeof(std::size_t) + 2> buf_;
template <class OutIter>
template<class OutIter>
static
OutIter
to_hex(OutIter last, std::size_t n)

View File

@@ -22,7 +22,7 @@ class has_content_length_value
decltype(std::declval<U>().content_length()),
std::uint64_t>>
static R check(int);
template <class>
template<class>
static std::false_type check(...);
using type = decltype(check<T>(0));
public:

View File

@@ -9,6 +9,7 @@
#define BEAST_HTTP_IMPL_BASIC_HEADERS_IPP
#include <beast/http/detail/rfc7230.hpp>
#include <algorithm>
namespace beast {
namespace http {
@@ -204,6 +205,18 @@ basic_headers(FwdIt first, FwdIt last)
insert(first->name(), first->value());
}
template<class Allocator>
std::size_t
basic_headers<Allocator>::
count(boost::string_ref const& name) const
{
auto const it = set_.find(name, less{});
if(it == set_.end())
return 0;
auto const last = set_.upper_bound(name, less{});
return static_cast<std::size_t>(std::distance(it, last));
}
template<class Allocator>
auto
basic_headers<Allocator>::
@@ -221,11 +234,9 @@ boost::string_ref
basic_headers<Allocator>::
operator[](boost::string_ref const& name) const
{
// VFALCO This none object looks sketchy
static boost::string_ref const none;
auto const it = find(name);
if(it == end())
return none;
return {};
return it->second;
}
@@ -244,15 +255,23 @@ std::size_t
basic_headers<Allocator>::
erase(boost::string_ref const& name)
{
auto const it = set_.find(name, less{});
auto it = set_.find(name, less{});
if(it == set_.end())
return 0;
auto& e = *it;
set_.erase(set_.iterator_to(e));
list_.erase(list_.iterator_to(e));
alloc_traits::destroy(this->member(), &e);
alloc_traits::deallocate(this->member(), &e, 1);
return 1;
auto const last = set_.upper_bound(name, less{});
std::size_t n = 1;
for(;;)
{
auto& e = *it++;
set_.erase(set_.iterator_to(e));
list_.erase(list_.iterator_to(e));
alloc_traits::destroy(this->member(), &e);
alloc_traits::deallocate(this->member(), &e, 1);
if(it == last)
break;
++n;
}
return n;
}
template<class Allocator>
@@ -262,25 +281,10 @@ insert(boost::string_ref const& name,
boost::string_ref value)
{
value = detail::trim(value);
typename set_t::insert_commit_data d;
auto const result =
set_.insert_check(name, less{}, d);
if(result.second)
{
auto const p = alloc_traits::allocate(
this->member(), 1);
alloc_traits::construct(
this->member(), p, name, value);
list_.push_back(*p);
set_.insert_commit(*p, d);
return;
}
// If field already exists, insert comma
// separated value as per RFC2616 section 4.2
auto& cur = result.first->data.second;
cur.reserve(cur.size() + 1 + value.size());
cur.append(1, ',');
cur.append(value.data(), value.size());
auto const p = alloc_traits::allocate(this->member(), 1);
alloc_traits::construct(this->member(), p, name, value);
set_.insert_before(set_.upper_bound(name, less{}), *p);
list_.push_back(*p);
}
template<class Allocator>

View File

@@ -8,6 +8,7 @@
#ifndef BEAST_HTTP_IMPL_MESSAGE_V1_IPP
#define BEAST_HTTP_IMPL_MESSAGE_V1_IPP
#include <beast/core/error.hpp>
#include <beast/http/rfc7230.hpp>
#include <beast/http/detail/has_content_length.hpp>
#include <boost/optional.hpp>
@@ -87,7 +88,11 @@ prepare_content_length(prepare_info& pi,
std::true_type)
{
typename Body::writer w(msg);
//w.init(ec); // VFALCO This is a design problem!
// VFALCO This is a design problem!
error_code ec;
w.init(ec);
if(ec)
throw system_error{ec};
pi.content_length = w.content_length();
}

View File

@@ -91,7 +91,7 @@ public:
return op->d_->cont;
}
template <class Function>
template<class Function>
friend
void asio_handler_invoke(Function&& f, parse_op* op)
{
@@ -277,7 +277,7 @@ public:
return op->d_->cont;
}
template <class Function>
template<class Function>
friend
void asio_handler_invoke(Function&& f, read_op* op)
{
@@ -412,7 +412,7 @@ read(SyncReadStream& stream, DynamicBuffer& dynabuf,
static_assert(is_ReadableBody<Body>::value,
"ReadableBody requirements not met");
error_code ec;
read(stream, dynabuf, msg, ec);
beast::http::read(stream, dynabuf, msg, ec);
if(ec)
throw system_error{ec};
}
@@ -431,7 +431,7 @@ read(SyncReadStream& stream, DynamicBuffer& dynabuf,
static_assert(is_ReadableBody<Body>::value,
"ReadableBody requirements not met");
parser_v1<isRequest, Body, Headers> p;
parse(stream, dynabuf, p, ec);
beast::http::parse(stream, dynabuf, p, ec);
if(ec)
return;
assert(p.complete());

View File

@@ -262,7 +262,7 @@ public:
return op->d_->cont;
}
template <class Function>
template<class Function>
friend
void asio_handler_invoke(Function&& f, write_op* op)
{

View File

@@ -15,6 +15,8 @@ namespace http {
enum class parse_error
{
success = 0,
connection_closed,
bad_method,

View File

@@ -35,6 +35,37 @@ struct parser_response
} // detail
/** Skip body option.
The options controls whether or not the parser expects to see a
HTTP body, regardless of the presence or absence of certain fields
such as Content-Length.
Depending on the request, some responses do not carry a body.
For example, a 200 response to a CONNECT request from a tunneling
proxy. In these cases, callers use the @ref skip_body option to
inform the parser that no body is expected. The parser will consider
the message complete after the all headers have been received.
Example:
@code
parser_v1<true, empty_body, headers> p;
p.set_option(skip_body{true});
@endcode
@note Objects of this type are passed to @ref basic_parser_v1::set_option.
*/
struct skip_body
{
bool value;
explicit
skip_body(bool v)
: value(v)
{
}
};
/** A parser for producing HTTP/1 messages.
This class uses the basic HTTP/1 wire format parser to convert
@@ -62,6 +93,7 @@ private:
std::string value_;
message_type m_;
typename message_type::body_type::reader r_;
std::uint8_t skip_body_ = 0;
public:
parser_v1(parser_v1&&) = default;
@@ -81,6 +113,13 @@ public:
{
}
/// Set the expect body option.
void
set_option(skip_body const& o)
{
skip_body_ = o.value ? 1 : 0;
}
/** Returns the parsed message.
Only valid if `complete()` would return `true`.
@@ -176,7 +215,7 @@ private:
{
flush();
m_.version = 10 * this->http_major() + this->http_minor();
return 0;
return skip_body_;
}
void on_request(error_code& ec)

View File

@@ -30,6 +30,16 @@ namespace http {
the behavior of the container will be as if a string containing
only characters up to but excluding the first invalid character
was used to construct the list.
@code
for(auto const& param : param_list{";level=9;no_context_takeover;bits=15"})
{
std::cout << ";" << param.first;
if(! param.second.empty())
std::cout << "=" << param.second;
std::cout << "\n";
}
@endcode
*/
class param_list
{
@@ -98,6 +108,24 @@ public:
the behavior of the container will be as if a string containing
only characters up to but excluding the first invalid character
was used to construct the list.
To use this class, construct with the string to be parsed and
then use @ref begin and @end, or range-for to iterate each
item:
@code
for(auto const& ext : ext_list{"none, 7z;level=9, zip;no_context_takeover;bits=15"})
{
std::cout << ext.first << "\n";
for(auto const& param : ext.second)
{
std::cout << ";" << param.first;
if(! param.second.empty())
std::cout << "=" << param.second;
std::cout << "\n";
}
}
@endcode
*/
class ext_list
{
@@ -181,6 +209,15 @@ public:
the behavior of the container will be as if a string containing
only characters up to but excluding the first invalid character
was used to construct the list.
To use this class, construct with the string to be parsed and
then use @ref begin and @end, or range-for to iterate each
item:
@code
for(auto const& token : token_list{"apple, pear, banana"})
std::cout << token << "\n";
@endcode
*/
class token_list
{

View File

@@ -1,71 +0,0 @@
//
// Copyright (c) 2013-2016 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_HTTP_STATUS_HPP
#define BEAST_HTTP_STATUS_HPP
namespace beast {
namespace http {
/** Returns the string corresponding to the numeric HTTP status code. */
template<class = void>
char const*
status_text(int status)
{
switch(status)
{
case 100: return "Continue";
case 101: return "Switching Protocols";
case 200: return "OK";
case 201: return "Created";
case 202: return "Accepted";
case 203: return "Non-Authoritative Information";
case 204: return "No Content";
case 205: return "Reset Content";
case 206: return "Partial Content";
case 300: return "Multiple Choices";
case 301: return "Moved Permanently";
case 302: return "Found";
case 303: return "See Other";
case 304: return "Not Modified";
case 305: return "Use Proxy";
// case 306: return "<reserved>";
case 307: return "Temporary Redirect";
case 400: return "Bad Request";
case 401: return "Unauthorized";
case 402: return "Payment Required";
case 403: return "Forbidden";
case 404: return "Not Found";
case 405: return "Method Not Allowed";
case 406: return "Not Acceptable";
case 407: return "Proxy Authentication Required";
case 408: return "Request Timeout";
case 409: return "Conflict";
case 410: return "Gone";
case 411: return "Length Required";
case 412: return "Precondition Failed";
case 413: return "Request Entity Too Large";
case 414: return "Request-URI Too Long";
case 415: return "Unsupported Media Type";
case 416: return "Requested Range Not Satisfiable";
case 417: return "Expectation Failed";
case 500: return "Internal Server Error";
case 501: return "Not Implemented";
case 502: return "Bad Gateway";
case 503: return "Service Unavailable";
case 504: return "Gateway Timeout";
case 505: return "HTTP Version Not Supported";
default:
break;
}
return "Unknown HTTP status";
}
} // http
} // beast
#endif

View File

@@ -14,8 +14,8 @@
// BEAST_VERSION / 100 % 1000 is the minor version
// BEAST_VERSION / 100000 is the major version
//
#define BEAST_VERSION 100006
#define BEAST_VERSION 100000
#define BEAST_VERSION_STRING "1.0.0-b6"
#define BEAST_VERSION_STRING "1.0.0-b13"
#endif

View File

@@ -110,7 +110,7 @@ is_valid(close_code::value code)
if(v >= 1016 && v <= 2999)
return false;
// not used
if(v >= 0 && v <= 999)
if(v <= 999)
return false;
return true;
}
@@ -136,12 +136,12 @@ write(DynamicBuffer& db, frame_header const& fh)
if(fh.rsv3)
b[0] |= 0x10;
b[1] = fh.mask ? 0x80 : 0x00;
if (fh.len <= 125)
if(fh.len <= 125)
{
b[1] |= fh.len;
n = 2;
}
else if (fh.len <= 65535)
else if(fh.len <= 65535)
{
b[1] |= 126;
::new(&b[2]) big_uint16_buf_t{

View File

@@ -113,7 +113,7 @@ mask_inplace_general(
{
using boost::asio::buffer_cast;
using boost::asio::buffer_size;
auto n = buffer_size(b);
auto const n = buffer_size(b);
auto p = buffer_cast<std::uint8_t*>(b);
for(auto i = n / sizeof(key); i; --i)
{
@@ -122,13 +122,14 @@ mask_inplace_general(
*p ^= (key >>16); ++p;
*p ^= (key >>24); ++p;
}
n %= sizeof(key);
switch(n)
auto const m =
static_cast<std::uint8_t>(n % sizeof(key));
switch(m)
{
case 3: p[2] ^= (key >>16);
case 2: p[1] ^= (key >> 8);
case 1: p[0] ^= key;
key = ror(key, n*8);
key = ror(key, m*8);
default:
break;
}
@@ -144,7 +145,7 @@ mask_inplace_general(
{
using boost::asio::buffer_cast;
using boost::asio::buffer_size;
auto n = buffer_size(b);
auto const n = buffer_size(b);
auto p = buffer_cast<std::uint8_t*>(b);
for(auto i = n / sizeof(key); i; --i)
{
@@ -157,8 +158,9 @@ mask_inplace_general(
*p ^= (key >>48); ++p;
*p ^= (key >>56); ++p;
}
n %= sizeof(key);
switch(n)
auto const m =
static_cast<std::uint8_t>(n % sizeof(key));
switch(m)
{
case 7: p[6] ^= (key >>16);
case 6: p[5] ^= (key >> 8);
@@ -167,7 +169,7 @@ mask_inplace_general(
case 3: p[2] ^= (key >>16);
case 2: p[1] ^= (key >> 8);
case 1: p[0] ^= key;
key = ror(key, n*8);
key = ror(key, m*8);
default:
break;
}

View File

@@ -131,7 +131,7 @@ utf8_checker_t<_>::write(BufferSequence const& bs)
{
using boost::asio::buffer_cast;
using boost::asio::buffer_size;
for (auto const& b : bs)
for(auto const& b : bs)
if(! write(buffer_cast<void const*>(b),
buffer_size(b)))
return false;

View File

@@ -16,8 +16,10 @@ namespace websocket {
/// Error codes returned from @ref stream operations.
enum class error
{
success = 0,
/// Both sides performed a WebSocket close
closed = 1,
closed,
/// WebSocket connection failed, protocol violation
failed,

View File

@@ -101,7 +101,7 @@ public:
return op->d_->cont;
}
template <class Function>
template<class Function>
friend
void asio_handler_invoke(Function&& f, accept_op* op)
{

View File

@@ -97,7 +97,7 @@ public:
return op->d_->cont;
}
template <class Function>
template<class Function>
friend
void asio_handler_invoke(Function&& f, close_op* op)
{

View File

@@ -93,7 +93,7 @@ public:
return op->d_->cont;
}
template <class Function>
template<class Function>
friend
void asio_handler_invoke(Function&& f, handshake_op* op)
{

View File

@@ -95,7 +95,7 @@ public:
return op->d_->cont;
}
template <class Function>
template<class Function>
friend
void asio_handler_invoke(Function&& f, ping_op* op)
{

View File

@@ -117,7 +117,7 @@ public:
return op->d_->cont;
}
template <class Function>
template<class Function>
friend
void asio_handler_invoke(Function&& f, read_frame_op* op)
{
@@ -252,7 +252,7 @@ operator()(error_code ec,std::size_t bytes_transferred, bool again)
break;
}
d.state = do_read_fh + 2;
if (n == 0)
if(n == 0)
{
bytes_transferred = 0;
break;

View File

@@ -88,7 +88,7 @@ public:
return op->d_->cont;
}
template <class Function>
template<class Function>
friend
void asio_handler_invoke(Function&& f, read_op* op)
{

View File

@@ -93,7 +93,7 @@ public:
return op->d_->cont;
}
template <class Function>
template<class Function>
friend
void asio_handler_invoke(Function&& f, response_op* op)
{

View File

@@ -93,7 +93,7 @@ public:
return op->d_->cont;
}
template <class Function>
template<class Function>
friend
void asio_handler_invoke(Function&& f,
teardown_ssl_op* op)
@@ -129,7 +129,7 @@ operator()(error_code ec, bool again)
template<class AsyncStream>
void
teardown(
teardown(teardown_tag,
boost::asio::ssl::stream<AsyncStream>& stream,
error_code& ec)
{
@@ -138,7 +138,7 @@ teardown(
template<class AsyncStream, class TeardownHandler>
void
async_teardown(
async_teardown(teardown_tag,
boost::asio::ssl::stream<AsyncStream>& stream,
TeardownHandler&& handler)
{

View File

@@ -920,7 +920,7 @@ build_request(boost::string_ref const& host,
boost::string_ref const& resource, std::string& key)
{
http::request_v1<http::empty_body> req;
req.url = "/";
req.url = { resource.data(), resource.size() };
req.version = 11;
req.method = "GET";
req.headers.insert("Host", host);

View File

@@ -80,7 +80,7 @@ public:
return op->d_->cont;
}
template <class Function>
template<class Function>
friend
void asio_handler_invoke(Function&& f,
teardown_tcp_op* op)
@@ -128,7 +128,7 @@ operator()(error_code ec, std::size_t, bool again)
inline
void
teardown(
teardown(teardown_tag,
boost::asio::ip::tcp::socket& socket,
error_code& ec)
{
@@ -151,7 +151,7 @@ teardown(
template<class TeardownHandler>
inline
void
async_teardown(
async_teardown(teardown_tag,
boost::asio::ip::tcp::socket& socket,
TeardownHandler&& handler)
{

View File

@@ -134,7 +134,7 @@ public:
return op->d_->cont;
}
template <class Function>
template<class Function>
friend
void asio_handler_invoke(Function&& f, write_frame_op* op)
{

View File

@@ -91,7 +91,7 @@ public:
return op->d_->cont;
}
template <class Function>
template<class Function>
friend
void asio_handler_invoke(Function&& f, write_op* op)
{

View File

@@ -31,7 +31,7 @@ namespace websocket {
*/
template<class SyncStream>
void
teardown(
teardown(teardown_tag,
boost::asio::ssl::stream<SyncStream>& stream,
error_code& ec);
@@ -62,7 +62,7 @@ teardown(
template<class AsyncStream, class TeardownHandler>
inline
void
async_teardown(
async_teardown(teardown_tag,
boost::asio::ssl::stream<AsyncStream>& stream,
TeardownHandler&& handler);

View File

@@ -13,8 +13,17 @@
#include <type_traits>
namespace beast {
namespace websocket {
/** Tag type used to find teardown and async_teardown overloads
Overloads of @ref teardown and @async_teardown for user defined
types must take a value of type @ref teardown_tag in the first
argument in order to be found by the implementation.
*/
struct teardown_tag {};
/** Tear down a connection.
This tears down a connection. The implementation will call
@@ -30,7 +39,19 @@ namespace websocket {
*/
template<class Socket>
void
teardown(Socket& socket, error_code& ec) = delete;
teardown(teardown_tag, Socket& socket, error_code& ec)
{
/*
If you are trying to use OpenSSL and this goes off, you need to
add an include for <beast/websocket/ssl.hpp>.
If you are creating an instance of beast::websocket::stream with your
own user defined type, you must provide an overload of teardown with
the corresponding signature (including the teardown_tag).
*/
static_assert(sizeof(Socket)==-1,
"Unknown Socket type in teardown.");
}
/** Start tearing down a connection.
@@ -49,7 +70,8 @@ teardown(Socket& socket, error_code& ec) = delete;
function signature of the handler must be:
@code void handler(
error_code const& error // result of operation
); @endcode
);
@endcode
Regardless of whether the asynchronous operation completes
immediately or not, the handler will not be invoked from within
this function. Invocation of the handler will be performed in a
@@ -58,57 +80,19 @@ teardown(Socket& socket, error_code& ec) = delete;
*/
template<class Socket, class TeardownHandler>
void
async_teardown(Socket& socket, TeardownHandler&& handler) = delete;
async_teardown(teardown_tag, Socket& socket, TeardownHandler&& handler)
{
/*
If you are trying to use OpenSSL and this goes off, you need to
add an include for <beast/websocket/ssl.hpp>.
//------------------------------------------------------------------------------
/** Tear down a `boost::asio::ip::tcp::socket`.
This tears down a connection. The implementation will call
the overload of this function based on the `Stream` parameter
used to consruct the socket. When `Stream` is a user defined
type, and not a `boost::asio::ip::tcp::socket` or any
`boost::asio::ssl::stream`, callers are responsible for
providing a suitable overload of this function.
@param socket The socket to tear down.
@param ec Set to the error if any occurred.
If you are creating an instance of beast::websocket::stream with your
own user defined type, you must provide an overload of teardown with
the corresponding signature (including the teardown_tag).
*/
void
teardown(
boost::asio::ip::tcp::socket& socket,
error_code& ec);
/** Start tearing down a `boost::asio::ip::tcp::socket`.
This begins tearing down a connection asynchronously.
The implementation will call the overload of this function
based on the `Stream` parameter used to consruct the socket.
When `Stream` is a user defined type, and not a
`boost::asio::ip::tcp::socket` or any `boost::asio::ssl::stream`,
callers are responsible for providing a suitable overload
of this function.
@param socket The socket to tear down.
@param handler The handler to be called when the request completes.
Copies will be made of the handler as required. The equivalent
function signature of the handler must be:
@code void handler(
error_code const& error // result of operation
); @endcode
Regardless of whether the asynchronous operation completes
immediately or not, the handler will not be invoked from within
this function. Invocation of the handler will be performed in a
manner equivalent to using boost::asio::io_service::post().
*/
template<class TeardownHandler>
void
async_teardown(
boost::asio::ip::tcp::socket& socket,
TeardownHandler&& handler);
static_assert(sizeof(Socket)==-1,
"Unknown Socket type in async_teardown.");
}
} // websocket
@@ -127,7 +111,7 @@ void
call_teardown(Socket& socket, error_code& ec)
{
using websocket::teardown;
teardown(socket, ec);
teardown(websocket::teardown_tag{}, socket, ec);
}
template<class Socket, class TeardownHandler>
@@ -136,12 +120,65 @@ void
call_async_teardown(Socket& socket, TeardownHandler&& handler)
{
using websocket::async_teardown;
async_teardown(socket,
async_teardown(websocket::teardown_tag{}, socket,
std::forward<TeardownHandler>(handler));
}
} // websocket_helpers
//------------------------------------------------------------------------------
namespace websocket {
/** Tear down a `boost::asio::ip::tcp::socket`.
This tears down a connection. The implementation will call
the overload of this function based on the `Stream` parameter
used to consruct the socket. When `Stream` is a user defined
type, and not a `boost::asio::ip::tcp::socket` or any
`boost::asio::ssl::stream`, callers are responsible for
providing a suitable overload of this function.
@param socket The socket to tear down.
@param ec Set to the error if any occurred.
*/
void
teardown(teardown_tag,
boost::asio::ip::tcp::socket& socket, error_code& ec);
/** Start tearing down a `boost::asio::ip::tcp::socket`.
This begins tearing down a connection asynchronously.
The implementation will call the overload of this function
based on the `Stream` parameter used to consruct the socket.
When `Stream` is a user defined type, and not a
`boost::asio::ip::tcp::socket` or any `boost::asio::ssl::stream`,
callers are responsible for providing a suitable overload
of this function.
@param socket The socket to tear down.
@param handler The handler to be called when the request completes.
Copies will be made of the handler as required. The equivalent
function signature of the handler must be:
@code void handler(
error_code const& error // result of operation
);
@endcode
Regardless of whether the asynchronous operation completes
immediately or not, the handler will not be invoked from within
this function. Invocation of the handler will be performed in a
manner equivalent to using boost::asio::io_service::post().
*/
template<class TeardownHandler>
void
async_teardown(teardown_tag,
boost::asio::ip::tcp::socket& socket, TeardownHandler&& handler);
} // websocket
} // beast
#include <beast/websocket/impl/teardown.ipp>