Merge subtree Beast 1.0.0-b4:

Merge commit 'c0952e54db7bd519440dc0611db7347cb048296d' into
This commit is contained in:
Vinnie Falco
2016-05-12 19:24:08 -04:00
187 changed files with 5332 additions and 2475 deletions

View File

@@ -12,7 +12,7 @@ if (WIN32)
else()
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_MULTITHREADED ON)
find_package(Boost REQUIRED COMPONENTS filesystem program_options system)
find_package(Boost REQUIRED COMPONENTS coroutine context thread filesystem program_options system)
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIR})
@@ -20,34 +20,45 @@ else()
find_package(Threads)
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -g -std=c++11 -Wall /Wextra /Wpedantic /Wconversion -Wno-unused-variable")
"${CMAKE_CXX_FLAGS} -g -std=c++11 -Wall -Wpedantic")
endif()
message ("cxx Flags: " ${CMAKE_CXX_FLAGS})
macro(GroupSources curdir)
function(DoGroupSources curdir rootdir folder)
file(GLOB children RELATIVE ${PROJECT_SOURCE_DIR}/${curdir} ${PROJECT_SOURCE_DIR}/${curdir}/*)
foreach(child ${children})
if(IS_DIRECTORY ${PROJECT_SOURCE_DIR}/${curdir}/${child})
GroupSources(${curdir}/${child})
DoGroupSources(${curdir}/${child} ${rootdir} ${folder})
elseif(${child} STREQUAL "CMakeLists.txt")
source_group("" FILES ${PROJECT_SOURCE_DIR}/${curdir}/${child})
else()
string(REPLACE "/" "\\" groupname ${curdir})
string(REPLACE "src" "Common" groupname ${groupname})
string(REGEX REPLACE ^${rootdir} ${folder} groupname ${curdir})
#set(groupname ${curdir})
string(REPLACE "/" "\\" groupname ${groupname})
source_group(${groupname} FILES ${PROJECT_SOURCE_DIR}/${curdir}/${child})
endif()
endforeach()
endmacro()
endfunction()
function(GroupSources curdir folder)
DoGroupSources(${curdir} ${curdir} ${folder})
endfunction()
include_directories (extras)
include_directories (include)
file(GLOB_RECURSE BEAST_INCLUDES
${PROJECT_SOURCE_DIR}/include/beast/*.hpp
${PROJECT_SOURCE_DIR}/include/beast/*.ipp
${PROJECT_SOURCE_DIR}/extras/beast/*.hpp
${PROJECT_SOURCE_DIR}/extras/beast/*.ipp
)
add_subdirectory (test)
add_subdirectory (examples)
add_subdirectory (test)
add_subdirectory (test/core)
add_subdirectory (test/http)
add_subdirectory (test/websocket)
#enable_testing()

View File

@@ -64,6 +64,7 @@ variant asan
project beast
: requirements
<include>.
<include>./extras
<include>./include
#<use>/boost//headers
<library>/boost/system//boost_system

View File

@@ -1,4 +1,8 @@
# Beast [![Build Status](https://travis-ci.org/vinniefalco/Beast.svg?branch=master)](https://travis-ci.org/vinniefalco/Beast) [![codecov](https://codecov.io/gh/sublimator/Beast/branch/master/graph/badge.svg)](https://codecov.io/gh/sublimator/Beast)
# Beast
[![Build Status](https://travis-ci.org/vinniefalco/Beast.svg?branch=master)](https://travis-ci.org/vinniefalco/Beast) [![codecov]
(https://codecov.io/gh/vinniefalco/Beast/branch/master/graph/badge.svg)](https://codecov.io/gh/vinniefalco/Beast) [![Documentation]
(https://img.shields.io/badge/documentation-master-brightgreen.svg)](http://vinniefalco.github.io/beast/)
Beast provides implementations of the HTTP and WebSocket protocols
built on top of Boost.Asio and other parts of boost.
@@ -9,10 +13,72 @@ Requirements:
* C++11 or greater
* OpenSSL (optional)
Linking applications with beast:
Example WebSocket program:
```C++
#include <beast/to_string.hpp>
#include <beast/websocket.hpp>
#include <boost/asio.hpp>
#include <iostream>
#include <string>
You need to include the .cpp file `src/beast_http_nodejs_parser.cpp`
in the build script or Makefile for your program in order to link.
int main()
{
// Normal boost::asio setup
std::string const host = "echo.websocket.org";
boost::asio::io_service ios;
boost::asio::ip::tcp::resolver r(ios);
boost::asio::ip::tcp::socket sock(ios);
boost::asio::connect(sock,
r.resolve(boost::asio::ip::tcp::resolver::query{host, "80"}));
// WebSocket connect and send message using beast
beast::websocket::stream<boost::asio::ip::tcp::socket&> ws(sock);
ws.handshake(host, "/");
ws.write(boost::asio::buffer("Hello, world!"));
// Receive WebSocket message, print and close using beast
beast::streambuf sb;
beast::websocket::opcode op;
ws.read(op, sb);
ws.close(beast::websocket::close_code::normal);
std::cout << to_string(sb.data()) << "\n";
}
```
Example HTTP program:
```C++
#include <beast/http.hpp>
#include <boost/asio.hpp>
#include <iostream>
#include <string>
int main()
{
// Normal boost::asio setup
std::string const host = "boost.org";
boost::asio::io_service ios;
boost::asio::ip::tcp::resolver r(ios);
boost::asio::ip::tcp::socket sock(ios);
boost::asio::connect(sock,
r.resolve(boost::asio::ip::tcp::resolver::query{host, "http"}));
// Send HTTP request using beast
beast::http::request_v1<beast::http::empty_body> req;
req.method = "GET";
req.url = "/";
req.version = 11;
req.headers.replace("Host", host + ":" + std::to_string(sock.remote_endpoint().port()));
req.headers.replace("User-Agent", "Beast");
beast::http::prepare(req);
beast::http::write(sock, req);
// Receive and print HTTP response using beast
beast::streambuf sb;
beast::http::response_v1<beast::http::streambuf_body> resp;
beast::http::read(sock, sb, resp);
std::cout << resp;
}
```
Links:

View File

@@ -2,6 +2,7 @@
General:
* Use SFINAE on return values (search for "class =")
* Remove http,websocket error_code types and use the one in <beast/error.hpp>
Boost.Http
* Use enum instead of bool in isRequest
@@ -17,22 +18,25 @@ Docs:
- See if we can include them now that xsl is fixed
* Implement cleanup-param to remove spaces around template arguments
e.g. in basic_streambuf move constructor members
* Don't put using namespace at file scope in examples,
do something like "using ba = boost::asio" instead.
Core:
* Replace Jamroot with Jamfile
* Fix bidirectional buffers iterators operator->()
* Complete allocator testing in basic_streambuf, basic_headers
* Complete allocator testing in basic_streambuf
WebSocket:
* optimized versions of key/masking, choose prepared_key size
* invokable unit test
* Finish up all of static_string including tests
* Don't rely on default constructible mutable buffers
type in read_frame_op (smb_type). To see the error, use
boost::asio::streambuf in websocket_async_echo_peer
* Don't try to read requests into empty_body
* Give callers control over the http request/response used during handshake
* Investigate poor autobahn results in Debug builds
HTTP:
* Define Parser concept in HTTP
- Need parse version of read() so caller can set parser options
like maximum size of headers, maximum body size, etc
* trim public interface of rfc2616.h to essentials only
* add bool should_close(message_v1 const&) to replace the use
of eof return value from write and async_write
@@ -40,6 +44,17 @@ HTTP:
* More fine grained parser errors
* HTTP parser size limit with test (configurable?)
* HTTP parser trailers with test
* URL parser, strong URL checking in HTTP parser
* Decode chunk encoding parameters
* URL parser, strong URL character checking in HTTP parser
* Update for rfc7230
* Consider rename to MessageBody concept
* Fix prepare() calling content_length() without init()
* Use construct,destroy allocator routines in basic_headers
* Complete allocator testing in basic_streambuf, basic_headers
* Add tests for writer using the resume function / coros
* Custom HTTP error codes for various situations
* Make empty_body write-only, remove reader nested type
* Add concepts WritableBody ReadableBody with type checks,
check them in read and write functions
* Branch prediction hints in parser
* Check basic_parser_v1 against rfc7230 for leading message whitespace

View File

@@ -104,6 +104,7 @@ WARN_LOGFILE =
#---------------------------------------------------------------------------
INPUT = \
../include/beast/ \
../include/beast/core \
../include/beast/http \
../include/beast/websocket \
../include/beast/doc_debug.hpp \

View File

@@ -40,11 +40,11 @@
[section:intro Introduction]
Beast is a cross-platform C++ library built on Boost, containing two modules
implementing widely used network protocols. Beast.HTTP offers a universal
model for describing, sending, and receiving HTTP messages while Beast.WebSocket
provides a complete implementation of the WebSocket protocol. Their design
achieves these goals:
Beast is a cross-platform C++ library built on Boost.Asio and Boost, containing
two modules implementing widely used network protocols. Beast.HTTP offers a
universal model for describing, sending, and receiving HTTP messages while
Beast.WebSocket provides a complete implementation of the WebSocket protocol.
Their design achieves these goals:
* [*Symmetry.] Interfaces are role-agnostic; the same interfaces can be
used to build clients, servers, or both.
@@ -60,7 +60,7 @@ strategies; important decisions such as buffer or thread management are
left to users of the library.
* [*Performance.] The implementation performs competitively, making it a
realistic choice for building a high performance network server.
realistic choice for building high performance network servers.
* [*Scalability.] Development of network applications that scale to thousands
of concurrent connections is possible with the implementation.
@@ -112,19 +112,20 @@ int main()
boost::asio::connect(sock,
r.resolve(boost::asio::ip::tcp::resolver::query{host, "http"}));
using namespace beast::http;
// Send HTTP request using beast
request<empty_body> req({"GET", "/", 11});
beast::http::request_v1<beast::http::empty_body> req;
req.method = "GET";
req.url = "/";
req.version = 11;
req.headers.replace("Host", host + ":" + std::to_string(sock.remote_endpoint().port()));
req.headers.replace("User-Agent", "Beast");
prepare(req);
write(sock, req);
beast::http::prepare(req);
beast::http::write(sock, req);
// Receive and print HTTP response using beast
beast::streambuf sb;
response<streambuf_body> resp;
read(sock, sb, resp);
beast::http::response_v1<beast::http::streambuf_body> resp;
beast::http::read(sock, sb, resp);
std::cout << resp;
}
```
@@ -147,18 +148,16 @@ int main()
boost::asio::connect(sock,
r.resolve(boost::asio::ip::tcp::resolver::query{host, "80"}));
using namespace beast::websocket;
// WebSocket connect and send message using beast
stream<boost::asio::ip::tcp::socket&> ws(sock);
beast::websocket::stream<boost::asio::ip::tcp::socket&> ws(sock);
ws.handshake(host, "/");
ws.write(boost::asio::buffer("Hello, world!"));
// Receive WebSocket message, print and close using beast
beast::streambuf sb;
opcode op;
beast::websocket::opcode op;
ws.read(op, sb);
ws.close(close_code::normal);
ws.close(beast::websocket::close_code::normal);
std::cout << to_string(sb.data()) << "\n";
}
```
@@ -169,12 +168,16 @@ int main()
[section:credits Credits]
Boost.Asio is the inspiration behind which all of the interfaces and
implementation strategies are built. Some parts of the documentation are
written to closely resemble the wording and presentation of Boost.Asio
documentation. Credit goes to Christopher Kohloff for the wonderful
Asio library and the ideas upon which Beast is built.
Beast would not be possible without the considerable time and patience
contributed by David Schwartz, Edward Hennis, Howard Hinnant, Miguel Portilla,
Nikolaos Bougalis, Scott Determan, Scott Schurr, and Ripple Labs for
supporting its development. Thanks also to Christopher Kohloff, whose Asio
C++ library is the inspiration behind which much of the design and
documentation is based.
supporting its development.
[endsect]

View File

@@ -12,7 +12,7 @@ their associated operations including synchronous and asynchronous reading and
writing of messages in the HTTP/1 wire format using Boost.Asio.
The HTTP protocol is described fully in
[@https://tools.ietf.org/html/rfc2616 rfc2616]
[@https://tools.ietf.org/html/rfc7230 rfc7230]
@@ -44,7 +44,7 @@ libraries. It is not designed to be end-user facing. There is no convenient
class that implements the core of a web server, nor is there a convenient
class to quickly perform common operations such as fetching a file or
connecting and retrieving a document from a secure connection. These
use-cases are important. But this library does not try to do that. Instead,
use-cases are important, but this library does not try to do that. Instead,
it offers primitives that can be used to build those user-facing algorithms.
A HTTP message (referred to hereafter as "message") contains request or

View File

@@ -33,7 +33,6 @@
<member><link linkend="beast.ref.http__basic_parser_v1">basic_parser_v1</link></member>
<member><link linkend="beast.ref.http__basic_streambuf_body">basic_streambuf_body</link></member>
<member><link linkend="beast.ref.http__empty_body">empty_body</link></member>
<member><link linkend="beast.ref.http__error_code">error_code</link></member>
<member><link linkend="beast.ref.http__headers">headers</link></member>
<member><link linkend="beast.ref.http__message">message</link></member>
<member><link linkend="beast.ref.http__resume_context">resume_context</link></member>
@@ -119,6 +118,7 @@
<member><link linkend="beast.ref.basic_streambuf">basic_streambuf</link></member>
<member><link linkend="beast.ref.buffers_adapter">buffers_adapter</link></member>
<member><link linkend="beast.ref.consuming_buffers">consuming_buffers</link></member>
<member><link linkend="beast.ref.error_code">error_code</link></member>
<member><link linkend="beast.ref.handler_alloc">handler_alloc</link></member>
<member><link linkend="beast.ref.prepared_buffers">prepared_buffers</link></member>
<member><link linkend="beast.ref.static_streambuf">static_streambuf</link></member>
@@ -126,6 +126,7 @@
<member><link linkend="beast.ref.static_string">static_string</link></member>
<member><link linkend="beast.ref.streambuf">streambuf</link></member>
<member><link linkend="beast.ref.streambuf_readstream">streambuf_readstream</link></member>
<member><link linkend="beast.ref.system_error">system_error</link></member>
</simplelist>
</entry>
<entry valign="top">

View File

@@ -774,6 +774,9 @@
<xsl:value-of select="substring-after($file, 'include/')"/>
<xsl:text>] &#xd;&#xd;</xsl:text>
<xsl:choose>
<xsl:when test="contains($file, 'beast/core')">
<xsl:text>['Convenience header: ][^beast/core.hpp]</xsl:text>
</xsl:when>
<xsl:when test="contains($file, 'beast/http')">
<xsl:text>['Convenience header: ][^beast/http.hpp]</xsl:text>
</xsl:when>

View File

@@ -1,8 +1,9 @@
# Part of Beast
GroupSources(include/beast)
GroupSources(examples)
GroupSources(test)
GroupSources(extras/beast beast)
GroupSources(include/beast beast)
GroupSources(examples "/")
add_executable (http-crawl
${BEAST_INCLUDES}
@@ -22,7 +23,6 @@ add_executable (http-server
http_stream.hpp
http_stream.ipp
http_sync_server.hpp
../test/sig_wait.hpp
http_server.cpp
)

View File

@@ -1,21 +1,9 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
//
// 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_EXAMPLE_FILE_BODY_H_INCLUDED
#define BEAST_EXAMPLE_FILE_BODY_H_INCLUDED

View File

@@ -1,21 +1,9 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
//
// 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_EXAMPLE_HTTP_ASYNC_SERVER_H_INCLUDED
#define BEAST_EXAMPLE_HTTP_ASYNC_SERVER_H_INCLUDED
@@ -23,7 +11,7 @@
#include "file_body.hpp"
#include "http_stream.hpp"
#include <beast/placeholders.hpp>
#include <beast/core/placeholders.hpp>
#include <boost/asio.hpp>
#include <cstdio>
#include <iostream>
@@ -127,8 +115,10 @@ private:
path = root_ + path;
if(! boost::filesystem::exists(path))
{
response_v1<string_body> resp(
{404, "Not Found", req_.version});
response_v1<string_body> resp;
resp.status = 404;
resp.reason = "Not Found";
resp.version = req_.version;
resp.headers.replace("Server", "http_async_server");
resp.body = "The file '" + path + "' was not found";
prepare(resp);
@@ -137,8 +127,10 @@ private:
asio::placeholders::error));
return;
}
resp_type resp(
{200, "OK", req_.version});
resp_type resp;
resp.status = 200;
resp.reason = "OK";
resp.version = req_.version;
resp.headers.replace("Server", "http_async_server");
resp.headers.replace("Content-Type", "text/html");
resp.body = path;

View File

@@ -1,21 +1,9 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
//
// 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)
//
#include "http_stream.hpp"
#include "urls_large_data.hpp"
@@ -28,7 +16,7 @@ using namespace boost::asio;
template<class String>
void
err(error_code const& ec, String const& what)
err(beast::error_code const& ec, String const& what)
{
std::cerr << what << ": " << ec.message() << std::endl;
}
@@ -46,7 +34,10 @@ int main(int, char const*[])
stream<ip::tcp::socket> hs(ios);
connect(hs.lowest_layer(), it);
auto ep = hs.lowest_layer().remote_endpoint();
request_v1<empty_body> req({"GET", "/", 11});
request_v1<empty_body> req;
req.method = "GET";
req.url = "/";
req.version = 11;
req.headers.insert("Host", host +
std::string(":") + std::to_string(ep.port()));
req.headers.insert("User-Agent", "beast/http");

View File

@@ -20,18 +20,19 @@ int main()
boost::asio::connect(sock,
r.resolve(boost::asio::ip::tcp::resolver::query{host, "http"}));
using namespace beast::http;
// Send HTTP request using beast
request_v1<empty_body> req({"GET", "/", 11});
beast::http::request_v1<beast::http::empty_body> req;
req.method = "GET";
req.url = "/";
req.version = 11;
req.headers.replace("Host", host + ":" + std::to_string(sock.remote_endpoint().port()));
req.headers.replace("User-Agent", "Beast");
prepare(req);
write(sock, req);
beast::http::prepare(req);
beast::http::write(sock, req);
// Receive and print HTTP response using beast
beast::streambuf sb;
response_v1<streambuf_body> resp;
read(sock, sb, resp);
beast::http::response_v1<beast::http::streambuf_body> resp;
beast::http::read(sock, sb, resp);
std::cout << resp;
}

View File

@@ -1,26 +1,14 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
//
// 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)
//
#include "http_async_server.hpp"
#include "http_sync_server.hpp"
#include "../test/sig_wait.hpp"
#include <beast/test/sig_wait.hpp>
#include <boost/program_options.hpp>
#include <iostream>
@@ -72,5 +60,5 @@ int main(int ac, char const* av[])
http_sync_server server(ep, root);
else
http_async_server server(ep, threads, root);
sig_wait();
beast::test::sig_wait();
}

View File

@@ -1,28 +1,16 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
//
// 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_STREAM_H_INCLUDED
#define BEAST_HTTP_STREAM_H_INCLUDED
#include <beast/core/async_completion.hpp>
#include <beast/core/basic_streambuf.hpp>
#include <beast/http.hpp>
#include <beast/async_completion.hpp>
#include <beast/basic_streambuf.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/intrusive/list.hpp>
#include <memory>
@@ -234,7 +222,7 @@ public:
error_code ec;
cancel(ec);
if(ec)
throw boost::system::system_error{ec};
throw system_error{ec};
}
/** Cancel pending operations.
@@ -273,7 +261,7 @@ public:
error_code ec;
read(msg, ec);
if(ec)
throw boost::system::system_error{ec};
throw system_error{ec};
}
/** Read a HTTP message from the stream.
@@ -370,7 +358,7 @@ public:
error_code ec;
write(msg, ec);
if(ec)
throw boost::system::system_error{ec};
throw system_error{ec};
}
/** Write a HTTP message to the stream.

View File

@@ -1,30 +1,18 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
//
// 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_STREAM_IPP_INCLUDED
#define BEAST_HTTP_STREAM_IPP_INCLUDED
#include <beast/core/bind_handler.hpp>
#include <beast/core/handler_alloc.hpp>
#include <beast/http/message_v1.hpp>
#include <beast/http/read.hpp>
#include <beast/http/write.hpp>
#include <beast/bind_handler.hpp>
#include <beast/handler_alloc.hpp>
#include <cassert>
namespace beast {

View File

@@ -1,21 +1,9 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
//
// 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_EXAMPLE_HTTP_SYNC_SERVER_H_INCLUDED
#define BEAST_EXAMPLE_HTTP_SYNC_SERVER_H_INCLUDED
@@ -155,8 +143,10 @@ public:
path = root_ + path;
if(! boost::filesystem::exists(path))
{
response_v1<string_body> resp(
{404, "Not Found", req.version});
response_v1<string_body> resp;
resp.status = 404;
resp.reason = "Not Found";
resp.version = req.version;
resp.headers.replace("Server", "http_sync_server");
resp.body = "The file '" + path + "' was not found";
prepare(resp);
@@ -164,8 +154,10 @@ public:
if(ec)
break;
}
resp_type resp(
{200, "OK", req.version});
resp_type resp;
resp.status = 200;
resp.reason = "OK";
resp.version = req.version;
resp.headers.replace("Server", "http_sync_server");
resp.headers.replace("Content-Type", "text/html");
resp.body = path;

View File

@@ -1,21 +1,9 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
//
// 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)
//
#include "urls_large_data.hpp"

View File

@@ -1,21 +1,9 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
//
// 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 URLS_LARGE_DATA_H_INCLUDED
#define URLS_LARGE_DATA_H_INCLUDED

View File

@@ -5,7 +5,7 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include <beast/to_string.hpp>
#include <beast/core/to_string.hpp>
#include <beast/websocket.hpp>
#include <boost/asio.hpp>
#include <iostream>
@@ -21,17 +21,15 @@ int main()
boost::asio::connect(sock,
r.resolve(boost::asio::ip::tcp::resolver::query{host, "80"}));
using namespace beast::websocket;
// WebSocket connect and send message using beast
stream<boost::asio::ip::tcp::socket&> ws(sock);
beast::websocket::stream<boost::asio::ip::tcp::socket&> ws(sock);
ws.handshake(host, "/");
ws.write(boost::asio::buffer("Hello, world!"));
// Receive WebSocket message, print and close using beast
beast::streambuf sb;
opcode op;
beast::websocket::opcode op;
ws.read(op, sb);
ws.close(close_code::normal);
ws.close(beast::websocket::close_code::normal);
std::cout << to_string(sb.data()) << "\n";
}

View File

@@ -0,0 +1,3 @@
# Extras
These are not part of the official public Beast interface but they are used by the tests and some third party programs.

View File

@@ -0,0 +1,69 @@
//
// 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_TEST_FAIL_COUNTER_HPP
#define BEAST_TEST_FAIL_COUNTER_HPP
#include <beast/core/error.hpp>
namespace beast {
namespace test {
/** A countdown to simulated failure.
On the Nth operation, the class will fail with the specified
error code, or the default error code of invalid_argument.
*/
class fail_counter
{
std::size_t n_;
error_code ec_;
public:
fail_counter(fail_counter&&) = default;
/** Construct a counter.
@param The 0-based index of the operation to fail on or after.
*/
explicit
fail_counter(std::size_t n = 0)
: n_(n)
, ec_(boost::system::errc::make_error_code(
boost::system::errc::errc_t::invalid_argument))
{
}
/// Throw an exception on the Nth failure
void
fail()
{
if(n_ > 0)
--n_;
if(! n_)
throw system_error{ec_};
}
/// Set an error code on the Nth failure
bool
fail(error_code& ec)
{
if(n_ > 0)
--n_;
if(! n_)
{
ec = ec_;
return true;
}
return false;
}
};
} // test
} // beast
#endif

