mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Merge subtree Beast 1.0.0-b5
Merge commit 'a9e507da9b636d394bb43d6bf8002d013530f57a' into develop
This commit is contained in:
@@ -35,6 +35,7 @@ unit-test core-tests :
|
||||
core/write_streambuf.cpp
|
||||
core/detail/base64.cpp
|
||||
core/detail/empty_base_optimization.cpp
|
||||
core/detail/get_lowest_layer.cpp
|
||||
core/detail/sha1.cpp
|
||||
;
|
||||
|
||||
@@ -43,6 +44,7 @@ unit-test http-tests :
|
||||
http/basic_headers.cpp
|
||||
http/basic_parser_v1.cpp
|
||||
http/body_type.cpp
|
||||
http/concepts.cpp
|
||||
http/empty_body.cpp
|
||||
http/headers.cpp
|
||||
http/message.cpp
|
||||
@@ -57,7 +59,6 @@ unit-test http-tests :
|
||||
http/status.cpp
|
||||
http/streambuf_body.cpp
|
||||
http/string_body.cpp
|
||||
http/type_check.cpp
|
||||
http/write.cpp
|
||||
http/detail/chunk_encode.cpp
|
||||
;
|
||||
@@ -77,6 +78,7 @@ unit-test websocket-tests :
|
||||
websocket/teardown.cpp
|
||||
websocket/detail/frame.cpp
|
||||
websocket/detail/mask.cpp
|
||||
websocket/detail/stream_base.cpp
|
||||
websocket/detail/utf8_checker.cpp
|
||||
;
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ add_executable (core-tests
|
||||
write_streambuf.cpp
|
||||
detail/base64.cpp
|
||||
detail/empty_base_optimization.cpp
|
||||
detail/get_lowest_layer.cpp
|
||||
detail/sha1.cpp
|
||||
)
|
||||
|
||||
|
||||
@@ -66,6 +66,14 @@ public:
|
||||
expect(buffer_size(buffer_cat(
|
||||
sb1.data(), sb2.data())) == 12);
|
||||
}
|
||||
for(auto it = bs.begin(); it != bs.end(); ++it)
|
||||
{
|
||||
decltype(bs)::const_iterator copy;
|
||||
copy = it;
|
||||
expect(copy == it);
|
||||
copy = copy;
|
||||
expect(copy == it);
|
||||
}
|
||||
}
|
||||
|
||||
void testIterators()
|
||||
|
||||
88
src/beast/test/core/detail/get_lowest_layer.cpp
Normal file
88
src/beast/test/core/detail/get_lowest_layer.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/core/detail/get_lowest_layer.hpp>
|
||||
|
||||
#include <beast/unit_test/suite.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace beast {
|
||||
namespace detail {
|
||||
|
||||
class get_lowest_layer_test
|
||||
: public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
struct F1
|
||||
{
|
||||
};
|
||||
|
||||
struct F2
|
||||
{
|
||||
};
|
||||
|
||||
template<class F>
|
||||
struct F3
|
||||
{
|
||||
using next_layer_type =
|
||||
typename std::remove_reference<F>::type;
|
||||
|
||||
using lowest_layer_type = typename
|
||||
get_lowest_layer<next_layer_type>::type;
|
||||
};
|
||||
|
||||
template<class F>
|
||||
struct F4
|
||||
{
|
||||
using next_layer_type =
|
||||
typename std::remove_reference<F>::type;
|
||||
|
||||
using lowest_layer_type = typename
|
||||
get_lowest_layer<next_layer_type>::type;
|
||||
};
|
||||
|
||||
void
|
||||
run()
|
||||
{
|
||||
static_assert(! has_lowest_layer<F1>::value, "");
|
||||
static_assert(! has_lowest_layer<F2>::value, "");
|
||||
static_assert(has_lowest_layer<F3<F1>>::value, "");
|
||||
static_assert(has_lowest_layer<F4<F3<F2>>>::value, "");
|
||||
|
||||
static_assert(std::is_same<
|
||||
get_lowest_layer<F1>::type, F1>::value, "");
|
||||
|
||||
static_assert(std::is_same<
|
||||
get_lowest_layer<F2>::type, F2>::value, "");
|
||||
|
||||
static_assert(std::is_same<
|
||||
get_lowest_layer<F3<F1>>::type, F1>::value, "");
|
||||
|
||||
static_assert(std::is_same<
|
||||
get_lowest_layer<F3<F2>>::type, F2>::value, "");
|
||||
|
||||
static_assert(std::is_same<
|
||||
get_lowest_layer<F4<F1>>::type, F1>::value, "");
|
||||
|
||||
static_assert(std::is_same<
|
||||
get_lowest_layer<F4<F2>>::type, F2>::value, "");
|
||||
|
||||
static_assert(std::is_same<
|
||||
get_lowest_layer<F4<F3<F1>>>::type, F1>::value, "");
|
||||
|
||||
static_assert(std::is_same<
|
||||
get_lowest_layer<F4<F3<F2>>>::type, F2>::value, "");
|
||||
|
||||
pass();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(get_lowest_layer,core,beast);
|
||||
|
||||
} // detail
|
||||
} // beast
|
||||
@@ -89,6 +89,7 @@ public:
|
||||
|
||||
void testIterator()
|
||||
{
|
||||
using boost::asio::buffer_size;
|
||||
using boost::asio::const_buffer;
|
||||
char b[3];
|
||||
std::array<const_buffer, 3> bs{{
|
||||
@@ -98,7 +99,12 @@ public:
|
||||
auto pb = prepare_buffers(2, bs);
|
||||
std::size_t n = 0;
|
||||
for(auto it = pb.end(); it != pb.begin(); --it)
|
||||
{
|
||||
decltype(pb)::const_iterator it2(std::move(it));
|
||||
expect(buffer_size(*it2) == 1);
|
||||
it = std::move(it2);
|
||||
++n;
|
||||
}
|
||||
expect(n == 2);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ add_executable (http-tests
|
||||
basic_headers.cpp
|
||||
basic_parser_v1.cpp
|
||||
body_type.cpp
|
||||
concepts.cpp
|
||||
empty_body.cpp
|
||||
headers.cpp
|
||||
message.cpp
|
||||
@@ -24,7 +25,6 @@ add_executable (http-tests
|
||||
status.cpp
|
||||
streambuf_body.cpp
|
||||
string_body.cpp
|
||||
type_check.cpp
|
||||
write.cpp
|
||||
detail/chunk_encode.cpp
|
||||
)
|
||||
|
||||
@@ -532,6 +532,7 @@ public:
|
||||
void testInvalidMatrix()
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::buffer_copy;
|
||||
std::string s;
|
||||
|
||||
for(std::size_t n = 0;; ++n)
|
||||
@@ -549,15 +550,24 @@ public:
|
||||
s[n] = 0;
|
||||
for(std::size_t m = 1; m < len - 1; ++m)
|
||||
{
|
||||
// Use separately allocated buffers so
|
||||
// address sanitizer has something to chew on.
|
||||
//
|
||||
std::unique_ptr<char[]> p1(new char[m]);
|
||||
std::unique_ptr<char[]> p2(new char[len - m]);
|
||||
auto const b1 = buffer(p1.get(), m);
|
||||
auto const b2 = buffer(p2.get(), len - m);
|
||||
buffer_copy(b1, buffer(s.data(), m));
|
||||
buffer_copy(b2, buffer(s.data() + m, len - m));
|
||||
null_parser<true> p;
|
||||
error_code ec;
|
||||
p.write(buffer(s.data(), m), ec);
|
||||
p.write(b1, ec);
|
||||
if(ec)
|
||||
{
|
||||
pass();
|
||||
continue;
|
||||
}
|
||||
p.write(buffer(s.data() + m, len - m), ec);
|
||||
p.write(b2, ec);
|
||||
expect(ec);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,4 +6,4 @@
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/http/type_check.hpp>
|
||||
#include <beast/http/concepts.hpp>
|
||||
@@ -59,6 +59,7 @@ public:
|
||||
}
|
||||
catch(std::exception const&)
|
||||
{
|
||||
pass();
|
||||
}
|
||||
m.headers.erase("Content-Length");
|
||||
m.headers.insert("Connection", "keep-alive");
|
||||
@@ -69,7 +70,12 @@ public:
|
||||
}
|
||||
catch(std::exception const&)
|
||||
{
|
||||
pass();
|
||||
}
|
||||
m.version = 11;
|
||||
m.headers.erase("Connection");
|
||||
m.headers.insert("Connection", "close");
|
||||
expect(! is_keep_alive(m));
|
||||
}
|
||||
|
||||
void run() override
|
||||
|
||||
@@ -85,7 +85,7 @@ public:
|
||||
{
|
||||
using namespace std::chrono;
|
||||
using clock_type = std::chrono::high_resolution_clock;
|
||||
log << name;
|
||||
log << name << std::endl;
|
||||
for(std::size_t trial = 1; trial <= repeat; ++trial)
|
||||
{
|
||||
auto const t0 = clock_type::now();
|
||||
@@ -93,7 +93,7 @@ public:
|
||||
auto const elapsed = clock_type::now() - t0;
|
||||
log <<
|
||||
"Trial " << trial << ": " <<
|
||||
duration_cast<milliseconds>(elapsed).count() << " ms";
|
||||
duration_cast<milliseconds>(elapsed).count() << " ms" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,10 +109,10 @@ public:
|
||||
static std::size_t constexpr Repeat = 50;
|
||||
|
||||
log << "sizeof(request parser) == " <<
|
||||
sizeof(basic_parser_v1<true, null_parser<true>>);
|
||||
sizeof(basic_parser_v1<true, null_parser<true>>) << '\n';
|
||||
|
||||
log << "sizeof(response parser) == " <<
|
||||
sizeof(basic_parser_v1<false, null_parser<true>>);
|
||||
sizeof(basic_parser_v1<false, null_parser<true>>)<< '\n';
|
||||
|
||||
testcase << "Parser speed test, " <<
|
||||
((Repeat * size_ + 512) / 1024) << "KB in " <<
|
||||
|
||||
@@ -12,8 +12,10 @@
|
||||
#include <beast/http/headers.hpp>
|
||||
#include <beast/http/parser_v1.hpp>
|
||||
#include <beast/http/read.hpp>
|
||||
#include <beast/http/write.hpp>
|
||||
#include <beast/test/string_stream.hpp>
|
||||
#include <beast/unit_test/suite.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
@@ -25,16 +27,18 @@ class streambuf_body_test : public beast::unit_test::suite
|
||||
public:
|
||||
void run() override
|
||||
{
|
||||
test::string_stream ss(ios_,
|
||||
std::string const s =
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
"Server: test\r\n"
|
||||
"Content-Length: 3\r\n"
|
||||
"\r\n"
|
||||
"xyz");
|
||||
"xyz";
|
||||
test::string_stream ss(ios_, s);
|
||||
parser_v1<false, streambuf_body, headers> p;
|
||||
streambuf sb;
|
||||
parse(ss, sb, p);
|
||||
expect(to_string(p.get().body.data()) == "xyz");
|
||||
expect(boost::lexical_cast<std::string>(p.get()) == s);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ add_executable (websocket-tests
|
||||
teardown.cpp
|
||||
detail/frame.cpp
|
||||
detail/mask.cpp
|
||||
detail/stream_base.cpp
|
||||
detail/utf8_checker.cpp
|
||||
)
|
||||
|
||||
|
||||
@@ -225,7 +225,6 @@ public:
|
||||
testCloseCodes();
|
||||
testFrameHeader();
|
||||
testBadFrameHeaders();
|
||||
pass();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/websocket/detail/mask.hpp>
|
||||
|
||||
#include <beast/unit_test/suite.hpp>
|
||||
|
||||
namespace beast {
|
||||
|
||||
40
src/beast/test/websocket/detail/stream_base.cpp
Normal file
40
src/beast/test/websocket/detail/stream_base.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/websocket/detail/stream_base.hpp>
|
||||
|
||||
#include <beast/unit_test/suite.hpp>
|
||||
#include <initializer_list>
|
||||
#include <climits>
|
||||
|
||||
namespace beast {
|
||||
namespace websocket {
|
||||
namespace detail {
|
||||
|
||||
class stream_base_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
void testClamp()
|
||||
{
|
||||
expect(detail::clamp(
|
||||
std::numeric_limits<std::uint64_t>::max()) ==
|
||||
std::numeric_limits<std::size_t>::max());
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
testClamp();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(stream_base,websocket,beast);
|
||||
|
||||
} // detail
|
||||
} // websocket
|
||||
} // beast
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -91,14 +91,16 @@ private:
|
||||
bool log;
|
||||
int state = 0;
|
||||
boost::optional<endpoint_type> ep;
|
||||
websocket::stream<socket_type> ws;
|
||||
websocket::opcode op;
|
||||
stream<socket_type> ws;
|
||||
boost::asio::io_service::strand strand;
|
||||
opcode op;
|
||||
beast::streambuf sb;
|
||||
int id;
|
||||
|
||||
data(bool log_, socket_type&& sock_)
|
||||
: log(log_)
|
||||
, ws(std::move(sock_))
|
||||
, strand(ws.get_io_service())
|
||||
, id([]
|
||||
{
|
||||
static int n = 0;
|
||||
@@ -112,6 +114,7 @@ private:
|
||||
: log(log_)
|
||||
, ep(ep_)
|
||||
, ws(std::move(sock_))
|
||||
, strand(ws.get_io_service())
|
||||
, id([]
|
||||
{
|
||||
static int n = 0;
|
||||
@@ -174,8 +177,34 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
template<class Streambuf, std::size_t N>
|
||||
static
|
||||
bool
|
||||
match(Streambuf& sb, char const(&s)[N])
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::buffer_copy;
|
||||
if(sb.size() < N-1)
|
||||
return false;
|
||||
static_string<N-1> t;
|
||||
t.resize(N-1);
|
||||
buffer_copy(buffer(t.data(), t.size()),
|
||||
sb.data());
|
||||
if(t != s)
|
||||
return false;
|
||||
sb.consume(N-1);
|
||||
return true;
|
||||
}
|
||||
|
||||
void operator()(error_code ec, std::size_t)
|
||||
{
|
||||
(*this)(ec);
|
||||
}
|
||||
|
||||
void operator()(error_code ec)
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::buffer_copy;
|
||||
auto& d = *d_;
|
||||
switch(d.state)
|
||||
{
|
||||
@@ -191,19 +220,54 @@ private:
|
||||
d.sb.consume(d.sb.size());
|
||||
// read message
|
||||
d.state = 2;
|
||||
d.ws.async_read(d.op, d.sb, std::move(*this));
|
||||
d.ws.async_read(d.op, d.sb,
|
||||
d.strand.wrap(std::move(*this)));
|
||||
return;
|
||||
|
||||
// got message
|
||||
case 2:
|
||||
if(ec == websocket::error::closed)
|
||||
if(ec == error::closed)
|
||||
return;
|
||||
if(ec)
|
||||
return fail(ec, "async_read");
|
||||
if(match(d.sb, "RAW"))
|
||||
{
|
||||
d.state = 1;
|
||||
boost::asio::async_write(d.ws.next_layer(),
|
||||
d.sb.data(), d.strand.wrap(std::move(*this)));
|
||||
return;
|
||||
}
|
||||
else if(match(d.sb, "TEXT"))
|
||||
{
|
||||
d.state = 1;
|
||||
d.ws.set_option(message_type{opcode::text});
|
||||
d.ws.async_write(
|
||||
d.sb.data(), d.strand.wrap(std::move(*this)));
|
||||
return;
|
||||
}
|
||||
else if(match(d.sb, "PING"))
|
||||
{
|
||||
ping_data payload;
|
||||
d.sb.consume(buffer_copy(
|
||||
buffer(payload.data(), payload.size()),
|
||||
d.sb.data()));
|
||||
d.state = 1;
|
||||
d.ws.async_ping(payload,
|
||||
d.strand.wrap(std::move(*this)));
|
||||
return;
|
||||
}
|
||||
else if(match(d.sb, "CLOSE"))
|
||||
{
|
||||
d.state = 1;
|
||||
d.ws.async_close({},
|
||||
d.strand.wrap(std::move(*this)));
|
||||
return;
|
||||
}
|
||||
// write message
|
||||
d.state = 1;
|
||||
d.ws.set_option(websocket::message_type(d.op));
|
||||
d.ws.async_write(d.sb.data(), std::move(*this));
|
||||
d.ws.set_option(message_type(d.op));
|
||||
d.ws.async_write(d.sb.data(),
|
||||
d.strand.wrap(std::move(*this)));
|
||||
return;
|
||||
|
||||
// connected
|
||||
@@ -214,7 +278,7 @@ private:
|
||||
d.ws.async_handshake(
|
||||
d.ep->address().to_string() + ":" +
|
||||
std::to_string(d.ep->port()),
|
||||
"/", std::move(*this));
|
||||
"/", d.strand.wrap(std::move(*this)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -226,7 +290,7 @@ private:
|
||||
auto& d = *d_;
|
||||
if(d.log)
|
||||
{
|
||||
if(ec != websocket::error::closed)
|
||||
if(ec != error::closed)
|
||||
std::cerr << "#" << d_->id << " " <<
|
||||
what << ": " << ec.message() << std::endl;
|
||||
}
|
||||
@@ -256,6 +320,8 @@ private:
|
||||
{
|
||||
if(! acceptor_.is_open())
|
||||
return;
|
||||
if(ec == boost::asio::error::operation_aborted)
|
||||
return;
|
||||
maybe_throw(ec, "accept");
|
||||
socket_type sock(std::move(sock_));
|
||||
acceptor_.async_accept(sock_,
|
||||
|
||||
@@ -101,15 +101,17 @@ private:
|
||||
{
|
||||
int id;
|
||||
sync_echo_peer& self;
|
||||
socket_type sock;
|
||||
boost::asio::io_service::work work;
|
||||
// Must be destroyed before work otherwise the
|
||||
// io_service could be destroyed before the socket.
|
||||
socket_type sock;
|
||||
|
||||
lambda(int id_, sync_echo_peer& self_,
|
||||
socket_type&& sock_)
|
||||
: id(id_)
|
||||
, self(self_)
|
||||
, work(sock_.get_io_service())
|
||||
, sock(std::move(sock_))
|
||||
, work(sock.get_io_service())
|
||||
{
|
||||
}
|
||||
|
||||
@@ -149,10 +151,31 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
template<class Streambuf, std::size_t N>
|
||||
static
|
||||
bool
|
||||
match(Streambuf& sb, char const(&s)[N])
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::buffer_copy;
|
||||
if(sb.size() < N-1)
|
||||
return false;
|
||||
static_string<N-1> t;
|
||||
t.resize(N-1);
|
||||
buffer_copy(buffer(t.data(), t.size()),
|
||||
sb.data());
|
||||
if(t != s)
|
||||
return false;
|
||||
sb.consume(N-1);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
do_peer(int id, socket_type&& sock)
|
||||
{
|
||||
websocket::stream<socket_type> ws(std::move(sock));
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::buffer_copy;
|
||||
stream<socket_type> ws(std::move(sock));
|
||||
ws.set_option(decorate(identity{}));
|
||||
ws.set_option(read_message_max(64 * 1024 * 1024));
|
||||
error_code ec;
|
||||
@@ -164,17 +187,45 @@ private:
|
||||
}
|
||||
for(;;)
|
||||
{
|
||||
websocket::opcode op;
|
||||
opcode op;
|
||||
beast::streambuf sb;
|
||||
ws.read(op, sb, ec);
|
||||
if(ec)
|
||||
{
|
||||
auto const s = ec.message();
|
||||
break;
|
||||
ws.set_option(websocket::message_type(op));
|
||||
ws.write(sb.data(), ec);
|
||||
}
|
||||
ws.set_option(message_type(op));
|
||||
if(match(sb, "RAW"))
|
||||
{
|
||||
boost::asio::write(
|
||||
ws.next_layer(), sb.data(), ec);
|
||||
}
|
||||
else if(match(sb, "TEXT"))
|
||||
{
|
||||
ws.set_option(message_type{opcode::text});
|
||||
ws.write(sb.data(), ec);
|
||||
}
|
||||
else if(match(sb, "PING"))
|
||||
{
|
||||
ping_data payload;
|
||||
sb.consume(buffer_copy(
|
||||
buffer(payload.data(), payload.size()),
|
||||
sb.data()));
|
||||
ws.ping(payload, ec);
|
||||
}
|
||||
else if(match(sb, "CLOSE"))
|
||||
{
|
||||
ws.close({}, ec);
|
||||
}
|
||||
else
|
||||
{
|
||||
ws.write(sb.data(), ec);
|
||||
}
|
||||
if(ec)
|
||||
break;
|
||||
}
|
||||
if(ec && ec != websocket::error::closed)
|
||||
if(ec && ec != error::closed)
|
||||
{
|
||||
fail(id, ec, "read");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user