forked from boostorg/beast
WebSocket refactoring and tests:
websocket:
* Move echo server to test/
* Fix warnings
* Fix maskgen being uncopyable
* Simplify utf8_checker special member declarations
* Fix stream move assignable when owning the next layer
* Add javadocs for stream special members
* Add stream unit tests
* Move throwing member definitions to the .ipp file
* Use get_lowest_layer in stream declaration
* Perform type checks at each call site instead of constructor
* Demote close_code to a non-class enum:
Otherwise, application specific close codes
cannot be assigned without using static_cast.
core:
* Add streambuf_readstream special members tests
* Add move assignment operator to streambuf_readstream
* Add detail/get_lowest_layer trait
* Add static_string tests
* Move static_string from websocket to core
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// 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_DETAIL_GET_LOWEST_LAYER_HPP
|
||||
#define BEAST_DETAIL_GET_LOWEST_LAYER_HPP
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace beast {
|
||||
namespace detail {
|
||||
|
||||
template<class T>
|
||||
class has_lowest_layer
|
||||
{
|
||||
template<class U, class R =
|
||||
typename U::lowest_layer_type>
|
||||
static std::true_type check(int);
|
||||
template<class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<T>(0));
|
||||
public:
|
||||
static bool constexpr value = type::value;
|
||||
};
|
||||
|
||||
template<class T, bool B>
|
||||
struct maybe_get_lowest_layer
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct maybe_get_lowest_layer<T, true>
|
||||
{
|
||||
using type = typename T::lowest_layer_type;
|
||||
};
|
||||
|
||||
// If T has a nested type lowest_layer_type,
|
||||
// returns that, else returns T.
|
||||
template<class T>
|
||||
struct get_lowest_layer
|
||||
{
|
||||
using type = typename maybe_get_lowest_layer<T,
|
||||
has_lowest_layer<T>::value>::type;
|
||||
};
|
||||
|
||||
} // detail
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -10,7 +10,6 @@
|
||||
|
||||
#include <beast/bind_handler.hpp>
|
||||
#include <beast/handler_alloc.hpp>
|
||||
#include <beast/type_check.hpp>
|
||||
|
||||
namespace beast {
|
||||
|
||||
@@ -158,8 +157,6 @@ streambuf_readstream<Stream, Streambuf>::
|
||||
streambuf_readstream(Args&&... args)
|
||||
: next_layer_(std::forward<Args>(args)...)
|
||||
{
|
||||
static_assert(is_Stream<next_layer_type>::value,
|
||||
"Stream requirements not met");
|
||||
static_assert(is_Streambuf<Streambuf>::value,
|
||||
"Streambuf requirements not met");
|
||||
}
|
||||
@@ -173,6 +170,8 @@ async_write_some(ConstBufferSequence const& buffers,
|
||||
typename async_completion<
|
||||
WriteHandler, void(error_code)>::result_type
|
||||
{
|
||||
static_assert(is_AsyncWriteStream<next_layer_type>::value,
|
||||
"AsyncWriteStream requirements not met");
|
||||
static_assert(is_ConstBufferSequence<
|
||||
ConstBufferSequence>::value,
|
||||
"ConstBufferSequence requirements not met");
|
||||
@@ -190,6 +189,8 @@ streambuf_readstream<Stream, Streambuf>::
|
||||
read_some(
|
||||
MutableBufferSequence const& buffers)
|
||||
{
|
||||
static_assert(is_SyncReadStream<next_layer_type>::value,
|
||||
"SyncReadStream requirements not met");
|
||||
static_assert(is_MutableBufferSequence<
|
||||
MutableBufferSequence>::value,
|
||||
"MutableBufferSequence requirements not met");
|
||||
@@ -207,6 +208,8 @@ streambuf_readstream<Stream, Streambuf>::
|
||||
read_some(MutableBufferSequence const& buffers,
|
||||
error_code& ec)
|
||||
{
|
||||
static_assert(is_SyncReadStream<next_layer_type>::value,
|
||||
"SyncReadStream requirements not met");
|
||||
static_assert(is_MutableBufferSequence<
|
||||
MutableBufferSequence>::value,
|
||||
"MutableBufferSequence requirements not met");
|
||||
@@ -239,6 +242,8 @@ async_read_some(
|
||||
typename async_completion<
|
||||
ReadHandler, void(error_code)>::result_type
|
||||
{
|
||||
static_assert(is_AsyncReadStream<next_layer_type>::value,
|
||||
"Stream requirements not met");
|
||||
static_assert(is_MutableBufferSequence<
|
||||
MutableBufferSequence>::value,
|
||||
"MutableBufferSequence requirements not met");
|
||||
|
||||
@@ -0,0 +1,696 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_WEBSOCKET_STATIC_STRING_HPP
|
||||
#define BEAST_WEBSOCKET_STATIC_STRING_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace beast {
|
||||
namespace websocket {
|
||||
|
||||
/** A string with a fixed-size storage area.
|
||||
|
||||
`static_string` objects behave like `std::string` except that
|
||||
the storage is not dynamically allocated but rather fixed in
|
||||
size.
|
||||
|
||||
These strings offer performance advantages when a protocol
|
||||
imposes a natural small upper limit on the size of a value.
|
||||
|
||||
@note The stored string is always null-terminated.
|
||||
*/
|
||||
template<
|
||||
std::size_t N,
|
||||
class CharT = char,
|
||||
class Traits = std::char_traits<CharT>>
|
||||
class static_string
|
||||
{
|
||||
template<std::size_t, class, class>
|
||||
friend class static_string;
|
||||
|
||||
std::size_t n_;
|
||||
std::array<CharT, N+1> s_;
|
||||
|
||||
public:
|
||||
using traits_type = Traits;
|
||||
using value_type = typename Traits::char_type;
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = value_type*;
|
||||
using reference = value_type&;
|
||||
using const_pointer = value_type const*;
|
||||
using const_reference = value_type const&;
|
||||
using iterator = value_type*;
|
||||
using const_iterator = value_type const*;
|
||||
using reverse_iterator =
|
||||
std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator =
|
||||
std::reverse_iterator<const_iterator>;
|
||||
|
||||
/** Default constructor.
|
||||
|
||||
The string is initially empty, and null terminated.
|
||||
*/
|
||||
static_string();
|
||||
|
||||
/// Copy constructor.
|
||||
static_string(static_string const& s);
|
||||
|
||||
/// Copy constructor.
|
||||
template<std::size_t M>
|
||||
static_string(static_string<M, CharT, Traits> const& s);
|
||||
|
||||
/// Copy assignment.
|
||||
static_string&
|
||||
operator=(static_string const& s);
|
||||
|
||||
/// Copy assignment.
|
||||
template<std::size_t M>
|
||||
static_string&
|
||||
operator=(static_string<M, CharT, Traits> const& s);
|
||||
|
||||
/// Construct from string literal.
|
||||
template<std::size_t M>
|
||||
static_string(const CharT (&s)[M]);
|
||||
|
||||
/// Assign from string literal.
|
||||
template<std::size_t M>
|
||||
static_string& operator=(const CharT (&s)[M]);
|
||||
|
||||
/// Access specified character with bounds checking.
|
||||
reference
|
||||
at(size_type pos);
|
||||
|
||||
/// Access specified character with bounds checking.
|
||||
const_reference
|
||||
at(size_type pos) const;
|
||||
|
||||
/// Access specified character.
|
||||
reference
|
||||
operator[](size_type pos)
|
||||
{
|
||||
return s_[pos];
|
||||
}
|
||||
|
||||
/// Access specified character.
|
||||
const_reference
|
||||
operator[](size_type pos) const
|
||||
{
|
||||
return s_[pos];
|
||||
}
|
||||
|
||||
/// Accesses the first character.
|
||||
CharT&
|
||||
front()
|
||||
{
|
||||
return s_[0];
|
||||
}
|
||||
|
||||
/// Accesses the first character.
|
||||
CharT const&
|
||||
front() const
|
||||
{
|
||||
return s_[0];
|
||||
}
|
||||
|
||||
/// Accesses the last character.
|
||||
CharT&
|
||||
back()
|
||||
{
|
||||
return s_[n_-1];
|
||||
}
|
||||
|
||||
/// Accesses the last character.
|
||||
CharT const&
|
||||
back() const
|
||||
{
|
||||
return s_[n_-1];
|
||||
}
|
||||
|
||||
/// Returns a pointer to the first character of a string.
|
||||
CharT*
|
||||
data()
|
||||
{
|
||||
return &s_[0];
|
||||
}
|
||||
|
||||
/// Returns a pointer to the first character of a string.
|
||||
CharT const*
|
||||
data() const
|
||||
{
|
||||
return &s_[0];
|
||||
}
|
||||
|
||||
/// Returns a non-modifiable standard C character array version of the string.
|
||||
CharT const*
|
||||
c_str() const
|
||||
{
|
||||
return &s_[0];
|
||||
}
|
||||
|
||||
/// Returns an iterator to the beginning.
|
||||
iterator
|
||||
begin()
|
||||
{
|
||||
return &s_[0];
|
||||
}
|
||||
|
||||
/// Returns an iterator to the beginning.
|
||||
const_iterator
|
||||
begin() const
|
||||
{
|
||||
return &s_[0];
|
||||
}
|
||||
|
||||
/// Returns an iterator to the beginning.
|
||||
const_iterator
|
||||
cbegin() const
|
||||
{
|
||||
return &s_[0];
|
||||
}
|
||||
|
||||
/// Returns an iterator to the end.
|
||||
iterator
|
||||
end()
|
||||
{
|
||||
return &s_[n_];
|
||||
}
|
||||
|
||||
/// Returns an iterator to the end.
|
||||
const_iterator
|
||||
end() const
|
||||
{
|
||||
return &s_[n_];
|
||||
}
|
||||
|
||||
/// Returns an iterator to the end.
|
||||
const_iterator
|
||||
cend() const
|
||||
{
|
||||
return &s_[n_];
|
||||
}
|
||||
|
||||
/// Returns a reverse iterator to the beginning.
|
||||
reverse_iterator
|
||||
rbegin()
|
||||
{
|
||||
return reverse_iterator{end()};
|
||||
}
|
||||
|
||||
/// Returns a reverse iterator to the beginning.
|
||||
const_reverse_iterator
|
||||
rbegin() const
|
||||
{
|
||||
return const_reverse_iterator{cend()};
|
||||
}
|
||||
|
||||
/// Returns a reverse iterator to the beginning.
|
||||
const_reverse_iterator
|
||||
crbegin() const
|
||||
{
|
||||
return const_reverse_iterator{cend()};
|
||||
}
|
||||
|
||||
/// Returns a reverse iterator to the end.
|
||||
reverse_iterator
|
||||
rend()
|
||||
{
|
||||
return reverse_iterator{begin()};
|
||||
}
|
||||
|
||||
/// Returns a reverse iterator to the end.
|
||||
const_reverse_iterator
|
||||
rend() const
|
||||
{
|
||||
return const_reverse_iterator{cbegin()};
|
||||
}
|
||||
|
||||
/// Returns a reverse iterator to the end.
|
||||
const_reverse_iterator
|
||||
crend() const
|
||||
{
|
||||
return const_reverse_iterator{cbegin()};
|
||||
}
|
||||
|
||||
/// Returns `true` if the string is empty.
|
||||
bool
|
||||
empty() const
|
||||
{
|
||||
return n_ == 0;
|
||||
}
|
||||
|
||||
/// Returns the number of characters, excluding the null terminator.
|
||||
size_type
|
||||
size() const
|
||||
{
|
||||
return n_;
|
||||
}
|
||||
|
||||
/// Returns the maximum number of characters that can be stored, excluding the null terminator.
|
||||
size_type constexpr
|
||||
max_size() const
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
/// Returns the number of characters that can be held in currently allocated storage.
|
||||
size_type
|
||||
capacity() const
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
/// Reduces memory usage by freeing unused memory.
|
||||
void
|
||||
shrink_to_fit()
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
|
||||
/// Clears the contents.
|
||||
void
|
||||
clear()
|
||||
{
|
||||
resize(0);
|
||||
}
|
||||
|
||||
/** Changes the number of characters stored.
|
||||
|
||||
@note No value-initialization is performed.
|
||||
*/
|
||||
void
|
||||
resize(std::size_t n);
|
||||
|
||||
/** Changes the number of characters stored.
|
||||
|
||||
If the resulting string is larger, the new
|
||||
characters are initialized to the value of `c`.
|
||||
*/
|
||||
void
|
||||
resize(std::size_t n, CharT c);
|
||||
|
||||
/// Compare two character sequences.
|
||||
template<std::size_t M>
|
||||
int compare(static_string<M, CharT, Traits> const& rhs) const;
|
||||
|
||||
/// Return the characters as a `basic_string`.
|
||||
std::basic_string<CharT, Traits>
|
||||
to_string() const
|
||||
{
|
||||
return std::basic_string<
|
||||
CharT, Traits>{&s_[0], n_};
|
||||
}
|
||||
|
||||
private:
|
||||
void
|
||||
assign(CharT const* s);
|
||||
};
|
||||
|
||||
template<std::size_t N, class CharT, class Traits>
|
||||
static_string<N, CharT, Traits>::
|
||||
static_string()
|
||||
: n_(0)
|
||||
{
|
||||
s_[0] = 0;
|
||||
}
|
||||
|
||||
template<std::size_t N, class CharT, class Traits>
|
||||
static_string<N, CharT, Traits>::
|
||||
static_string(static_string const& s)
|
||||
: n_(s.n_)
|
||||
{
|
||||
Traits::copy(&s_[0], &s.s_[0], n_ + 1);
|
||||
}
|
||||
|
||||
template<std::size_t N, class CharT, class Traits>
|
||||
template<std::size_t M>
|
||||
static_string<N, CharT, Traits>::
|
||||
static_string(static_string<M, CharT, Traits> const& s)
|
||||
{
|
||||
if(s.size() > N)
|
||||
throw std::length_error("static_string overflow");
|
||||
n_ = s.size();
|
||||
Traits::copy(&s_[0], &s.s_[0], n_ + 1);
|
||||
}
|
||||
|
||||
template<std::size_t N, class CharT, class Traits>
|
||||
auto
|
||||
static_string<N, CharT, Traits>::
|
||||
operator=(static_string const& s) ->
|
||||
static_string&
|
||||
{
|
||||
n_ = s.n_;
|
||||
Traits::copy(&s_[0], &s.s_[0], n_ + 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<std::size_t N, class CharT, class Traits>
|
||||
template<std::size_t M>
|
||||
auto
|
||||
static_string<N, CharT, Traits>::
|
||||
operator=(static_string<M, CharT, Traits> const& s) ->
|
||||
static_string&
|
||||
{
|
||||
if(s.size() > N)
|
||||
throw std::length_error("static_string overflow");
|
||||
n_ = s.size();
|
||||
Traits::copy(&s_[0], &s.s_[0], n_ + 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<std::size_t N, class CharT, class Traits>
|
||||
template<std::size_t M>
|
||||
static_string<N, CharT, Traits>::
|
||||
static_string(const CharT (&s)[M])
|
||||
: n_(M-1)
|
||||
{
|
||||
static_assert(M-1 <= N,
|
||||
"static_string overflow");
|
||||
Traits::copy(&s_[0], &s[0], M);
|
||||
}
|
||||
|
||||
template<std::size_t N, class CharT, class Traits>
|
||||
template<std::size_t M>
|
||||
auto
|
||||
static_string<N, CharT, Traits>::
|
||||
operator=(const CharT (&s)[M]) ->
|
||||
static_string&
|
||||
{
|
||||
static_assert(M-1 <= N,
|
||||
"static_string overflow");
|
||||
n_ = M-1;
|
||||
std::copy(&s[0], &s[M], &s_[0]);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<std::size_t N, class CharT, class Traits>
|
||||
auto
|
||||
static_string<N, CharT, Traits>::
|
||||
at(size_type pos) ->
|
||||
reference
|
||||
{
|
||||
if(pos >= n_)
|
||||
throw std::out_of_range("static_string::at");
|
||||
return s_[pos];
|
||||
}
|
||||
|
||||
template<std::size_t N, class CharT, class Traits>
|
||||
auto
|
||||
static_string<N, CharT, Traits>::
|
||||
at(size_type pos) const ->
|
||||
const_reference
|
||||
{
|
||||
if(pos >= n_)
|
||||
throw std::out_of_range("static_string::at");
|
||||
return s_[pos];
|
||||
}
|
||||
|
||||
template<std::size_t N, class CharT, class Traits>
|
||||
void
|
||||
static_string<N, CharT, Traits>::
|
||||
resize(std::size_t n)
|
||||
{
|
||||
if(n > N)
|
||||
throw std::length_error("static_string overflow");
|
||||
n_ = n;
|
||||
s_[n_] = 0;
|
||||
}
|
||||
|
||||
template<std::size_t N, class CharT, class Traits>
|
||||
void
|
||||
static_string<N, CharT, Traits>::
|
||||
resize(std::size_t n, CharT c)
|
||||
{
|
||||
if(n > N)
|
||||
throw std::length_error("static_string overflow");
|
||||
if(n > n_)
|
||||
Traits::assign(&s_[n_], n - n_, c);
|
||||
n_ = n;
|
||||
s_[n_] = 0;
|
||||
}
|
||||
|
||||
template<std::size_t N, class CharT, class Traits>
|
||||
template<std::size_t M>
|
||||
int
|
||||
static_string<N, CharT, Traits>::
|
||||
compare(static_string<M, CharT, Traits> const& rhs) const
|
||||
{
|
||||
if(size() < rhs.size())
|
||||
{
|
||||
auto const v = Traits::compare(
|
||||
data(), rhs.data(), size());
|
||||
if(v == 0)
|
||||
return -1;
|
||||
return v;
|
||||
}
|
||||
else if(size() > rhs.size())
|
||||
{
|
||||
auto const v = Traits::compare(
|
||||
data(), rhs.data(), rhs.size());
|
||||
if(v == 0)
|
||||
return 1;
|
||||
return v;
|
||||
}
|
||||
return Traits::compare(data(), rhs.data(), size());
|
||||
}
|
||||
|
||||
template<std::size_t N, class CharT, class Traits>
|
||||
void
|
||||
static_string<N, CharT, Traits>::
|
||||
assign(CharT const* s)
|
||||
{
|
||||
auto const n = Traits::length(s);
|
||||
if(n > N)
|
||||
throw std::out_of_range("too large");
|
||||
n_ = n;
|
||||
Traits::copy(&s_[0], s, n_ + 1);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<std::size_t N, std::size_t M, class CharT, class Traits>
|
||||
int compare(
|
||||
static_string<N, CharT, Traits> const& lhs,
|
||||
const CharT (&s)[M])
|
||||
{
|
||||
if(lhs.size() < M-1)
|
||||
{
|
||||
auto const v = Traits::compare(
|
||||
lhs.data(), &s[0], lhs.size());
|
||||
if(v == 0)
|
||||
return -1;
|
||||
return v;
|
||||
}
|
||||
else if(lhs.size() > M-1)
|
||||
{
|
||||
auto const v = Traits::compare(
|
||||
lhs.data(), &s[0], M-1);
|
||||
if(v == 0)
|
||||
return 1;
|
||||
return v;
|
||||
}
|
||||
return Traits::compare(lhs.data(), &s[0], lhs.size());
|
||||
}
|
||||
|
||||
template<std::size_t N, std::size_t M, class CharT, class Traits>
|
||||
int compare(
|
||||
const CharT (&s)[M],
|
||||
static_string<N, CharT, Traits> const& rhs)
|
||||
{
|
||||
if(M-1 < rhs.size())
|
||||
{
|
||||
auto const v = Traits::compare(
|
||||
&s[0], rhs.data(), M-1);
|
||||
if(v == 0)
|
||||
return -1;
|
||||
return v;
|
||||
}
|
||||
else if(M-1 > rhs.size())
|
||||
{
|
||||
auto const v = Traits::compare(
|
||||
&s[0], rhs.data(), rhs.size());
|
||||
if(v == 0)
|
||||
return 1;
|
||||
return v;
|
||||
}
|
||||
return Traits::compare(&s[0], rhs.data(), M-1);
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
#if ! GENERATING_DOCS
|
||||
|
||||
template<std::size_t N, std::size_t M, class CharT, class Traits>
|
||||
bool operator==(
|
||||
static_string<N, CharT, Traits> const& lhs,
|
||||
static_string<M, CharT, Traits> const& rhs)
|
||||
{
|
||||
return lhs.compare(rhs) == 0;
|
||||
}
|
||||
|
||||
template<std::size_t N, std::size_t M, class CharT, class Traits>
|
||||
bool operator!=(
|
||||
static_string<N, CharT, Traits> const& lhs,
|
||||
static_string<M, CharT, Traits> const& rhs)
|
||||
{
|
||||
return lhs.compare(rhs) != 0;
|
||||
}
|
||||
|
||||
template<std::size_t N, std::size_t M, class CharT, class Traits>
|
||||
bool operator<(
|
||||
static_string<N, CharT, Traits> const& lhs,
|
||||
static_string<M, CharT, Traits> const& rhs)
|
||||
{
|
||||
return lhs.compare(rhs) < 0;
|
||||
}
|
||||
|
||||
template<std::size_t N, std::size_t M, class CharT, class Traits>
|
||||
bool operator<=(
|
||||
static_string<N, CharT, Traits> const& lhs,
|
||||
static_string<M, CharT, Traits> const& rhs)
|
||||
{
|
||||
return lhs.compare(rhs) <= 0;
|
||||
}
|
||||
|
||||
template<std::size_t N, std::size_t M, class CharT, class Traits>
|
||||
bool operator>(
|
||||
static_string<N, CharT, Traits> const& lhs,
|
||||
static_string<M, CharT, Traits> const& rhs)
|
||||
{
|
||||
return lhs.compare(rhs) > 0;
|
||||
}
|
||||
|
||||
template<std::size_t N, std::size_t M, class CharT, class Traits>
|
||||
bool operator>=(
|
||||
static_string<N, CharT, Traits> const& lhs,
|
||||
static_string<M, CharT, Traits> const& rhs)
|
||||
{
|
||||
return lhs.compare(rhs) >= 0;
|
||||
}
|
||||
|
||||
//---
|
||||
|
||||
template<std::size_t N, std::size_t M, class CharT, class Traits>
|
||||
bool operator==(
|
||||
const CharT (&s)[N],
|
||||
static_string<M, CharT, Traits> const& rhs)
|
||||
{
|
||||
return detail::compare(s, rhs) == 0;
|
||||
}
|
||||
|
||||
template<std::size_t N, class CharT, class Traits, std::size_t M>
|
||||
bool operator==(
|
||||
static_string<N, CharT, Traits> const& lhs,
|
||||
const CharT (&s)[M])
|
||||
{
|
||||
return detail::compare(lhs, s) == 0;
|
||||
}
|
||||
|
||||
template<std::size_t N, std::size_t M, class CharT, class Traits>
|
||||
bool operator!=(
|
||||
const CharT (&s)[N],
|
||||
static_string<M, CharT, Traits> const& rhs)
|
||||
{
|
||||
return detail::compare(s, rhs) != 0;
|
||||
}
|
||||
|
||||
template<std::size_t N, class CharT, class Traits, std::size_t M>
|
||||
bool operator!=(
|
||||
static_string<N, CharT, Traits> const& lhs,
|
||||
const CharT (&s)[M])
|
||||
{
|
||||
return detail::compare(lhs, s) != 0;
|
||||
}
|
||||
|
||||
template<std::size_t N, std::size_t M, class CharT, class Traits>
|
||||
bool operator<(
|
||||
const CharT (&s)[N],
|
||||
static_string<M, CharT, Traits> const& rhs)
|
||||
{
|
||||
return detail::compare(s, rhs) < 0;
|
||||
}
|
||||
|
||||
template<std::size_t N, class CharT, class Traits, std::size_t M>
|
||||
bool operator<(
|
||||
static_string<N, CharT, Traits> const& lhs,
|
||||
const CharT (&s)[M])
|
||||
{
|
||||
return detail::compare(lhs, s) < 0;
|
||||
}
|
||||
|
||||
template<std::size_t N, std::size_t M, class CharT, class Traits>
|
||||
bool operator<=(
|
||||
const CharT (&s)[N],
|
||||
static_string<M, CharT, Traits> const& rhs)
|
||||
{
|
||||
return detail::compare(s, rhs) <= 0;
|
||||
}
|
||||
|
||||
template<std::size_t N, class CharT, class Traits, std::size_t M>
|
||||
bool operator<=(
|
||||
static_string<N, CharT, Traits> const& lhs,
|
||||
const CharT (&s)[M])
|
||||
{
|
||||
return detail::compare(lhs, s) <= 0;
|
||||
}
|
||||
|
||||
template<std::size_t N, std::size_t M, class CharT, class Traits>
|
||||
bool operator>(
|
||||
const CharT (&s)[N],
|
||||
static_string<M, CharT, Traits> const& rhs)
|
||||
{
|
||||
return detail::compare(s, rhs) > 0;
|
||||
}
|
||||
|
||||
template<std::size_t N, class CharT, class Traits, std::size_t M>
|
||||
bool operator>(
|
||||
static_string<N, CharT, Traits> const& lhs,
|
||||
const CharT (&s)[M])
|
||||
{
|
||||
return detail::compare(lhs, s) > 0;
|
||||
}
|
||||
|
||||
template<std::size_t N, std::size_t M, class CharT, class Traits>
|
||||
bool operator>=(
|
||||
const CharT (&s)[N],
|
||||
static_string<M, CharT, Traits> const& rhs)
|
||||
{
|
||||
return detail::compare(s, rhs) >= 0;
|
||||
}
|
||||
|
||||
template<std::size_t N, class CharT, class Traits, std::size_t M>
|
||||
bool operator>=(
|
||||
static_string<N, CharT, Traits> const& lhs,
|
||||
const CharT (&s)[M])
|
||||
{
|
||||
return detail::compare(lhs, s) >= 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // websocket
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
#include <beast/async_completion.hpp>
|
||||
#include <beast/streambuf.hpp>
|
||||
#include <beast/type_check.hpp>
|
||||
#include <beast/detail/get_lowest_layer.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
@@ -83,8 +85,7 @@ namespace beast {
|
||||
|
||||
@tparam Streambuf The type of stream buffer to use.
|
||||
*/
|
||||
template<class Stream,
|
||||
class Streambuf = streambuf>
|
||||
template<class Stream, class Streambuf>
|
||||
class streambuf_readstream
|
||||
{
|
||||
using error_code = boost::system::error_code;
|
||||
@@ -106,11 +107,23 @@ public:
|
||||
|
||||
/// The type of the lowest layer.
|
||||
using lowest_layer_type =
|
||||
typename next_layer_type::lowest_layer_type;
|
||||
typename detail::get_lowest_layer<
|
||||
next_layer_type>::type;
|
||||
|
||||
/// Move constructor.
|
||||
/** Move constructor.
|
||||
|
||||
@note The behavior of move assignment on or from streams
|
||||
with active or pending operations is undefined.
|
||||
*/
|
||||
streambuf_readstream(streambuf_readstream&&) = default;
|
||||
|
||||
/** Move assignment.
|
||||
|
||||
@note The behavior of move assignment on or from streams
|
||||
with active or pending operations is undefined.
|
||||
*/
|
||||
streambuf_readstream& operator=(streambuf_readstream&&) = default;
|
||||
|
||||
/** Construct the wrapping stream.
|
||||
|
||||
@param args Parameters forwarded to the `Stream` constructor.
|
||||
@@ -200,6 +213,8 @@ public:
|
||||
std::size_t
|
||||
write_some(ConstBufferSequence const& buffers)
|
||||
{
|
||||
static_assert(is_SyncWriteStream<next_layer_type>::value,
|
||||
"SyncWriteStream requirements not met");
|
||||
return next_layer_.write_some(buffers);
|
||||
}
|
||||
|
||||
@@ -210,6 +225,8 @@ public:
|
||||
write_some(ConstBufferSequence const& buffers,
|
||||
error_code& ec)
|
||||
{
|
||||
static_assert(is_SyncWriteStream<next_layer_type>::value,
|
||||
"SyncWriteStream requirements not met");
|
||||
return next_layer_.write_some(buffers, ec);
|
||||
}
|
||||
|
||||
|
||||
@@ -272,18 +272,26 @@ public:
|
||||
};
|
||||
static_assert(! is_SyncWriteStream<int>::value, "");
|
||||
|
||||
/// Determine if `T` meets the requirements of `Stream`.
|
||||
/// Determine if `T` meets the requirements of `SyncStream`.
|
||||
template<class T>
|
||||
struct is_Stream
|
||||
struct is_SyncStream
|
||||
{
|
||||
/// `true` if `T` meets the requirements.
|
||||
/// `true` if `T` meets the requirements.
|
||||
static bool const value =
|
||||
is_AsyncReadStream<T>::value &&
|
||||
is_AsyncWriteStream<T>::value &&
|
||||
is_SyncReadStream<T>::value &&
|
||||
is_SyncWriteStream<T>::value;
|
||||
};
|
||||
|
||||
/// Determine if `T` meets the requirements of `SyncStream`.
|
||||
template<class T>
|
||||
struct is_AsyncStream
|
||||
{
|
||||
/// `true` if `T` meets the requirements.
|
||||
static bool const value =
|
||||
is_AsyncReadStream<T>::value &&
|
||||
is_AsyncWriteStream<T>::value;
|
||||
};
|
||||
|
||||
/// Determine if `T` meets the requirements of `Streambuf`.
|
||||
template<class T>
|
||||
class is_Streambuf
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include <beast/websocket/option.hpp>
|
||||
#include <beast/websocket/rfc6455.hpp>
|
||||
#include <beast/websocket/stream.hpp>
|
||||
#include <beast/websocket/static_string.hpp>
|
||||
#include <beast/websocket/teardown.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
#define BEAST_WEBSOCKET_DETAIL_FRAME_HPP
|
||||
|
||||
#include <beast/websocket/rfc6455.hpp>
|
||||
#include <beast/websocket/static_string.hpp>
|
||||
#include <beast/websocket/detail/endian.hpp>
|
||||
#include <beast/websocket/detail/utf8_checker.hpp>
|
||||
#include <beast/consuming_buffers.hpp>
|
||||
#include <beast/static_streambuf.hpp>
|
||||
#include <beast/static_string.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/endian/buffers.hpp>
|
||||
#include <cassert>
|
||||
@@ -70,10 +70,9 @@ is_control(opcode op)
|
||||
// Returns `true` if a close code is valid
|
||||
inline
|
||||
bool
|
||||
is_valid(close_code code)
|
||||
is_valid(close_code::value code)
|
||||
{
|
||||
auto const v = static_cast<
|
||||
std::uint16_t>(code);
|
||||
auto const v = code;
|
||||
switch(v)
|
||||
{
|
||||
case 1000:
|
||||
@@ -154,7 +153,7 @@ write(Streambuf& sb, frame_header const& fh)
|
||||
template<class Streambuf>
|
||||
std::size_t
|
||||
read_fh1(frame_header& fh, Streambuf& sb,
|
||||
role_type role, close_code& code)
|
||||
role_type role, close_code::value& code)
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::buffer_copy;
|
||||
@@ -171,7 +170,8 @@ read_fh1(frame_header& fh, Streambuf& sb,
|
||||
default:
|
||||
need = 0;
|
||||
}
|
||||
if((fh.mask = (b[1] & 0x80) != 0))
|
||||
fh.mask = (b[1] & 0x80) != 0;
|
||||
if(fh.mask)
|
||||
need += 4;
|
||||
fh.op = static_cast<opcode>(b[0] & 0x0f);
|
||||
fh.fin = (b[0] & 0x80) != 0;
|
||||
@@ -230,7 +230,7 @@ read_fh1(frame_header& fh, Streambuf& sb,
|
||||
template<class Streambuf>
|
||||
void
|
||||
read_fh2(frame_header& fh, Streambuf& sb,
|
||||
role_type role, close_code& code)
|
||||
role_type role, close_code::value& code)
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::buffer_copy;
|
||||
@@ -301,7 +301,7 @@ read_fh2(frame_header& fh, Streambuf& sb,
|
||||
template<class Buffers>
|
||||
void
|
||||
read(ping_payload_type& data,
|
||||
Buffers const& bs, close_code& code)
|
||||
Buffers const& bs, close_code::value& code)
|
||||
{
|
||||
using boost::asio::buffer_copy;
|
||||
using boost::asio::buffer_size;
|
||||
@@ -318,7 +318,7 @@ read(ping_payload_type& data,
|
||||
template<class Buffers>
|
||||
void
|
||||
read(close_reason& cr,
|
||||
Buffers const& bs, close_code& code)
|
||||
Buffers const& bs, close_code::value& code)
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::buffer_copy;
|
||||
@@ -341,15 +341,7 @@ read(close_reason& cr,
|
||||
{
|
||||
std::uint8_t b[2];
|
||||
buffer_copy(buffer(b), cb);
|
||||
#if 0
|
||||
// Causes strict-aliasing warning in gcc
|
||||
cr.code = static_cast<close_code>(
|
||||
reinterpret_cast<
|
||||
big_uint16_buf_t const*>(&b[0])->value());
|
||||
#else
|
||||
cr.code = static_cast<close_code>(
|
||||
big_uint16_to_native(&b[0]));
|
||||
#endif
|
||||
cr.code = big_uint16_to_native(&b[0]);
|
||||
cb.consume(2);
|
||||
n -= 2;
|
||||
if(! is_valid(cr.code))
|
||||
|
||||
@@ -85,8 +85,6 @@ public:
|
||||
#endif
|
||||
|
||||
invokable() = default;
|
||||
invokable(invokable const&) = delete;
|
||||
invokable& operator=(invokable const&) = delete;
|
||||
|
||||
invokable(invokable&& other)
|
||||
{
|
||||
|
||||
@@ -41,9 +41,6 @@ class maskgen_t
|
||||
public:
|
||||
using result_type = typename std::mt19937::result_type;
|
||||
|
||||
maskgen_t(maskgen_t const&) = delete;
|
||||
maskgen_t& operator=(maskgen_t const&) = delete;
|
||||
|
||||
maskgen_t();
|
||||
|
||||
result_type
|
||||
|
||||
@@ -108,7 +108,7 @@ protected:
|
||||
|
||||
template<class = void>
|
||||
void
|
||||
prepare_fh(close_code& code);
|
||||
prepare_fh(close_code::value& code);
|
||||
|
||||
template<class Streambuf>
|
||||
void
|
||||
|
||||
@@ -73,12 +73,6 @@ class utf8_checker_t
|
||||
std::uint32_t codepoint_ = 0;
|
||||
|
||||
public:
|
||||
utf8_checker_t() = default;
|
||||
utf8_checker_t(utf8_checker_t&&) = default;
|
||||
utf8_checker_t(utf8_checker_t const&) = default;
|
||||
utf8_checker_t& operator=(utf8_checker_t&&) = default;
|
||||
utf8_checker_t& operator=(utf8_checker_t const&) = default;
|
||||
|
||||
void
|
||||
reset();
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ operator()(error_code const& ec,
|
||||
case 0:
|
||||
// read message
|
||||
d.state = 1;
|
||||
http::async_read(d.ws.next_layer_,
|
||||
http::async_read(d.ws.next_layer(),
|
||||
d.ws.stream_.buffer(), d.req,
|
||||
std::move(*this));
|
||||
return;
|
||||
|
||||
@@ -134,7 +134,7 @@ stream<NextLayer>::handshake_op<
|
||||
case 1:
|
||||
// read http response
|
||||
d.state = 2;
|
||||
http::async_read(d.ws.next_layer_,
|
||||
http::async_read(d.ws.next_layer(),
|
||||
d.ws.stream_.buffer(), d.resp,
|
||||
std::move(*this));
|
||||
return;
|
||||
|
||||
@@ -132,7 +132,7 @@ operator()(error_code ec,std::size_t bytes_transferred, bool again)
|
||||
{
|
||||
auto& d = *d_;
|
||||
d.cont = d.cont || again;
|
||||
close_code code;
|
||||
close_code::value code = close_code::none;
|
||||
while(! ec && d.state != 99)
|
||||
{
|
||||
switch(d.state)
|
||||
@@ -195,7 +195,7 @@ operator()(error_code ec,std::size_t bytes_transferred, bool again)
|
||||
d.state = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// call handler
|
||||
case 4:
|
||||
d.state = 99;
|
||||
@@ -397,7 +397,7 @@ operator()(error_code ec,std::size_t bytes_transferred, bool again)
|
||||
case 11:
|
||||
d.state = 12;
|
||||
wsproto_helpers::call_async_teardown(
|
||||
d.ws.next_layer_, std::move(*this));
|
||||
d.ws.next_layer(), std::move(*this));
|
||||
return;
|
||||
|
||||
case 12:
|
||||
@@ -483,7 +483,7 @@ operator()(error_code ec,std::size_t bytes_transferred, bool again)
|
||||
case 19:
|
||||
d.state = 20;
|
||||
wsproto_helpers::call_async_teardown(
|
||||
d.ws.next_layer_, std::move(*this));
|
||||
d.ws.next_layer(), std::move(*this));
|
||||
return;
|
||||
|
||||
case 20:
|
||||
|
||||
@@ -113,7 +113,7 @@ operator()(error_code ec, bool again)
|
||||
case 0:
|
||||
// send response
|
||||
d.state = 1;
|
||||
http::async_write(d.ws.next_layer_,
|
||||
http::async_write(d.ws.next_layer(),
|
||||
d.resp, std::move(*this));
|
||||
return;
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace detail {
|
||||
|
||||
template<class _>
|
||||
void
|
||||
stream_base::prepare_fh(close_code& code)
|
||||
stream_base::prepare_fh(close_code::value& code)
|
||||
{
|
||||
// continuation without an active message
|
||||
if(! rd_cont_ && rd_fh_.op == opcode::cont)
|
||||
@@ -170,11 +170,20 @@ template<class NextLayer>
|
||||
template<class... Args>
|
||||
stream<NextLayer>::
|
||||
stream(Args&&... args)
|
||||
: next_layer_(std::forward<Args>(args)...)
|
||||
, stream_(next_layer_)
|
||||
: stream_(std::forward<Args>(args)...)
|
||||
{
|
||||
static_assert(is_Stream<next_layer_type>::value,
|
||||
"Stream requirements not met");
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
accept()
|
||||
{
|
||||
static_assert(is_SyncStream<next_layer_type>::value,
|
||||
"SyncStream requirements not met");
|
||||
error_code ec;
|
||||
accept(boost::asio::null_buffers{}, ec);
|
||||
detail::maybe_throw(ec, "accept");
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
@@ -182,6 +191,8 @@ void
|
||||
stream<NextLayer>::
|
||||
accept(error_code& ec)
|
||||
{
|
||||
static_assert(is_SyncStream<next_layer_type>::value,
|
||||
"SyncStream requirements not met");
|
||||
accept(boost::asio::null_buffers{}, ec);
|
||||
}
|
||||
|
||||
@@ -192,6 +203,8 @@ typename async_completion<
|
||||
stream<NextLayer>::
|
||||
async_accept(AcceptHandler&& handler)
|
||||
{
|
||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
||||
"AsyncStream requirements requirements not met");
|
||||
return async_accept(boost::asio::null_buffers{},
|
||||
std::forward<AcceptHandler>(handler));
|
||||
}
|
||||
@@ -202,6 +215,8 @@ void
|
||||
stream<NextLayer>::
|
||||
accept(ConstBufferSequence const& buffers)
|
||||
{
|
||||
static_assert(is_SyncStream<next_layer_type>::value,
|
||||
"SyncStream requirements not met");
|
||||
static_assert(is_ConstBufferSequence<
|
||||
ConstBufferSequence>::value,
|
||||
"ConstBufferSequence requirements not met");
|
||||
@@ -216,6 +231,8 @@ void
|
||||
stream<NextLayer>::
|
||||
accept(ConstBufferSequence const& buffers, error_code& ec)
|
||||
{
|
||||
static_assert(is_SyncStream<next_layer_type>::value,
|
||||
"SyncStream requirements not met");
|
||||
static_assert(beast::is_ConstBufferSequence<
|
||||
ConstBufferSequence>::value,
|
||||
"ConstBufferSequence requirements not met");
|
||||
@@ -225,7 +242,7 @@ accept(ConstBufferSequence const& buffers, error_code& ec)
|
||||
stream_.buffer().prepare(
|
||||
buffer_size(buffers)), buffers));
|
||||
http::request<http::empty_body> m;
|
||||
http::read(next_layer_, stream_.buffer(), m, ec);
|
||||
http::read(next_layer(), stream_.buffer(), m, ec);
|
||||
if(ec)
|
||||
return;
|
||||
accept(m, ec);
|
||||
@@ -238,6 +255,8 @@ typename async_completion<
|
||||
stream<NextLayer>::
|
||||
async_accept(ConstBufferSequence const& bs, AcceptHandler&& handler)
|
||||
{
|
||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
||||
"AsyncStream requirements requirements not met");
|
||||
static_assert(beast::is_ConstBufferSequence<
|
||||
ConstBufferSequence>::value,
|
||||
"ConstBufferSequence requirements not met");
|
||||
@@ -255,6 +274,8 @@ void
|
||||
stream<NextLayer>::
|
||||
accept(http::message<true, Body, Headers> const& request)
|
||||
{
|
||||
static_assert(is_SyncStream<next_layer_type>::value,
|
||||
"SyncStream requirements not met");
|
||||
error_code ec;
|
||||
accept(request, ec);
|
||||
detail::maybe_throw(ec, "accept");
|
||||
@@ -267,6 +288,8 @@ stream<NextLayer>::
|
||||
accept(http::message<true, Body, Headers> const& req,
|
||||
error_code& ec)
|
||||
{
|
||||
static_assert(is_SyncStream<next_layer_type>::value,
|
||||
"SyncStream requirements not met");
|
||||
auto resp = build_response(req);
|
||||
http::write(stream_, resp, ec);
|
||||
if(resp.status != 101)
|
||||
@@ -287,6 +310,8 @@ stream<NextLayer>::
|
||||
async_accept(http::message<true, Body, Headers> const& req,
|
||||
AcceptHandler&& handler)
|
||||
{
|
||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
||||
"AsyncStream requirements requirements not met");
|
||||
beast::async_completion<
|
||||
AcceptHandler, void(error_code)
|
||||
> completion(handler);
|
||||
@@ -297,19 +322,34 @@ async_accept(http::message<true, Body, Headers> const& req,
|
||||
return completion.result.get();
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
handshake(boost::string_ref const& host,
|
||||
boost::string_ref const& resource)
|
||||
{
|
||||
static_assert(is_SyncStream<next_layer_type>::value,
|
||||
"SyncStream requirements not met");
|
||||
error_code ec;
|
||||
handshake(host, resource, ec);
|
||||
detail::maybe_throw(ec, "upgrade");
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
handshake(boost::string_ref const& host,
|
||||
boost::string_ref const& resource, error_code& ec)
|
||||
{
|
||||
static_assert(is_SyncStream<next_layer_type>::value,
|
||||
"SyncStream requirements not met");
|
||||
std::string key;
|
||||
http::write(stream_,
|
||||
build_request(host, resource, key), ec);
|
||||
if(ec)
|
||||
return;
|
||||
http::response<http::string_body> resp;
|
||||
http::read(next_layer_, stream_.buffer(), resp, ec);
|
||||
http::read(next_layer(), stream_.buffer(), resp, ec);
|
||||
if(ec)
|
||||
return;
|
||||
do_response(resp, key, ec);
|
||||
@@ -323,6 +363,8 @@ stream<NextLayer>::
|
||||
async_handshake(boost::string_ref const& host,
|
||||
boost::string_ref const& resource, HandshakeHandler&& handler)
|
||||
{
|
||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
||||
"AsyncStream requirements not met");
|
||||
beast::async_completion<
|
||||
HandshakeHandler, void(error_code)
|
||||
> completion(handler);
|
||||
@@ -331,11 +373,25 @@ async_handshake(boost::string_ref const& host,
|
||||
return completion.result.get();
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
close(close_reason const& cr)
|
||||
{
|
||||
static_assert(is_SyncStream<next_layer_type>::value,
|
||||
"SyncStream requirements not met");
|
||||
error_code ec;
|
||||
close(cr, ec);
|
||||
detail::maybe_throw(ec, "close");
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
close(close_reason const& cr, error_code& ec)
|
||||
{
|
||||
static_assert(is_SyncStream<next_layer_type>::value,
|
||||
"SyncStream requirements not met");
|
||||
assert(! wr_close_);
|
||||
wr_close_ = true;
|
||||
detail::frame_streambuf fb;
|
||||
@@ -351,6 +407,8 @@ typename async_completion<
|
||||
stream<NextLayer>::
|
||||
async_close(close_reason const& cr, CloseHandler&& handler)
|
||||
{
|
||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
||||
"AsyncStream requirements not met");
|
||||
beast::async_completion<
|
||||
CloseHandler, void(error_code)
|
||||
> completion(handler);
|
||||
@@ -359,12 +417,27 @@ async_close(close_reason const& cr, CloseHandler&& handler)
|
||||
return completion.result.get();
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
template<class Streambuf>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
read(opcode& op, Streambuf& streambuf)
|
||||
{
|
||||
static_assert(is_SyncStream<next_layer_type>::value,
|
||||
"SyncStream requirements not met");
|
||||
error_code ec;
|
||||
read(op, streambuf, ec);
|
||||
detail::maybe_throw(ec, "read");
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
template<class Streambuf>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
read(opcode& op, Streambuf& streambuf, error_code& ec)
|
||||
{
|
||||
static_assert(is_SyncStream<next_layer_type>::value,
|
||||
"SyncStream requirements not met");
|
||||
frame_info fi;
|
||||
for(;;)
|
||||
{
|
||||
@@ -385,6 +458,8 @@ stream<NextLayer>::
|
||||
async_read(opcode& op,
|
||||
Streambuf& streambuf, ReadHandler&& handler)
|
||||
{
|
||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
||||
"AsyncStream requirements requirements not met");
|
||||
static_assert(beast::is_Streambuf<Streambuf>::value,
|
||||
"Streambuf requirements not met");
|
||||
beast::async_completion<
|
||||
@@ -395,13 +470,28 @@ async_read(opcode& op,
|
||||
return completion.result.get();
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
template<class Streambuf>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
read_frame(frame_info& fi, Streambuf& streambuf)
|
||||
{
|
||||
static_assert(is_SyncStream<next_layer_type>::value,
|
||||
"SyncStream requirements not met");
|
||||
error_code ec;
|
||||
read_frame(fi, streambuf, ec);
|
||||
detail::maybe_throw(ec, "read_some");
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
template<class Streambuf>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
read_frame(frame_info& fi, Streambuf& streambuf, error_code& ec)
|
||||
{
|
||||
close_code code{};
|
||||
static_assert(is_SyncStream<next_layer_type>::value,
|
||||
"SyncStream requirements not met");
|
||||
close_code::value code{};
|
||||
for(;;)
|
||||
{
|
||||
if(rd_need_ == 0)
|
||||
@@ -409,7 +499,8 @@ read_frame(frame_info& fi, Streambuf& streambuf, error_code& ec)
|
||||
// read header
|
||||
detail::frame_streambuf fb;
|
||||
do_read_fh(fb, code, ec);
|
||||
if((error_ = ec != 0))
|
||||
error_ = ec != 0;
|
||||
if(error_)
|
||||
return;
|
||||
if(code != close_code::none)
|
||||
break;
|
||||
@@ -421,7 +512,8 @@ read_frame(frame_info& fi, Streambuf& streambuf, error_code& ec)
|
||||
auto const mb = fb.prepare(
|
||||
static_cast<std::size_t>(rd_fh_.len));
|
||||
fb.commit(boost::asio::read(stream_, mb, ec));
|
||||
if((error_ = ec != 0))
|
||||
error_ = ec != 0;
|
||||
if(error_)
|
||||
return;
|
||||
if(rd_fh_.mask)
|
||||
detail::mask_inplace(mb, rd_key_);
|
||||
@@ -437,7 +529,8 @@ read_frame(frame_info& fi, Streambuf& streambuf, error_code& ec)
|
||||
write_ping<static_streambuf>(
|
||||
fb, opcode::pong, data);
|
||||
boost::asio::write(stream_, fb.data(), ec);
|
||||
if((error_ = ec != 0))
|
||||
error_ = ec != 0;
|
||||
if(error_)
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
@@ -445,7 +538,7 @@ read_frame(frame_info& fi, Streambuf& streambuf, error_code& ec)
|
||||
{
|
||||
ping_payload_type data;
|
||||
detail::read(data, fb.data(), code);
|
||||
if((error_ = ec != 0))
|
||||
if(code != close_code::none)
|
||||
break;
|
||||
// VFALCO How to notify callers using
|
||||
// the synchronous interface?
|
||||
@@ -466,7 +559,8 @@ read_frame(frame_info& fi, Streambuf& streambuf, error_code& ec)
|
||||
wr_close_ = true;
|
||||
write_close<static_streambuf>(fb, cr);
|
||||
boost::asio::write(stream_, fb.data(), ec);
|
||||
if((error_ = ec != 0))
|
||||
error_ = ec != 0;
|
||||
if(error_)
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@@ -483,7 +577,8 @@ read_frame(frame_info& fi, Streambuf& streambuf, error_code& ec)
|
||||
detail::clamp(rd_need_));
|
||||
auto const bytes_transferred =
|
||||
stream_.read_some(smb, ec);
|
||||
if((error_ = ec != 0))
|
||||
error_ = ec != 0;
|
||||
if(error_)
|
||||
return;
|
||||
rd_need_ -= bytes_transferred;
|
||||
auto const pb = prepare_buffers(
|
||||
@@ -514,18 +609,20 @@ read_frame(frame_info& fi, Streambuf& streambuf, error_code& ec)
|
||||
detail::frame_streambuf fb;
|
||||
write_close<static_streambuf>(fb, code);
|
||||
boost::asio::write(stream_, fb.data(), ec);
|
||||
if((error_ = ec != 0))
|
||||
error_ = ec != 0;
|
||||
if(error_)
|
||||
return;
|
||||
}
|
||||
wsproto_helpers::call_teardown(next_layer_, ec);
|
||||
if((error_ = ec != 0))
|
||||
wsproto_helpers::call_teardown(next_layer(), ec);
|
||||
error_ = ec != 0;
|
||||
if(error_)
|
||||
return;
|
||||
ec = error::failed;
|
||||
error_ = true;
|
||||
return;
|
||||
}
|
||||
if(! ec)
|
||||
wsproto_helpers::call_teardown(next_layer_, ec);
|
||||
wsproto_helpers::call_teardown(next_layer(), ec);
|
||||
if(! ec)
|
||||
ec = error::closed;
|
||||
error_ = ec != 0;
|
||||
@@ -539,6 +636,8 @@ stream<NextLayer>::
|
||||
async_read_frame(frame_info& fi,
|
||||
Streambuf& streambuf, ReadHandler&& handler)
|
||||
{
|
||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
||||
"AsyncStream requirements requirements not met");
|
||||
static_assert(beast::is_Streambuf<Streambuf>::value,
|
||||
"Streambuf requirements not met");
|
||||
beast::async_completion<
|
||||
@@ -548,12 +647,27 @@ async_read_frame(frame_info& fi,
|
||||
return completion.result.get();
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
template<class ConstBufferSequence>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
write(ConstBufferSequence const& buffers)
|
||||
{
|
||||
static_assert(is_SyncStream<next_layer_type>::value,
|
||||
"SyncStream requirements not met");
|
||||
error_code ec;
|
||||
write(buffers, ec);
|
||||
detail::maybe_throw(ec, "write");
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
template<class ConstBufferSequence>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
write(ConstBufferSequence const& bs, error_code& ec)
|
||||
{
|
||||
static_assert(is_SyncStream<next_layer_type>::value,
|
||||
"SyncStream requirements not met");
|
||||
static_assert(beast::is_ConstBufferSequence<
|
||||
ConstBufferSequence>::value,
|
||||
"ConstBufferSequence requirements not met");
|
||||
@@ -582,6 +696,8 @@ typename async_completion<
|
||||
stream<NextLayer>::
|
||||
async_write(ConstBufferSequence const& bs, WriteHandler&& handler)
|
||||
{
|
||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
||||
"AsyncStream requirements not met");
|
||||
static_assert(beast::is_ConstBufferSequence<
|
||||
ConstBufferSequence>::value,
|
||||
"ConstBufferSequence requirements not met");
|
||||
@@ -592,12 +708,27 @@ async_write(ConstBufferSequence const& bs, WriteHandler&& handler)
|
||||
return completion.result.get();
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
template<class ConstBufferSequence>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
write_frame(bool fin, ConstBufferSequence const& buffers)
|
||||
{
|
||||
static_assert(is_SyncStream<next_layer_type>::value,
|
||||
"SyncStream requirements not met");
|
||||
error_code ec;
|
||||
write_frame(fin, buffers, ec);
|
||||
detail::maybe_throw(ec, "write");
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
template<class ConstBufferSequence>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
write_frame(bool fin, ConstBufferSequence const& bs, error_code& ec)
|
||||
{
|
||||
static_assert(is_SyncStream<next_layer_type>::value,
|
||||
"SyncStream requirements not met");
|
||||
static_assert(beast::is_ConstBufferSequence<
|
||||
ConstBufferSequence>::value,
|
||||
"ConstBufferSequence requirements not met");
|
||||
@@ -678,6 +809,8 @@ stream<NextLayer>::
|
||||
async_write_frame(bool fin,
|
||||
ConstBufferSequence const& bs, WriteHandler&& handler)
|
||||
{
|
||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
||||
"AsyncStream requirements not met");
|
||||
static_assert(beast::is_ConstBufferSequence<
|
||||
ConstBufferSequence>::value,
|
||||
"ConstBufferSequence requirements not met");
|
||||
@@ -792,7 +925,7 @@ template<class NextLayer>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
do_read_fh(detail::frame_streambuf& fb,
|
||||
close_code& code, error_code& ec)
|
||||
close_code::value& code, error_code& ec)
|
||||
{
|
||||
fb.commit(boost::asio::read(
|
||||
stream_, fb.prepare(2), ec));
|
||||
|
||||
@@ -61,7 +61,8 @@ class stream<NextLayer>::write_frame_op
|
||||
fh.rsv2 = 0;
|
||||
fh.rsv3 = 0;
|
||||
fh.len = boost::asio::buffer_size(cb);
|
||||
if((fh.mask = (ws.role_ == role_type::client)))
|
||||
fh.mask = ws.role_ == role_type::client;
|
||||
if(fh.mask)
|
||||
{
|
||||
fh.key = ws.maskgen_();
|
||||
detail::prepare_key(key, fh.key);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#ifndef BEAST_WEBSOCKET_RFC6455_HPP
|
||||
#define BEAST_WEBSOCKET_RFC6455_HPP
|
||||
|
||||
#include <beast/websocket/static_string.hpp>
|
||||
#include <beast/static_string.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
@@ -44,7 +44,9 @@ enum class opcode : std::uint8_t
|
||||
@see RFC 6455 7.4.1 Defined Status Codes
|
||||
https://tools.ietf.org/html/rfc6455#section-7.4.1
|
||||
*/
|
||||
enum class close_code : std::uint16_t
|
||||
namespace close_code {
|
||||
using value = std::uint16_t;
|
||||
enum
|
||||
{
|
||||
// used internally to mean "no error"
|
||||
none = 0,
|
||||
@@ -69,6 +71,7 @@ enum class close_code : std::uint16_t
|
||||
|
||||
last = 5000 // satisfy warnings
|
||||
};
|
||||
} // close_code
|
||||
|
||||
#if ! GENERATING_DOCS
|
||||
|
||||
@@ -89,7 +92,7 @@ using ping_payload_type =
|
||||
struct close_reason
|
||||
{
|
||||
/// The close code.
|
||||
close_code code = close_code::none;
|
||||
close_code::value code = close_code::none;
|
||||
|
||||
/// The optional utf8-encoded reason string.
|
||||
reason_string_type reason;
|
||||
@@ -102,7 +105,7 @@ struct close_reason
|
||||
close_reason() = default;
|
||||
|
||||
/// Construct from a code.
|
||||
close_reason(close_code code_)
|
||||
close_reason(close_code::value code_)
|
||||
: code(code_)
|
||||
{
|
||||
}
|
||||
@@ -117,7 +120,7 @@ struct close_reason
|
||||
|
||||
/// Construct from a code and reason.
|
||||
template<class CharT>
|
||||
close_reason(close_code code_,
|
||||
close_reason(close_code::value code_,
|
||||
CharT const* reason_)
|
||||
: code(code_)
|
||||
, reason(reason_)
|
||||
|
||||
@@ -1,337 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_WEBSOCKET_STATIC_STRING_HPP
|
||||
#define BEAST_WEBSOCKET_STATIC_STRING_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace beast {
|
||||
namespace websocket {
|
||||
|
||||
/** A string with a fixed-size storage area.
|
||||
|
||||
`static_string` objects behave like `std::string` except that
|
||||
the storage is not dynamically allocated but rather fixed in
|
||||
size.
|
||||
|
||||
These strings offer performance advantages when a protocol
|
||||
imposes a natural small upper limit on the size of a value.
|
||||
*/
|
||||
template<std::size_t N, class CharT,
|
||||
class Traits = std::char_traits<CharT>>
|
||||
class static_string
|
||||
{
|
||||
std::size_t n_;
|
||||
std::array<CharT, N+1> s_;
|
||||
|
||||
public:
|
||||
using traits_type = Traits;
|
||||
using value_type = typename Traits::char_type;
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = value_type*;
|
||||
using reference = value_type&;
|
||||
using const_pointer = value_type const*;
|
||||
using const_reference = value_type const&;
|
||||
using iterator = value_type*;
|
||||
using const_iterator = value_type const*;
|
||||
using reverse_iterator =
|
||||
std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator =
|
||||
std::reverse_iterator<const_iterator>;
|
||||
|
||||
static_string()
|
||||
{
|
||||
resize(0);
|
||||
}
|
||||
|
||||
static_string(static_string const& s)
|
||||
: n_(s.n_)
|
||||
{
|
||||
std::copy(&s.s_[0], &s.s_[0]+s.n_+1, &s_[0]);
|
||||
}
|
||||
|
||||
static_string&
|
||||
operator=(static_string const& s)
|
||||
{
|
||||
n_ = s.n_;
|
||||
std::copy(&s.s_[0], &s.s_[0]+s.n_+1, &s_[0]);
|
||||
return *this;
|
||||
}
|
||||
|
||||
static_string(CharT const* s)
|
||||
{
|
||||
assign(s);
|
||||
}
|
||||
|
||||
static_string& operator=(CharT const* s)
|
||||
{
|
||||
assign(s);
|
||||
return *this;
|
||||
}
|
||||
|
||||
reference
|
||||
at(size_type pos)
|
||||
{
|
||||
if(pos >= n_)
|
||||
throw std::out_of_range("static_string::at");
|
||||
return s_[pos];
|
||||
}
|
||||
|
||||
const_reference
|
||||
at(size_type pos) const
|
||||
{
|
||||
if(pos >= n_)
|
||||
throw std::out_of_range("static_string::at");
|
||||
return s_[pos];
|
||||
}
|
||||
|
||||
reference
|
||||
operator[](size_type pos);
|
||||
|
||||
const_reference
|
||||
operator[](size_type pos) const;
|
||||
|
||||
CharT&
|
||||
front()
|
||||
{
|
||||
return s_[0];
|
||||
}
|
||||
|
||||
CharT const&
|
||||
front() const
|
||||
{
|
||||
return s_[0];
|
||||
}
|
||||
|
||||
CharT&
|
||||
back()
|
||||
{
|
||||
return s_[n_-1];
|
||||
}
|
||||
|
||||
CharT const&
|
||||
back() const
|
||||
{
|
||||
return s_[n_-1];
|
||||
}
|
||||
|
||||
CharT*
|
||||
data()
|
||||
{
|
||||
return &s_[0];
|
||||
}
|
||||
|
||||
CharT const*
|
||||
data() const
|
||||
{
|
||||
return &s_[0];
|
||||
}
|
||||
|
||||
CharT const*
|
||||
c_str() const
|
||||
{
|
||||
s_[n_] = 0;
|
||||
return &s_[0];
|
||||
}
|
||||
|
||||
iterator
|
||||
begin()
|
||||
{
|
||||
return &s_[0];
|
||||
}
|
||||
|
||||
const_iterator
|
||||
begin() const
|
||||
{
|
||||
return &s_[0];
|
||||
}
|
||||
|
||||
const_iterator
|
||||
cbegin() const
|
||||
{
|
||||
return &s_[0];
|
||||
}
|
||||
|
||||
iterator
|
||||
end()
|
||||
{
|
||||
return &s_[n_];
|
||||
}
|
||||
|
||||
const_iterator
|
||||
end() const
|
||||
{
|
||||
return &s_[n_];
|
||||
}
|
||||
|
||||
const_iterator
|
||||
cend() const
|
||||
{
|
||||
return &s_[n_];
|
||||
}
|
||||
|
||||
reverse_iterator
|
||||
rbegin()
|
||||
{
|
||||
return reverse_iterator{end()};
|
||||
}
|
||||
|
||||
const_reverse_iterator
|
||||
rbegin() const
|
||||
{
|
||||
return reverse_iterator{end()};
|
||||
}
|
||||
|
||||
const_reverse_iterator
|
||||
crbegin() const
|
||||
{
|
||||
return reverse_iterator{cend()};
|
||||
}
|
||||
|
||||
reverse_iterator
|
||||
rend()
|
||||
{
|
||||
return reverse_iterator{begin()};
|
||||
}
|
||||
|
||||
const_reverse_iterator
|
||||
rend() const
|
||||
{
|
||||
return reverse_iterator{begin()};
|
||||
}
|
||||
|
||||
const_reverse_iterator
|
||||
crend() const
|
||||
{
|
||||
return reverse_iterator{cbegin()};
|
||||
}
|
||||
|
||||
bool
|
||||
empty() const
|
||||
{
|
||||
return n_ == 0;
|
||||
}
|
||||
|
||||
size_type
|
||||
size() const
|
||||
{
|
||||
return n_;
|
||||
}
|
||||
|
||||
size_type constexpr
|
||||
max_size() const
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
size_type
|
||||
capacity() const
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
void
|
||||
shrink_to_fit()
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
|
||||
void
|
||||
clear()
|
||||
{
|
||||
resize(0);
|
||||
}
|
||||
|
||||
// Does not perform value-initialization
|
||||
void
|
||||
resize(std::size_t n);
|
||||
|
||||
std::basic_string<CharT, Traits>
|
||||
to_string() const
|
||||
{
|
||||
return std::basic_string<
|
||||
CharT, Traits>{&s_[0], n_};
|
||||
}
|
||||
|
||||
private:
|
||||
void
|
||||
assign(CharT const* s);
|
||||
};
|
||||
|
||||
template<std::size_t N, class CharT, class Traits>
|
||||
auto
|
||||
static_string<N, CharT, Traits>::
|
||||
operator[](size_type pos) ->
|
||||
reference
|
||||
{
|
||||
static CharT null{0};
|
||||
if(pos == n_)
|
||||
return null;
|
||||
return s_[pos];
|
||||
}
|
||||
|
||||
template<std::size_t N, class CharT, class Traits>
|
||||
auto
|
||||
static_string<N, CharT, Traits>::
|
||||
operator[](size_type pos) const ->
|
||||
const_reference
|
||||
{
|
||||
static CharT constexpr null{0};
|
||||
if(pos == n_)
|
||||
return null;
|
||||
return s_[pos];
|
||||
}
|
||||
|
||||
template<std::size_t N, class CharT, class Traits>
|
||||
void
|
||||
static_string<N, CharT, Traits>::
|
||||
resize(std::size_t n)
|
||||
{
|
||||
if(n > N)
|
||||
throw std::length_error(
|
||||
"static_string overflow");
|
||||
n_ = n;
|
||||
s_[n_] = 0;
|
||||
}
|
||||
|
||||
template<std::size_t N, class CharT, class Traits>
|
||||
void
|
||||
static_string<N, CharT, Traits>::
|
||||
assign(CharT const* s)
|
||||
{
|
||||
size_type n = 0;
|
||||
for(auto p = s; *p; ++p)
|
||||
++n;
|
||||
if(n > N)
|
||||
throw std::out_of_range(
|
||||
"too large");
|
||||
std::copy(s, s+n, s_.begin());
|
||||
}
|
||||
|
||||
} // websocket
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <beast/websocket/detail/stream_base.hpp>
|
||||
#include <beast/streambuf_readstream.hpp>
|
||||
#include <beast/async_completion.hpp>
|
||||
#include <beast/detail/get_lowest_layer.hpp>
|
||||
#include <beast/http/message.hpp>
|
||||
#include <beast/http/string_body.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
@@ -80,8 +81,7 @@ class stream : public detail::stream_base
|
||||
{
|
||||
friend class ws_test;
|
||||
|
||||
NextLayer next_layer_;
|
||||
streambuf_readstream<NextLayer&, streambuf> stream_;
|
||||
streambuf_readstream<NextLayer, streambuf> stream_;
|
||||
|
||||
public:
|
||||
/// The type of the next layer.
|
||||
@@ -90,26 +90,26 @@ public:
|
||||
|
||||
/// The type of the lowest layer.
|
||||
using lowest_layer_type =
|
||||
typename next_layer_type::lowest_layer_type;
|
||||
typename beast::detail::get_lowest_layer<
|
||||
next_layer_type>::type;
|
||||
|
||||
/// The type of endpoint of the lowest layer.
|
||||
using endpoint_type =
|
||||
typename lowest_layer_type::endpoint_type;
|
||||
/** Move-construct a stream.
|
||||
|
||||
/// The protocol of the next layer.
|
||||
using protocol_type =
|
||||
typename lowest_layer_type::protocol_type;
|
||||
If @c NextLayer is move constructible, this function
|
||||
will move-construct a new stream from the existing stream.
|
||||
|
||||
/// The type of resolver of the next layer.
|
||||
using resolver_type =
|
||||
typename protocol_type::resolver;
|
||||
|
||||
/// Move constructor.
|
||||
@note The behavior of move assignment on or from streams
|
||||
with active or pending operations is undefined.
|
||||
*/
|
||||
stream(stream&&) = default;
|
||||
|
||||
/** Move assignment.
|
||||
|
||||
Undefined behavior if operations are active or pending.
|
||||
If @c NextLayer is move constructible, this function
|
||||
will move-construct a new stream from the existing stream.
|
||||
|
||||
@note The behavior of move assignment on or from streams
|
||||
with active or pending operations is undefined.
|
||||
*/
|
||||
stream& operator=(stream&&) = default;
|
||||
|
||||
@@ -217,7 +217,7 @@ public:
|
||||
boost::asio::io_service&
|
||||
get_io_service()
|
||||
{
|
||||
return next_layer_.lowest_layer().get_io_service();
|
||||
return stream_.get_io_service();
|
||||
}
|
||||
|
||||
/** Get a reference to the next layer.
|
||||
@@ -231,7 +231,7 @@ public:
|
||||
next_layer_type&
|
||||
next_layer()
|
||||
{
|
||||
return next_layer_;
|
||||
return stream_.next_layer();
|
||||
}
|
||||
|
||||
/** Get a reference to the next layer.
|
||||
@@ -245,7 +245,7 @@ public:
|
||||
next_layer_type const&
|
||||
next_layer() const
|
||||
{
|
||||
return next_layer_;
|
||||
return stream_.next_layer();
|
||||
}
|
||||
|
||||
/** Get a reference to the lowest layer.
|
||||
@@ -259,7 +259,7 @@ public:
|
||||
lowest_layer_type&
|
||||
lowest_layer()
|
||||
{
|
||||
return next_layer_.lowest_layer();
|
||||
return stream_.lowest_layer();
|
||||
}
|
||||
|
||||
/** Get a reference to the lowest layer.
|
||||
@@ -273,7 +273,7 @@ public:
|
||||
lowest_layer_type const&
|
||||
lowest_layer() const
|
||||
{
|
||||
return next_layer_.lowest_layer();
|
||||
return stream_.lowest_layer();
|
||||
}
|
||||
|
||||
/** Returns the close reason received from the peer.
|
||||
@@ -309,12 +309,7 @@ public:
|
||||
@throws boost::system::system_error Thrown on failure.
|
||||
*/
|
||||
void
|
||||
accept()
|
||||
{
|
||||
error_code ec;
|
||||
accept(boost::asio::null_buffers{}, ec);
|
||||
detail::maybe_throw(ec, "accept");
|
||||
}
|
||||
accept();
|
||||
|
||||
/** Read and respond to a WebSocket HTTP Upgrade request.
|
||||
|
||||
@@ -603,12 +598,7 @@ public:
|
||||
*/
|
||||
void
|
||||
handshake(boost::string_ref const& host,
|
||||
boost::string_ref const& resource)
|
||||
{
|
||||
error_code ec;
|
||||
handshake(host, resource, ec);
|
||||
detail::maybe_throw(ec, "upgrade");
|
||||
}
|
||||
boost::string_ref const& resource);
|
||||
|
||||
/** Send a WebSocket Upgrade request.
|
||||
|
||||
@@ -692,12 +682,7 @@ public:
|
||||
@param cr The reason for the close.
|
||||
*/
|
||||
void
|
||||
close(close_reason const& cr)
|
||||
{
|
||||
error_code ec;
|
||||
close(cr, ec);
|
||||
detail::maybe_throw(ec, "close");
|
||||
}
|
||||
close(close_reason const& cr);
|
||||
|
||||
/** Perform a WebSocket close.
|
||||
|
||||
@@ -773,12 +758,7 @@ public:
|
||||
*/
|
||||
template<class Streambuf>
|
||||
void
|
||||
read(opcode& op, Streambuf& streambuf)
|
||||
{
|
||||
error_code ec;
|
||||
read(op, streambuf, ec);
|
||||
detail::maybe_throw(ec, "read");
|
||||
}
|
||||
read(opcode& op, Streambuf& streambuf);
|
||||
|
||||
/** Read a message.
|
||||
|
||||
@@ -868,12 +848,7 @@ public:
|
||||
*/
|
||||
template<class Streambuf>
|
||||
void
|
||||
read_frame(frame_info& fi, Streambuf& streambuf)
|
||||
{
|
||||
error_code ec;
|
||||
read_frame(fi, streambuf, ec);
|
||||
detail::maybe_throw(ec, "read_some");
|
||||
}
|
||||
read_frame(frame_info& fi, Streambuf& streambuf);
|
||||
|
||||
/** Read a message frame.
|
||||
|
||||
@@ -978,12 +953,7 @@ public:
|
||||
*/
|
||||
template<class ConstBufferSequence>
|
||||
void
|
||||
write(ConstBufferSequence const& buffers)
|
||||
{
|
||||
error_code ec;
|
||||
write(buffers, ec);
|
||||
detail::maybe_throw(ec, "write");
|
||||
}
|
||||
write(ConstBufferSequence const& buffers);
|
||||
|
||||
/** Send a message.
|
||||
|
||||
@@ -1081,12 +1051,7 @@ public:
|
||||
*/
|
||||
template<class ConstBufferSequence>
|
||||
void
|
||||
write_frame(bool fin, ConstBufferSequence const& buffers)
|
||||
{
|
||||
error_code ec;
|
||||
write_frame(fin, buffers, ec);
|
||||
detail::maybe_throw(ec, "write");
|
||||
}
|
||||
write_frame(bool fin, ConstBufferSequence const& buffers);
|
||||
|
||||
/** Send a frame.
|
||||
|
||||
@@ -1180,7 +1145,7 @@ private:
|
||||
|
||||
void
|
||||
do_read_fh(detail::frame_streambuf& fb,
|
||||
close_code& code, error_code& ec);
|
||||
close_code::value& code, error_code& ec);
|
||||
};
|
||||
|
||||
} // websocket
|
||||
|
||||
Reference in New Issue
Block a user