View File

@@ -0,0 +1,182 @@
//
// 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_TEST_FAIL_STREAM_HPP
#define BEAST_TEST_FAIL_STREAM_HPP
#include <beast/core/async_completion.hpp>
#include <beast/core/bind_handler.hpp>
#include <beast/core/error.hpp>
#include <beast/core/detail/get_lowest_layer.hpp>
#include <beast/websocket/teardown.hpp>
#include <beast/test/fail_counter.hpp>
namespace beast {
namespace test {
/** A stream wrapper that fails.
On the Nth operation, the stream will fail with the specified
error code, or the default error code of invalid_argument.
*/
template<class NextLayer>
class fail_stream
{
fail_counter* pfc_;
fail_counter fc_;
NextLayer next_layer_;
public:
using next_layer_type =
typename std::remove_reference<NextLayer>::type;
using lowest_layer_type =
typename beast::detail::get_lowest_layer<
next_layer_type>::type;
fail_stream(fail_stream&&) = delete;
fail_stream(fail_stream const&) = delete;
fail_stream& operator=(fail_stream&&) = delete;
fail_stream& operator=(fail_stream const&) = delete;
template<class... Args>
explicit
fail_stream(std::size_t n, Args&&... args)
: pfc_(&fc_)
, fc_(n)
, next_layer_(std::forward<Args>(args)...)
{
}
template<class... Args>
explicit
fail_stream(fail_counter& fc, Args&&... args)
: pfc_(&fc)
, next_layer_(std::forward<Args>(args)...)
{
}
next_layer_type&
next_layer()
{
return next_layer_;
}
lowest_layer_type&
lowest_layer()
{
return next_layer_.lowest_layer();
}
lowest_layer_type const&
lowest_layer() const
{
return next_layer_.lowest_layer();
}
boost::asio::io_service&
get_io_service()
{
return next_layer_.get_io_service();
}
template<class MutableBufferSequence>
std::size_t
read_some(MutableBufferSequence const& buffers)
{
pfc_->fail();
return next_layer_.read_some(buffers);
}
template<class MutableBufferSequence>
std::size_t
read_some(MutableBufferSequence const& buffers, error_code& ec)
{
if(pfc_->fail(ec))
return 0;
return next_layer_.read_some(buffers, ec);
}
template<class MutableBufferSequence, class ReadHandler>
typename async_completion<
ReadHandler, void(error_code)>::result_type
async_read_some(MutableBufferSequence const& buffers,
ReadHandler&& handler)
{
error_code ec;
if(pfc_->fail(ec))
{
async_completion<
ReadHandler, void(error_code, std::size_t)
> completion(handler);
next_layer_.get_io_service().post(
bind_handler(completion.handler, ec, 0));
return completion.result.get();
}
return next_layer_.async_read_some(buffers,
std::forward<ReadHandler>(handler));
}
template<class ConstBufferSequence>
std::size_t
write_some(ConstBufferSequence const& buffers)
{
pfc_->fail();
return next_layer_.write_some(buffers);
}
template<class ConstBufferSequence>
std::size_t
write_some(ConstBufferSequence const& buffers, error_code& ec)
{
if(pfc_->fail(ec))
return 0;
return next_layer_.write_some(buffers, ec);
}
template<class ConstBufferSequence, class WriteHandler>
typename async_completion<
WriteHandler, void(error_code)>::result_type
async_write_some(ConstBufferSequence const& buffers,
WriteHandler&& handler)
{
error_code ec;
if(pfc_->fail(ec))
{
async_completion<
WriteHandler, void(error_code, std::size_t)
> completion(handler);
next_layer_.get_io_service().post(
bind_handler(completion.handler, ec, 0));
return completion.result.get();
}
return next_layer_.async_write_some(buffers,
std::forward<WriteHandler>(handler));
}
};
template<class NextLayer>
void
teardown(fail_stream<NextLayer>& stream,
boost::system::error_code& ec)
{
websocket_helpers::call_teardown(stream.next_layer(), ec);
}
template<class NextLayer, class TeardownHandler>
void
async_teardown(fail_stream<NextLayer>& stream,
TeardownHandler&& handler)
{
websocket_helpers::call_async_teardown(
stream.next_layer(), std::forward<TeardownHandler>(handler));
}
} // test
} // beast
#endif

View File

@@ -0,0 +1,36 @@
//
// 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_TEST_SIG_WAIT_HPP
#define BEAST_TEST_SIG_WAIT_HPP
#include <boost/asio.hpp>
#include <condition_variable>
#include <mutex>
namespace beast {
namespace test {
/// Block until SIGINT or SIGTERM is received.
inline
void
sig_wait()
{
boost::asio::io_service ios;
boost::asio::signal_set signals(
ios, SIGINT, SIGTERM);
signals.async_wait(
[&](boost::system::error_code const&, int)
{
});
ios.run();
}
} // test
} // beast
#endif

View File

@@ -0,0 +1,126 @@
//
// 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_TEST_STRING_STREAM_HPP
#define BEAST_TEST_STRING_STREAM_HPP
#include <beast/core/bind_handler.hpp>
#include <beast/core/error.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio/io_service.hpp>
#include <string>
namespace beast {
namespace test {
/** A SyncStream and AsyncStream that reads from a string.
This class behaves like a socket, except that written data is simply
discarded, and when data is read it comes from a string provided
at construction.
*/
class string_stream
{
std::string s_;
boost::asio::io_service& ios_;
public:
string_stream(boost::asio::io_service& ios,
std::string s)
: s_(std::move(s))
, ios_(ios)
{
}
boost::asio::io_service&
get_io_service()
{
return ios_;
}
template<class MutableBufferSequence>
std::size_t
read_some(MutableBufferSequence const& buffers)
{
error_code ec;
auto const n = read_some(buffers, ec);
if(ec)
throw system_error{ec};
return n;
}
template<class MutableBufferSequence>
std::size_t
read_some(MutableBufferSequence const& buffers,
error_code& ec)
{
auto const n = boost::asio::buffer_copy(
buffers, boost::asio::buffer(s_));
if(n > 0)
s_.erase(0, n);
else
ec = boost::asio::error::eof;
return n;
}
template<class MutableBufferSequence, class ReadHandler>
typename async_completion<ReadHandler,
void(error_code, std::size_t)>::result_type
async_read_some(MutableBufferSequence const& buffers,
ReadHandler&& handler)
{
auto const n = boost::asio::buffer_copy(
buffers, boost::asio::buffer(s_));
error_code ec;
if(n > 0)
s_.erase(0, n);
else
ec = boost::asio::error::eof;
async_completion<ReadHandler,
void(error_code, std::size_t)> completion(handler);
ios_.post(bind_handler(
completion.handler, ec, n));
return completion.result.get();
}
template<class ConstBufferSequence>
std::size_t
write_some(ConstBufferSequence const& buffers)
{
error_code ec;
auto const n = write_some(buffers, ec);
if(ec)
throw system_error{ec};
return n;
}
template<class ConstBufferSequence>
std::size_t
write_some(ConstBufferSequence const& buffers,
error_code&)
{
return boost::asio::buffer_size(buffers);
}
template<class ConstBuffeSequence, class WriteHandler>
typename async_completion<WriteHandler,
void(error_code, std::size_t)>::result_type
async_write_some(ConstBuffeSequence const& buffers,
WriteHandler&& handler)
{
async_completion<WriteHandler,
void(error_code, std::size_t)> completion(handler);
ios_.post(bind_handler(completion.handler,
error_code{}, boost::asio::buffer_size(buffers)));
return completion.result.get();
}
};
} // test
} // beast
#endif

View File

@@ -0,0 +1,108 @@
//
// 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_TEST_YIELD_TO_HPP
#define BEAST_TEST_YIELD_TO_HPP
#include <boost/asio/io_service.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/optional.hpp>
#include <condition_variable>
#include <functional>
#include <mutex>
#include <thread>
namespace beast {
namespace test {
/** Mix-in to support tests using asio coroutines.
Derive from this class and use yield_to to launch test functions
inside coroutines. This is handy for testing asynchronous asio
code.
*/
class enable_yield_to
{
protected:
boost::asio::io_service ios_;
private:
boost::optional<boost::asio::io_service::work> work_;
std::thread thread_;
std::mutex m_;
std::condition_variable cv_;
bool running_ = false;
public:
/// The type of yield context passed to functions.
using yield_context =
boost::asio::yield_context;
enable_yield_to()
: work_(ios_)
, thread_([&]
{
ios_.run();
}
)
{
}
~enable_yield_to()
{
work_ = boost::none;
thread_.join();
}
/// Return the `io_service` associated with the object
boost::asio::io_service&
get_io_service()
{
return ios_;
}
/** Run a function in a coroutine.
This call will block until the coroutine terminates.
Function will be called with this signature:
@code
void f(yield_context);
@endcode
*/
template<class Function>
void
yield_to(Function&& f);
};
template<class Function>
void
enable_yield_to::yield_to(Function&& f)
{
{
std::lock_guard<std::mutex> lock(m_);
running_ = true;
}
boost::asio::spawn(ios_,
[&](boost::asio::yield_context do_yield)
{
f(do_yield);
std::lock_guard<std::mutex> lock(m_);
running_ = false;
cv_.notify_all();
}
, boost::coroutines::attributes(2 * 1024 * 1024));
std::unique_lock<std::mutex> lock(m_);
cv_.wait(lock, [&]{ return ! running_; });
}
} // test
} // beast
#endif

View File

@@ -5,18 +5,16 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BEAST_DETAIL_STREAM_ABSTRACT_OSTREAM_HPP
#define BEAST_DETAIL_STREAM_ABSTRACT_OSTREAM_HPP
#ifndef BEAST_UNIT_TEST_ABSTRACT_OSTREAM_HPP
#define BEAST_UNIT_TEST_ABSTRACT_OSTREAM_HPP
#include <beast/detail/stream/basic_abstract_ostream.hpp>
#include <beast/unit_test/basic_abstract_ostream.hpp>
namespace beast {
namespace detail {
/** An abstract ostream for `char`. */
using abstract_ostream = basic_abstract_ostream <char>;
} // detail
} // beast
#endif

View File

@@ -5,17 +5,14 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BEAST_DETAIL_UNIT_TEST_AMOUNT_HPP
#define BEAST_DETAIL_UNIT_TEST_AMOUNT_HPP
#ifndef BEAST_UNIT_TEST_AMOUNT_HPP
#define BEAST_UNIT_TEST_AMOUNT_HPP
#include <cstddef>
#include <ostream>
#include <string>
namespace beast {
namespace detail {
inline
namespace unit_test {
/** Utility for producing nicely composed output of amounts with units. */
@@ -53,7 +50,6 @@ operator<< (std::ostream& s, amount const& t)
}
} // unit_test
} // detail
} // beast
#endif

View File

@@ -5,16 +5,15 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BEAST_DETAIL_STREAM_BASIC_ABSTRACT_OSTREAM_HPP
#define BEAST_DETAIL_STREAM_BASIC_ABSTRACT_OSTREAM_HPP
#ifndef BEAST_UNIT_TEST_BASIC_ABSTRACT_OSTREAM_HPP
#define BEAST_UNIT_TEST_BASIC_ABSTRACT_OSTREAM_HPP
#include <beast/detail/stream/basic_scoped_ostream.hpp>
#include <beast/unit_test/basic_scoped_ostream.hpp>
#include <functional>
#include <memory>
#include <sstream>
namespace beast {
namespace detail {
/** Abstraction for an output stream similar to std::basic_ostream. */
template <
@@ -81,7 +80,6 @@ public:
}
};
} // detail
} // beast
#endif

View File

@@ -5,8 +5,8 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BEAST_DETAIL_STREAM_BASIC_SCOPED_OSTREAM_HPP
#define BEAST_DETAIL_STREAM_BASIC_SCOPED_OSTREAM_HPP
#ifndef BEAST_UNIT_TEST_BASIC_SCOPED_OSTREAM_HPP
#define BEAST_UNIT_TEST_BASIC_SCOPED_OSTREAM_HPP
#include <functional>
#include <memory>
@@ -24,7 +24,6 @@
#endif
namespace beast {
namespace detail {
template <
class CharT,
@@ -132,7 +131,6 @@ public:
}
};
} // detail
} // beast
#endif

View File

@@ -5,14 +5,13 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BEAST_DETAIL_STREAM_BASIC_STD_OSTREAM_H_INCLUDED
#define BEAST_DETAIL_STREAM_BASIC_STD_OSTREAM_H_INCLUDED
#ifndef BEAST_UNIT_TEST_BASIC_STD_OSTREAM_HPP
#define BEAST_UNIT_TEST_BASIC_STD_OSTREAM_HPP
#include <beast/detail/stream/basic_abstract_ostream.hpp>
#include <beast/unit_test/basic_abstract_ostream.hpp>
#include <ostream>
namespace beast {
namespace detail {
/** Wraps an existing std::basic_ostream as an abstract_ostream. */
template <
@@ -56,7 +55,6 @@ make_std_ostream (std::basic_ostream <CharT, Traits>& stream)
return basic_std_ostream <CharT, Traits> (stream);
}
} // detail
} // beast
#endif

View File

@@ -5,10 +5,10 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BEAST_DETAIL_STREAM_DEBUG_OSTREAM_HPP
#define BEAST_DETAIL_STREAM_DEBUG_OSTREAM_HPP
#ifndef BEAST_UNIT_TEST_DEBUG_OSTREAM_HPP
#define BEAST_UNIT_TEST_DEBUG_OSTREAM_HPP
#include <beast/detail/stream/abstract_ostream.hpp>
#include <beast/unit_test/abstract_ostream.hpp>
#include <iostream>
#ifdef _MSC_VER
@@ -28,7 +28,6 @@
#endif
namespace beast {
namespace detail {
#ifdef _MSC_VER
/** A basic_abstract_ostream that redirects output to an attached debugger. */
@@ -74,7 +73,6 @@ public:
#endif
} // detail
} // beast
#endif

View File

@@ -5,10 +5,11 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BEAST_DETAIL_CONST_CONTAINER_HPP
#define BEAST_DETAIL_CONST_CONTAINER_HPP
#ifndef BEAST_UNIT_TEST_DETAIL_CONST_CONTAINER_HPP
#define BEAST_UNIT_TEST_DETAIL_CONST_CONTAINER_HPP
namespace beast {
namespace unit_test {
namespace detail {
/** Adapter to constrain a container interface.
@@ -84,6 +85,7 @@ public:
};
} // detail
} // unit_test
} // beast
#endif

View File

@@ -5,15 +5,12 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BEAST_DETAIL_UNIT_TEST_GLOBAL_SUITES_HPP
#define BEAST_DETAIL_UNIT_TEST_GLOBAL_SUITES_HPP
#ifndef BEAST_UNIT_TEST_GLOBAL_SUITES_HPP
#define BEAST_UNIT_TEST_GLOBAL_SUITES_HPP
#include <beast/detail/unit_test/suite_list.hpp>
#include <beast/unit_test/suite_list.hpp>
namespace beast {
namespace detail {
inline
namespace unit_test {
namespace detail {
@@ -54,7 +51,6 @@ global_suites()
}
} // unit_test
} // detail
} // beast
#endif

View File

@@ -1,28 +1,16 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
//
// 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)
//
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.
*/
//==============================================================================
#include <beast/detail/unit_test/amount.hpp>
#include <beast/detail/unit_test/global_suites.hpp>
#include <beast/detail/unit_test/match.hpp>
#include <beast/detail/unit_test/reporter.hpp>
#include <beast/detail/unit_test/suite.hpp>
#include <beast/detail/stream/debug_ostream.hpp>
#include <beast/unit_test/amount.hpp>
#include <beast/unit_test/global_suites.hpp>
#include <beast/unit_test/match.hpp>
#include <beast/unit_test/reporter.hpp>
#include <beast/unit_test/suite.hpp>
#include <beast/unit_test/debug_ostream.hpp>
#include <boost/program_options.hpp>
#include <iostream>
#include <vector>
@@ -40,7 +28,6 @@
#include <cstdlib>
namespace beast {
namespace detail {
namespace unit_test {
std::string
@@ -80,7 +67,6 @@ print(Log& log)
}
} // unit_test
} // detail
} // beast
// Simple main used to produce stand
@@ -88,7 +74,7 @@ print(Log& log)
int main(int ac, char const* av[])
{
using namespace std;
using namespace beast::detail::unit_test;
using namespace beast::unit_test;
#ifdef _MSC_VER
{
@@ -111,7 +97,7 @@ int main(int ac, char const* av[])
po::store(po::parse_command_line(ac, av, desc), vm);
po::notify(vm);
beast::detail::debug_ostream log;
beast::debug_ostream log;
if(vm.count("help"))
{

View File

@@ -5,16 +5,13 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BEAST_DETAIL_UNIT_TEST_MATCH_HPP
#define BEAST_DETAIL_UNIT_TEST_MATCH_HPP
#ifndef BEAST_UNIT_TEST_MATCH_HPP
#define BEAST_UNIT_TEST_MATCH_HPP
#include <beast/detail/unit_test/suite_info.hpp>
#include <beast/unit_test/suite_info.hpp>
#include <string>
namespace beast {
namespace detail {
inline
namespace unit_test {
// Predicate for implementing matches
@@ -171,7 +168,6 @@ match_library (std::string const& name)
}
} // unit_test
} // detail
} // beast
#endif

View File

@@ -5,28 +5,25 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BEAST_DETAIL_UNIT_TEST_PRINT_H_INCLUDED
#define BEAST_DETAIL_UNIT_TEST_PRINT_H_INCLUDED
#ifndef BEAST_UNIT_TEST_PRINT_H_INCLUDED
#define BEAST_UNIT_TEST_PRINT_H_INCLUDED
#include <beast/detail/unit_test/amount.hpp>
#include <beast/detail/unit_test/results.hpp>
#include <beast/detail/stream/abstract_ostream.hpp>
#include <beast/detail/stream/basic_std_ostream.hpp>
#include <beast/unit_test/amount.hpp>
#include <beast/unit_test/results.hpp>
#include <beast/unit_test/abstract_ostream.hpp>
#include <beast/unit_test/basic_std_ostream.hpp>
#include <iostream>
#include <string>
namespace beast {
namespace detail {
inline
namespace unit_test {
/** Write test results to the specified output stream. */
/** @{ */
template <class = void>
void
print (results const& r, beast::detail::abstract_ostream& stream)
print (results const& r, abstract_ostream& stream)
{
for (auto const& s : r)
{
@@ -65,7 +62,6 @@ print (results const& r, std::ostream& stream = std::cout)
}
} // unit_test
} // detail
} // beast
#endif

View File

@@ -5,16 +5,13 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BEAST_DETAIL_UNIT_TEST_RECORDER_HPP
#define BEAST_DETAIL_UNIT_TEST_RECORDER_HPP
#ifndef BEAST_UNIT_TEST_RECORDER_HPP
#define BEAST_UNIT_TEST_RECORDER_HPP
#include <beast/detail/unit_test/results.hpp>
#include <beast/detail/unit_test/runner.hpp>
#include <beast/unit_test/results.hpp>
#include <beast/unit_test/runner.hpp>
namespace beast {
namespace detail {
inline
namespace unit_test {
/** A test runner that stores the results. */
@@ -90,7 +87,6 @@ private:
};
} // unit_test
} // detail
} // beast
#endif

View File

@@ -5,13 +5,13 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BEAST_DETAIL_UNIT_TEST_REPORTER_HPP
#define BEAST_DETAIL_UNIT_TEST_REPORTER_HPP
#ifndef BEAST_UNIT_TEST_REPORTER_HPP
#define BEAST_UNIT_TEST_REPORTER_HPP
#include <beast/detail/unit_test/amount.hpp>
#include <beast/detail/unit_test/recorder.hpp>
#include <beast/detail/stream/abstract_ostream.hpp>
#include <beast/detail/stream/basic_std_ostream.hpp>
#include <beast/unit_test/amount.hpp>
#include <beast/unit_test/recorder.hpp>
#include <beast/unit_test/abstract_ostream.hpp>
#include <beast/unit_test/basic_std_ostream.hpp>
#include <boost/optional.hpp>
#include <algorithm>
#include <chrono>
@@ -23,9 +23,6 @@
#include <utility>
namespace beast {
namespace detail {
inline
namespace unit_test {
namespace detail {
@@ -87,7 +84,7 @@ private:
};
boost::optional <std_ostream> std_ostream_;
std::reference_wrapper <beast::detail::abstract_ostream> stream_;
std::reference_wrapper <beast::abstract_ostream> stream_;
results results_;
suite_results suite_results_;
case_results case_results_;
@@ -102,7 +99,7 @@ public:
reporter (std::ostream& stream = std::cout);
explicit
reporter (beast::detail::abstract_ostream& stream);
reporter (beast::abstract_ostream& stream);
private:
static
@@ -229,7 +226,7 @@ reporter<_>::~reporter()
template <class _>
reporter<_>::reporter (
beast::detail::abstract_ostream& stream)
abstract_ostream& stream)
: stream_ (stream)
{
}
@@ -318,7 +315,6 @@ reporter<_>::on_log (
using reporter = detail::reporter<>;
} // unit_test
} // detail
} // beast
#endif

View File

@@ -5,18 +5,15 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BEAST_DETAIL_UNIT_TEST_RESULTS_HPP
#define BEAST_DETAIL_UNIT_TEST_RESULTS_HPP
#ifndef BEAST_UNIT_TEST_RESULTS_HPP
#define BEAST_UNIT_TEST_RESULTS_HPP
#include <beast/detail/const_container.hpp>
#include <beast/unit_test/detail/const_container.hpp>
#include <string>
#include <vector>
namespace beast {
namespace detail {
inline
namespace unit_test {
/** Holds a set of test condition outcomes in a testcase. */
@@ -43,7 +40,7 @@ public:
private:
class tests_t
: public const_container <std::vector <test>>
: public detail::const_container <std::vector <test>>
{
private:
std::size_t failed_;
@@ -85,7 +82,7 @@ private:
};
class log_t
: public const_container <std::vector <std::string>>
: public detail::const_container <std::vector <std::string>>
{
public:
/** Insert a string into the log. */
@@ -122,7 +119,7 @@ public:
/** Holds the set of testcase results in a suite. */
class suite_results
: public const_container <std::vector <case_results>>
: public detail::const_container <std::vector <case_results>>
{
private:
std::string name_;
@@ -181,7 +178,7 @@ public:
// VFALCO TODO Make this a template class using scoped allocators
/** Holds the results of running a set of testsuites. */
class results
: public const_container <std::vector <suite_results>>
: public detail::const_container <std::vector <suite_results>>
{
private:
std::size_t m_cases;
@@ -240,7 +237,6 @@ public:
};
} // unit_test
} // detail
} // beast
#endif

View File

@@ -5,19 +5,16 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BEAST_DETAIL_UNIT_TEST_RUNNER_H_INCLUDED
#define BEAST_DETAIL_UNIT_TEST_RUNNER_H_INCLUDED
#ifndef BEAST_UNIT_TEST_RUNNER_H_INCLUDED
#define BEAST_UNIT_TEST_RUNNER_H_INCLUDED
#include <beast/detail/unit_test/suite_info.hpp>
#include <beast/detail/stream/abstract_ostream.hpp>
#include <beast/unit_test/suite_info.hpp>
#include <beast/unit_test/abstract_ostream.hpp>
#include <cassert>
#include <mutex>
#include <string>
namespace beast {
namespace detail {
inline
namespace unit_test {
/** Unit test runner interface.
@@ -28,7 +25,7 @@ class runner
{
private:
// Reroutes log output to the runner
class stream_t : public beast::detail::abstract_ostream
class stream_t : public abstract_ostream
{
private:
runner& owner_;
@@ -332,7 +329,6 @@ runner::log (std::string const& s)
}
} // unit_test
} // detail
} // beast
#endif

View File

@@ -5,17 +5,14 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BEAST_DETAIL_UNIT_TEST_SUITE_HPP
#define BEAST_DETAIL_UNIT_TEST_SUITE_HPP
#ifndef BEAST_UNIT_TEST_SUITE_HPP
#define BEAST_UNIT_TEST_SUITE_HPP
#include <beast/detail/unit_test/runner.hpp>
#include <beast/unit_test/runner.hpp>
#include <string>
#include <sstream>
namespace beast {
namespace detail {
inline
namespace unit_test {
class thread;
@@ -537,7 +534,6 @@ suite::run (runner& r)
}
} // unit_test
} // detail
} // beast
//------------------------------------------------------------------------------
@@ -545,9 +541,9 @@ suite::run (runner& r)
// detail:
// This inserts the suite with the given manual flag
#define BEAST_DEFINE_TESTSUITE_INSERT(Class,Module,Library,manual) \
static beast::detail::unit_test::detail::insert_suite <Class##_test> \
static beast::unit_test::detail::insert_suite <Class##_test> \
Library ## Module ## Class ## _test_instance ( \
#Class, #Module, #Library, manual);
#Class, #Module, #Library, manual)
//------------------------------------------------------------------------------
@@ -593,7 +589,7 @@ suite::run (runner& r)
#define BEAST_DEFINE_TESTSUITE(Class,Module,Library)
#else
#include <beast/detail/unit_test/global_suites.hpp>
#include <beast/unit_test/global_suites.hpp>
#define BEAST_DEFINE_TESTSUITE(Class,Module,Library) \
BEAST_DEFINE_TESTSUITE_INSERT(Class,Module,Library,false)
#define BEAST_DEFINE_TESTSUITE_MANUAL(Class,Module,Library) \

View File

@@ -5,17 +5,14 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BEAST_DETAIL_UNIT_TEST_SUITE_INFO_HPP
#define BEAST_DETAIL_UNIT_TEST_SUITE_INFO_HPP
#ifndef BEAST_UNIT_TEST_SUITE_INFO_HPP
#define BEAST_UNIT_TEST_SUITE_INFO_HPP
#include <functional>
#include <string>
#include <utility>
namespace beast {
namespace detail {
inline
namespace unit_test {
class runner;
@@ -113,7 +110,6 @@ make_suite_info (std::string const& name, std::string const& module,
}
} // unit_test
} // detail
} // beast
#endif

View File

@@ -5,25 +5,22 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BEAST_DETAIL_UNIT_TEST_SUITE_LIST_HPP
#define BEAST_DETAIL_UNIT_TEST_SUITE_LIST_HPP
#ifndef BEAST_UNIT_TEST_SUITE_LIST_HPP
#define BEAST_UNIT_TEST_SUITE_LIST_HPP
#include <beast/detail/unit_test/suite_info.hpp>
#include <beast/detail/const_container.hpp>
#include <beast/unit_test/suite_info.hpp>
#include <beast/unit_test/detail/const_container.hpp>
#include <cassert>
#include <typeindex>
#include <set>
#include <unordered_set>
namespace beast {
namespace detail {
inline
namespace unit_test {
/** A container of test suites. */
class suite_list
: public const_container <std::set <suite_info>>
: public detail::const_container <std::set <suite_info>>
{
private:
#ifndef NDEBUG
@@ -68,7 +65,6 @@ suite_list::insert (char const* name, char const* module, char const* library,
}
} // unit_test
} // detail
} // beast
#endif

View File

@@ -5,18 +5,15 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BEAST_DETAIL_UNIT_TEST_THREAD_HPP
#define BEAST_DETAIL_UNIT_TEST_THREAD_HPP
#ifndef BEAST_UNIT_TEST_THREAD_HPP
#define BEAST_UNIT_TEST_THREAD_HPP
#include <beast/detail/unit_test/suite.hpp>
#include <beast/unit_test/suite.hpp>
#include <functional>
#include <thread>
#include <utility>
namespace beast {
namespace detail {
inline
namespace unit_test {
/** Replacement for std::thread that handles exceptions in unit tests. */
@@ -122,7 +119,6 @@ private:
};
} // unit_test
} // detail
} // beast
#endif

View File

@@ -0,0 +1,31 @@
//
// 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_CORE_HPP
#define BEAST_CORE_HPP
#include <beast/core/async_completion.hpp>
#include <beast/core/basic_streambuf.hpp>
#include <beast/core/bind_handler.hpp>
#include <beast/core/buffer_cat.hpp>
#include <beast/core/buffer_concepts.hpp>
#include <beast/core/buffers_adapter.hpp>
#include <beast/core/consuming_buffers.hpp>
#include <beast/core/error.hpp>
#include <beast/core/handler_alloc.hpp>
#include <beast/core/handler_concepts.hpp>
#include <beast/core/placeholders.hpp>
#include <beast/core/prepare_buffers.hpp>
#include <beast/core/static_streambuf.hpp>
#include <beast/core/static_string.hpp>
#include <beast/core/stream_concepts.hpp>
#include <beast/core/streambuf.hpp>
#include <beast/core/streambuf_readstream.hpp>
#include <beast/core/to_string.hpp>
#include <beast/core/write_streambuf.hpp>
#endif

View File

@@ -8,7 +8,7 @@
#ifndef BEAST_ASYNC_COMPLETION_HPP
#define BEAST_ASYNC_COMPLETION_HPP
#include <beast/handler_concepts.hpp>
#include <beast/core/handler_concepts.hpp>
#include <boost/asio/async_result.hpp>
#include <boost/asio/handler_type.hpp>
#include <type_traits>

View File

@@ -8,7 +8,7 @@
#ifndef BEAST_BASIC_STREAMBUF_HPP
#define BEAST_BASIC_STREAMBUF_HPP
#include <beast/detail/empty_base_optimization.hpp>
#include <beast/core/detail/empty_base_optimization.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/intrusive/list.hpp>
#include <iterator>
@@ -298,6 +298,6 @@ operator<<(basic_streambuf<Allocator>& streambuf, T const& t);
} // beast
#include <beast/impl/basic_streambuf.ipp>
#include <beast/core/impl/basic_streambuf.ipp>
#endif

View File

@@ -8,8 +8,8 @@
#ifndef BEAST_BIND_HANDLER_HPP
#define BEAST_BIND_HANDLER_HPP
#include <beast/handler_concepts.hpp>
#include <beast/detail/bind_handler.hpp>
#include <beast/core/handler_concepts.hpp>
#include <beast/core/detail/bind_handler.hpp>
#include <type_traits>
#include <utility>

View File

@@ -8,7 +8,7 @@
#ifndef BEAST_BUFFER_CAT_HPP
#define BEAST_BUFFER_CAT_HPP
#include <beast/detail/buffer_cat.hpp>
#include <beast/core/detail/buffer_cat.hpp>
#include <boost/asio/buffer.hpp>
#include <cstdint>
#include <iterator>

View File

@@ -8,7 +8,7 @@
#ifndef BEAST_BUFFER_CONCEPTS_HPP
#define BEAST_BUFFER_CONCEPTS_HPP
#include <beast/detail/buffer_concepts.hpp>
#include <beast/core/detail/buffer_concepts.hpp>
#include <boost/asio/buffer.hpp>
#include <type_traits>

View File

@@ -8,7 +8,7 @@
#ifndef BEAST_BUFFERS_ADAPTER_HPP
#define BEAST_BUFFERS_ADAPTER_HPP
#include <beast/buffer_concepts.hpp>
#include <beast/core/buffer_concepts.hpp>
#include <boost/asio/buffer.hpp>
#include <type_traits>
@@ -31,7 +31,6 @@ namespace beast {
template<class MutableBufferSequence>
class buffers_adapter
{
private:
static_assert(is_MutableBufferSequence<MutableBufferSequence>::value,
"MutableBufferSequence requirements not met");
@@ -146,6 +145,6 @@ public:
} // beast
#include <beast/impl/buffers_adapter.ipp>
#include <beast/core/impl/buffers_adapter.ipp>
#endif

View File

@@ -8,7 +8,7 @@
#ifndef BEAST_CONSUMING_BUFFERS_HPP
#define BEAST_CONSUMING_BUFFERS_HPP
#include <beast/buffer_concepts.hpp>
#include <beast/core/buffer_concepts.hpp>
#include <boost/asio/buffer.hpp>
#include <cstdint>
#include <iterator>
@@ -135,6 +135,6 @@ consumed_buffers(BufferSequence const& buffers, std::size_t n);
} // beast
#include <beast/impl/consuming_buffers.ipp>
#include <beast/core/impl/consuming_buffers.ipp>
#endif

View File

@@ -8,7 +8,7 @@
#ifndef BEAST_BIND_DETAIL_HANDLER_HPP
#define BEAST_BIND_DETAIL_HANDLER_HPP
#include <beast/detail/integer_sequence.hpp>
#include <beast/core/detail/integer_sequence.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_cont_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>

View File

@@ -197,7 +197,6 @@ private:
void
move(C<sizeof...(Bs)>, const_iterator&&)
{
return;
}
template<std::size_t I>
@@ -216,7 +215,6 @@ private:
void
copy(C<sizeof...(Bs)>, const_iterator const&)
{
return;
}
template<std::size_t I>

View File

@@ -218,13 +218,13 @@ transform(
struct sha1_context
{
static unsigned int const block_size = sha1::BLOCK_BYTES;
static unsigned int const digest_size = 20;
static unsigned int constexpr block_size = sha1::BLOCK_BYTES;
static unsigned int constexpr digest_size = 20;
std::uint32_t digest[5];
std::uint8_t buf[block_size];
std::size_t buflen;
std::size_t blocks;
std::uint32_t digest[5];
std::uint8_t buf[block_size];
};
template<class = void>
@@ -232,12 +232,12 @@ void
init(sha1_context& ctx) noexcept
{
ctx.buflen = 0;
ctx.blocks = 0;
ctx.digest[0] = 0x67452301;
ctx.digest[1] = 0xefcdab89;
ctx.digest[2] = 0x98badcfe;
ctx.digest[3] = 0x10325476;
ctx.digest[4] = 0xc3d2e1f0;
ctx.blocks = 0;
}
template<class = void>
@@ -275,15 +275,14 @@ finish(sha1_context& ctx, void* digest) noexcept
std::uint64_t total_bits =
(ctx.blocks*64 + ctx.buflen) * 8;
// pad
auto const buflen = ctx.buflen;
ctx.buf[ctx.buflen++] = 0x80;
auto const buflen = ctx.buflen;
while(ctx.buflen < 64)
ctx.buf[ctx.buflen++] = 0x00;
std::uint32_t block[BLOCK_INTS];
sha1::make_block(ctx.buf, block);
if (buflen > BLOCK_BYTES - 8)
{
++ctx.blocks;
sha1::transform(ctx.digest, block);
for (size_t i = 0; i < BLOCK_INTS - 2; i++)
block[i] = 0;

View File

@@ -8,7 +8,7 @@
#ifndef BEAST_DETAIL_STREAM_CONCEPTS_HPP
#define BEAST_DETAIL_STREAM_CONCEPTS_HPP
#include <beast/buffer_concepts.hpp>
#include <beast/core/buffer_concepts.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/system/error_code.hpp>
#include <type_traits>

View File

@@ -8,7 +8,7 @@
#ifndef BEAST_DETAIL_WRITE_STREAMBUF_HPP
#define BEAST_DETAIL_WRITE_STREAMBUF_HPP
#include <beast/buffer_concepts.hpp>
#include <beast/core/buffer_concepts.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/lexical_cast.hpp>
#include <utility>

View File

@@ -5,18 +5,20 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BEAST_HTTP_ERROR_HPP
#define BEAST_HTTP_ERROR_HPP
#ifndef BEAST_ERROR_HPP
#define BEAST_ERROR_HPP
#include <boost/system/error_code.hpp>
#include <boost/system/system_error.hpp>
namespace beast {
namespace http {
/// The type of error code used by the library
using error_code = boost::system::error_code;
} // http
/// The type of system error thrown by the library
using system_error = boost::system::system_error;
} // beast
#endif

View File

@@ -8,7 +8,7 @@
#ifndef BEAST_HANDLER_CONCEPTS_HPP
#define BEAST_HANDLER_CONCEPTS_HPP
#include <beast/detail/is_call_possible.hpp>
#include <beast/core/detail/is_call_possible.hpp>
#include <type_traits>
namespace beast {

View File

@@ -8,7 +8,7 @@
#ifndef BEAST_IMPL_BASIC_STREAMBUF_IPP
#define BEAST_IMPL_BASIC_STREAMBUF_IPP
#include <beast/detail/write_streambuf.hpp>
#include <beast/core/detail/write_streambuf.hpp>
#include <algorithm>
#include <cassert>
#include <exception>
@@ -582,7 +582,7 @@ basic_streambuf<Allocator>::prepare(size_type n) ->
list_.push_back(e);
if(out_ == list_.end())
out_ = list_.iterator_to(e);
if(n > e.size())
if(n >= e.size())
{
out_end_ = e.size();
n -= e.size();
@@ -855,8 +855,11 @@ std::size_t
read_size_helper(basic_streambuf<
Allocator> const& streambuf, std::size_t max_size)
{
return std::min<std::size_t>(max_size,
std::max<std::size_t>(512, streambuf.prepare_size()));
auto const avail = streambuf.prepare_size();
if(avail == 0)
return std::min(max_size,
std::max<std::size_t>(512, streambuf.alloc_size_));
return std::min(max_size, avail);
}
template<class Alloc, class T>

View File

@@ -469,49 +469,32 @@ template<class MutableBufferSequence>
void
buffers_adapter<MutableBufferSequence>::consume(std::size_t n)
{
for(;;)
using boost::asio::buffer_size;
while(begin_ != out_)
{
if(begin_ != out_)
auto const avail =
buffer_size(*begin_) - in_pos_;
if(n < avail)
{
auto const avail =
buffer_size(*begin_) - in_pos_;
if(n < avail)
{
in_size_ -= n;
in_pos_ += n;
break;
}
n -= avail;
in_size_ -= avail;
in_pos_ = 0;
++begin_;
}
else
{
auto const avail = out_pos_ - in_pos_;
if(n < avail)
{
in_size_ -= n;
in_pos_ += n;
}
else
{
in_size_ -= avail;
if(out_pos_ != out_end_||
out_ != std::prev(bs_.end()))
{
in_pos_ = out_pos_;
}
else
{
// Use the whole buffer now.
in_pos_ = 0;
out_pos_ = 0;
out_end_ = 0;
}
}
break;
in_size_ -= n;
in_pos_ += n;
return;
}
n -= avail;
in_size_ -= avail;
in_pos_ = 0;
++begin_;
}
auto const avail = out_pos_ - in_pos_;
if(n < avail)
{
in_size_ -= n;
in_pos_ += n;
}
else
{
in_size_ -= avail;
in_pos_ = out_pos_;
}
}

View File

@@ -8,7 +8,7 @@
#ifndef BEAST_IMPL_CONSUMING_BUFFERS_IPP
#define BEAST_IMPL_CONSUMING_BUFFERS_IPP
#include <beast/buffer_concepts.hpp>
#include <beast/core/buffer_concepts.hpp>
#include <boost/asio/buffer.hpp>
#include <algorithm>
#include <cstdint>

View File

@@ -8,9 +8,9 @@
#ifndef BEAST_IMPL_STREAMBUF_READSTREAM_IPP
#define BEAST_IMPL_STREAMBUF_READSTREAM_IPP
#include <beast/bind_handler.hpp>
#include <beast/handler_concepts.hpp>
#include <beast/handler_alloc.hpp>
#include <beast/core/bind_handler.hpp>
#include <beast/core/handler_concepts.hpp>
#include <beast/core/handler_alloc.hpp>
#include <boost/system/error_code.hpp>
#include <boost/system/system_error.hpp>
@@ -26,16 +26,16 @@ class streambuf_readstream<
struct data
{
streambuf_readstream& brs;
streambuf_readstream& srs;
MutableBufferSequence bs;
Handler h;
int state = 0;
template<class DeducedHandler>
data(DeducedHandler&& h_,
streambuf_readstream& brs_,
streambuf_readstream& srs_,
MutableBufferSequence const& bs_)
: brs(brs_)
: srs(srs_)
, bs(bs_)
, h(std::forward<DeducedHandler>(h_))
{
@@ -49,9 +49,10 @@ public:
read_some_op(read_some_op const&) = default;
template<class DeducedHandler, class... Args>
read_some_op(DeducedHandler&& h, Args&&... args)
read_some_op(DeducedHandler&& h,
streambuf_readstream& srs, Args&&... args)
: d_(std::allocate_shared<data>(alloc_type{h},
std::forward<DeducedHandler>(h),
std::forward<DeducedHandler>(h), srs,
std::forward<Args>(args)...))
{
(*this)(error_code{}, 0);
@@ -106,44 +107,44 @@ read_some_op<MutableBufferSequence, Handler>::operator()(
switch(d.state)
{
case 0:
if(d.brs.sb_.size() == 0)
if(d.srs.sb_.size() == 0)
{
d.state =
d.brs.size_ > 0 ? 2 : 1;
d.srs.capacity_ > 0 ? 2 : 1;
break;
}
d.state = 4;
d.brs.get_io_service().post(
d.srs.get_io_service().post(
bind_handler(std::move(*this), ec, 0));
return;
case 1:
// read (unbuffered)
d.state = 99;
d.brs.next_layer_.async_read_some(
d.srs.next_layer_.async_read_some(
d.bs, std::move(*this));
return;
case 2:
// read
d.state = 3;
d.brs.next_layer_.async_read_some(
d.brs.sb_.prepare(d.brs.size_),
d.srs.next_layer_.async_read_some(
d.srs.sb_.prepare(d.srs.capacity_),
std::move(*this));
return;
// got data
case 3:
d.state = 4;
d.brs.sb_.commit(bytes_transferred);
d.srs.sb_.commit(bytes_transferred);
break;
// copy
case 4:
bytes_transferred =
boost::asio::buffer_copy(
d.bs, d.brs.sb_.data());
d.brs.sb_.consume(bytes_transferred);
d.bs, d.srs.sb_.data());
d.srs.sb_.consume(bytes_transferred);
// call handler
d.state = 99;
break;
@@ -198,7 +199,7 @@ read_some(
error_code ec;
auto n = read_some(buffers, ec);
if(ec)
throw boost::system::system_error{ec};
throw system_error{ec};
return n;
}
@@ -216,14 +217,12 @@ read_some(MutableBufferSequence const& buffers,
"MutableBufferSequence requirements not met");
using boost::asio::buffer_size;
using boost::asio::buffer_copy;
if(buffer_size(buffers) == 0)
return 0;
if(size_ == 0)
return next_layer_.read_some(buffers, ec);
if(sb_.size() == 0)
{
if(capacity_ == 0)
return next_layer_.read_some(buffers, ec);
sb_.commit(next_layer_.read_some(
sb_.prepare(size_), ec));
sb_.prepare(capacity_), ec));
if(ec)
return 0;
}

View File

@@ -152,6 +152,6 @@ prepare_buffers(std::size_t n, BufferSequence const& buffers);
} // beast
#include <beast/impl/prepare_buffers.ipp>
#include <beast/core/impl/prepare_buffers.ipp>
#endif

View File

@@ -184,6 +184,6 @@ public:
} // beast
#include <beast/impl/static_streambuf.ipp>
#include <beast/core/impl/static_streambuf.ipp>
#endif

View File

@@ -1,21 +1,9 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
//
// 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_WEBSOCKET_STATIC_STRING_HPP
#define BEAST_WEBSOCKET_STATIC_STRING_HPP
@@ -279,13 +267,6 @@ public:
return N;
}
/// Reduces memory usage by freeing unused memory.
void
shrink_to_fit()
{
// no-op
}
/// Clears the contents.
void
clear()
@@ -310,7 +291,8 @@ public:
/// Compare two character sequences.
template<std::size_t M>
int compare(static_string<M, CharT, Traits> const& rhs) const;
int
compare(static_string<M, CharT, Traits> const& rhs) const;
/// Return the characters as a `basic_string`.
std::basic_string<CharT, Traits>
@@ -488,7 +470,8 @@ assign(CharT const* s)
namespace detail {
template<std::size_t N, std::size_t M, class CharT, class Traits>
int compare(
int
compare(
static_string<N, CharT, Traits> const& lhs,
const CharT (&s)[M])
{
@@ -512,27 +495,13 @@ int compare(
}
template<std::size_t N, std::size_t M, class CharT, class Traits>
int compare(
inline
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);
return -compare(rhs, s);
}
} // detail
@@ -540,7 +509,8 @@ int compare(
#if ! GENERATING_DOCS
template<std::size_t N, std::size_t M, class CharT, class Traits>
bool operator==(
bool
operator==(
static_string<N, CharT, Traits> const& lhs,
static_string<M, CharT, Traits> const& rhs)
{
@@ -548,7 +518,8 @@ bool operator==(
}
template<std::size_t N, std::size_t M, class CharT, class Traits>
bool operator!=(
bool
operator!=(
static_string<N, CharT, Traits> const& lhs,
static_string<M, CharT, Traits> const& rhs)
{
@@ -556,7 +527,8 @@ bool operator!=(
}
template<std::size_t N, std::size_t M, class CharT, class Traits>
bool operator<(
bool
operator<(
static_string<N, CharT, Traits> const& lhs,
static_string<M, CharT, Traits> const& rhs)
{
@@ -564,7 +536,8 @@ bool operator<(
}
template<std::size_t N, std::size_t M, class CharT, class Traits>
bool operator<=(
bool
operator<=(
static_string<N, CharT, Traits> const& lhs,
static_string<M, CharT, Traits> const& rhs)
{
@@ -572,7 +545,8 @@ bool operator<=(
}
template<std::size_t N, std::size_t M, class CharT, class Traits>
bool operator>(
bool
operator>(
static_string<N, CharT, Traits> const& lhs,
static_string<M, CharT, Traits> const& rhs)
{
@@ -580,7 +554,8 @@ bool operator>(
}
template<std::size_t N, std::size_t M, class CharT, class Traits>
bool operator>=(
bool
operator>=(
static_string<N, CharT, Traits> const& lhs,
static_string<M, CharT, Traits> const& rhs)
{
@@ -590,7 +565,8 @@ bool operator>=(
//---
template<std::size_t N, std::size_t M, class CharT, class Traits>
bool operator==(
bool
operator==(
const CharT (&s)[N],
static_string<M, CharT, Traits> const& rhs)
{
@@ -598,7 +574,8 @@ bool operator==(
}
template<std::size_t N, class CharT, class Traits, std::size_t M>
bool operator==(
bool
operator==(
static_string<N, CharT, Traits> const& lhs,
const CharT (&s)[M])
{
@@ -606,7 +583,8 @@ bool operator==(
}
template<std::size_t N, std::size_t M, class CharT, class Traits>
bool operator!=(
bool
operator!=(
const CharT (&s)[N],
static_string<M, CharT, Traits> const& rhs)
{
@@ -614,7 +592,8 @@ bool operator!=(
}
template<std::size_t N, class CharT, class Traits, std::size_t M>
bool operator!=(
bool
operator!=(
static_string<N, CharT, Traits> const& lhs,
const CharT (&s)[M])
{
@@ -622,7 +601,8 @@ bool operator!=(
}
template<std::size_t N, std::size_t M, class CharT, class Traits>
bool operator<(
bool
operator<(
const CharT (&s)[N],
static_string<M, CharT, Traits> const& rhs)
{
@@ -630,7 +610,8 @@ bool operator<(
}
template<std::size_t N, class CharT, class Traits, std::size_t M>
bool operator<(
bool
operator<(
static_string<N, CharT, Traits> const& lhs,
const CharT (&s)[M])
{
@@ -638,7 +619,8 @@ bool operator<(
}
template<std::size_t N, std::size_t M, class CharT, class Traits>
bool operator<=(
bool
operator<=(
const CharT (&s)[N],
static_string<M, CharT, Traits> const& rhs)
{
@@ -646,7 +628,8 @@ bool operator<=(
}
template<std::size_t N, class CharT, class Traits, std::size_t M>
bool operator<=(
bool
operator<=(
static_string<N, CharT, Traits> const& lhs,
const CharT (&s)[M])
{
@@ -654,7 +637,8 @@ bool operator<=(
}
template<std::size_t N, std::size_t M, class CharT, class Traits>
bool operator>(
bool
operator>(
const CharT (&s)[N],
static_string<M, CharT, Traits> const& rhs)
{
@@ -662,7 +646,8 @@ bool operator>(
}
template<std::size_t N, class CharT, class Traits, std::size_t M>
bool operator>(
bool
operator>(
static_string<N, CharT, Traits> const& lhs,
const CharT (&s)[M])
{
@@ -670,7 +655,8 @@ bool operator>(
}
template<std::size_t N, std::size_t M, class CharT, class Traits>
bool operator>=(
bool
operator>=(
const CharT (&s)[N],
static_string<M, CharT, Traits> const& rhs)
{
@@ -678,7 +664,8 @@ bool operator>=(
}
template<std::size_t N, class CharT, class Traits, std::size_t M>
bool operator>=(
bool
operator>=(
static_string<N, CharT, Traits> const& lhs,
const CharT (&s)[M])
{

View File

@@ -8,7 +8,7 @@
#ifndef BEAST_STREAM_CONCEPTS_HPP
#define BEAST_STREAM_CONCEPTS_HPP
#include <beast/detail/stream_concepts.hpp>
#include <beast/core/detail/stream_concepts.hpp>
#include <type_traits>
namespace beast {

View File

@@ -8,7 +8,7 @@
#ifndef BEAST_STREAMBUF_HPP
#define BEAST_STREAMBUF_HPP
#include <beast/basic_streambuf.hpp>
#include <beast/core/basic_streambuf.hpp>
namespace beast {

View File

@@ -8,11 +8,12 @@
#ifndef BEAST_STREAMBUF_READSTREAM_HPP
#define BEAST_STREAMBUF_READSTREAM_HPP
#include <beast/async_completion.hpp>
#include <beast/buffer_concepts.hpp>
#include <beast/stream_concepts.hpp>
#include <beast/streambuf.hpp>
#include <beast/detail/get_lowest_layer.hpp>
#include <beast/core/async_completion.hpp>
#include <beast/core/buffer_concepts.hpp>
#include <beast/core/error.hpp>
#include <beast/core/stream_concepts.hpp>
#include <beast/core/streambuf.hpp>
#include <beast/core/detail/get_lowest_layer.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/system/error_code.hpp>
@@ -98,7 +99,7 @@ class streambuf_readstream
class read_some_op;
Streambuf sb_;
std::size_t size_ = 0;
std::size_t capacity_ = 0;
Stream next_layer_;
public:
@@ -210,9 +211,9 @@ public:
than the amount of data in the buffer, no bytes are discarded.
*/
void
reserve(std::size_t size)
capacity(std::size_t size)
{
size_ = size;
capacity_ = size;
}
/// Write the given data to the stream. Returns the number of bytes written.
@@ -276,6 +277,6 @@ public:
} // beast
#include <beast/impl/streambuf_readstream.ipp>
#include <beast/core/impl/streambuf_readstream.ipp>
#endif

View File

@@ -8,7 +8,7 @@
#ifndef BEAST_TO_STRING_HPP
#define BEAST_TO_STRING_HPP
#include <beast/buffer_concepts.hpp>
#include <beast/core/buffer_concepts.hpp>
#include <boost/asio/buffer.hpp>
#include <string>

View File

@@ -8,8 +8,8 @@
#ifndef BEAST_WRITE_STREAMBUF_HPP
#define BEAST_WRITE_STREAMBUF_HPP
#include <beast/buffer_concepts.hpp>
#include <beast/detail/write_streambuf.hpp>
#include <beast/core/buffer_concepts.hpp>
#include <beast/core/detail/write_streambuf.hpp>
#include <type_traits>
#include <utility>

View File

@@ -1,90 +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)
//
#include <beast/detail/unit_test/amount.hpp>
#include <beast/detail/unit_test/global_suites.hpp>
#include <beast/detail/unit_test/suite.hpp>
#include <string>
// Include this .cpp in your project to gain access to the printing suite
namespace beast {
namespace detail {
inline
namespace unit_test {
namespace detail {
/** A suite that prints the list of globally defined suites. */
class print_test : public suite
{
private:
template <class = void>
void
do_run();
public:
template <class = void>
static
std::string
prefix (suite_info const& s);
template <class = void>
void
print (suite_list &c);
void
run()
{
do_run();
}
};
template <class>
void
print_test::do_run()
{
log << "------------------------------------------";
print (global_suites());
log << "------------------------------------------";
pass();
}
template <class>
std::string
print_test::prefix (suite_info const& s)
{
if (s.manual())
return "|M| ";
return " ";
}
template <class>
void
print_test::print (suite_list &c)
{
std::size_t manual (0);
for (auto const& s : c)
{
log <<
prefix (s) <<
s.full_name();
if (s.manual())
++manual;
}
log <<
amount (c.size(), "suite") << " total, " <<
amount (manual, "manual suite")
;
}
BEAST_DEFINE_TESTSUITE_MANUAL(print,unit_test,beast);
} // detail
} // unit_test
} // detail
} // beast

View File

@@ -12,7 +12,6 @@
#include <beast/http/basic_parser_v1.hpp>
#include <beast/http/body_type.hpp>
#include <beast/http/empty_body.hpp>
#include <beast/http/error.hpp>
#include <beast/http/headers.hpp>
#include <beast/http/message.hpp>
#include <beast/http/message_v1.hpp>

View File

@@ -8,8 +8,8 @@
#ifndef BEAST_HTTP_BASIC_HEADERS_HPP
#define BEAST_HTTP_BASIC_HEADERS_HPP
#include <beast/detail/ci_char_traits.hpp>
#include <beast/detail/empty_base_optimization.hpp>
#include <beast/core/detail/ci_char_traits.hpp>
#include <beast/core/detail/empty_base_optimization.hpp>
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/set.hpp>
#include <boost/lexical_cast.hpp>

View File

@@ -36,11 +36,26 @@ enum values
};
} // parse_flag
/** Base class for parsing HTTP/1 requests and responses.
/** A parser for decoding HTTP/1 wire format messages.
During parsing, callbacks will be made to the derived class
if those members are present (detected through SFINAE). The
signatures which can be present in the derived class are:<br>
This parser is designed to efficiently parse messages in the
HTTP/1 wire format. It allocates no memory and uses minimal
state. It will handle chunked encoding and it understands the
semantics of the Connection and Content-Length header fields.
The interface uses CRTP (Curiously Recurring Template Pattern).
To use this class, derive from basic_parser. When bytes are
presented, the implementation will make a series of zero or
more calls to derived class members functions (referred to as
"callbacks" from here on) matching a specific signature.
Callbacks are detected through SFINAE. The derived class may
implement as few or as many of the members as needed.
These are the signatures of the callbacks:<br>
@li `void on_start(error_code&)`
Called when the first valid octet of a new message is received
@li `void on_method(boost::string_ref const&, error_code&)`
@@ -106,6 +121,9 @@ enum values
If a callback sets an error, parsing stops at the current octet
and the error is returned to the caller.
@tparam isRequest A `bool` indicating whether the parser will be
presented with request or response message.
*/
template<bool isRequest, class Derived>
class basic_parser_v1
@@ -188,7 +206,8 @@ private:
s_chunk_data_done,
s_complete,
s_restart
s_restart,
s_closed_complete
};
enum field_state : std::uint8_t
@@ -341,7 +360,7 @@ public:
bool
complete() const
{
return s_ == s_restart;
return s_ == s_restart || s_ == s_closed_complete;
}
/** Write a sequence of buffers to the parser.
@@ -411,6 +430,24 @@ private:
bool
needs_eof(std::false_type) const;
template<class C>
class has_on_start_t
{
template<class T, class R =
decltype(std::declval<T>().on_start(
std::declval<error_code&>()),
std::true_type{})>
static R check(int);
template <class>
static std::false_type check(...);
using type = decltype(check<C>(0));
public:
static bool const value = type::value;
};
template<class C>
using has_on_start =
std::integral_constant<bool, has_on_start_t<C>::value>;
template<class C>
class has_on_method_t
{
@@ -596,6 +633,20 @@ private:
using has_on_complete =
std::integral_constant<bool, has_on_complete_t<C>::value>;
void call_on_start(error_code& ec, std::true_type)
{
impl().on_start(ec);
}
void call_on_start(error_code& ec, std::false_type)
{
}
void call_on_start(error_code& ec)
{
call_on_start(ec, has_on_start<Derived>{});
}
void call_on_method(error_code& ec,
boost::string_ref const& s, std::true_type)
{

View File

@@ -11,7 +11,7 @@
// Convenience header to include everything
// needed when declarating a user defined Body type.
#include <beast/http/error.hpp>
#include <beast/core/error.hpp>
#include <beast/http/message.hpp>
#include <beast/http/resume_context.hpp>
#include <boost/logic/tribool.hpp>

View File

@@ -132,7 +132,7 @@ to_value_char(char c)
}
inline
std::uint8_t
std::int8_t
unhex(char c)
{
static std::array<std::int8_t, 256> constexpr tab = {{
@@ -146,7 +146,7 @@ unhex(char c)
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 // 112
}};
return tab[static_cast<std::uint8_t>(c)];
};
}
template<class = void>
struct parser_str_t

View File

@@ -8,7 +8,9 @@
#ifndef BEAST_HTTP_DETAIL_CHUNK_ENCODE_HPP
#define BEAST_HTTP_DETAIL_CHUNK_ENCODE_HPP
#include <beast/core/buffer_cat.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/logic/tribool.hpp>
#include <algorithm>
#include <array>
#include <cassert>
@@ -20,244 +22,94 @@ namespace beast {
namespace http {
namespace detail {
template <class Buffers>
class chunk_encoded_buffers
class chunk_encode_text
{
private:
using const_buffer = boost::asio::const_buffer;
Buffers buffers_;
const_buffer head_;
const_buffer tail_;
boost::asio::const_buffer cb_;
// Storage for the longest hex string we might need, plus delimiters.
std::array<char, 2 * sizeof(std::size_t) + 2> data_;
std::array<char, 2 * sizeof(std::size_t) + 2> buf_;
template <class OutIter>
static
OutIter
to_hex(OutIter last, std::size_t n)
{
if(n == 0)
{
*--last = '0';
return last;
}
while(n)
{
*--last = "0123456789abcdef"[n&0xf];
n>>=4;
}
return last;
}
public:
using value_type = boost::asio::const_buffer;
class const_iterator;
using const_iterator = value_type const*;
chunk_encoded_buffers() = delete;
chunk_encoded_buffers (chunk_encoded_buffers const&) = default;
chunk_encoded_buffers& operator= (chunk_encoded_buffers const&) = default;
chunk_encode_text(chunk_encode_text const& other)
{
auto const n =
boost::asio::buffer_size(other.cb_);
buf_ = other.buf_;
cb_ = boost::asio::const_buffer(
&buf_[buf_.size() - n], n);
}
chunk_encoded_buffers (Buffers const& buffers, bool final_chunk);
explicit
chunk_encode_text(std::size_t n)
{
buf_[buf_.size() - 2] = '\r';
buf_[buf_.size() - 1] = '\n';
auto it = to_hex(buf_.end() - 2, n);
cb_ = boost::asio::const_buffer{&*it,
static_cast<std::size_t>(
std::distance(it, buf_.end()))};
}
const_iterator
begin() const
{
return const_iterator(*this, false);
return &cb_;
}
const_iterator
end() const
{
return const_iterator(*this, true);
return begin() + 1;
}
private:
// Unchecked conversion of unsigned to hex string
template<class OutIter, class Unsigned>
static
typename std::enable_if<
std::is_unsigned<Unsigned>::value, OutIter>::type
to_hex(OutIter const first, OutIter const last, Unsigned n);
};
template <class Buffers>
class chunk_encoded_buffers<Buffers>::const_iterator
: public std::iterator<std::bidirectional_iterator_tag, const_buffer>
{
private:
using iterator = typename Buffers::const_iterator;
enum class Where { head, input, end };
chunk_encoded_buffers const* buffers_;
Where where_;
iterator iter_;
/** Returns a chunk-encoded ConstBufferSequence.
public:
const_iterator();
const_iterator (const_iterator const&) = default;
const_iterator& operator= (const_iterator const&) = default;
bool operator== (const_iterator const& other) const;
bool operator!= (const_iterator const& other) const;
const_iterator& operator++();
const_iterator& operator--();
const_iterator operator++(int) const;
const_iterator operator--(int) const;
const_buffer operator*() const;
private:
friend class chunk_encoded_buffers;
const_iterator(chunk_encoded_buffers const& buffers, bool past_the_end);
};
//------------------------------------------------------------------------------
template <class Buffers>
chunk_encoded_buffers<Buffers>::chunk_encoded_buffers (
Buffers const& buffers, bool final_chunk)
: buffers_(buffers)
{
auto const size = boost::asio::buffer_size(buffers);
data_[data_.size() - 2] = '\r';
data_[data_.size() - 1] = '\n';
auto pos = to_hex(data_.begin(), data_.end() - 2, size);
head_ = const_buffer(&*pos,
std::distance(pos, data_.end()));
if (size > 0 && final_chunk)
tail_ = const_buffer("\r\n0\r\n\r\n", 7);
else
tail_ = const_buffer("\r\n", 2);
}
template <class Buffers>
template <class OutIter, class Unsigned>
typename std::enable_if<
std::is_unsigned<Unsigned>::value, OutIter>::type
chunk_encoded_buffers<Buffers>::to_hex(
OutIter const first, OutIter const last, Unsigned n)
{
assert(first != last);
OutIter iter = last;
if(n == 0)
{
*--iter = '0';
return iter;
}
while(n)
{
assert(iter != first);
*--iter = "0123456789abcdef"[n&0xf];
n>>=4;
}
return iter;
}
template <class Buffers>
chunk_encoded_buffers<Buffers>::const_iterator::const_iterator()
: buffers_(nullptr)
, where_(Where::end)
{
}
template <class Buffers>
bool
chunk_encoded_buffers<Buffers>::const_iterator::operator==(
const_iterator const& other) const
{
return buffers_ == other.buffers_ &&
where_ == other.where_ && iter_ == other.iter_;
}
template <class Buffers>
bool
chunk_encoded_buffers<Buffers>::const_iterator::operator!=(
const_iterator const& other) const
{
return buffers_ != other.buffers_ ||
where_ != other.where_ || iter_ != other.iter_;
}
template <class Buffers>
auto
chunk_encoded_buffers<Buffers>::const_iterator::operator++() ->
const_iterator&
{
assert(buffers_);
assert(where_ != Where::end);
if (where_ == Where::head)
where_ = Where::input;
else if (iter_ != buffers_->buffers_.end())
++iter_;
else
where_ = Where::end;
return *this;
}
template <class Buffers>
auto
chunk_encoded_buffers<Buffers>::const_iterator::operator--() ->
const_iterator&
{
assert(buffers_);
assert(where_ != Where::head);
if (where_ == Where::end)
where_ = Where::input;
else if (iter_ != buffers_->buffers_.begin())
--iter_;
else
where_ = Where::head;
return *this;
}
template <class Buffers>
auto
chunk_encoded_buffers<Buffers>::const_iterator::operator++(int) const ->
const_iterator
{
auto iter = *this;
++iter;
return iter;
}
template <class Buffers>
auto
chunk_encoded_buffers<Buffers>::const_iterator::operator--(int) const ->
const_iterator
{
auto iter = *this;
--iter;
return iter;
}
template <class Buffers>
auto
chunk_encoded_buffers<Buffers>::const_iterator::operator*() const ->
const_buffer
{
assert(buffers_);
assert(where_ != Where::end);
if (where_ == Where::head)
return buffers_->head_;
if (iter_ != buffers_->buffers_.end())
return *iter_;
return buffers_->tail_;
}
template <class Buffers>
chunk_encoded_buffers<Buffers>::const_iterator::const_iterator(
chunk_encoded_buffers const& buffers, bool past_the_end)
: buffers_(&buffers)
, where_(past_the_end ? Where::end : Where::head)
, iter_(past_the_end ? buffers_->buffers_.end() :
buffers_->buffers_.begin())
{
}
/* Returns a chunk-encoded BufferSequence.
See:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6.1
This returns a buffer sequence representing the
first chunk of a chunked transfer coded body.
@param buffers The input buffer sequence.
@param final_chunk `true` If this should include a final-chunk.
@return A chunk-encoded ConstBufferSequence representing the input.
@see <a href=https://tools.ietf.org/html/rfc7230#section-4.1.3>rfc7230 section 4.1.3</a>
*/
template<class ConstBufferSequence>
#if GENERATING_DOCS
implementation_defined
#else
detail::chunk_encoded_buffers<ConstBufferSequence>
beast::detail::buffer_cat_helper<boost::asio::const_buffer,
chunk_encode_text, ConstBufferSequence, boost::asio::const_buffers_1>
#endif
chunk_encode(ConstBufferSequence const& buffers,
bool final_chunk = false)
chunk_encode(ConstBufferSequence const& buffers)
{
return detail::chunk_encoded_buffers<
ConstBufferSequence>{buffers, final_chunk};
using boost::asio::buffer_size;
return buffer_cat(
chunk_encode_text{buffer_size(buffers)},
buffers,
boost::asio::const_buffers_1{"\r\n", 2});
}
/// Returns a chunked encoding final chunk.

View File

@@ -9,7 +9,7 @@
#define BEAST_HTTP_EMPTY_BODY_HPP
#include <beast/http/body_type.hpp>
#include <beast/streambuf.hpp>
#include <beast/core/streambuf.hpp>
#include <boost/asio/buffer.hpp>
#include <memory>
#include <string>

View File

@@ -136,8 +136,6 @@ basic_headers(basic_headers&& other)
, detail::basic_headers_base(
std::move(other.set_), std::move(other.list_))
{
other.list_.clear();
other.set_.clear();
}
template<class Allocator>

View File

@@ -8,7 +8,8 @@
#ifndef BEAST_HTTP_IMPL_BASIC_PARSER_V1_IPP
#define BEAST_HTTP_IMPL_BASIC_PARSER_V1_IPP
#include <beast/buffer_concepts.hpp>
#include <beast/core/buffer_concepts.hpp>
#include <cassert>
namespace beast {
namespace http {
@@ -88,6 +89,11 @@ write(boost::asio::const_buffer const& buffer, error_code& ec)
s_ = s_closed;
return used();
};
auto errc = [&]
{
s_ = s_closed;
return used();
};
auto piece = [&]
{
return boost::string_ref{
@@ -113,6 +119,7 @@ write(boost::asio::const_buffer const& buffer, error_code& ec)
switch(s_)
{
case s_closed:
case s_closed_complete:
return err(parse_error::connection_closed);
break;
@@ -126,6 +133,9 @@ write(boost::asio::const_buffer const& buffer, error_code& ec)
case s_req_method_start:
if(! is_token(ch))
return err(parse_error::bad_method);
call_on_start(ec);
if(ec)
return errc();
cb_ = &self::call_on_method;
s_ = s_req_method;
break;
@@ -134,7 +144,7 @@ write(boost::asio::const_buffer const& buffer, error_code& ec)
if(! is_token(ch))
{
if(cb(nullptr))
return used();
return errc();
s_ = s_req_space_before_url;
goto redo;
}
@@ -147,23 +157,29 @@ write(boost::asio::const_buffer const& buffer, error_code& ec)
break;
case s_req_url_start:
{
if(ch == ' ')
return err(parse_error::bad_uri);
// VFALCO TODO Require valid URL character
if(cb(&self::call_on_uri))
return used();
// VFALCO TODO Better checking for valid URL characters
if(! is_text(ch))
return err(parse_error::bad_uri);
assert(! cb_);
cb(&self::call_on_uri);
s_ = s_req_url;
break;
}
case s_req_url:
if(ch == ' ')
{
if(cb(nullptr))
return used();
return errc();
s_ = s_req_http_start;
break;
}
// VFALCO TODO Require valid URL character
// VFALCO TODO Better checking for valid URL characters
if(! is_text(ch))
return err(parse_error::bad_uri);
break;
case s_req_http_start:
@@ -241,7 +257,7 @@ write(boost::asio::const_buffer const& buffer, error_code& ec)
return err(parse_error::bad_crlf);
call_on_request(ec);
if(ec)
return used();
return errc();
s_ = s_header_field_start;
break;
@@ -253,7 +269,14 @@ write(boost::asio::const_buffer const& buffer, error_code& ec)
content_length_ = no_content_length;
switch(ch)
{
case 'H': s_ = s_res_H; break;
case 'H':
call_on_start(ec);
if(ec)
return errc();
s_ = s_res_H;
break;
// VFALCO NOTE this allows whitespace at the beginning,
// need to check rfc7230
case '\r':
case '\n':
break;
@@ -361,13 +384,16 @@ write(boost::asio::const_buffer const& buffer, error_code& ec)
s_ = s_res_line_almost_done;
break;
}
// VFALCO Is this up to spec?
if(ch == '\n')
{
s_ = s_header_field_start;
break;
}
if(! is_text(ch))
return err(parse_error::bad_status);
if(cb(&self::call_on_reason))
return used();
return errc();
pos_ = 0;
s_ = s_res_status;
break;
@@ -376,17 +402,19 @@ write(boost::asio::const_buffer const& buffer, error_code& ec)
if(ch == '\r')
{
if(cb(nullptr))
return used();
return errc();
s_ = s_res_line_almost_done;
break;
}
if(ch == '\n')
{
if(cb(nullptr))
return used();
return errc();
s_ = s_header_field_start;
break;
}
if(! is_text(ch))
return err(parse_error::bad_status);
break;
case s_res_line_almost_done:
@@ -398,7 +426,7 @@ write(boost::asio::const_buffer const& buffer, error_code& ec)
case s_res_line_done:
call_on_response(ec);
if(ec)
return used();
return errc();
s_ = s_header_field_start;
goto redo;
@@ -427,8 +455,8 @@ write(boost::asio::const_buffer const& buffer, error_code& ec)
fs_ = h_general;
break;
}
if(cb(&self::call_on_field))
return used();
assert(! cb_);
cb(&self::call_on_field);
s_ = s_header_field;
break;
}
@@ -525,7 +553,7 @@ write(boost::asio::const_buffer const& buffer, error_code& ec)
if(ch == ':')
{
if(cb(nullptr))
return used();
return errc();
s_ = s_header_value_start;
break;
}
@@ -575,7 +603,7 @@ write(boost::asio::const_buffer const& buffer, error_code& ec)
}
call_on_value(ec, boost::string_ref{"", 0});
if(ec)
return used();
return errc();
s_ = s_header_field_start;
goto redo;
@@ -625,7 +653,7 @@ write(boost::asio::const_buffer const& buffer, error_code& ec)
}
pos_ = 0;
if(cb(&self::call_on_value))
return used();
return errc();
s_ = s_header_value_text;
break;
}
@@ -637,7 +665,7 @@ write(boost::asio::const_buffer const& buffer, error_code& ec)
if(ch == '\r')
{
if(cb(nullptr))
return used();
return errc();
s_ = s_header_value_discard_lWs;
break;
}
@@ -771,9 +799,9 @@ write(boost::asio::const_buffer const& buffer, error_code& ec)
return err(parse_error::bad_value);
call_on_value(ec, boost::string_ref(" ", 1));
if(ec)
return used();
return errc();
if(cb(&self::call_on_value))
return used();
return errc();
s_ = s_header_value_text;
break;
@@ -807,7 +835,7 @@ write(boost::asio::const_buffer const& buffer, error_code& ec)
return err(parse_error::bad_crlf);
if(flags_ & parse_flag::trailing)
{
//if(cb(&self::call_on_chunk_complete)) return used();
//if(cb(&self::call_on_chunk_complete)) return errc();
s_ = s_complete;
goto redo;
}
@@ -817,7 +845,7 @@ write(boost::asio::const_buffer const& buffer, error_code& ec)
(parse_flag::upgrade | parse_flag::connection_upgrade)) /*|| method == "connect"*/;
auto const maybe_skip = call_on_headers(ec);
if(ec)
return used();
return errc();
switch(maybe_skip)
{
case 0: break;
@@ -835,7 +863,7 @@ write(boost::asio::const_buffer const& buffer, error_code& ec)
assert(! cb_);
call_on_headers(ec);
if(ec)
return used();
return errc();
bool const hasBody =
(flags_ & parse_flag::chunked) || (content_length_ > 0 &&
content_length_ != no_content_length);
@@ -874,8 +902,8 @@ write(boost::asio::const_buffer const& buffer, error_code& ec)
}
case s_body_identity0:
if(cb(&self::call_on_body))
return used();
assert(! cb_);
cb(&self::call_on_body);
s_ = s_body_identity;
goto redo; // VFALCO fall through?
@@ -899,8 +927,8 @@ write(boost::asio::const_buffer const& buffer, error_code& ec)
}
case s_body_identity_eof0:
if(cb(&self::call_on_body))
return used();
assert(! cb_);
cb(&self::call_on_body);
s_ = s_body_identity_eof;
goto redo; // VFALCO fall through?
@@ -959,13 +987,13 @@ write(boost::asio::const_buffer const& buffer, error_code& ec)
s_ = s_header_field_start;
break;
}
//call_chunk_header(ec); if(ec) return used();
//call_chunk_header(ec); if(ec) return errc();
s_ = s_chunk_data_start;
break;
case s_chunk_data_start:
if(cb(&self::call_on_body))
return used();
assert(! cb_);
cb(&self::call_on_body);
s_ = s_chunk_data;
goto redo; // VFALCO fall through?
@@ -987,7 +1015,7 @@ write(boost::asio::const_buffer const& buffer, error_code& ec)
if(ch != '\r')
return err(parse_error::bad_crlf);
if(cb(nullptr))
return used();
return errc();
s_ = s_chunk_data_done;
break;
@@ -1001,10 +1029,10 @@ write(boost::asio::const_buffer const& buffer, error_code& ec)
case s_complete:
++p;
if(cb(nullptr))
return used();
return errc();
call_on_complete(ec);
if(ec)
return used();
return errc();
s_ = s_restart;
return used();
@@ -1020,7 +1048,7 @@ write(boost::asio::const_buffer const& buffer, error_code& ec)
{
(this->*cb_)(ec, piece());
if(ec)
return used();
return errc();
}
return used();
}
@@ -1032,17 +1060,31 @@ write_eof(error_code& ec)
{
switch(s_)
{
case s_restart:
s_ = s_closed_complete;
break;
case s_closed:
case s_closed_complete:
break;
case s_body_identity_eof0:
case s_body_identity_eof:
cb_ = nullptr;
call_on_complete(ec);
if(ec)
return;
return;
{
s_ = s_closed;
break;
}
s_ = s_closed_complete;
break;
default:
s_ = s_closed;
ec = parse_error::short_read;
break;
}
ec = parse_error::short_read;
s_ = s_closed;
}
template<bool isRequest, class Derived>

View File

@@ -16,28 +16,6 @@
namespace beast {
namespace http {
template<bool isRequest, class Body, class Headers>
message_v1<isRequest, Body, Headers>::
message_v1(request_params params)
{
static_assert(isRequest, "message is not a request");
this->method = params.method;
this->url = std::move(params.url);
version = params.version;
}
template<bool isRequest, class Body, class Headers>
message_v1<isRequest, Body, Headers>::
message_v1(response_params params)
{
static_assert(! isRequest, "message is not a response");
this->status = params.status;
this->reason = std::move(params.reason);
version = params.version;
}
//------------------------------------------------------------------------------
template<bool isRequest, class Body, class Headers>
bool
is_keep_alive(message_v1<isRequest, Body, Headers> const& msg)
@@ -228,12 +206,6 @@ prepare(message_v1<isRequest, Body, Headers>& msg,
msg.headers["Connection"], "upgrade"))
throw std::invalid_argument(
"invalid version for Connection: upgrade");
// rfc7230 3.3.2
if(msg.headers.exists("Content-Length") &&
msg.headers.exists("Transfer-Encoding"))
throw std::invalid_argument(
"Content-Length and Transfer-Encoding cannot be combined");
}
} // http

View File

@@ -9,9 +9,10 @@
#define BEAST_HTTP_IMPL_READ_IPP_HPP
#include <beast/http/parser_v1.hpp>
#include <beast/bind_handler.hpp>
#include <beast/handler_alloc.hpp>
#include <beast/stream_concepts.hpp>
#include <beast/http/type_check.hpp>
#include <beast/core/bind_handler.hpp>
#include <beast/core/handler_alloc.hpp>
#include <beast/core/stream_concepts.hpp>
#include <cassert>
namespace beast {
@@ -19,6 +20,185 @@ namespace http {
namespace detail {
template<class Stream,
class Streambuf, class Parser, class Handler>
class parse_op
{
using alloc_type =
handler_alloc<char, Handler>;
struct data
{
Stream& s;
Streambuf& sb;
Parser& p;
Handler h;
bool started = false;
bool cont;
int state = 0;
template<class DeducedHandler>
data(DeducedHandler&& h_, Stream& s_,
Streambuf& sb_, Parser& p_)
: s(s_)
, sb(sb_)
, p(p_)
, h(std::forward<DeducedHandler>(h_))
, cont(boost_asio_handler_cont_helpers::
is_continuation(h))
{
}
};
std::shared_ptr<data> d_;
public:
parse_op(parse_op&&) = default;
parse_op(parse_op const&) = default;
template<class DeducedHandler, class... Args>
parse_op(DeducedHandler&& h, Stream& s, Args&&... args)
: d_(std::allocate_shared<data>(alloc_type{h},
std::forward<DeducedHandler>(h), s,
std::forward<Args>(args)...))
{
(*this)(error_code{}, 0, false);
}
void
operator()(error_code ec,
std::size_t bytes_transferred, bool again = true);
friend
void* asio_handler_allocate(
std::size_t size, parse_op* op)
{
return boost_asio_handler_alloc_helpers::
allocate(size, op->d_->h);
}
friend
void asio_handler_deallocate(
void* p, std::size_t size, parse_op* op)
{
return boost_asio_handler_alloc_helpers::
deallocate(p, size, op->d_->h);
}
friend
bool asio_handler_is_continuation(parse_op* op)
{
return op->d_->cont;
}
template <class Function>
friend
void asio_handler_invoke(Function&& f, parse_op* op)
{
return boost_asio_handler_invoke_helpers::
invoke(f, op->d_->h);
}
};
template<class Stream,
class Streambuf, class Parser, class Handler>
void
parse_op<Stream, Streambuf, Parser, Handler>::
operator()(error_code ec, std::size_t bytes_transferred, bool again)
{
auto& d = *d_;
d.cont = d.cont || again;
while(d.state != 99)
{
switch(d.state)
{
case 0:
{
auto const used =
d.p.write(d.sb.data(), ec);
if(ec)
{
// call handler
d.state = 99;
d.s.get_io_service().post(
bind_handler(std::move(*this), ec, 0));
return;
}
if(used > 0)
d.started = true;
d.sb.consume(used);
if(d.p.complete())
{
// call handler
d.state = 99;
d.s.get_io_service().post(
bind_handler(std::move(*this), ec, 0));
return;
}
d.state = 1;
break;
}
case 1:
// read
d.state = 2;
d.s.async_read_some(d.sb.prepare(
read_size_helper(d.sb, 65536)),
std::move(*this));
return;
// got data
case 2:
{
if(ec == boost::asio::error::eof)
{
if(! d.started)
{
// call handler
d.state = 99;
break;
}
// Caller will see eof on next read.
ec = {};
d.p.write_eof(ec);
assert(ec || d.p.complete());
// call handler
d.state = 99;
break;
}
if(ec)
{
// call handler
d.state = 99;
break;
}
d.sb.commit(bytes_transferred);
auto const used = d.p.write(d.sb.data(), ec);
if(ec)
{
// call handler
d.state = 99;
break;
}
if(used > 0)
d.started = true;
d.sb.consume(used);
if(d.p.complete())
{
// call handler
d.state = 99;
break;
}
d.state = 1;
break;
}
}
}
d.h(ec);
}
//------------------------------------------------------------------------------
template<class Stream, class Streambuf,
bool isRequest, class Body, class Headers,
class Handler>
@@ -64,17 +244,16 @@ public:
read_op(read_op const&) = default;
template<class DeducedHandler, class... Args>
read_op(DeducedHandler&& h, Stream&s, Args&&... args)
read_op(DeducedHandler&& h, Stream& s, Args&&... args)
: d_(std::allocate_shared<data>(alloc_type{h},
std::forward<DeducedHandler>(h), s,
std::forward<Args>(args)...))
{
(*this)(error_code{}, 0, false);
(*this)(error_code{}, false);
}
void
operator()(error_code ec,
std::size_t bytes_transferred, bool again = true);
operator()(error_code ec, bool again = true);
friend
void* asio_handler_allocate(
@@ -112,98 +291,25 @@ template<class Stream, class Streambuf,
class Handler>
void
read_op<Stream, Streambuf, isRequest, Body, Headers, Handler>::
operator()(error_code ec, std::size_t bytes_transferred, bool again)
operator()(error_code ec, bool again)
{
auto& d = *d_;
d.cont = d.cont || again;
while(d.state != 99)
while(! ec && d.state != 99)
{
switch(d.state)
{
case 0:
{
auto const used =
d.p.write(d.sb.data(), ec);
if(ec)
{
// call handler
d.state = 99;
d.s.get_io_service().post(
bind_handler(std::move(*this), ec, 0));
return;
}
if(used > 0)
d.started = true;
d.sb.consume(used);
if(d.p.complete())
{
// call handler
d.state = 99;
d.m = d.p.release();
d.s.get_io_service().post(
bind_handler(std::move(*this), ec, 0));
return;
}
d.state = 1;
break;
}
case 1:
// read
d.state = 2;
d.s.async_read_some(d.sb.prepare(
read_size_helper(d.sb, 65536)),
std::move(*this));
async_parse(d.s, d.sb, d.p, std::move(*this));
return;
// got data
case 2:
{
if(ec == boost::asio::error::eof)
{
if(! d.started)
{
// call handler
d.state = 99;
break;
}
// Caller will see eof on next read.
ec = {};
d.p.write_eof(ec);
if(! ec)
{
assert(d.p.complete());
d.m = d.p.release();
}
// call handler
d.state = 99;
break;
}
if(ec)
{
// call handler
d.state = 99;
break;
}
d.sb.commit(bytes_transferred);
d.sb.consume(d.p.write(d.sb.data(), ec));
if(ec)
{
// call handler
d.state = 99;
break;
}
if(d.p.complete())
{
// call handler
d.state = 99;
d.m = d.p.release();
break;
}
d.state = 1;
case 1:
// call handler
d.state = 99;
d.m = d.p.release();
break;
}
}
}
d.h(ec);
}
@@ -212,6 +318,97 @@ operator()(error_code ec, std::size_t bytes_transferred, bool again)
//------------------------------------------------------------------------------
template<class SyncReadStream, class Streambuf, class Parser>
void
parse(SyncReadStream& stream,
Streambuf& streambuf, Parser& parser)
{
error_code ec;
parse(stream, streambuf, parser, ec);
if(ec)
throw boost::system::system_error{ec};
}
template<class SyncReadStream, class Streambuf, class Parser>
void
parse(SyncReadStream& stream, Streambuf& streambuf,
Parser& parser, error_code& ec)
{
static_assert(is_SyncReadStream<SyncReadStream>::value,
"SyncReadStream requirements not met");
static_assert(is_Streambuf<Streambuf>::value,
"Streambuf requirements not met");
static_assert(is_Parser<Parser>::value,
"Parser requirements not met");
bool started = false;
for(;;)
{
auto used =
parser.write(streambuf.data(), ec);
if(ec)
return;
streambuf.consume(used);
if(used > 0)
started = true;
if(parser.complete())
break;
streambuf.commit(stream.read_some(
streambuf.prepare(read_size_helper(
streambuf, 65536)), ec));
if(ec && ec != boost::asio::error::eof)
return;
if(ec == boost::asio::error::eof)
{
if(! started)
return;
// Caller will see eof on next read.
ec = {};
parser.write_eof(ec);
if(ec)
return;
assert(parser.complete());
break;
}
}
}
template<class AsyncReadStream,
class Streambuf, class Parser, class ReadHandler>
typename async_completion<
ReadHandler, void(error_code)>::result_type
async_parse(AsyncReadStream& stream,
Streambuf& streambuf, Parser& parser, ReadHandler&& handler)
{
static_assert(is_AsyncReadStream<AsyncReadStream>::value,
"AsyncReadStream requirements not met");
static_assert(is_Streambuf<Streambuf>::value,
"Streambuf requirements not met");
static_assert(is_Parser<Parser>::value,
"Parser requirements not met");
beast::async_completion<ReadHandler,
void(error_code)> completion(handler);
detail::parse_op<AsyncReadStream, Streambuf,
Parser, decltype(completion.handler)>{
completion.handler, stream, streambuf, parser};
return completion.result.get();
}
template<class SyncReadStream, class Streambuf,
bool isRequest, class Body, class Headers>
void
read(SyncReadStream& stream, Streambuf& streambuf,
message_v1<isRequest, Body, Headers>& msg)
{
static_assert(is_SyncReadStream<SyncReadStream>::value,
"SyncReadStream requirements not met");
static_assert(is_Streambuf<Streambuf>::value,
"Streambuf requirements not met");
error_code ec;
read(stream, streambuf, msg, ec);
if(ec)
throw system_error{ec};
}
template<class SyncReadStream, class Streambuf,
bool isRequest, class Body, class Headers>
void
@@ -224,40 +421,11 @@ read(SyncReadStream& stream, Streambuf& streambuf,
static_assert(is_Streambuf<Streambuf>::value,
"Streambuf requirements not met");
parser_v1<isRequest, Body, Headers> p;
bool started = false;
for(;;)
{
auto used =
p.write(streambuf.data(), ec);
if(ec)
return;
streambuf.consume(used);
if(used > 0)
started = true;
if(p.complete())
{
m = p.release();
break;
}
streambuf.commit(stream.read_some(
streambuf.prepare(read_size_helper(
streambuf, 65536)), ec));
if(ec && ec != boost::asio::error::eof)
return;
if(ec == boost::asio::error::eof)
{
if(! started)
return;
// Caller will see eof on next read.
ec = {};
p.write_eof(ec);
if(ec)
return;
assert(p.complete());
m = p.release();
break;
}
}
parse(stream, streambuf, p, ec);
if(ec)
return;
assert(p.complete());
m = p.release();
}
template<class AsyncReadStream, class Streambuf,

View File

@@ -11,13 +11,13 @@
#include <beast/http/resume_context.hpp>
#include <beast/http/detail/chunk_encode.hpp>
#include <beast/http/detail/has_content_length.hpp>
#include <beast/buffer_cat.hpp>
#include <beast/bind_handler.hpp>
#include <beast/buffer_concepts.hpp>
#include <beast/handler_alloc.hpp>
#include <beast/stream_concepts.hpp>
#include <beast/streambuf.hpp>
#include <beast/write_streambuf.hpp>
#include <beast/core/buffer_cat.hpp>
#include <beast/core/bind_handler.hpp>
#include <beast/core/buffer_concepts.hpp>
#include <beast/core/handler_alloc.hpp>
#include <beast/core/stream_concepts.hpp>
#include <beast/core/streambuf.hpp>
#include <beast/core/write_streambuf.hpp>
#include <boost/asio/write.hpp>
#include <boost/logic/tribool.hpp>
#include <condition_variable>
@@ -39,22 +39,11 @@ write_firstline(Streambuf& streambuf,
write(streambuf, msg.method);
write(streambuf, " ");
write(streambuf, msg.url);
switch(msg.version)
{
case 10:
write(streambuf, " HTTP/1.0\r\n");
break;
case 11:
write(streambuf, " HTTP/1.1\r\n");
break;
default:
write(streambuf, " HTTP/");
write(streambuf, msg.version / 10);
write(streambuf, ".");
write(streambuf, msg.version % 10);
write(streambuf, "\r\n");
break;
}
write(streambuf, " HTTP/");
write(streambuf, msg.version / 10);
write(streambuf, ".");
write(streambuf, msg.version % 10);
write(streambuf, "\r\n");
}
template<class Streambuf, class Body, class Headers>
@@ -62,22 +51,11 @@ void
write_firstline(Streambuf& streambuf,
message_v1<false, Body, Headers> const& msg)
{
switch(msg.version)
{
case 10:
write(streambuf, "HTTP/1.0 ");
break;
case 11:
write(streambuf, "HTTP/1.1 ");
break;
default:
write(streambuf, " HTTP/");
write(streambuf, msg.version / 10);
write(streambuf, ".");
write(streambuf, msg.version % 10);
write(streambuf, " ");
break;
}
write(streambuf, "HTTP/");
write(streambuf, msg.version / 10);
write(streambuf, ".");
write(streambuf, msg.version % 10);
write(streambuf, " ");
write(streambuf, msg.status);
write(streambuf, " ");
write(streambuf, msg.reason);
@@ -170,13 +148,13 @@ class write_op
}
};
class writef0
class writef0_lambda
{
write_op& self_;
public:
explicit
writef0(write_op& self)
writef0_lambda(write_op& self)
: self_(self)
{
}
@@ -198,13 +176,13 @@ class write_op
}
};
class writef
class writef_lambda
{
write_op& self_;
public:
explicit
writef(write_op& self)
writef_lambda(write_op& self)
: self_(self)
{
}
@@ -322,7 +300,7 @@ operator()(error_code ec, std::size_t, bool again)
case 1:
{
auto const result = d.wp.w(
std::move(d.copy), ec, writef0{*this});
std::move(d.copy), ec, writef0_lambda{*this});
if(ec)
{
// call handler
@@ -353,7 +331,7 @@ operator()(error_code ec, std::size_t, bool again)
case 3:
{
auto const result = d.wp.w(
std::move(d.copy), ec, writef{*this});
std::move(d.copy), ec, writef_lambda{*this});
if(ec)
{
// call handler
@@ -400,7 +378,7 @@ operator()(error_code ec, std::size_t, bool again)
}
template<class SyncWriteStream, class Streambuf>
class writef0_write
class writef0_lambda
{
Streambuf const& sb_;
SyncWriteStream& stream_;
@@ -408,7 +386,7 @@ class writef0_write
error_code& ec_;
public:
writef0_write(SyncWriteStream& stream,
writef0_lambda(SyncWriteStream& stream,
Streambuf const& sb, bool chunked, error_code& ec)
: sb_(sb)
, stream_(stream)
@@ -431,14 +409,14 @@ public:
};
template<class SyncWriteStream>
class writef_write
class writef_lambda
{
SyncWriteStream& stream_;
bool chunked_;
error_code& ec_;
public:
writef_write(SyncWriteStream& stream,
writef_lambda(SyncWriteStream& stream,
bool chunked, error_code& ec)
: stream_(stream)
, chunked_(chunked)
@@ -473,7 +451,7 @@ write(SyncWriteStream& stream,
error_code ec;
write(stream, msg, ec);
if(ec)
throw boost::system::system_error{ec};
throw system_error{ec};
}
template<class SyncWriteStream,
@@ -500,45 +478,42 @@ write(SyncWriteStream& stream,
cv.notify_one();
}};
auto copy = resume;
for(;;)
boost::tribool result = wp.w(std::move(copy),
ec, detail::writef0_lambda<SyncWriteStream,
decltype(wp.sb)>{stream, wp.sb, wp.chunked, ec});
if(ec)
return;
if(boost::indeterminate(result))
{
copy = resume;
{
auto result = wp.w(std::move(copy), ec,
detail::writef0_write<SyncWriteStream, decltype(wp.sb)>{
stream, wp.sb, wp.chunked, ec});
if(ec)
return;
if(result)
break;
if(boost::indeterminate(result))
{
boost::asio::write(stream, wp.sb.data(), ec);
if(ec)
return;
wp.sb.consume(wp.sb.size());
copy = resume;
std::unique_lock<std::mutex> lock(m);
cv.wait(lock, [&]{ return ready; });
ready = false;
}
std::unique_lock<std::mutex> lock(m);
cv.wait(lock, [&]{ return ready; });
ready = false;
}
wp.sb.consume(wp.sb.size());
boost::asio::write(stream, wp.sb.data(), ec);
if(ec)
return;
result = false;
}
wp.sb.consume(wp.sb.size());
if(! result)
{
for(;;)
{
auto result = wp.w(std::move(copy), ec,
detail::writef_write<SyncWriteStream>{
result = wp.w(std::move(copy), ec,
detail::writef_lambda<SyncWriteStream>{
stream, wp.chunked, ec});
if(ec)
return;
if(result)
break;
if(boost::indeterminate(result))
{
copy = resume;
std::unique_lock<std::mutex> lock(m);
cv.wait(lock, [&]{ return ready; });
ready = false;
}
if(! result)
continue;
copy = resume;
std::unique_lock<std::mutex> lock(m);
cv.wait(lock, [&]{ return ready; });
ready = false;
}
}
if(wp.chunked)
@@ -597,7 +572,7 @@ public:
error_code ec;
auto const n = write_some(buffers, ec);
if(ec)
throw boost::system::system_error{ec};
throw system_error{ec};
return n;
}
@@ -636,7 +611,7 @@ operator<<(std::ostream& os,
error_code ec;
write(oss, msg, ec);
if(ec && ec != boost::asio::error::eof)
throw boost::system::system_error{ec};
throw system_error{ec};
return os;
}

View File

@@ -9,8 +9,11 @@
#define BEAST_HTTP_MESSAGE_HPP
#include <beast/http/basic_headers.hpp>
#include <beast/core/detail/integer_sequence.hpp>
#include <memory>
#include <string>
#include <tuple>
#include <utility>
namespace beast {
namespace http {
@@ -69,6 +72,77 @@ struct message
/// A container representing the body.
typename Body::value_type body;
/// Default constructor
message() = default;
/** Construct a message.
@param u An argument forwarded to the body constructor.
*/
template<class U>
explicit
message(U&& u)
: body(std::forward<U>(u))
{
}
/** Construct a message.
@param u An argument forwarded to the body constructor.
@param v An argument forwarded to the headers constructor.
*/
template<class U, class V>
message(U&& u, V&& v)
: headers(std::forward<V>(v))
, body(std::forward<U>(u))
{
}
/** Construct a message.
@param un A tuple forwarded as a parameter pack to the body constructor.
*/
template<class... Un>
message(std::piecewise_construct_t, std::tuple<Un...> un)
: message(std::piecewise_construct, un,
beast::detail::make_index_sequence<sizeof...(Un)>{})
{
}
/** Construct a message.
@param un A tuple forwarded as a parameter pack to the body constructor.
@param vn A tuple forwarded as a parameter pack to the headers constructor.
*/
template<class... Un, class... Vn>
message(std::piecewise_construct_t,
std::tuple<Un...>&& un, std::tuple<Vn...>&& vn)
: message(std::piecewise_construct, un, vn,
beast::detail::make_index_sequence<sizeof...(Un)>{},
beast::detail::make_index_sequence<sizeof...(Vn)>{})
{
}
private:
template<class... Un, size_t... IUn>
message(std::piecewise_construct_t,
std::tuple<Un...>& tu, beast::detail::index_sequence<IUn...>)
: body(std::forward<Un>(std::get<IUn>(tu))...)
{
}
template<class... Un, class... Vn,
std::size_t... IUn, std::size_t... IVn>
message(std::piecewise_construct_t,
std::tuple<Un...>& tu, std::tuple<Vn...>& tv,
beast::detail::index_sequence<IUn...>,
beast::detail::index_sequence<IVn...>)
: headers(std::forward<Vn>(std::get<IVn>(tv))...)
, body(std::forward<Un>(std::get<IUn>(tu))...)
{
}
};
#if ! GENERATING_DOCS

Some files were not shown because too many files have changed in this diff Show More