mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Merge subtree Beast 1.0.0-b6:
Merge commit '999e2fa0318b5982736d3ea01a418770ea802671'
This commit is contained in:
@@ -296,7 +296,9 @@
|
|||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\core\detail\stream_concepts.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\core\detail\stream_concepts.hpp">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\core\detail\write_streambuf.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\core\detail\write_dynabuf.hpp">
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\beast\include\beast\core\dynabuf_readstream.hpp">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\core\error.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\core\error.hpp">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@@ -308,12 +310,12 @@
|
|||||||
</None>
|
</None>
|
||||||
<None Include="..\..\src\beast\include\beast\core\impl\consuming_buffers.ipp">
|
<None Include="..\..\src\beast\include\beast\core\impl\consuming_buffers.ipp">
|
||||||
</None>
|
</None>
|
||||||
|
<None Include="..\..\src\beast\include\beast\core\impl\dynabuf_readstream.ipp">
|
||||||
|
</None>
|
||||||
<None Include="..\..\src\beast\include\beast\core\impl\prepare_buffers.ipp">
|
<None Include="..\..\src\beast\include\beast\core\impl\prepare_buffers.ipp">
|
||||||
</None>
|
</None>
|
||||||
<None Include="..\..\src\beast\include\beast\core\impl\static_streambuf.ipp">
|
<None Include="..\..\src\beast\include\beast\core\impl\static_streambuf.ipp">
|
||||||
</None>
|
</None>
|
||||||
<None Include="..\..\src\beast\include\beast\core\impl\streambuf_readstream.ipp">
|
|
||||||
</None>
|
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\core\placeholders.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\core\placeholders.hpp">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\core\prepare_buffers.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\core\prepare_buffers.hpp">
|
||||||
@@ -324,16 +326,16 @@
|
|||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\core\streambuf.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\core\streambuf.hpp">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\core\streambuf_readstream.hpp">
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\core\stream_concepts.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\core\stream_concepts.hpp">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\core\to_string.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\core\to_string.hpp">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\core\write_streambuf.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\core\write_dynabuf.hpp">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\http.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\http.hpp">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\beast\include\beast\http\basic_dynabuf_body.hpp">
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\http\basic_headers.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\http\basic_headers.hpp">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\http\basic_parser_v1.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\http\basic_parser_v1.hpp">
|
||||||
@@ -348,6 +350,8 @@
|
|||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\http\detail\has_content_length.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\http\detail\has_content_length.hpp">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\beast\include\beast\http\detail\rfc7230.hpp">
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\http\empty_body.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\http\empty_body.hpp">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\http\headers.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\http\headers.hpp">
|
||||||
@@ -360,6 +364,8 @@
|
|||||||
</None>
|
</None>
|
||||||
<None Include="..\..\src\beast\include\beast\http\impl\read.ipp">
|
<None Include="..\..\src\beast\include\beast\http\impl\read.ipp">
|
||||||
</None>
|
</None>
|
||||||
|
<None Include="..\..\src\beast\include\beast\http\impl\rfc7230.ipp">
|
||||||
|
</None>
|
||||||
<None Include="..\..\src\beast\include\beast\http\impl\write.ipp">
|
<None Include="..\..\src\beast\include\beast\http\impl\write.ipp">
|
||||||
</None>
|
</None>
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\http\message.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\http\message.hpp">
|
||||||
@@ -376,8 +382,6 @@
|
|||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\http\resume_context.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\http\resume_context.hpp">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\http\rfc2616.hpp">
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\http\rfc7230.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\http\rfc7230.hpp">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\http\streambuf_body.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\http\streambuf_body.hpp">
|
||||||
|
|||||||
@@ -627,9 +627,12 @@
|
|||||||
<ClInclude Include="..\..\src\beast\include\beast\core\detail\stream_concepts.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\core\detail\stream_concepts.hpp">
|
||||||
<Filter>include\beast\core\detail</Filter>
|
<Filter>include\beast\core\detail</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\core\detail\write_streambuf.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\core\detail\write_dynabuf.hpp">
|
||||||
<Filter>include\beast\core\detail</Filter>
|
<Filter>include\beast\core\detail</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\beast\include\beast\core\dynabuf_readstream.hpp">
|
||||||
|
<Filter>include\beast\core</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\core\error.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\core\error.hpp">
|
||||||
<Filter>include\beast\core</Filter>
|
<Filter>include\beast\core</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@@ -645,15 +648,15 @@
|
|||||||
<None Include="..\..\src\beast\include\beast\core\impl\consuming_buffers.ipp">
|
<None Include="..\..\src\beast\include\beast\core\impl\consuming_buffers.ipp">
|
||||||
<Filter>include\beast\core\impl</Filter>
|
<Filter>include\beast\core\impl</Filter>
|
||||||
</None>
|
</None>
|
||||||
|
<None Include="..\..\src\beast\include\beast\core\impl\dynabuf_readstream.ipp">
|
||||||
|
<Filter>include\beast\core\impl</Filter>
|
||||||
|
</None>
|
||||||
<None Include="..\..\src\beast\include\beast\core\impl\prepare_buffers.ipp">
|
<None Include="..\..\src\beast\include\beast\core\impl\prepare_buffers.ipp">
|
||||||
<Filter>include\beast\core\impl</Filter>
|
<Filter>include\beast\core\impl</Filter>
|
||||||
</None>
|
</None>
|
||||||
<None Include="..\..\src\beast\include\beast\core\impl\static_streambuf.ipp">
|
<None Include="..\..\src\beast\include\beast\core\impl\static_streambuf.ipp">
|
||||||
<Filter>include\beast\core\impl</Filter>
|
<Filter>include\beast\core\impl</Filter>
|
||||||
</None>
|
</None>
|
||||||
<None Include="..\..\src\beast\include\beast\core\impl\streambuf_readstream.ipp">
|
|
||||||
<Filter>include\beast\core\impl</Filter>
|
|
||||||
</None>
|
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\core\placeholders.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\core\placeholders.hpp">
|
||||||
<Filter>include\beast\core</Filter>
|
<Filter>include\beast\core</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@@ -669,21 +672,21 @@
|
|||||||
<ClInclude Include="..\..\src\beast\include\beast\core\streambuf.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\core\streambuf.hpp">
|
||||||
<Filter>include\beast\core</Filter>
|
<Filter>include\beast\core</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\core\streambuf_readstream.hpp">
|
|
||||||
<Filter>include\beast\core</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\core\stream_concepts.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\core\stream_concepts.hpp">
|
||||||
<Filter>include\beast\core</Filter>
|
<Filter>include\beast\core</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\core\to_string.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\core\to_string.hpp">
|
||||||
<Filter>include\beast\core</Filter>
|
<Filter>include\beast\core</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\core\write_streambuf.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\core\write_dynabuf.hpp">
|
||||||
<Filter>include\beast\core</Filter>
|
<Filter>include\beast\core</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\http.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\http.hpp">
|
||||||
<Filter>include\beast</Filter>
|
<Filter>include\beast</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\beast\include\beast\http\basic_dynabuf_body.hpp">
|
||||||
|
<Filter>include\beast\http</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\http\basic_headers.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\http\basic_headers.hpp">
|
||||||
<Filter>include\beast\http</Filter>
|
<Filter>include\beast\http</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@@ -705,6 +708,9 @@
|
|||||||
<ClInclude Include="..\..\src\beast\include\beast\http\detail\has_content_length.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\http\detail\has_content_length.hpp">
|
||||||
<Filter>include\beast\http\detail</Filter>
|
<Filter>include\beast\http\detail</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\beast\include\beast\http\detail\rfc7230.hpp">
|
||||||
|
<Filter>include\beast\http\detail</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\http\empty_body.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\http\empty_body.hpp">
|
||||||
<Filter>include\beast\http</Filter>
|
<Filter>include\beast\http</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@@ -723,6 +729,9 @@
|
|||||||
<None Include="..\..\src\beast\include\beast\http\impl\read.ipp">
|
<None Include="..\..\src\beast\include\beast\http\impl\read.ipp">
|
||||||
<Filter>include\beast\http\impl</Filter>
|
<Filter>include\beast\http\impl</Filter>
|
||||||
</None>
|
</None>
|
||||||
|
<None Include="..\..\src\beast\include\beast\http\impl\rfc7230.ipp">
|
||||||
|
<Filter>include\beast\http\impl</Filter>
|
||||||
|
</None>
|
||||||
<None Include="..\..\src\beast\include\beast\http\impl\write.ipp">
|
<None Include="..\..\src\beast\include\beast\http\impl\write.ipp">
|
||||||
<Filter>include\beast\http\impl</Filter>
|
<Filter>include\beast\http\impl</Filter>
|
||||||
</None>
|
</None>
|
||||||
@@ -747,9 +756,6 @@
|
|||||||
<ClInclude Include="..\..\src\beast\include\beast\http\resume_context.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\http\resume_context.hpp">
|
||||||
<Filter>include\beast\http</Filter>
|
<Filter>include\beast\http</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\http\rfc2616.hpp">
|
|
||||||
<Filter>include\beast\http</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\src\beast\include\beast\http\rfc7230.hpp">
|
<ClInclude Include="..\..\src\beast\include\beast\http\rfc7230.hpp">
|
||||||
<Filter>include\beast\http</Filter>
|
<Filter>include\beast\http</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|||||||
4
src/beast/.gitignore
vendored
4
src/beast/.gitignore
vendored
@@ -24,3 +24,7 @@ contents.xcworkspacedata
|
|||||||
.svn
|
.svn
|
||||||
profile
|
profile
|
||||||
bin/
|
bin/
|
||||||
|
node_modules/
|
||||||
|
cov-int/
|
||||||
|
nohup.out
|
||||||
|
venv/
|
||||||
|
|||||||
@@ -14,13 +14,6 @@ env:
|
|||||||
packages: &gcc5_pkgs
|
packages: &gcc5_pkgs
|
||||||
- gcc-5
|
- gcc-5
|
||||||
- g++-5
|
- g++-5
|
||||||
# - gcc-5-multilib
|
|
||||||
# - g++-5-multilib
|
|
||||||
# - gcc-multilib
|
|
||||||
# - g++-multilib
|
|
||||||
# - libgd2-xpm
|
|
||||||
# - ia32-libs
|
|
||||||
# - ia32-libs-multiarch
|
|
||||||
- python-software-properties
|
- python-software-properties
|
||||||
- libssl-dev
|
- libssl-dev
|
||||||
- libffi-dev
|
- libffi-dev
|
||||||
@@ -52,20 +45,7 @@ packages: &clang38_pkgs
|
|||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
# GCC/Debug
|
# GCC/Coverage
|
||||||
# - compiler: gcc
|
|
||||||
# env: GCC_VER=5 VARIANT=debug ADDRESS_MODEL=64
|
|
||||||
# addons: &ao_gcc5
|
|
||||||
# apt:
|
|
||||||
# sources: ['ubuntu-toolchain-r-test']
|
|
||||||
# packages: *gcc5_pkgs
|
|
||||||
|
|
||||||
# # GCC/Release
|
|
||||||
# - compiler: gcc
|
|
||||||
# env: GCC_VER=5 VARIANT=release ADDRESS_MODEL=64
|
|
||||||
# addons: *ao_gcc5
|
|
||||||
|
|
||||||
# Coverage
|
|
||||||
- compiler: gcc
|
- compiler: gcc
|
||||||
env: GCC_VER=5 VARIANT=coverage ADDRESS_MODEL=64
|
env: GCC_VER=5 VARIANT=coverage ADDRESS_MODEL=64
|
||||||
addons: &ao_gcc5
|
addons: &ao_gcc5
|
||||||
@@ -73,36 +53,25 @@ matrix:
|
|||||||
sources: ['ubuntu-toolchain-r-test']
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
packages: *gcc5_pkgs
|
packages: *gcc5_pkgs
|
||||||
|
|
||||||
# # Clang/Debug
|
# # GCC/Debug
|
||||||
# - compiler: clang
|
# - compiler: gcc
|
||||||
# env: GCC_VER=5 VARIANT=debug CLANG_VER=3.8 ADDRESS_MODEL=64
|
# env: GCC_VER=5 VARIANT=debug ADDRESS_MODEL=64
|
||||||
# addons: &ao_clang38
|
# addons: *ao_gcc5
|
||||||
# apt:
|
# branches: # NOTE: this does NOT work, though it SHOULD
|
||||||
# sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.8']
|
# - master
|
||||||
# packages: *clang38_pkgs
|
# - develop
|
||||||
|
|
||||||
# # Clang/Release
|
# Clang/UndefinedBehaviourSanitizer
|
||||||
# - compiler: clang
|
|
||||||
# env: GCC_VER=5 VARIANT=release CLANG_VER=3.8 ADDRESS_MODEL=64
|
|
||||||
# addons: *ao_clang38
|
|
||||||
|
|
||||||
# Clang/AddressSanitizer
|
|
||||||
- compiler: clang
|
- compiler: clang
|
||||||
env: GCC_VER=5 VARIANT=asan CLANG_VER=3.8 ADDRESS_MODEL=64
|
env: GCC_VER=5 VARIANT=usan CLANG_VER=3.8 ADDRESS_MODEL=64 UBSAN_OPTIONS='print_stacktrace=1'
|
||||||
addons: &ao_clang38
|
addons: &ao_clang38
|
||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.8']
|
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.8']
|
||||||
packages: *clang38_pkgs
|
packages: *clang38_pkgs
|
||||||
|
|
||||||
# Clang/MemorySanitizer
|
# Clang/AddressSanitizer
|
||||||
# VFALCO Generates false positives unless libc++ is compiled with msan turned on
|
|
||||||
#- compiler: clang
|
|
||||||
# env: GCC_VER=5 VARIANT=msan CLANG_VER=3.8 ADDRESS_MODEL=64 MSAN_OPTIONS=poison_in_dtor=1,sanitize-memory-track-origins=2
|
|
||||||
# addons: *ao_clang38
|
|
||||||
|
|
||||||
# Clang/UndefinedBehaviourSanitizer
|
|
||||||
- compiler: clang
|
- compiler: clang
|
||||||
env: GCC_VER=5 VARIANT=usan CLANG_VER=3.8 ADDRESS_MODEL=64
|
env: GCC_VER=5 VARIANT=asan CLANG_VER=3.8 ADDRESS_MODEL=64
|
||||||
addons: *ao_clang38
|
addons: *ao_clang38
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
|
|||||||
21
src/beast/CHANGELOG
Normal file
21
src/beast/CHANGELOG
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
1.0.0-b6
|
||||||
|
|
||||||
|
* Use SFINAE on return values
|
||||||
|
* Use beast::error_code instead of nested types
|
||||||
|
* Tidy up use of GENERATING_DOCS
|
||||||
|
* Remove obsolete RFC2616 functions
|
||||||
|
* Add message swap members and free functions
|
||||||
|
* Add HTTP field value parser containers: ext_list, param_list, token_list
|
||||||
|
* Fixes for some corner cases in basic_parser_v1
|
||||||
|
* Configurable limits on headers and body sizes in basic_parser_v1
|
||||||
|
|
||||||
|
API Changes:
|
||||||
|
|
||||||
|
* ci_equal is moved to beast::http namespace, in rfc7230.hpp
|
||||||
|
|
||||||
|
* "DynamicBuffer","dynabuf" renamed from "Streambuf", "streambuf". See:
|
||||||
|
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4478.html#requirements.dynamic_buffers
|
||||||
|
|
||||||
|
* basic_parser_v1 adheres to rfc7230 as strictly as possible
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
# Beast
|
# Beast
|
||||||
|
|
||||||
[](https://travis-ci.org/vinniefalco/Beast) [![codecov]
|
[](https://gitter.im/vinniefalco/Beast?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Build Status]
|
||||||
(https://codecov.io/gh/vinniefalco/Beast/branch/master/graph/badge.svg)](https://codecov.io/gh/vinniefalco/Beast) [![Documentation]
|
(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) [![coveralls]
|
||||||
|
(https://coveralls.io/repos/github/vinniefalco/Beast/badge.svg?branch=master)](https://coveralls.io/github/vinniefalco/Beast?branch=master) [![Documentation]
|
||||||
(https://img.shields.io/badge/documentation-master-brightgreen.svg)](http://vinniefalco.github.io/beast/) [![License]
|
(https://img.shields.io/badge/documentation-master-brightgreen.svg)](http://vinniefalco.github.io/beast/) [![License]
|
||||||
(https://img.shields.io/badge/license-boost-brightgreen.svg)](LICENSE_1_0.txt)
|
(https://img.shields.io/badge/license-boost-brightgreen.svg)](LICENSE_1_0.txt)
|
||||||
|
|
||||||
@@ -14,6 +16,11 @@ Requirements:
|
|||||||
* C++11 or greater
|
* C++11 or greater
|
||||||
* OpenSSL (optional)
|
* OpenSSL (optional)
|
||||||
|
|
||||||
|
This software is currently in beta: interfaces are subject to change. For
|
||||||
|
recent changes see [CHANGELOG](CHANGELOG).
|
||||||
|
The library has been submitted to the
|
||||||
|
[Boost Library Incubator](http://rrsd.com/blincubator.com/bi_library/beast-2/?gform_post_id=1579)
|
||||||
|
|
||||||
Example WebSocket program:
|
Example WebSocket program:
|
||||||
```C++
|
```C++
|
||||||
#include <beast/to_string.hpp>
|
#include <beast/to_string.hpp>
|
||||||
|
|||||||
@@ -1,21 +1,12 @@
|
|||||||
* Add writer::prepare(msg&) interface to set Content-Type
|
* Add writer::prepare(msg&) interface to set Content-Type
|
||||||
|
|
||||||
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
|
Boost.Http
|
||||||
* Use enum instead of bool in isRequest
|
* Use enum instead of bool in isRequest
|
||||||
* move version to a subclass of message
|
|
||||||
|
|
||||||
Docs:
|
Docs:
|
||||||
* Include Example program listings in the docs
|
* Include Example program listings in the docs
|
||||||
* Fix index in docs
|
* Fix index in docs
|
||||||
* Figure out why namespace rfc2616 is included in docs
|
|
||||||
(currently disabled via GENERATING_DOCS macro)
|
|
||||||
* melpon sandbox?
|
* melpon sandbox?
|
||||||
* Check DOXYGEN, GENERATIC_DOCS directives in source
|
|
||||||
- See if we can include them now that xsl is fixed
|
|
||||||
* Implement cleanup-param to remove spaces around template arguments
|
* Implement cleanup-param to remove spaces around template arguments
|
||||||
e.g. in basic_streambuf move constructor members
|
e.g. in basic_streambuf move constructor members
|
||||||
* Don't put using namespace at file scope in examples,
|
* Don't put using namespace at file scope in examples,
|
||||||
@@ -27,15 +18,12 @@ Core:
|
|||||||
* Complete allocator testing in basic_streambuf
|
* Complete allocator testing in basic_streambuf
|
||||||
|
|
||||||
WebSocket:
|
WebSocket:
|
||||||
|
* more invokable unit test coverage
|
||||||
|
* More control over the HTTP request and response during handshakes
|
||||||
* optimized versions of key/masking, choose prepared_key size
|
* optimized versions of key/masking, choose prepared_key size
|
||||||
* invokable unit test
|
|
||||||
* Don't try to read requests into empty_body
|
|
||||||
* Give callers control over the http request/response used during handshake
|
* Give callers control over the http request/response used during handshake
|
||||||
* Investigate poor autobahn results in Debug builds
|
* Investigate poor autobahn results in Debug builds
|
||||||
* Fall through composed operation switch cases
|
* Fall through composed operation switch cases
|
||||||
* Replace stream::error_ with stream::state_, example states: ok, error, abort_io
|
|
||||||
Need a cancel state so waking up a ping stored in invokable knows to call the
|
|
||||||
final handler with operation_aborted
|
|
||||||
* Use close_code::no_code instead of close_code::none
|
* Use close_code::no_code instead of close_code::none
|
||||||
* Make request_type, response_type public APIs,
|
* Make request_type, response_type public APIs,
|
||||||
use in stream member function signatures
|
use in stream member function signatures
|
||||||
@@ -44,24 +32,25 @@ HTTP:
|
|||||||
* Define Parser concept in HTTP
|
* Define Parser concept in HTTP
|
||||||
- Need parse version of read() so caller can set parser options
|
- Need parse version of read() so caller can set parser options
|
||||||
like maximum size of headers, maximum body size, etc
|
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
|
* add bool should_close(message_v1 const&) to replace the use
|
||||||
of eof return value from write and async_write
|
of eof return value from write and async_write
|
||||||
* http type_check, e.g. is_WritableBody
|
|
||||||
* More fine grained parser errors
|
* More fine grained parser errors
|
||||||
* HTTP parser size limit with test (configurable?)
|
* HTTP parser size limit with test (configurable?)
|
||||||
* HTTP parser trailers with test
|
* HTTP parser trailers with test
|
||||||
* Decode chunk encoding parameters
|
* Decode chunk encoding parameters
|
||||||
* URL parser, strong URL character checking in HTTP parser
|
* URL parser, strong URL character checking in HTTP parser
|
||||||
* Update for rfc7230
|
|
||||||
* Consider rename to MessageBody concept
|
|
||||||
* Fix prepare() calling content_length() without init()
|
* Fix prepare() calling content_length() without init()
|
||||||
* Use construct,destroy allocator routines in basic_headers
|
|
||||||
* Complete allocator testing in basic_streambuf, 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
|
* 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
|
* Branch prediction hints in parser
|
||||||
* Check basic_parser_v1 against rfc7230 for leading message whitespace
|
* Check basic_parser_v1 against rfc7230 for leading message whitespace
|
||||||
|
* Fix the order of message constructor parameters:
|
||||||
|
body first then headers (since body is constructed with arguments more often)
|
||||||
|
* Unit tests for char tables
|
||||||
|
* Remove status_code() from API when isRequest==true, et. al.
|
||||||
|
* Permit sending trailers and parameters in chunk-encoding chunks
|
||||||
|
|
||||||
|
Future:
|
||||||
|
|
||||||
|
* SOCKS proxy client and server implementations
|
||||||
|
|
||||||
|
|||||||
@@ -192,11 +192,11 @@ supporting its development.
|
|||||||
[section:types Type Requirements]
|
[section:types Type Requirements]
|
||||||
[include types/Body.qbk]
|
[include types/Body.qbk]
|
||||||
[include types/BufferSequence.qbk]
|
[include types/BufferSequence.qbk]
|
||||||
|
[include types/DynamicBuffer.qbk]
|
||||||
[include types/Field.qbk]
|
[include types/Field.qbk]
|
||||||
[include types/FieldSequence.qbk]
|
[include types/FieldSequence.qbk]
|
||||||
[include types/Parser.qbk]
|
[include types/Parser.qbk]
|
||||||
[include types/Reader.qbk]
|
[include types/Reader.qbk]
|
||||||
[include types/Streambuf.qbk]
|
|
||||||
[include types/Streams.qbk]
|
[include types/Streams.qbk]
|
||||||
[include types/Writer.qbk]
|
[include types/Writer.qbk]
|
||||||
[endsect]
|
[endsect]
|
||||||
|
|||||||
@@ -25,13 +25,13 @@ libraries:
|
|||||||
* Let library users make the important decisions such as how to
|
* Let library users make the important decisions such as how to
|
||||||
allocate memory or how to leverage flow control.
|
allocate memory or how to leverage flow control.
|
||||||
|
|
||||||
Beast formalizes the [link beast.types.Streambuf [*`Streambuf`]] concept,
|
Beast uses the [link beast.types.DynamicBuffer [*`DynamicBuffer`]] concept
|
||||||
and relies heavily on the Boost.Asio [*`ConstBufferSequence`] and
|
presented in the Netwoking TS, and relies heavily on the Boost.Asio
|
||||||
[*`MutableBufferSequence`] concepts for passing buffers to functions.
|
[*`ConstBufferSequence`] and [*`MutableBufferSequence`] concepts for passing
|
||||||
The authors have found the `Streambuf` and buffer sequence interfaces
|
buffers to functions. The authors have found the dynamic buffer and buffer
|
||||||
to be optimal for interacting with Asio, and for other tasks such as
|
sequence interfaces to be optimal for interacting with Asio, and for other
|
||||||
incremental parsing of data in buffers (for example, parsing websocket
|
tasks such as incremental parsing of data in buffers (for example, parsing
|
||||||
frames stored in a [link beast.ref.static_streambuf `static_streambuf`]).
|
websocket frames stored in a [link beast.ref.static_streambuf `static_streambuf`]).
|
||||||
|
|
||||||
During the development of Beast the authors have studied other software
|
During the development of Beast the authors have studied other software
|
||||||
packages and in particular the comments left during the Boost Review process
|
packages and in particular the comments left during the Boost Review process
|
||||||
|
|||||||
@@ -182,21 +182,9 @@ used in the examples:
|
|||||||
resp.body = "Here is the data you requested";
|
resp.body = "Here is the data you requested";
|
||||||
```
|
```
|
||||||
|
|
||||||
* [link beast.ref.http__basic_streambuf_body [*`basic_streambuf_body`:]] A body with a
|
* [link beast.ref.http__streambuf_body [*`streambuf_body`:]] A body with a
|
||||||
`value_type` of `streambuf`. A streambuf is an efficient storage object which
|
`value_type` of [link beast.ref.streambuf `streambuf`]: an efficient storage
|
||||||
uses multiple octet arrays of varying lengths to represent data. Here is
|
object which uses multiple octet arrays of varying lengths to represent data.
|
||||||
a body that uses a `boost::asio::streambuf` as its container:
|
|
||||||
```
|
|
||||||
template<class ConstBufferSequence>
|
|
||||||
http::response<http::basic_streambuf_body<boost::asio::streambuf>>
|
|
||||||
make_response(ConstBufferSequence const& buffers)
|
|
||||||
{
|
|
||||||
http::response<http::streambuf_body<boost::asio::streambuf>> resp;
|
|
||||||
resp.body.commit(boost::asio::buffer_copy(resp.body.prepare(
|
|
||||||
boost::asio::buffer_size(buffers)), buffers));
|
|
||||||
return resp;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
[heading Sockets]
|
[heading Sockets]
|
||||||
|
|
||||||
@@ -234,7 +222,7 @@ When the implementation reads messages from a socket, it can read bytes lying
|
|||||||
after the end of the message if they are present (the alternative is to read
|
after the end of the message if they are present (the alternative is to read
|
||||||
a single byte at a time which is unsuitable for performance reasons). To
|
a single byte at a time which is unsuitable for performance reasons). To
|
||||||
store and re-use these extra bytes on subsequent messages, the read interface
|
store and re-use these extra bytes on subsequent messages, the read interface
|
||||||
requires an additional paramter: a [link beast.types.Streambuf [*`Streambuf`]]
|
requires an additional paramter: a [link beast.types.DynamicBuffer [*`DynamicBuffer`]]
|
||||||
object. This example reads a message from the socket, with the extra bytes
|
object. This example reads a message from the socket, with the extra bytes
|
||||||
stored in the streambuf parameter for use in a subsequent call to read:
|
stored in the streambuf parameter for use in a subsequent call to read:
|
||||||
```
|
```
|
||||||
@@ -264,7 +252,7 @@ called:
|
|||||||
|
|
||||||
An alternative to using a `boost::asio::streambuf` is to use a
|
An alternative to using a `boost::asio::streambuf` is to use a
|
||||||
[link beast.ref.streambuf `beast::streambuf`], which meets the requirements of
|
[link beast.ref.streambuf `beast::streambuf`], which meets the requirements of
|
||||||
[*`Streambuf`] and is optimized for performance:
|
[*`DynamicBuffer`] and is optimized for performance:
|
||||||
```
|
```
|
||||||
void handle_read(boost::system::error_code);
|
void handle_read(boost::system::error_code);
|
||||||
...
|
...
|
||||||
@@ -274,7 +262,7 @@ An alternative to using a `boost::asio::streambuf` is to use a
|
|||||||
```
|
```
|
||||||
|
|
||||||
The `read` implementation can use any object meeting the requirements of
|
The `read` implementation can use any object meeting the requirements of
|
||||||
[link beast.types.Streambuf [*`Streambuf`]], allowing callers to define custom
|
[link beast.types.DynamicBuffer [*`DynamicBuffer`]], allowing callers to define custom
|
||||||
memory management strategies used by the implementation.
|
memory management strategies used by the implementation.
|
||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
|||||||
@@ -29,9 +29,9 @@
|
|||||||
<entry valign="top">
|
<entry valign="top">
|
||||||
<bridgehead renderas="sect3">Classes</bridgehead>
|
<bridgehead renderas="sect3">Classes</bridgehead>
|
||||||
<simplelist type="vert" columns="1">
|
<simplelist type="vert" columns="1">
|
||||||
|
<member><link linkend="beast.ref.http__basic_dynabuf_body">basic_dynabuf_body</link></member>
|
||||||
<member><link linkend="beast.ref.http__basic_headers">basic_headers</link></member>
|
<member><link linkend="beast.ref.http__basic_headers">basic_headers</link></member>
|
||||||
<member><link linkend="beast.ref.http__basic_parser_v1">basic_parser_v1</link></member>
|
<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__empty_body">empty_body</link></member>
|
||||||
<member><link linkend="beast.ref.http__headers">headers</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__message">message</link></member>
|
||||||
@@ -39,6 +39,11 @@
|
|||||||
<member><link linkend="beast.ref.http__streambuf_body">streambuf_body</link></member>
|
<member><link linkend="beast.ref.http__streambuf_body">streambuf_body</link></member>
|
||||||
<member><link linkend="beast.ref.http__string_body">string_body</link></member>
|
<member><link linkend="beast.ref.http__string_body">string_body</link></member>
|
||||||
</simplelist>
|
</simplelist>
|
||||||
|
<bridgehead renderas="sect3">Options</bridgehead>
|
||||||
|
<simplelist type="vert" columns="1">
|
||||||
|
<member><link linkend="beast.ref.http__body_max_size">body_max_size</link></member>
|
||||||
|
<member><link linkend="beast.ref.http__headers_max_size">headers_max_size</link></member>
|
||||||
|
</simplelist>
|
||||||
<bridgehead renderas="sect3">Type Traits</bridgehead>
|
<bridgehead renderas="sect3">Type Traits</bridgehead>
|
||||||
<simplelist type="vert" columns="1">
|
<simplelist type="vert" columns="1">
|
||||||
<member><link linkend="beast.ref.http__is_Body">is_Body</link></member>
|
<member><link linkend="beast.ref.http__is_Body">is_Body</link></member>
|
||||||
@@ -56,6 +61,7 @@
|
|||||||
<member><link linkend="beast.ref.http__parse">parse</link></member>
|
<member><link linkend="beast.ref.http__parse">parse</link></member>
|
||||||
<member><link linkend="beast.ref.http__prepare">prepare</link></member>
|
<member><link linkend="beast.ref.http__prepare">prepare</link></member>
|
||||||
<member><link linkend="beast.ref.http__read">read</link></member>
|
<member><link linkend="beast.ref.http__read">read</link></member>
|
||||||
|
<member><link linkend="beast.ref.http__swap">swap</link></member>
|
||||||
<member><link linkend="beast.ref.http__write">write</link></member>
|
<member><link linkend="beast.ref.http__write">write</link></member>
|
||||||
</simplelist>
|
</simplelist>
|
||||||
<bridgehead renderas="sect3">Constants</bridgehead>
|
<bridgehead renderas="sect3">Constants</bridgehead>
|
||||||
@@ -129,6 +135,7 @@
|
|||||||
<member><link linkend="beast.ref.basic_streambuf">basic_streambuf</link></member>
|
<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.buffers_adapter">buffers_adapter</link></member>
|
||||||
<member><link linkend="beast.ref.consuming_buffers">consuming_buffers</link></member>
|
<member><link linkend="beast.ref.consuming_buffers">consuming_buffers</link></member>
|
||||||
|
<member><link linkend="beast.ref.dynabuf_readstream">dynabuf_readstream</link></member>
|
||||||
<member><link linkend="beast.ref.error_code">error_code</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.handler_alloc">handler_alloc</link></member>
|
||||||
<member><link linkend="beast.ref.prepared_buffers">prepared_buffers</link></member>
|
<member><link linkend="beast.ref.prepared_buffers">prepared_buffers</link></member>
|
||||||
@@ -136,7 +143,6 @@
|
|||||||
<member><link linkend="beast.ref.static_streambuf_n">static_streambuf_n</link></member>
|
<member><link linkend="beast.ref.static_streambuf_n">static_streambuf_n</link></member>
|
||||||
<member><link linkend="beast.ref.static_string">static_string</link></member>
|
<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">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>
|
<member><link linkend="beast.ref.system_error">system_error</link></member>
|
||||||
</simplelist>
|
</simplelist>
|
||||||
</entry>
|
</entry>
|
||||||
@@ -163,8 +169,8 @@
|
|||||||
<member><link linkend="beast.ref.is_BufferSequence">is_BufferSequence</link></member>
|
<member><link linkend="beast.ref.is_BufferSequence">is_BufferSequence</link></member>
|
||||||
<member><link linkend="beast.ref.is_CompletionHandler">is_CompletionHandler</link></member>
|
<member><link linkend="beast.ref.is_CompletionHandler">is_CompletionHandler</link></member>
|
||||||
<member><link linkend="beast.ref.is_ConstBufferSequence">is_ConstBufferSequence</link></member>
|
<member><link linkend="beast.ref.is_ConstBufferSequence">is_ConstBufferSequence</link></member>
|
||||||
|
<member><link linkend="beast.ref.is_DynamicBuffer">is_DynamicBuffer</link></member>
|
||||||
<member><link linkend="beast.ref.is_MutableBufferSequence">is_MutableBufferSequence</link></member>
|
<member><link linkend="beast.ref.is_MutableBufferSequence">is_MutableBufferSequence</link></member>
|
||||||
<member><link linkend="beast.ref.is_Streambuf">is_Streambuf</link></member>
|
|
||||||
<member><link linkend="beast.ref.is_SyncReadStream">is_SyncReadStream</link></member>
|
<member><link linkend="beast.ref.is_SyncReadStream">is_SyncReadStream</link></member>
|
||||||
<member><link linkend="beast.ref.is_SyncStream">is_SyncStream</link></member>
|
<member><link linkend="beast.ref.is_SyncStream">is_SyncStream</link></member>
|
||||||
<member><link linkend="beast.ref.is_SyncWriteStream">is_SyncWriteStream</link></member>
|
<member><link linkend="beast.ref.is_SyncWriteStream">is_SyncWriteStream</link></member>
|
||||||
@@ -173,10 +179,10 @@
|
|||||||
<entry valign="top">
|
<entry valign="top">
|
||||||
<bridgehead renderas="sect3">Concepts</bridgehead>
|
<bridgehead renderas="sect3">Concepts</bridgehead>
|
||||||
<simplelist type="vert" columns="1">
|
<simplelist type="vert" columns="1">
|
||||||
<member><link linkend="beast.types.BufferSequence">BufferSequence</link></member>
|
|
||||||
<member><link linkend="beast.types.streams.AsyncStream">AsyncStream</link></member>
|
<member><link linkend="beast.types.streams.AsyncStream">AsyncStream</link></member>
|
||||||
|
<member><link linkend="beast.types.BufferSequence">BufferSequence</link></member>
|
||||||
|
<member><link linkend="beast.types.DynamicBuffer">DynamicBuffer</link></member>
|
||||||
<member><link linkend="beast.types.streams.Stream">Stream</link></member>
|
<member><link linkend="beast.types.streams.Stream">Stream</link></member>
|
||||||
<member><link linkend="beast.types.Streambuf">Streambuf</link></member>
|
|
||||||
<member><link linkend="beast.types.streams.SyncStream">SyncStream</link></member>
|
<member><link linkend="beast.types.streams.SyncStream">SyncStream</link></member>
|
||||||
</simplelist>
|
</simplelist>
|
||||||
</entry>
|
</entry>
|
||||||
|
|||||||
@@ -1552,15 +1552,15 @@
|
|||||||
<xsl:when test="declname = 'ConstBufferSequence' or type = 'class ConstBufferSequence'">
|
<xsl:when test="declname = 'ConstBufferSequence' or type = 'class ConstBufferSequence'">
|
||||||
<xsl:text>class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/ConstBufferSequence.html [*ConstBufferSequence]]``</xsl:text>
|
<xsl:text>class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/ConstBufferSequence.html [*ConstBufferSequence]]``</xsl:text>
|
||||||
</xsl:when>
|
</xsl:when>
|
||||||
|
<xsl:when test="declname = 'DynamicBuffer' or type = 'class DynamicBuffer'">
|
||||||
|
<xsl:text>class ``[link beast.types.DynamicBuffer [*DynamicBuffer]]``</xsl:text>
|
||||||
|
</xsl:when>
|
||||||
<xsl:when test="declname = 'MutableBufferSequence' or type = 'class MutableBufferSequence'">
|
<xsl:when test="declname = 'MutableBufferSequence' or type = 'class MutableBufferSequence'">
|
||||||
<xsl:text>class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/MutableBufferSequence.html [*MutableBufferSequence]]``</xsl:text>
|
<xsl:text>class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/MutableBufferSequence.html [*MutableBufferSequence]]``</xsl:text>
|
||||||
</xsl:when>
|
</xsl:when>
|
||||||
<xsl:when test="declname = 'Stream' or type = 'class Stream'">
|
<xsl:when test="declname = 'Stream' or type = 'class Stream'">
|
||||||
<xsl:text>class ``[link beast.types.streams.Stream [*Stream]]``</xsl:text>
|
<xsl:text>class ``[link beast.types.streams.Stream [*Stream]]``</xsl:text>
|
||||||
</xsl:when>
|
</xsl:when>
|
||||||
<xsl:when test="declname = 'Streambuf' or type = 'class Streambuf'">
|
|
||||||
<xsl:text>class ``[link beast.types.Streambuf [*Streambuf]]``</xsl:text>
|
|
||||||
</xsl:when>
|
|
||||||
<xsl:when test="type = 'class SyncStream'">
|
<xsl:when test="type = 'class SyncStream'">
|
||||||
<xsl:text>class ``[link beast.types.streams.SyncStream [*SyncStream]]``</xsl:text>
|
<xsl:text>class ``[link beast.types.streams.SyncStream [*SyncStream]]``</xsl:text>
|
||||||
</xsl:when>
|
</xsl:when>
|
||||||
|
|||||||
125
src/beast/doc/types/DynamicBuffer.qbk
Normal file
125
src/beast/doc/types/DynamicBuffer.qbk
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
[/
|
||||||
|
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)
|
||||||
|
]
|
||||||
|
|
||||||
|
[section:DynamicBuffer DynamicBuffer]
|
||||||
|
|
||||||
|
A dynamic buffer encapsulates memory storage that may be automatically resized
|
||||||
|
as required, where the memory is divided into an input sequence followed by an
|
||||||
|
output sequence. These memory regions are internal to the dynamic buffer, but
|
||||||
|
direct access to the elements is provided to permit them to be efficiently used
|
||||||
|
with I/O operations, such as the send or receive operations of a socket. Data
|
||||||
|
written to the output sequence of a dynamic buffer object is appended to the
|
||||||
|
input sequence of the same object.
|
||||||
|
|
||||||
|
The interface to this concept is intended to permit the following
|
||||||
|
implementation strategies:
|
||||||
|
|
||||||
|
* A single contiguous octet array, which is reallocated as necessary to
|
||||||
|
accommodate changes in the size of the octet sequence.
|
||||||
|
|
||||||
|
* A sequence of one or more octet arrays, where each array is of the same
|
||||||
|
size. Additional octet array objects are appended to the sequence to
|
||||||
|
accommodate changes in the size of the octet sequence.
|
||||||
|
|
||||||
|
* A sequence of one or more octet arrays of varying sizes. Additional octet
|
||||||
|
array objects are appended to the sequence to accommodate changes in the
|
||||||
|
size of the character sequence. This is the implementation approached
|
||||||
|
currently offered by [link beast.ref.basic_streambuf `basic_streambuf`].
|
||||||
|
|
||||||
|
In the table below:
|
||||||
|
|
||||||
|
* `X` denotes a dynamic buffer class.
|
||||||
|
* `a` denotes a value of type `X`.
|
||||||
|
* `c` denotes a (possibly const) value of type `X`.
|
||||||
|
* `n` denotes a value of type `std::size_t`.
|
||||||
|
* `T` denotes a type meeting the requirements for [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/ConstBufferSequence.html `ConstBufferSequence`].
|
||||||
|
* `U` denotes a type meeting the requirements for [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/MutableBufferSequence.html `MutableBufferSequence`].
|
||||||
|
|
||||||
|
[table DynamicBuffer requirements
|
||||||
|
[[operation] [type] [semantics, pre/post-conditions]]
|
||||||
|
[
|
||||||
|
[`X::const_buffers_type`]
|
||||||
|
[`T`]
|
||||||
|
[
|
||||||
|
This type represents the memory associated with the input sequence.
|
||||||
|
]
|
||||||
|
]
|
||||||
|
[
|
||||||
|
[`X::mutable_buffers_type`]
|
||||||
|
[`U`]
|
||||||
|
[
|
||||||
|
This type represents the memory associated with the output sequence.
|
||||||
|
]
|
||||||
|
]
|
||||||
|
[
|
||||||
|
[`c.size()`]
|
||||||
|
[`std::size_t`]
|
||||||
|
[
|
||||||
|
Returns the size, in bytes, of the input sequence.
|
||||||
|
]
|
||||||
|
]
|
||||||
|
[
|
||||||
|
[`c.max_size()`]
|
||||||
|
[`std::size_t`]
|
||||||
|
[
|
||||||
|
Returns the permitted maximum of the sum of the sizes of the input
|
||||||
|
sequence and output sequence.
|
||||||
|
]
|
||||||
|
]
|
||||||
|
[
|
||||||
|
[`c.capacity()`]
|
||||||
|
[`std::size_t`]
|
||||||
|
[
|
||||||
|
Returns the maximum sum of the sizes of the input sequence and output
|
||||||
|
sequence that the dynamic buffer can hold without requiring reallocation.
|
||||||
|
]
|
||||||
|
]
|
||||||
|
[
|
||||||
|
[`c.data()`]
|
||||||
|
[`X::const_buffers_type`]
|
||||||
|
[
|
||||||
|
Returns a constant buffer sequence u that represents the memory
|
||||||
|
associated with the input sequence, and where `buffer_size(u) == size()`.
|
||||||
|
]
|
||||||
|
]
|
||||||
|
[
|
||||||
|
[`a.prepare(n)`]
|
||||||
|
[`X:mutable_buffers_type`]
|
||||||
|
[
|
||||||
|
Returns a mutable buffer sequence u representing the output sequence,
|
||||||
|
and where `buffer_size(u) == n`. The dynamic buffer reallocates memory
|
||||||
|
as required. All constant or mutable buffer sequences previously
|
||||||
|
obtained using `data()` or `prepare()` are invalidated.
|
||||||
|
|
||||||
|
Throws: `length_error` if `size() + n` exceeds `max_size()`.
|
||||||
|
]
|
||||||
|
]
|
||||||
|
[
|
||||||
|
[`a.commit(n)`]
|
||||||
|
[ ]
|
||||||
|
[
|
||||||
|
Appends `n` bytes from the start of the output sequence to the end of
|
||||||
|
the input sequence. The remainder of the output sequence is discarded.
|
||||||
|
If `n` is greater than the size of the output sequence, the entire
|
||||||
|
output sequence is appended to the input sequence. All constant or
|
||||||
|
mutable buffer sequences previously obtained using `data()` or
|
||||||
|
`prepare()` are invalidated.
|
||||||
|
]
|
||||||
|
]
|
||||||
|
[
|
||||||
|
[`a.consume(n)`]
|
||||||
|
[ ]
|
||||||
|
[
|
||||||
|
Removes `n` bytes from beginning of the input sequence. If `n` is
|
||||||
|
greater than the size of the input sequence, the entire input sequence
|
||||||
|
is removed. All constant or mutable buffer sequences previously
|
||||||
|
obtained using `data()` or `prepare()` are invalidated.
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
[endsect]
|
||||||
@@ -1,96 +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)
|
|
||||||
]
|
|
||||||
|
|
||||||
[section:Streambuf Streambuf]
|
|
||||||
|
|
||||||
A [*`Streambuf`] represents a logical octet sequence divided in two sections,
|
|
||||||
the input sequence and the output sequence. Octets are written to the output
|
|
||||||
sequence, then moved to the input sequence where they are available for
|
|
||||||
reading. When some or all of the input sequence is no longer needed, it may
|
|
||||||
be consumed.
|
|
||||||
|
|
||||||
The interface to this concept is intended to permit the following
|
|
||||||
implementation strategies:
|
|
||||||
|
|
||||||
* A single contiguous octet array, which is reallocated as necessary to
|
|
||||||
accommodate changes in the size of the octet sequence.
|
|
||||||
|
|
||||||
* A sequence of one or more octet arrays, where each array is of the same
|
|
||||||
size. Additional octet array objects are appended to the sequence to
|
|
||||||
accommodate changes in the size of the octet sequence.
|
|
||||||
|
|
||||||
* A sequence of one or more octet arrays of varying sizes. Additional octet
|
|
||||||
array objects are appended to the sequence to accommodate changes in the
|
|
||||||
size of the character sequence. This is the implementation approached
|
|
||||||
currently offered by [link beast.ref.basic_streambuf `basic_streambuf`].
|
|
||||||
|
|
||||||
In the table below:
|
|
||||||
|
|
||||||
* `X` denotes a class meeting the requirements of [*`Streambuf`]
|
|
||||||
* `a` denotes a value of type `X`
|
|
||||||
* `n` denotes a value convertible to `std::size_t`
|
|
||||||
* `U`, `T` denote unspecified types.
|
|
||||||
|
|
||||||
[table Streambuf requirements
|
|
||||||
[[operation] [type] [semantics, pre/post-conditions]]
|
|
||||||
[
|
|
||||||
[`X::const_buffers_type`]
|
|
||||||
[`T`]
|
|
||||||
[`T` meets the requirements for [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/ConstBufferSequence.html `ConstBufferSequence`].]
|
|
||||||
]
|
|
||||||
[
|
|
||||||
[`X::mutable_buffers_type`]
|
|
||||||
[`U`]
|
|
||||||
[`U` meets the requirements for [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/MutableBufferSequence.html `MutableBufferSequence`].]
|
|
||||||
]
|
|
||||||
[
|
|
||||||
[`a.commit(n)`]
|
|
||||||
[`void`]
|
|
||||||
[Moves bytes from the output sequence to the input sequence.]
|
|
||||||
]
|
|
||||||
[
|
|
||||||
[`a.consume(n)`]
|
|
||||||
[`void`]
|
|
||||||
[Removes bytes from the input sequence.]
|
|
||||||
]
|
|
||||||
[
|
|
||||||
[`a.data()`]
|
|
||||||
[`T`]
|
|
||||||
[Returns a list of buffers that represents the input sequence.]
|
|
||||||
]
|
|
||||||
[
|
|
||||||
[`a.prepare(n)`]
|
|
||||||
[`U`]
|
|
||||||
[Returns a list of buffers that represents the output sequence, with
|
|
||||||
the given size.]
|
|
||||||
]
|
|
||||||
[
|
|
||||||
[`a.size()`]
|
|
||||||
[`std::size_t`]
|
|
||||||
[Returns the size of the input sequence.]
|
|
||||||
]
|
|
||||||
[
|
|
||||||
[`a.max_size()`]
|
|
||||||
[`std::size_t`]
|
|
||||||
[Returns the maximum size of the stream buffer.]
|
|
||||||
]
|
|
||||||
[
|
|
||||||
[`read_size_helper(a, n)`]
|
|
||||||
[`std::size_t`]
|
|
||||||
[
|
|
||||||
Returns the suggested number of bytes to read into the output
|
|
||||||
sequence where `n` is an upper limit on this value. One possible
|
|
||||||
implementation is to return the number of bytes that may be prepared
|
|
||||||
without causing a dynamic allocation or `n`, whichever is smaller.
|
|
||||||
Calls to `read_size_helper` will be made without namespace
|
|
||||||
qualification, to allow the rules for argument dependent lookup to
|
|
||||||
take effect.
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
[endsect]
|
|
||||||
@@ -358,7 +358,7 @@ handler of the corresponding read function.]
|
|||||||
|
|
||||||
Because calls to read data may return a variable amount of bytes, the
|
Because calls to read data may return a variable amount of bytes, the
|
||||||
interface to calls that read data require an object that meets the requirements
|
interface to calls that read data require an object that meets the requirements
|
||||||
of [link beast.types.Streambuf [*`Streambuf`]]. This concept is modeled on
|
of [link beast.types.DynamicBuffer [*`DynamicBuffer`]]. This concept is modeled on
|
||||||
[@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/basic_streambuf.html `boost::asio::basic_streambuf`].
|
[@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/basic_streambuf.html `boost::asio::basic_streambuf`].
|
||||||
|
|
||||||
The implementation does not perform queueing or buffering of messages. If
|
The implementation does not perform queueing or buffering of messages. If
|
||||||
|
|||||||
@@ -321,12 +321,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
template<bool isRequest, class Body, class Headers,
|
template<bool isRequest, class Body, class Headers,
|
||||||
class ReadHandler>
|
class ReadHandler>
|
||||||
#if GENERATING_DOCS
|
#if GENERATING_DOCS
|
||||||
void_or_deduced
|
void_or_deduced
|
||||||
#else
|
#else
|
||||||
typename async_completion<
|
typename async_completion<
|
||||||
ReadHandler, void(error_code)>::result_type
|
ReadHandler, void(error_code)>::result_type
|
||||||
#endif
|
#endif
|
||||||
async_read(message_v1<isRequest, Body, Headers>& msg,
|
async_read(message_v1<isRequest, Body, Headers>& msg,
|
||||||
ReadHandler&& handler);
|
ReadHandler&& handler);
|
||||||
|
|
||||||
@@ -416,12 +416,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
template<bool isRequest, class Body, class Headers,
|
template<bool isRequest, class Body, class Headers,
|
||||||
class WriteHandler>
|
class WriteHandler>
|
||||||
#if GENERATING_DOCS
|
#if GENERATING_DOCS
|
||||||
void_or_deduced
|
void_or_deduced
|
||||||
#else
|
#else
|
||||||
typename async_completion<
|
typename async_completion<
|
||||||
WriteHandler, void(error_code)>::result_type
|
WriteHandler, void(error_code)>::result_type
|
||||||
#endif
|
#endif
|
||||||
async_write(message_v1<isRequest, Body, Headers> const& msg,
|
async_write(message_v1<isRequest, Body, Headers> const& msg,
|
||||||
WriteHandler&& handler);
|
WriteHandler&& handler);
|
||||||
|
|
||||||
|
|||||||
@@ -13,10 +13,78 @@
|
|||||||
namespace beast {
|
namespace beast {
|
||||||
namespace test {
|
namespace test {
|
||||||
|
|
||||||
|
enum error
|
||||||
|
{
|
||||||
|
fail_error = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
class fail_error_category : public boost::system::error_category
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const char*
|
||||||
|
name() const noexcept override
|
||||||
|
{
|
||||||
|
return "test";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
message(int ev) const override
|
||||||
|
{
|
||||||
|
switch(static_cast<error>(ev))
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case error::fail_error:
|
||||||
|
return "test error";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::system::error_condition
|
||||||
|
default_error_condition(int ev) const noexcept override
|
||||||
|
{
|
||||||
|
return boost::system::error_condition{ev, *this};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
equivalent(int ev,
|
||||||
|
boost::system::error_condition const& condition
|
||||||
|
) const noexcept override
|
||||||
|
{
|
||||||
|
return condition.value() == ev &&
|
||||||
|
&condition.category() == this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
equivalent(error_code const& error, int ev) const noexcept override
|
||||||
|
{
|
||||||
|
return error.value() == ev &&
|
||||||
|
&error.category() == this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline
|
||||||
|
boost::system::error_category const&
|
||||||
|
get_error_category()
|
||||||
|
{
|
||||||
|
static fail_error_category const cat{};
|
||||||
|
return cat;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
|
||||||
|
inline
|
||||||
|
error_code
|
||||||
|
make_error_code(error ev)
|
||||||
|
{
|
||||||
|
return error_code{static_cast<int>(ev),
|
||||||
|
detail::get_error_category()};
|
||||||
|
}
|
||||||
|
|
||||||
/** A countdown to simulated failure.
|
/** A countdown to simulated failure.
|
||||||
|
|
||||||
On the Nth operation, the class will fail with the specified
|
On the Nth operation, the class will fail with the specified
|
||||||
error code, or the default error code of invalid_argument.
|
error code, or the default error code of @ref fail_error.
|
||||||
*/
|
*/
|
||||||
class fail_counter
|
class fail_counter
|
||||||
{
|
{
|
||||||
@@ -31,10 +99,10 @@ public:
|
|||||||
@param The 0-based index of the operation to fail on or after.
|
@param The 0-based index of the operation to fail on or after.
|
||||||
*/
|
*/
|
||||||
explicit
|
explicit
|
||||||
fail_counter(std::size_t n = 0)
|
fail_counter(std::size_t n,
|
||||||
|
error_code ev = make_error_code(fail_error))
|
||||||
: n_(n)
|
: n_(n)
|
||||||
, ec_(boost::system::errc::make_error_code(
|
, ec_(ev)
|
||||||
boost::system::errc::errc_t::invalid_argument))
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,4 +134,14 @@ public:
|
|||||||
} // test
|
} // test
|
||||||
} // beast
|
} // beast
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace system {
|
||||||
|
template<>
|
||||||
|
struct is_error_code_enum<beast::test::error>
|
||||||
|
{
|
||||||
|
static bool const value = true;
|
||||||
|
};
|
||||||
|
} // system
|
||||||
|
} // boost
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include <beast/core/detail/get_lowest_layer.hpp>
|
#include <beast/core/detail/get_lowest_layer.hpp>
|
||||||
#include <beast/websocket/teardown.hpp>
|
#include <beast/websocket/teardown.hpp>
|
||||||
#include <beast/test/fail_counter.hpp>
|
#include <beast/test/fail_counter.hpp>
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace test {
|
namespace test {
|
||||||
@@ -26,8 +27,8 @@ namespace test {
|
|||||||
template<class NextLayer>
|
template<class NextLayer>
|
||||||
class fail_stream
|
class fail_stream
|
||||||
{
|
{
|
||||||
|
boost::optional<fail_counter> fc_;
|
||||||
fail_counter* pfc_;
|
fail_counter* pfc_;
|
||||||
fail_counter fc_;
|
|
||||||
NextLayer next_layer_;
|
NextLayer next_layer_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -46,8 +47,8 @@ public:
|
|||||||
template<class... Args>
|
template<class... Args>
|
||||||
explicit
|
explicit
|
||||||
fail_stream(std::size_t n, Args&&... args)
|
fail_stream(std::size_t n, Args&&... args)
|
||||||
: pfc_(&fc_)
|
: fc_(n)
|
||||||
, fc_(n)
|
, pfc_(&*fc_)
|
||||||
, next_layer_(std::forward<Args>(args)...)
|
, next_layer_(std::forward<Args>(args)...)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,8 +24,8 @@
|
|||||||
#include <beast/core/static_string.hpp>
|
#include <beast/core/static_string.hpp>
|
||||||
#include <beast/core/stream_concepts.hpp>
|
#include <beast/core/stream_concepts.hpp>
|
||||||
#include <beast/core/streambuf.hpp>
|
#include <beast/core/streambuf.hpp>
|
||||||
#include <beast/core/streambuf_readstream.hpp>
|
#include <beast/core/dynabuf_readstream.hpp>
|
||||||
#include <beast/core/to_string.hpp>
|
#include <beast/core/to_string.hpp>
|
||||||
#include <beast/core/write_streambuf.hpp>
|
#include <beast/core/write_dynabuf.hpp>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -18,14 +18,14 @@
|
|||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
/** A @b `Streambuf` that uses multiple buffers internally.
|
/** A @b `DynamicBuffer` that uses multiple buffers internally.
|
||||||
|
|
||||||
The implementation uses a sequence of one or more character arrays
|
The implementation uses a sequence of one or more character arrays
|
||||||
of varying sizes. Additional character array objects are appended to
|
of varying sizes. Additional character array objects are appended to
|
||||||
the sequence to accommodate changes in the size of the character
|
the sequence to accommodate changes in the size of the character
|
||||||
sequence.
|
sequence.
|
||||||
|
|
||||||
@note Meets the requirements of @b Streambuf.
|
@note Meets the requirements of @b `DynamicBuffer`.
|
||||||
|
|
||||||
@tparam Allocator The allocator to use for managing memory.
|
@tparam Allocator The allocator to use for managing memory.
|
||||||
*/
|
*/
|
||||||
@@ -202,26 +202,37 @@ public:
|
|||||||
basic_streambuf(std::size_t alloc_size = 1024,
|
basic_streambuf(std::size_t alloc_size = 1024,
|
||||||
Allocator const& alloc = allocator_type{});
|
Allocator const& alloc = allocator_type{});
|
||||||
|
|
||||||
/// Get the associated allocator
|
/// Returns a copy of the associated allocator.
|
||||||
allocator_type
|
allocator_type
|
||||||
get_allocator() const
|
get_allocator() const
|
||||||
{
|
{
|
||||||
return this->member();
|
return this->member();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the maximum size of the basic_streambuf.
|
/// Returns the size of the input sequence.
|
||||||
|
size_type
|
||||||
|
size() const
|
||||||
|
{
|
||||||
|
return in_size_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the permitted maximum sum of the sizes of the input and output sequence.
|
||||||
size_type
|
size_type
|
||||||
max_size() const
|
max_size() const
|
||||||
{
|
{
|
||||||
return std::numeric_limits<std::size_t>::max();
|
return std::numeric_limits<std::size_t>::max();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the size of the input sequence.
|
/// Returns the maximum sum of the sizes of the input sequence and output sequence the buffer can hold without requiring reallocation.
|
||||||
size_type
|
std::size_t
|
||||||
size() const
|
capacity() const;
|
||||||
{
|
|
||||||
return in_size_;
|
/** Get a list of buffers that represents the input sequence.
|
||||||
}
|
|
||||||
|
@note These buffers remain valid across subsequent calls to `prepare`.
|
||||||
|
*/
|
||||||
|
const_buffers_type
|
||||||
|
data() const;
|
||||||
|
|
||||||
/** Get a list of buffers that represents the output sequence, with the given size.
|
/** Get a list of buffers that represents the output sequence, with the given size.
|
||||||
|
|
||||||
@@ -239,22 +250,11 @@ public:
|
|||||||
void
|
void
|
||||||
commit(size_type n);
|
commit(size_type n);
|
||||||
|
|
||||||
/** Get a list of buffers that represents the input sequence.
|
|
||||||
|
|
||||||
@note These buffers remain valid across subsequent calls to `prepare`.
|
|
||||||
*/
|
|
||||||
const_buffers_type
|
|
||||||
data() const;
|
|
||||||
|
|
||||||
/// Remove bytes from the input sequence.
|
/// Remove bytes from the input sequence.
|
||||||
void
|
void
|
||||||
consume(size_type n);
|
consume(size_type n);
|
||||||
|
|
||||||
/// Clear everything.
|
// Helper for boost::asio::read_until
|
||||||
void
|
|
||||||
clear();
|
|
||||||
|
|
||||||
// Helper for read_until
|
|
||||||
template<class OtherAllocator>
|
template<class OtherAllocator>
|
||||||
friend
|
friend
|
||||||
std::size_t
|
std::size_t
|
||||||
@@ -262,6 +262,9 @@ public:
|
|||||||
OtherAllocator> const& streambuf, std::size_t max_size);
|
OtherAllocator> const& streambuf, std::size_t max_size);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void
|
||||||
|
clear();
|
||||||
|
|
||||||
void
|
void
|
||||||
move_assign(basic_streambuf& other, std::false_type);
|
move_assign(basic_streambuf& other, std::false_type);
|
||||||
|
|
||||||
@@ -277,20 +280,17 @@ private:
|
|||||||
void
|
void
|
||||||
delete_list();
|
delete_list();
|
||||||
|
|
||||||
std::size_t
|
|
||||||
prepare_size() const;
|
|
||||||
|
|
||||||
void
|
void
|
||||||
debug_check() const;
|
debug_check() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Format output to a stream buffer.
|
/** Format output to a @ref basic_streambuf.
|
||||||
|
|
||||||
@param streambuf The streambuf to write to.
|
@param streambuf The @ref basic_streambuf to write to.
|
||||||
|
|
||||||
@param t The object to write.
|
@param t The object to write.
|
||||||
|
|
||||||
@return The stream buffer.
|
@return A reference to the @ref basic_streambuf.
|
||||||
*/
|
*/
|
||||||
template<class Allocator, class T>
|
template<class Allocator, class T>
|
||||||
basic_streambuf<Allocator>&
|
basic_streambuf<Allocator>&
|
||||||
|
|||||||
@@ -35,6 +35,16 @@ struct is_ConstBufferSequence :
|
|||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Determine if `T` meets the requirements of @b `DynamicBuffer`.
|
||||||
|
template<class T>
|
||||||
|
#if GENERATING_DOCS
|
||||||
|
struct is_DynamicBuffer : std::integral_constant<bool, ...>
|
||||||
|
#else
|
||||||
|
struct is_DynamicBuffer : detail::is_DynamicBuffer<T>::type
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
/// Determine if `T` meets the requirements of @b `MutableBufferSequence`.
|
/// Determine if `T` meets the requirements of @b `MutableBufferSequence`.
|
||||||
template<class T>
|
template<class T>
|
||||||
#if GENERATING_DOCS
|
#if GENERATING_DOCS
|
||||||
@@ -46,16 +56,6 @@ struct is_MutableBufferSequence :
|
|||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Determine if `T` meets the requirements of @b `Streambuf`.
|
|
||||||
template<class T>
|
|
||||||
#if GENERATING_DOCS
|
|
||||||
struct is_Streambuf : std::integral_constant<bool, ...>
|
|
||||||
#else
|
|
||||||
struct is_Streambuf : detail::is_Streambuf<T>::type
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
} // beast
|
} // beast
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
class is_Streambuf
|
class is_DynamicBuffer
|
||||||
{
|
{
|
||||||
template<class U, class R = std::integral_constant<
|
template<class U, class R = std::integral_constant<
|
||||||
bool, is_BufferSequence<decltype(
|
bool, is_BufferSequence<decltype(
|
||||||
|
|||||||
@@ -8,76 +8,96 @@
|
|||||||
#ifndef BEAST_DETAIL_CI_CHAR_TRAITS_HPP
|
#ifndef BEAST_DETAIL_CI_CHAR_TRAITS_HPP
|
||||||
#define BEAST_DETAIL_CI_CHAR_TRAITS_HPP
|
#define BEAST_DETAIL_CI_CHAR_TRAITS_HPP
|
||||||
|
|
||||||
|
#include <boost/range/algorithm/equal.hpp>
|
||||||
#include <boost/utility/string_ref.hpp>
|
#include <boost/utility/string_ref.hpp>
|
||||||
#include <algorithm>
|
#include <array>
|
||||||
#include <type_traits>
|
#include <cstdint>
|
||||||
#include <cctype>
|
|
||||||
#include <iterator>
|
|
||||||
#include <string>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
/** Case-insensitive function object for performing less than comparisons. */
|
inline
|
||||||
|
char
|
||||||
|
tolower(char c)
|
||||||
|
{
|
||||||
|
static std::array<std::uint8_t, 256> constexpr tab = {{
|
||||||
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||||
|
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
||||||
|
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
|
||||||
|
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
|
||||||
|
64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
|
||||||
|
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95,
|
||||||
|
96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
|
||||||
|
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
|
||||||
|
128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
|
||||||
|
144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
|
||||||
|
160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
|
||||||
|
176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
|
||||||
|
192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
|
||||||
|
208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
|
||||||
|
224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
|
||||||
|
240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
|
||||||
|
}};
|
||||||
|
return static_cast<char>(tab[static_cast<std::uint8_t>(c)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N>
|
||||||
|
inline
|
||||||
|
boost::string_ref
|
||||||
|
string_helper(const char (&s)[N])
|
||||||
|
{
|
||||||
|
return boost::string_ref{s, N-1};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
inline
|
||||||
|
T const&
|
||||||
|
string_helper(T const& t)
|
||||||
|
{
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Case-insensitive less
|
||||||
struct ci_less
|
struct ci_less
|
||||||
{
|
{
|
||||||
static bool const is_transparent = true;
|
static bool const is_transparent = true;
|
||||||
|
|
||||||
|
template<class S1, class S2>
|
||||||
bool
|
bool
|
||||||
operator()(boost::string_ref const& lhs,
|
operator()(S1 const& lhs, S2 const& rhs) const noexcept
|
||||||
boost::string_ref const& rhs) const noexcept
|
|
||||||
{
|
{
|
||||||
using std::begin;
|
using std::begin;
|
||||||
using std::end;
|
using std::end;
|
||||||
|
auto const s1 = string_helper(lhs);
|
||||||
|
auto const s2 = string_helper(rhs);
|
||||||
return std::lexicographical_compare(
|
return std::lexicographical_compare(
|
||||||
begin(lhs), end(lhs), begin(rhs), end(rhs),
|
begin(s1), end(s1), begin(s2), end(s2),
|
||||||
[](char lhs, char rhs)
|
[](char lhs, char rhs)
|
||||||
{
|
{
|
||||||
return std::tolower(lhs) < std::tolower(rhs);
|
return tolower(lhs) < tolower(rhs);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline
|
// Case-insensitive equal
|
||||||
bool
|
struct ci_equal_pred
|
||||||
ci_equal(std::pair<const char*, std::size_t> lhs,
|
|
||||||
std::pair<const char*, std::size_t> rhs)
|
|
||||||
{
|
{
|
||||||
if(lhs.second != rhs.second)
|
bool
|
||||||
return false;
|
operator()(char c1, char c2) const noexcept
|
||||||
return std::equal (lhs.first, lhs.first + lhs.second,
|
|
||||||
rhs.first,
|
|
||||||
[] (char lhs, char rhs)
|
|
||||||
{
|
{
|
||||||
return std::tolower(lhs) == std::tolower(rhs);
|
return tolower(c1) == tolower(c2);
|
||||||
}
|
}
|
||||||
);
|
};
|
||||||
}
|
|
||||||
|
|
||||||
template <size_t N>
|
// Case-insensitive equal
|
||||||
inline
|
template<class S1, class S2>
|
||||||
std::pair<const char*, std::size_t>
|
|
||||||
view(const char (&s)[N])
|
|
||||||
{
|
|
||||||
return {s, N-1};
|
|
||||||
}
|
|
||||||
|
|
||||||
inline
|
|
||||||
std::pair<const char*, std::size_t>
|
|
||||||
view(std::string const& s)
|
|
||||||
{
|
|
||||||
return {s.data(), s.size()};
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns `true` if strings are case-insensitive equal. */
|
|
||||||
template <class String1, class String2>
|
|
||||||
inline
|
|
||||||
bool
|
bool
|
||||||
ci_equal(String1 const& lhs, String2 const& rhs)
|
ci_equal(S1 const& lhs, S2 const& rhs)
|
||||||
{
|
{
|
||||||
return ci_equal(view(lhs), view(rhs));
|
return boost::range::equal(
|
||||||
|
string_helper(lhs), string_helper(rhs),
|
||||||
|
ci_equal_pred{});
|
||||||
}
|
}
|
||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef BEAST_DETAIL_WRITE_STREAMBUF_HPP
|
#ifndef BEAST_DETAIL_WRITE_DYNABUF_HPP
|
||||||
#define BEAST_DETAIL_WRITE_STREAMBUF_HPP
|
#define BEAST_DETAIL_WRITE_DYNABUF_HPP
|
||||||
|
|
||||||
#include <beast/core/buffer_concepts.hpp>
|
#include <beast/core/buffer_concepts.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
@@ -42,73 +42,73 @@ public:
|
|||||||
! is_string_literal<T>::value;
|
! is_string_literal<T>::value;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Streambuf>
|
template<class DynamicBuffer>
|
||||||
void
|
void
|
||||||
write_streambuf(Streambuf& streambuf,
|
write_dynabuf(DynamicBuffer& dynabuf,
|
||||||
boost::asio::const_buffer const& buffer)
|
boost::asio::const_buffer const& buffer)
|
||||||
{
|
{
|
||||||
using boost::asio::buffer_copy;
|
using boost::asio::buffer_copy;
|
||||||
using boost::asio::buffer_size;
|
using boost::asio::buffer_size;
|
||||||
streambuf.commit(buffer_copy(
|
dynabuf.commit(buffer_copy(
|
||||||
streambuf.prepare(buffer_size(buffer)),
|
dynabuf.prepare(buffer_size(buffer)),
|
||||||
buffer));
|
buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Streambuf>
|
template<class DynamicBuffer>
|
||||||
void
|
void
|
||||||
write_streambuf(Streambuf& streambuf,
|
write_dynabuf(DynamicBuffer& dynabuf,
|
||||||
boost::asio::mutable_buffer const& buffer)
|
boost::asio::mutable_buffer const& buffer)
|
||||||
{
|
{
|
||||||
using boost::asio::buffer_copy;
|
using boost::asio::buffer_copy;
|
||||||
using boost::asio::buffer_size;
|
using boost::asio::buffer_size;
|
||||||
streambuf.commit(buffer_copy(
|
dynabuf.commit(buffer_copy(
|
||||||
streambuf.prepare(buffer_size(buffer)),
|
dynabuf.prepare(buffer_size(buffer)),
|
||||||
buffer));
|
buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Streambuf, class T>
|
template<class DynamicBuffer, class T>
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
is_BufferConvertible<T>::value &&
|
is_BufferConvertible<T>::value &&
|
||||||
! std::is_convertible<T, boost::asio::const_buffer>::value &&
|
! std::is_convertible<T, boost::asio::const_buffer>::value &&
|
||||||
! std::is_convertible<T, boost::asio::mutable_buffer>::value
|
! std::is_convertible<T, boost::asio::mutable_buffer>::value
|
||||||
>::type
|
>::type
|
||||||
write_streambuf(Streambuf& streambuf, T const& t)
|
write_dynabuf(DynamicBuffer& dynabuf, T const& t)
|
||||||
{
|
{
|
||||||
using boost::asio::buffer_copy;
|
using boost::asio::buffer_copy;
|
||||||
using boost::asio::buffer_size;
|
using boost::asio::buffer_size;
|
||||||
auto const buffers = boost::asio::buffer(t);
|
auto const buffers = boost::asio::buffer(t);
|
||||||
streambuf.commit(buffer_copy(
|
dynabuf.commit(buffer_copy(
|
||||||
streambuf.prepare(buffer_size(buffers)),
|
dynabuf.prepare(buffer_size(buffers)),
|
||||||
buffers));
|
buffers));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Streambuf, class Buffers>
|
template<class DynamicBuffer, class Buffers>
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
is_ConstBufferSequence<Buffers>::value &&
|
is_ConstBufferSequence<Buffers>::value &&
|
||||||
! is_BufferConvertible<Buffers>::value &&
|
! is_BufferConvertible<Buffers>::value &&
|
||||||
! std::is_convertible<Buffers, boost::asio::const_buffer>::value &&
|
! std::is_convertible<Buffers, boost::asio::const_buffer>::value &&
|
||||||
! std::is_convertible<Buffers, boost::asio::mutable_buffer>::value
|
! std::is_convertible<Buffers, boost::asio::mutable_buffer>::value
|
||||||
>::type
|
>::type
|
||||||
write_streambuf(Streambuf& streambuf, Buffers const& buffers)
|
write_dynabuf(DynamicBuffer& dynabuf, Buffers const& buffers)
|
||||||
{
|
{
|
||||||
using boost::asio::buffer_copy;
|
using boost::asio::buffer_copy;
|
||||||
using boost::asio::buffer_size;
|
using boost::asio::buffer_size;
|
||||||
streambuf.commit(buffer_copy(
|
dynabuf.commit(buffer_copy(
|
||||||
streambuf.prepare(buffer_size(buffers)),
|
dynabuf.prepare(buffer_size(buffers)),
|
||||||
buffers));
|
buffers));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Streambuf, std::size_t N>
|
template<class DynamicBuffer, std::size_t N>
|
||||||
void
|
void
|
||||||
write_streambuf(Streambuf& streambuf, const char (&s)[N])
|
write_dynabuf(DynamicBuffer& dynabuf, const char (&s)[N])
|
||||||
{
|
{
|
||||||
using boost::asio::buffer_copy;
|
using boost::asio::buffer_copy;
|
||||||
streambuf.commit(buffer_copy(
|
dynabuf.commit(buffer_copy(
|
||||||
streambuf.prepare(N - 1),
|
dynabuf.prepare(N - 1),
|
||||||
boost::asio::buffer(s, N - 1)));
|
boost::asio::buffer(s, N - 1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Streambuf, class T>
|
template<class DynamicBuffer, class T>
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
! is_string_literal<T>::value &&
|
! is_string_literal<T>::value &&
|
||||||
! is_ConstBufferSequence<T>::value &&
|
! is_ConstBufferSequence<T>::value &&
|
||||||
@@ -116,22 +116,22 @@ typename std::enable_if<
|
|||||||
! std::is_convertible<T, boost::asio::const_buffer>::value &&
|
! std::is_convertible<T, boost::asio::const_buffer>::value &&
|
||||||
! std::is_convertible<T, boost::asio::mutable_buffer>::value
|
! std::is_convertible<T, boost::asio::mutable_buffer>::value
|
||||||
>::type
|
>::type
|
||||||
write_streambuf(Streambuf& streambuf, T const& t)
|
write_dynabuf(DynamicBuffer& dynabuf, T const& t)
|
||||||
{
|
{
|
||||||
using boost::asio::buffer;
|
using boost::asio::buffer;
|
||||||
using boost::asio::buffer_copy;
|
using boost::asio::buffer_copy;
|
||||||
auto const s = boost::lexical_cast<std::string>(t);
|
auto const s = boost::lexical_cast<std::string>(t);
|
||||||
streambuf.commit(buffer_copy(
|
dynabuf.commit(buffer_copy(
|
||||||
streambuf.prepare(s.size()), buffer(s)));
|
dynabuf.prepare(s.size()), buffer(s)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Streambuf, class T0, class T1, class... TN>
|
template<class DynamicBuffer, class T0, class T1, class... TN>
|
||||||
void
|
void
|
||||||
write_streambuf(Streambuf& streambuf,
|
write_dynabuf(DynamicBuffer& dynabuf,
|
||||||
T0 const& t0, T1 const& t1, TN const&... tn)
|
T0 const& t0, T1 const& t1, TN const&... tn)
|
||||||
{
|
{
|
||||||
write_streambuf(streambuf, t0);
|
write_dynabuf(dynabuf, t0);
|
||||||
write_streambuf(streambuf, t1, tn...);
|
write_dynabuf(dynabuf, t1, tn...);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
@@ -5,8 +5,8 @@
|
|||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef BEAST_STREAMBUF_READSTREAM_HPP
|
#ifndef BEAST_DYNABUF_READSTREAM_HPP
|
||||||
#define BEAST_STREAMBUF_READSTREAM_HPP
|
#define BEAST_DYNABUF_READSTREAM_HPP
|
||||||
|
|
||||||
#include <beast/core/async_completion.hpp>
|
#include <beast/core/async_completion.hpp>
|
||||||
#include <beast/core/buffer_concepts.hpp>
|
#include <beast/core/buffer_concepts.hpp>
|
||||||
@@ -22,11 +22,11 @@
|
|||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
/** A @b `Stream` with attached @b `Streambuf` to buffer reads.
|
/** A @b `Stream` with attached @b `DynamicBuffer` to buffer reads.
|
||||||
|
|
||||||
This wraps a @b `Stream` implementation so that calls to write are
|
This wraps a @b `Stream` implementation so that calls to write are
|
||||||
passed through to the underlying stream, while calls to read will
|
passed through to the underlying stream, while calls to read will
|
||||||
first consume the input sequence stored in a @b `Streambuf` which
|
first consume the input sequence stored in a @b `DynamicBuffer` which
|
||||||
is part of the object.
|
is part of the object.
|
||||||
|
|
||||||
The use-case for this class is different than that of the
|
The use-case for this class is different than that of the
|
||||||
@@ -50,9 +50,9 @@ namespace beast {
|
|||||||
// Process the next HTTP headers on the stream,
|
// Process the next HTTP headers on the stream,
|
||||||
// leaving excess bytes behind for the next call.
|
// leaving excess bytes behind for the next call.
|
||||||
//
|
//
|
||||||
template<class Streambuf>
|
template<class DynamicBuffer>
|
||||||
void process_http_message(
|
void process_http_message(
|
||||||
streambuf_readstream<Streambuf>& stream)
|
dynabuf_readstream<DynamicBuffer>& stream)
|
||||||
{
|
{
|
||||||
// Read up to and including the end of the HTTP
|
// Read up to and including the end of the HTTP
|
||||||
// headers, leaving the sequence in the stream's
|
// headers, leaving the sequence in the stream's
|
||||||
@@ -85,26 +85,24 @@ namespace beast {
|
|||||||
|
|
||||||
@tparam Stream The type of stream to wrap.
|
@tparam Stream The type of stream to wrap.
|
||||||
|
|
||||||
@tparam Streambuf The type of stream buffer to use.
|
@tparam DynamicBuffer The type of stream buffer to use.
|
||||||
*/
|
*/
|
||||||
template<class Stream, class Streambuf>
|
template<class Stream, class DynamicBuffer>
|
||||||
class streambuf_readstream
|
class dynabuf_readstream
|
||||||
{
|
{
|
||||||
static_assert(is_Streambuf<Streambuf>::value,
|
static_assert(is_DynamicBuffer<DynamicBuffer>::value,
|
||||||
"Streambuf requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
|
|
||||||
using error_code = boost::system::error_code;
|
|
||||||
|
|
||||||
template<class Buffers, class Handler>
|
template<class Buffers, class Handler>
|
||||||
class read_some_op;
|
class read_some_op;
|
||||||
|
|
||||||
Streambuf sb_;
|
DynamicBuffer sb_;
|
||||||
std::size_t capacity_ = 0;
|
std::size_t capacity_ = 0;
|
||||||
Stream next_layer_;
|
Stream next_layer_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// The type of the internal buffer
|
/// The type of the internal buffer
|
||||||
using streambuf_type = Streambuf;
|
using dynabuf_type = DynamicBuffer;
|
||||||
|
|
||||||
/// The type of the next layer.
|
/// The type of the next layer.
|
||||||
using next_layer_type =
|
using next_layer_type =
|
||||||
@@ -124,14 +122,14 @@ public:
|
|||||||
@note The behavior of move assignment on or from streams
|
@note The behavior of move assignment on or from streams
|
||||||
with active or pending operations is undefined.
|
with active or pending operations is undefined.
|
||||||
*/
|
*/
|
||||||
streambuf_readstream(streambuf_readstream&&) = default;
|
dynabuf_readstream(dynabuf_readstream&&) = default;
|
||||||
|
|
||||||
/** Move assignment.
|
/** Move assignment.
|
||||||
|
|
||||||
@note The behavior of move assignment on or from streams
|
@note The behavior of move assignment on or from streams
|
||||||
with active or pending operations is undefined.
|
with active or pending operations is undefined.
|
||||||
*/
|
*/
|
||||||
streambuf_readstream& operator=(streambuf_readstream&&) = default;
|
dynabuf_readstream& operator=(dynabuf_readstream&&) = default;
|
||||||
|
|
||||||
/** Construct the wrapping stream.
|
/** Construct the wrapping stream.
|
||||||
|
|
||||||
@@ -139,7 +137,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
explicit
|
explicit
|
||||||
streambuf_readstream(Args&&... args);
|
dynabuf_readstream(Args&&... args);
|
||||||
|
|
||||||
/// Get a reference to the next layer.
|
/// Get a reference to the next layer.
|
||||||
next_layer_type&
|
next_layer_type&
|
||||||
@@ -176,7 +174,7 @@ public:
|
|||||||
by causing the internal buffer size to increase beyond
|
by causing the internal buffer size to increase beyond
|
||||||
the caller defined maximum.
|
the caller defined maximum.
|
||||||
*/
|
*/
|
||||||
Streambuf&
|
DynamicBuffer&
|
||||||
buffer()
|
buffer()
|
||||||
{
|
{
|
||||||
return sb_;
|
return sb_;
|
||||||
@@ -189,7 +187,7 @@ public:
|
|||||||
by causing the internal buffer size to increase beyond
|
by causing the internal buffer size to increase beyond
|
||||||
the caller defined maximum.
|
the caller defined maximum.
|
||||||
*/
|
*/
|
||||||
Streambuf const&
|
DynamicBuffer const&
|
||||||
buffer() const
|
buffer() const
|
||||||
{
|
{
|
||||||
return sb_;
|
return sb_;
|
||||||
@@ -277,6 +275,6 @@ public:
|
|||||||
|
|
||||||
} // beast
|
} // beast
|
||||||
|
|
||||||
#include <beast/core/impl/streambuf_readstream.ipp>
|
#include <beast/core/impl/dynabuf_readstream.ipp>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
#ifndef BEAST_IMPL_BASIC_STREAMBUF_IPP
|
#ifndef BEAST_IMPL_BASIC_STREAMBUF_IPP
|
||||||
#define BEAST_IMPL_BASIC_STREAMBUF_IPP
|
#define BEAST_IMPL_BASIC_STREAMBUF_IPP
|
||||||
|
|
||||||
#include <beast/core/detail/write_streambuf.hpp>
|
#include <beast/core/detail/write_dynabuf.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
@@ -527,6 +527,28 @@ basic_streambuf<Allocator>::basic_streambuf(
|
|||||||
"basic_streambuf: invalid alloc_size");
|
"basic_streambuf: invalid alloc_size");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Allocator>
|
||||||
|
std::size_t
|
||||||
|
basic_streambuf<Allocator>::capacity() const
|
||||||
|
{
|
||||||
|
auto pos = out_;
|
||||||
|
if(pos == list_.end())
|
||||||
|
return 0;
|
||||||
|
auto n = pos->size() - out_pos_;
|
||||||
|
while(++pos != list_.end())
|
||||||
|
n += pos->size();
|
||||||
|
return in_size_ + n;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Allocator>
|
||||||
|
auto
|
||||||
|
basic_streambuf<Allocator>::
|
||||||
|
data() const ->
|
||||||
|
const_buffers_type
|
||||||
|
{
|
||||||
|
return const_buffers_type(*this);
|
||||||
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
auto
|
auto
|
||||||
basic_streambuf<Allocator>::prepare(size_type n) ->
|
basic_streambuf<Allocator>::prepare(size_type n) ->
|
||||||
@@ -646,14 +668,6 @@ basic_streambuf<Allocator>::commit(size_type n)
|
|||||||
debug_check();
|
debug_check();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
|
||||||
auto
|
|
||||||
basic_streambuf<Allocator>::data() const ->
|
|
||||||
const_buffers_type
|
|
||||||
{
|
|
||||||
return const_buffers_type(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
void
|
void
|
||||||
basic_streambuf<Allocator>::consume(size_type n)
|
basic_streambuf<Allocator>::consume(size_type n)
|
||||||
@@ -717,7 +731,8 @@ basic_streambuf<Allocator>::consume(size_type n)
|
|||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
void
|
void
|
||||||
basic_streambuf<Allocator>::clear()
|
basic_streambuf<Allocator>::
|
||||||
|
clear()
|
||||||
{
|
{
|
||||||
delete_list();
|
delete_list();
|
||||||
list_.clear();
|
list_.clear();
|
||||||
@@ -795,21 +810,6 @@ basic_streambuf<Allocator>::delete_list()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of bytes which can be
|
|
||||||
// prepared without causing a memory allocation.
|
|
||||||
template<class Allocator>
|
|
||||||
std::size_t
|
|
||||||
basic_streambuf<Allocator>::prepare_size() const
|
|
||||||
{
|
|
||||||
auto pos = out_;
|
|
||||||
if(pos == list_.end())
|
|
||||||
return 0;
|
|
||||||
auto n = pos->size() - out_pos_;
|
|
||||||
while(++pos != list_.end())
|
|
||||||
n += pos->size();
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
void
|
void
|
||||||
basic_streambuf<Allocator>::debug_check() const
|
basic_streambuf<Allocator>::debug_check() const
|
||||||
@@ -855,7 +855,7 @@ std::size_t
|
|||||||
read_size_helper(basic_streambuf<
|
read_size_helper(basic_streambuf<
|
||||||
Allocator> const& streambuf, std::size_t max_size)
|
Allocator> const& streambuf, std::size_t max_size)
|
||||||
{
|
{
|
||||||
auto const avail = streambuf.prepare_size();
|
auto const avail = streambuf.capacity() - streambuf.size();
|
||||||
if(avail == 0)
|
if(avail == 0)
|
||||||
return std::min(max_size,
|
return std::min(max_size,
|
||||||
std::max<std::size_t>(512, streambuf.alloc_size_));
|
std::max<std::size_t>(512, streambuf.alloc_size_));
|
||||||
@@ -866,7 +866,7 @@ template<class Alloc, class T>
|
|||||||
basic_streambuf<Alloc>&
|
basic_streambuf<Alloc>&
|
||||||
operator<<(basic_streambuf<Alloc>& streambuf, T const& t)
|
operator<<(basic_streambuf<Alloc>& streambuf, T const& t)
|
||||||
{
|
{
|
||||||
detail::write_streambuf(streambuf, t);
|
detail::write_dynabuf(streambuf, t);
|
||||||
return streambuf;
|
return streambuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef BEAST_IMPL_STREAMBUF_READSTREAM_IPP
|
#ifndef BEAST_IMPL_DYNABUF_READSTREAM_HPP
|
||||||
#define BEAST_IMPL_STREAMBUF_READSTREAM_IPP
|
#define BEAST_IMPL_DYNABUF_READSTREAM_HPP
|
||||||
|
|
||||||
#include <beast/core/bind_handler.hpp>
|
#include <beast/core/bind_handler.hpp>
|
||||||
#include <beast/core/handler_concepts.hpp>
|
#include <beast/core/handler_concepts.hpp>
|
||||||
@@ -16,24 +16,24 @@
|
|||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
template<class Stream, class Streambuf>
|
template<class Stream, class DynamicBuffer>
|
||||||
template<class MutableBufferSequence, class Handler>
|
template<class MutableBufferSequence, class Handler>
|
||||||
class streambuf_readstream<
|
class dynabuf_readstream<
|
||||||
Stream, Streambuf>::read_some_op
|
Stream, DynamicBuffer>::read_some_op
|
||||||
{
|
{
|
||||||
using alloc_type =
|
using alloc_type =
|
||||||
handler_alloc<char, Handler>;
|
handler_alloc<char, Handler>;
|
||||||
|
|
||||||
struct data
|
struct data
|
||||||
{
|
{
|
||||||
streambuf_readstream& srs;
|
dynabuf_readstream& srs;
|
||||||
MutableBufferSequence bs;
|
MutableBufferSequence bs;
|
||||||
Handler h;
|
Handler h;
|
||||||
int state = 0;
|
int state = 0;
|
||||||
|
|
||||||
template<class DeducedHandler>
|
template<class DeducedHandler>
|
||||||
data(DeducedHandler&& h_,
|
data(DeducedHandler&& h_,
|
||||||
streambuf_readstream& srs_,
|
dynabuf_readstream& srs_,
|
||||||
MutableBufferSequence const& bs_)
|
MutableBufferSequence const& bs_)
|
||||||
: srs(srs_)
|
: srs(srs_)
|
||||||
, bs(bs_)
|
, bs(bs_)
|
||||||
@@ -50,7 +50,7 @@ public:
|
|||||||
|
|
||||||
template<class DeducedHandler, class... Args>
|
template<class DeducedHandler, class... Args>
|
||||||
read_some_op(DeducedHandler&& h,
|
read_some_op(DeducedHandler&& h,
|
||||||
streambuf_readstream& srs, Args&&... args)
|
dynabuf_readstream& srs, Args&&... args)
|
||||||
: d_(std::allocate_shared<data>(alloc_type{h},
|
: d_(std::allocate_shared<data>(alloc_type{h},
|
||||||
std::forward<DeducedHandler>(h), srs,
|
std::forward<DeducedHandler>(h), srs,
|
||||||
std::forward<Args>(args)...))
|
std::forward<Args>(args)...))
|
||||||
@@ -94,10 +94,10 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Stream, class Streambuf>
|
template<class Stream, class DynamicBuffer>
|
||||||
template<class MutableBufferSequence, class Handler>
|
template<class MutableBufferSequence, class Handler>
|
||||||
void
|
void
|
||||||
streambuf_readstream<Stream, Streambuf>::
|
dynabuf_readstream<Stream, DynamicBuffer>::
|
||||||
read_some_op<MutableBufferSequence, Handler>::operator()(
|
read_some_op<MutableBufferSequence, Handler>::operator()(
|
||||||
error_code const& ec, std::size_t bytes_transferred)
|
error_code const& ec, std::size_t bytes_transferred)
|
||||||
{
|
{
|
||||||
@@ -155,18 +155,18 @@ read_some_op<MutableBufferSequence, Handler>::operator()(
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class Stream, class Streambuf>
|
template<class Stream, class DynamicBuffer>
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
streambuf_readstream<Stream, Streambuf>::
|
dynabuf_readstream<Stream, DynamicBuffer>::
|
||||||
streambuf_readstream(Args&&... args)
|
dynabuf_readstream(Args&&... args)
|
||||||
: next_layer_(std::forward<Args>(args)...)
|
: next_layer_(std::forward<Args>(args)...)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Stream, class Streambuf>
|
template<class Stream, class DynamicBuffer>
|
||||||
template<class ConstBufferSequence, class WriteHandler>
|
template<class ConstBufferSequence, class WriteHandler>
|
||||||
auto
|
auto
|
||||||
streambuf_readstream<Stream, Streambuf>::
|
dynabuf_readstream<Stream, DynamicBuffer>::
|
||||||
async_write_some(ConstBufferSequence const& buffers,
|
async_write_some(ConstBufferSequence const& buffers,
|
||||||
WriteHandler&& handler) ->
|
WriteHandler&& handler) ->
|
||||||
typename async_completion<
|
typename async_completion<
|
||||||
@@ -184,10 +184,10 @@ async_write_some(ConstBufferSequence const& buffers,
|
|||||||
std::forward<WriteHandler>(handler));
|
std::forward<WriteHandler>(handler));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Stream, class Streambuf>
|
template<class Stream, class DynamicBuffer>
|
||||||
template<class MutableBufferSequence>
|
template<class MutableBufferSequence>
|
||||||
std::size_t
|
std::size_t
|
||||||
streambuf_readstream<Stream, Streambuf>::
|
dynabuf_readstream<Stream, DynamicBuffer>::
|
||||||
read_some(
|
read_some(
|
||||||
MutableBufferSequence const& buffers)
|
MutableBufferSequence const& buffers)
|
||||||
{
|
{
|
||||||
@@ -203,10 +203,10 @@ read_some(
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Stream, class Streambuf>
|
template<class Stream, class DynamicBuffer>
|
||||||
template<class MutableBufferSequence>
|
template<class MutableBufferSequence>
|
||||||
std::size_t
|
std::size_t
|
||||||
streambuf_readstream<Stream, Streambuf>::
|
dynabuf_readstream<Stream, DynamicBuffer>::
|
||||||
read_some(MutableBufferSequence const& buffers,
|
read_some(MutableBufferSequence const& buffers,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
@@ -232,10 +232,10 @@ read_some(MutableBufferSequence const& buffers,
|
|||||||
return bytes_transferred;
|
return bytes_transferred;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Stream, class Streambuf>
|
template<class Stream, class DynamicBuffer>
|
||||||
template<class MutableBufferSequence, class ReadHandler>
|
template<class MutableBufferSequence, class ReadHandler>
|
||||||
auto
|
auto
|
||||||
streambuf_readstream<Stream, Streambuf>::
|
dynabuf_readstream<Stream, DynamicBuffer>::
|
||||||
async_read_some(
|
async_read_some(
|
||||||
MutableBufferSequence const& buffers,
|
MutableBufferSequence const& buffers,
|
||||||
ReadHandler&& handler) ->
|
ReadHandler&& handler) ->
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
/** A @b `Streambuf` with a fixed size internal buffer.
|
/** A @b `DynamicBuffer` with a fixed size internal buffer.
|
||||||
|
|
||||||
Ownership of the underlying storage belongs to the derived class.
|
Ownership of the underlying storage belongs to the derived class.
|
||||||
|
|
||||||
|
|||||||
@@ -506,8 +506,6 @@ compare(
|
|||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
|
|
||||||
#if ! GENERATING_DOCS
|
|
||||||
|
|
||||||
template<std::size_t N, std::size_t M, class CharT, class Traits>
|
template<std::size_t N, std::size_t M, class CharT, class Traits>
|
||||||
bool
|
bool
|
||||||
operator==(
|
operator==(
|
||||||
@@ -672,8 +670,6 @@ operator>=(
|
|||||||
return detail::compare(lhs, s) >= 0;
|
return detail::compare(lhs, s) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // beast
|
} // beast
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -25,15 +25,16 @@ namespace beast {
|
|||||||
@return A string representing the contents of the input area.
|
@return A string representing the contents of the input area.
|
||||||
|
|
||||||
@note This function participates in overload resolution only if
|
@note This function participates in overload resolution only if
|
||||||
the streambuf parameter meets the requirements of @b `Streambuf`.
|
the buffers parameter meets the requirements of @b `ConstBufferSequence`.
|
||||||
*/
|
*/
|
||||||
template<class ConstBufferSequence
|
template<class ConstBufferSequence>
|
||||||
#if ! GENERATING_DOCS
|
#if GENERATING_DOCS
|
||||||
,class = std::enable_if<is_ConstBufferSequence<
|
|
||||||
ConstBufferSequence>::value>
|
|
||||||
#endif
|
|
||||||
>
|
|
||||||
std::string
|
std::string
|
||||||
|
#else
|
||||||
|
typename std::enable_if<
|
||||||
|
is_ConstBufferSequence<ConstBufferSequence>::value,
|
||||||
|
std::string>::type
|
||||||
|
#endif
|
||||||
to_string(ConstBufferSequence const& buffers)
|
to_string(ConstBufferSequence const& buffers)
|
||||||
{
|
{
|
||||||
using boost::asio::buffer_cast;
|
using boost::asio::buffer_cast;
|
||||||
|
|||||||
@@ -5,20 +5,20 @@
|
|||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef BEAST_WRITE_STREAMBUF_HPP
|
#ifndef BEAST_WRITE_DYNABUF_HPP
|
||||||
#define BEAST_WRITE_STREAMBUF_HPP
|
#define BEAST_WRITE_DYNABUF_HPP
|
||||||
|
|
||||||
#include <beast/core/buffer_concepts.hpp>
|
#include <beast/core/buffer_concepts.hpp>
|
||||||
#include <beast/core/detail/write_streambuf.hpp>
|
#include <beast/core/detail/write_dynabuf.hpp>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
/** Write to a Streambuf.
|
/** Write to a @b `DynamicBuffer`.
|
||||||
|
|
||||||
This function appends the serialized representation of each provided
|
This function appends the serialized representation of each provided
|
||||||
argument into the stream buffer. It is capable of converting the
|
argument into the dynamic buffer. It is capable of converting the
|
||||||
following types of arguments:
|
following types of arguments:
|
||||||
|
|
||||||
@li `boost::asio::const_buffer`
|
@li `boost::asio::const_buffer`
|
||||||
@@ -33,29 +33,29 @@ namespace beast {
|
|||||||
|
|
||||||
For all types not listed above, the function will invoke
|
For all types not listed above, the function will invoke
|
||||||
`boost::lexical_cast` on the argument in an attempt to convert to
|
`boost::lexical_cast` on the argument in an attempt to convert to
|
||||||
a string, which is then appended to the stream buffer.
|
a string, which is then appended to the dynamic buffer.
|
||||||
|
|
||||||
When this function serializes numbers, it converts them to
|
When this function serializes numbers, it converts them to
|
||||||
their text representation as if by a call to `std::to_string`.
|
their text representation as if by a call to `std::to_string`.
|
||||||
|
|
||||||
@param streambuf The stream buffer to write to.
|
@param dynabuf The dynamic buffer to write to.
|
||||||
|
|
||||||
@param args A list of one or more arguments to write.
|
@param args A list of one or more arguments to write.
|
||||||
|
|
||||||
@throws unspecified Any exceptions thrown by `boost::lexical_cast`.
|
@throws unspecified Any exceptions thrown by `boost::lexical_cast`.
|
||||||
|
|
||||||
@note This function participates in overload resolution only if
|
@note This function participates in overload resolution only if
|
||||||
the `streambuf` parameter meets the requirements of @b `Streambuf`.
|
the `dynabuf` parameter meets the requirements of @b `DynamicBuffer`.
|
||||||
*/
|
*/
|
||||||
template<class Streambuf, class... Args>
|
template<class DynamicBuffer, class... Args>
|
||||||
#if GENERATING_DOCS
|
#if GENERATING_DOCS
|
||||||
void
|
void
|
||||||
#else
|
#else
|
||||||
typename std::enable_if<is_Streambuf<Streambuf>::value>::type
|
typename std::enable_if<is_DynamicBuffer<DynamicBuffer>::value>::type
|
||||||
#endif
|
#endif
|
||||||
write(Streambuf& streambuf, Args const&... args)
|
write(DynamicBuffer& dynabuf, Args const&... args)
|
||||||
{
|
{
|
||||||
detail::write_streambuf(streambuf, args...);
|
detail::write_dynabuf(dynabuf, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // beast
|
} // beast
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
#include <beast/http/read.hpp>
|
#include <beast/http/read.hpp>
|
||||||
#include <beast/http/reason.hpp>
|
#include <beast/http/reason.hpp>
|
||||||
#include <beast/http/resume_context.hpp>
|
#include <beast/http/resume_context.hpp>
|
||||||
#include <beast/http/rfc2616.hpp>
|
#include <beast/http/rfc7230.hpp>
|
||||||
#include <beast/http/streambuf_body.hpp>
|
#include <beast/http/streambuf_body.hpp>
|
||||||
#include <beast/http/string_body.hpp>
|
#include <beast/http/string_body.hpp>
|
||||||
#include <beast/http/write.hpp>
|
#include <beast/http/write.hpp>
|
||||||
|
|||||||
95
src/beast/include/beast/http/basic_dynabuf_body.hpp
Normal file
95
src/beast/include/beast/http/basic_dynabuf_body.hpp
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
//
|
||||||
|
// 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_BASIC_DYNABUF_BODY_HPP
|
||||||
|
#define BEAST_HTTP_BASIC_DYNABUF_BODY_HPP
|
||||||
|
|
||||||
|
#include <beast/http/body_type.hpp>
|
||||||
|
#include <boost/asio/buffer.hpp>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
namespace http {
|
||||||
|
|
||||||
|
/** A message body represented by a @b `DynamicBuffer`
|
||||||
|
|
||||||
|
Meets the requirements of @b `Body`.
|
||||||
|
*/
|
||||||
|
template<class DynamicBuffer>
|
||||||
|
struct basic_dynabuf_body
|
||||||
|
{
|
||||||
|
/// The type of the `message::body` member
|
||||||
|
using value_type = DynamicBuffer;
|
||||||
|
|
||||||
|
#if GENERATING_DOCS
|
||||||
|
private:
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class reader
|
||||||
|
{
|
||||||
|
value_type& sb_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
template<bool isRequest, class Headers>
|
||||||
|
explicit
|
||||||
|
reader(message<isRequest,
|
||||||
|
basic_dynabuf_body, Headers>& m) noexcept
|
||||||
|
: sb_(m.body)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
write(void const* data,
|
||||||
|
std::size_t size, error_code&) noexcept
|
||||||
|
{
|
||||||
|
using boost::asio::buffer;
|
||||||
|
using boost::asio::buffer_copy;
|
||||||
|
sb_.commit(buffer_copy(
|
||||||
|
sb_.prepare(size), buffer(data, size)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class writer
|
||||||
|
{
|
||||||
|
DynamicBuffer const& body_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
writer(writer const&) = delete;
|
||||||
|
writer& operator=(writer const&) = delete;
|
||||||
|
|
||||||
|
template<bool isRequest, class Headers>
|
||||||
|
explicit
|
||||||
|
writer(message<
|
||||||
|
isRequest, basic_dynabuf_body, Headers> const& m)
|
||||||
|
: body_(m.body)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
init(error_code& ec)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint64_t
|
||||||
|
content_length() const
|
||||||
|
{
|
||||||
|
return body_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Write>
|
||||||
|
boost::tribool
|
||||||
|
operator()(resume_context&&, error_code&, Write&& write)
|
||||||
|
{
|
||||||
|
write(body_.data());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // http
|
||||||
|
} // beast
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -246,8 +246,7 @@ public:
|
|||||||
Field names are stored as-is, but comparison are case-insensitive.
|
Field names are stored as-is, but comparison are case-insensitive.
|
||||||
The container preserves the order of insertion of fields with
|
The container preserves the order of insertion of fields with
|
||||||
different names. For fields with the same name, the implementation
|
different names. For fields with the same name, the implementation
|
||||||
concatenates values inserted with duplicate names as per the
|
concatenates values inserted with duplicate names as per rfc7230.
|
||||||
rules in rfc2616 section 4.2.
|
|
||||||
|
|
||||||
@note Meets the requirements of @b `FieldSequence`.
|
@note Meets the requirements of @b `FieldSequence`.
|
||||||
*/
|
*/
|
||||||
@@ -393,18 +392,16 @@ public:
|
|||||||
*/
|
*/
|
||||||
// VFALCO TODO Consider allowing rvalue references for std::move?
|
// VFALCO TODO Consider allowing rvalue references for std::move?
|
||||||
void
|
void
|
||||||
insert(boost::string_ref const& name,
|
insert(boost::string_ref const& name, boost::string_ref value);
|
||||||
boost::string_ref const& value);
|
|
||||||
|
|
||||||
/** Insert a field value.
|
/** Insert a field value.
|
||||||
|
|
||||||
If a field value already exists the new value will be
|
If a field value already exists the new value will be
|
||||||
extended as per RFC2616 Section 4.2.
|
extended as per RFC2616 Section 4.2.
|
||||||
*/
|
*/
|
||||||
template<class T,
|
template<class T>
|
||||||
class = typename std::enable_if<
|
typename std::enable_if<
|
||||||
! std::is_constructible<boost::string_ref, T>::value>::type>
|
! std::is_constructible<boost::string_ref, T>::value>::type
|
||||||
void
|
|
||||||
insert(boost::string_ref name, T const& value)
|
insert(boost::string_ref name, T const& value)
|
||||||
{
|
{
|
||||||
insert(name,
|
insert(name,
|
||||||
@@ -414,21 +411,19 @@ public:
|
|||||||
/** Replace a field value.
|
/** Replace a field value.
|
||||||
|
|
||||||
The current field value, if any, is removed. Then the
|
The current field value, if any, is removed. Then the
|
||||||
specified value is inserted as if by insert(field, value).
|
specified value is inserted as if by `insert(field, value)`.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
replace(boost::string_ref const& name,
|
replace(boost::string_ref const& name, boost::string_ref value);
|
||||||
boost::string_ref const& value);
|
|
||||||
|
|
||||||
/** Replace a field value.
|
/** Replace a field value.
|
||||||
|
|
||||||
The current field value, if any, is removed. Then the
|
The current field value, if any, is removed. Then the
|
||||||
specified value is inserted as if by insert(field, value).
|
specified value is inserted as if by `insert(field, value)`.
|
||||||
*/
|
*/
|
||||||
template<class T,
|
template<class T>
|
||||||
class = typename std::enable_if<
|
typename std::enable_if<
|
||||||
! std::is_constructible<boost::string_ref, T>::value>::type>
|
! std::is_constructible<boost::string_ref, T>::value>::type
|
||||||
void
|
|
||||||
replace(boost::string_ref const& name, T const& value)
|
replace(boost::string_ref const& name, T const& value)
|
||||||
{
|
{
|
||||||
replace(name,
|
replace(name,
|
||||||
|
|||||||
@@ -25,17 +25,65 @@ namespace http {
|
|||||||
namespace parse_flag {
|
namespace parse_flag {
|
||||||
enum values
|
enum values
|
||||||
{
|
{
|
||||||
chunked = 1 << 0,
|
chunked = 1,
|
||||||
connection_keep_alive = 1 << 1,
|
connection_keep_alive = 2,
|
||||||
connection_close = 1 << 2,
|
connection_close = 4,
|
||||||
connection_upgrade = 1 << 3,
|
connection_upgrade = 8,
|
||||||
trailing = 1 << 4,
|
trailing = 16,
|
||||||
upgrade = 1 << 5,
|
upgrade = 32,
|
||||||
skipbody = 1 << 6,
|
skipbody = 64,
|
||||||
contentlength = 1 << 7
|
contentlength = 128
|
||||||
};
|
};
|
||||||
} // parse_flag
|
} // parse_flag
|
||||||
|
|
||||||
|
/** Headers maximum size option.
|
||||||
|
|
||||||
|
Sets the maximum number of cumulative bytes allowed
|
||||||
|
including all header octets. A value of zero indicates
|
||||||
|
no limit on the number of header octets
|
||||||
|
|
||||||
|
The default headers maximum size is 16KB (16,384 bytes).
|
||||||
|
|
||||||
|
@note Objects of this type are passed to @ref set_option.
|
||||||
|
*/
|
||||||
|
struct headers_max_size
|
||||||
|
{
|
||||||
|
std::size_t value;
|
||||||
|
|
||||||
|
explicit
|
||||||
|
headers_max_size(std::size_t v)
|
||||||
|
: value(v)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Body maximum size option.
|
||||||
|
|
||||||
|
Sets the maximum number of cumulative bytes allowed including
|
||||||
|
all body octets. Octets in chunk-encoded bodies are counted
|
||||||
|
after decoding. A value of zero indicates no limit on
|
||||||
|
the number of body octets.
|
||||||
|
|
||||||
|
The default body maximum size for requests is 4MB (four
|
||||||
|
megabytes or 4,194,304 bytes) and unlimited for responses.
|
||||||
|
|
||||||
|
@note Objects of this type are passed to @ref set_option.
|
||||||
|
*/
|
||||||
|
struct body_max_size
|
||||||
|
{
|
||||||
|
std::size_t value;
|
||||||
|
|
||||||
|
explicit
|
||||||
|
body_max_size(std::size_t v)
|
||||||
|
: value(v)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// The value returned when no content length is known or applicable.
|
||||||
|
static std::uint64_t constexpr no_content_length =
|
||||||
|
std::numeric_limits<std::uint64_t>::max();
|
||||||
|
|
||||||
/** A parser for decoding HTTP/1 wire format messages.
|
/** A parser for decoding HTTP/1 wire format messages.
|
||||||
|
|
||||||
This parser is designed to efficiently parse messages in the
|
This parser is designed to efficiently parse messages in the
|
||||||
@@ -85,7 +133,7 @@ enum values
|
|||||||
|
|
||||||
Called for each piece of the current header value.
|
Called for each piece of the current header value.
|
||||||
|
|
||||||
@li `int on_headers(error_code&)`
|
@li `int on_headers(std::uint64_t content_length, error_code&)`
|
||||||
|
|
||||||
Called when all the headers have been parsed successfully.
|
Called when all the headers have been parsed successfully.
|
||||||
|
|
||||||
@@ -126,90 +174,12 @@ enum values
|
|||||||
presented with request or response message.
|
presented with request or response message.
|
||||||
*/
|
*/
|
||||||
template<bool isRequest, class Derived>
|
template<bool isRequest, class Derived>
|
||||||
class basic_parser_v1
|
class basic_parser_v1 : public detail::parser_base
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
using self = basic_parser_v1;
|
using self = basic_parser_v1;
|
||||||
typedef void(self::*pmf_t)(error_code&, boost::string_ref const&);
|
typedef void(self::*pmf_t)(error_code&, boost::string_ref const&);
|
||||||
|
|
||||||
static std::uint64_t constexpr no_content_length =
|
|
||||||
std::numeric_limits<std::uint64_t>::max();
|
|
||||||
|
|
||||||
enum state : std::uint8_t
|
|
||||||
{
|
|
||||||
s_closed = 1,
|
|
||||||
|
|
||||||
s_req_start,
|
|
||||||
s_req_method_start,
|
|
||||||
s_req_method,
|
|
||||||
s_req_space_before_url,
|
|
||||||
s_req_url_start,
|
|
||||||
s_req_url,
|
|
||||||
s_req_http_start,
|
|
||||||
s_req_http_H,
|
|
||||||
s_req_http_HT,
|
|
||||||
s_req_http_HTT,
|
|
||||||
s_req_http_HTTP,
|
|
||||||
s_req_major_start,
|
|
||||||
s_req_major,
|
|
||||||
s_req_minor_start,
|
|
||||||
s_req_minor,
|
|
||||||
s_req_line_end,
|
|
||||||
|
|
||||||
s_res_start,
|
|
||||||
s_res_H,
|
|
||||||
s_res_HT,
|
|
||||||
s_res_HTT,
|
|
||||||
s_res_HTTP,
|
|
||||||
s_res_major_start,
|
|
||||||
s_res_major,
|
|
||||||
s_res_minor_start,
|
|
||||||
s_res_minor,
|
|
||||||
s_res_status_code_start,
|
|
||||||
s_res_status_code,
|
|
||||||
s_res_status_start,
|
|
||||||
s_res_status,
|
|
||||||
s_res_line_almost_done,
|
|
||||||
s_res_line_done,
|
|
||||||
|
|
||||||
s_header_field_start,
|
|
||||||
s_header_field,
|
|
||||||
s_header_value_start,
|
|
||||||
s_header_value_discard_lWs0,
|
|
||||||
s_header_value_discard_ws0,
|
|
||||||
s_header_value_almost_done0,
|
|
||||||
s_header_value_text_start,
|
|
||||||
s_header_value_discard_lWs,
|
|
||||||
s_header_value_discard_ws,
|
|
||||||
s_header_value_text,
|
|
||||||
s_header_value_almost_done,
|
|
||||||
|
|
||||||
s_headers_almost_done,
|
|
||||||
s_headers_done,
|
|
||||||
|
|
||||||
s_chunk_size_start,
|
|
||||||
s_chunk_size,
|
|
||||||
s_chunk_parameters,
|
|
||||||
s_chunk_size_almost_done,
|
|
||||||
|
|
||||||
// states below do not count towards
|
|
||||||
// the limit on the size of the message
|
|
||||||
|
|
||||||
s_body_identity0,
|
|
||||||
s_body_identity,
|
|
||||||
s_body_identity_eof0,
|
|
||||||
s_body_identity_eof,
|
|
||||||
|
|
||||||
s_chunk_data_start,
|
|
||||||
s_chunk_data,
|
|
||||||
s_chunk_data_almost_done,
|
|
||||||
s_chunk_data_done,
|
|
||||||
|
|
||||||
s_complete,
|
|
||||||
s_restart,
|
|
||||||
s_closed_complete
|
|
||||||
};
|
|
||||||
|
|
||||||
enum field_state : std::uint8_t
|
enum field_state : std::uint8_t
|
||||||
{
|
{
|
||||||
h_general = 0,
|
h_general = 0,
|
||||||
@@ -224,25 +194,36 @@ private:
|
|||||||
h_matching_upgrade,
|
h_matching_upgrade,
|
||||||
|
|
||||||
h_connection,
|
h_connection,
|
||||||
|
h_content_length0,
|
||||||
h_content_length,
|
h_content_length,
|
||||||
|
h_content_length_ows,
|
||||||
h_transfer_encoding,
|
h_transfer_encoding,
|
||||||
h_upgrade,
|
h_upgrade,
|
||||||
|
|
||||||
h_matching_transfer_encoding_chunked,
|
h_matching_transfer_encoding_chunked,
|
||||||
h_matching_connection_token_start,
|
h_matching_transfer_encoding_general,
|
||||||
h_matching_connection_keep_alive,
|
h_matching_connection_keep_alive,
|
||||||
h_matching_connection_close,
|
h_matching_connection_close,
|
||||||
h_matching_connection_upgrade,
|
h_matching_connection_upgrade,
|
||||||
h_matching_connection_token,
|
|
||||||
|
|
||||||
h_transfer_encoding_chunked,
|
h_transfer_encoding_chunked,
|
||||||
|
h_transfer_encoding_chunked_ows,
|
||||||
|
|
||||||
h_connection_keep_alive,
|
h_connection_keep_alive,
|
||||||
|
h_connection_keep_alive_ows,
|
||||||
h_connection_close,
|
h_connection_close,
|
||||||
|
h_connection_close_ows,
|
||||||
h_connection_upgrade,
|
h_connection_upgrade,
|
||||||
|
h_connection_upgrade_ows,
|
||||||
|
h_connection_token,
|
||||||
|
h_connection_token_ows
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::size_t h_max_;
|
||||||
|
std::size_t h_left_;
|
||||||
|
std::size_t b_max_;
|
||||||
|
std::size_t b_left_;
|
||||||
std::uint64_t content_length_;
|
std::uint64_t content_length_;
|
||||||
std::uint64_t nread_;
|
|
||||||
pmf_t cb_;
|
pmf_t cb_;
|
||||||
state s_ : 8;
|
state s_ : 8;
|
||||||
unsigned flags_ : 8;
|
unsigned flags_ : 8;
|
||||||
@@ -260,10 +241,42 @@ public:
|
|||||||
/// Copy assignment.
|
/// Copy assignment.
|
||||||
basic_parser_v1& operator=(basic_parser_v1 const&) = default;
|
basic_parser_v1& operator=(basic_parser_v1 const&) = default;
|
||||||
|
|
||||||
/// Constructor
|
/// Default constructor
|
||||||
basic_parser_v1()
|
basic_parser_v1();
|
||||||
|
|
||||||
|
/** Set options on the parser.
|
||||||
|
|
||||||
|
@param args One or more parser options to set.
|
||||||
|
*/
|
||||||
|
#if GENERATING_DOCS
|
||||||
|
template<class... Args>
|
||||||
|
void
|
||||||
|
set_option(Args&&... args)
|
||||||
|
#else
|
||||||
|
template<class A1, class A2, class... An>
|
||||||
|
void
|
||||||
|
set_option(A1&& a1, A2&& a2, An&&... an)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
init(std::integral_constant<bool, isRequest>{});
|
set_option(std::forward<A1>(a1));
|
||||||
|
set_option(std::forward<A2>(a2),
|
||||||
|
std::forward<An>(an)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the headers maximum size option
|
||||||
|
void
|
||||||
|
set_option(headers_max_size const& o)
|
||||||
|
{
|
||||||
|
h_max_ = o.value;
|
||||||
|
h_left_ = h_max_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the body maximum size option
|
||||||
|
void
|
||||||
|
set_option(body_max_size const& o)
|
||||||
|
{
|
||||||
|
b_max_ = o.value;
|
||||||
|
b_left_ = b_max_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns internal flags associated with the parser.
|
/// Returns internal flags associated with the parser.
|
||||||
@@ -373,14 +386,14 @@ public:
|
|||||||
@return The number of bytes consumed in the input sequence.
|
@return The number of bytes consumed in the input sequence.
|
||||||
*/
|
*/
|
||||||
template<class ConstBufferSequence>
|
template<class ConstBufferSequence>
|
||||||
#if GENERATING_DOCS
|
#if GENERATING_DOCS
|
||||||
std::size_t
|
std::size_t
|
||||||
#else
|
#else
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
! std::is_convertible<ConstBufferSequence,
|
! std::is_convertible<ConstBufferSequence,
|
||||||
boost::asio::const_buffer>::value,
|
boost::asio::const_buffer>::value,
|
||||||
std::size_t>::type
|
std::size_t>::type
|
||||||
#endif
|
#endif
|
||||||
write(ConstBufferSequence const& buffers, error_code& ec);
|
write(ConstBufferSequence const& buffers, error_code& ec);
|
||||||
|
|
||||||
/** Write a single buffer of data to the parser.
|
/** Write a single buffer of data to the parser.
|
||||||
@@ -413,17 +426,48 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
init(std::true_type)
|
reset(std::true_type)
|
||||||
{
|
{
|
||||||
s_ = s_req_start;
|
s_ = s_req_start;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
init(std::false_type)
|
reset(std::false_type)
|
||||||
{
|
{
|
||||||
s_ = s_res_start;
|
s_ = s_res_start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
reset()
|
||||||
|
{
|
||||||
|
h_left_ = h_max_;
|
||||||
|
b_left_ = b_max_;
|
||||||
|
reset(std::integral_constant<bool, isRequest>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
init(std::true_type)
|
||||||
|
{
|
||||||
|
// 16KB max headers, 4MB max body
|
||||||
|
h_max_ = 16 * 1024;
|
||||||
|
b_max_ = 4 * 1024 * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
init(std::false_type)
|
||||||
|
{
|
||||||
|
// 16KB max headers, unlimited body
|
||||||
|
h_max_ = 16 * 1024;
|
||||||
|
b_max_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
init()
|
||||||
|
{
|
||||||
|
init(std::integral_constant<bool, isRequest>{});
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
needs_eof(std::true_type) const;
|
needs_eof(std::true_type) const;
|
||||||
|
|
||||||
@@ -584,7 +628,7 @@ private:
|
|||||||
{
|
{
|
||||||
template<class T, class R = std::is_same<int,
|
template<class T, class R = std::is_same<int,
|
||||||
decltype(std::declval<T>().on_headers(
|
decltype(std::declval<T>().on_headers(
|
||||||
std::declval<error_code&>()))>>
|
std::declval<std::uint64_t>(), std::declval<error_code&>()))>>
|
||||||
static R check(int);
|
static R check(int);
|
||||||
template <class>
|
template <class>
|
||||||
static std::false_type check(...);
|
static std::false_type check(...);
|
||||||
@@ -661,9 +705,17 @@ private:
|
|||||||
void call_on_method(error_code& ec,
|
void call_on_method(error_code& ec,
|
||||||
boost::string_ref const& s)
|
boost::string_ref const& s)
|
||||||
{
|
{
|
||||||
|
if(! h_max_ || s.size() <= h_left_)
|
||||||
|
{
|
||||||
|
h_left_ -= s.size();
|
||||||
call_on_method(ec, s, std::integral_constant<bool,
|
call_on_method(ec, s, std::integral_constant<bool,
|
||||||
isRequest && has_on_method<Derived>::value>{});
|
isRequest && has_on_method<Derived>::value>{});
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ec = parse_error::headers_too_big;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void call_on_uri(error_code& ec,
|
void call_on_uri(error_code& ec,
|
||||||
boost::string_ref const& s, std::true_type)
|
boost::string_ref const& s, std::true_type)
|
||||||
@@ -678,9 +730,17 @@ private:
|
|||||||
|
|
||||||
void call_on_uri(error_code& ec, boost::string_ref const& s)
|
void call_on_uri(error_code& ec, boost::string_ref const& s)
|
||||||
{
|
{
|
||||||
|
if(! h_max_ || s.size() <= h_left_)
|
||||||
|
{
|
||||||
|
h_left_ -= s.size();
|
||||||
call_on_uri(ec, s, std::integral_constant<bool,
|
call_on_uri(ec, s, std::integral_constant<bool,
|
||||||
isRequest && has_on_uri<Derived>::value>{});
|
isRequest && has_on_uri<Derived>::value>{});
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ec = parse_error::headers_too_big;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void call_on_reason(error_code& ec,
|
void call_on_reason(error_code& ec,
|
||||||
boost::string_ref const& s, std::true_type)
|
boost::string_ref const& s, std::true_type)
|
||||||
@@ -695,9 +755,17 @@ private:
|
|||||||
|
|
||||||
void call_on_reason(error_code& ec, boost::string_ref const& s)
|
void call_on_reason(error_code& ec, boost::string_ref const& s)
|
||||||
{
|
{
|
||||||
|
if(! h_max_ || s.size() <= h_left_)
|
||||||
|
{
|
||||||
|
h_left_ -= s.size();
|
||||||
call_on_reason(ec, s, std::integral_constant<bool,
|
call_on_reason(ec, s, std::integral_constant<bool,
|
||||||
! isRequest && has_on_reason<Derived>::value>{});
|
! isRequest && has_on_reason<Derived>::value>{});
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ec = parse_error::headers_too_big;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void call_on_request(error_code& ec, std::true_type)
|
void call_on_request(error_code& ec, std::true_type)
|
||||||
{
|
{
|
||||||
@@ -742,8 +810,16 @@ private:
|
|||||||
|
|
||||||
void call_on_field(error_code& ec, boost::string_ref const& s)
|
void call_on_field(error_code& ec, boost::string_ref const& s)
|
||||||
{
|
{
|
||||||
|
if(! h_max_ || s.size() <= h_left_)
|
||||||
|
{
|
||||||
|
h_left_ -= s.size();
|
||||||
call_on_field(ec, s, has_on_field<Derived>{});
|
call_on_field(ec, s, has_on_field<Derived>{});
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ec = parse_error::headers_too_big;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void call_on_value(error_code& ec,
|
void call_on_value(error_code& ec,
|
||||||
boost::string_ref const& s, std::true_type)
|
boost::string_ref const& s, std::true_type)
|
||||||
@@ -758,22 +834,32 @@ private:
|
|||||||
|
|
||||||
void call_on_value(error_code& ec, boost::string_ref const& s)
|
void call_on_value(error_code& ec, boost::string_ref const& s)
|
||||||
{
|
{
|
||||||
|
if(! h_max_ || s.size() <= h_left_)
|
||||||
|
{
|
||||||
|
h_left_ -= s.size();
|
||||||
call_on_value(ec, s, has_on_value<Derived>{});
|
call_on_value(ec, s, has_on_value<Derived>{});
|
||||||
}
|
}
|
||||||
|
else
|
||||||
int call_on_headers(error_code& ec, std::true_type)
|
|
||||||
{
|
{
|
||||||
return impl().on_headers(ec);
|
ec = parse_error::headers_too_big;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int call_on_headers(error_code& ec, std::false_type)
|
int call_on_headers(error_code& ec,
|
||||||
|
std::uint64_t content_length, std::true_type)
|
||||||
|
{
|
||||||
|
return impl().on_headers(content_length, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
int call_on_headers(error_code& ec, std::uint64_t, std::false_type)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int call_on_headers(error_code& ec)
|
int call_on_headers(error_code& ec)
|
||||||
{
|
{
|
||||||
return call_on_headers(ec, has_on_headers<Derived>{});
|
return call_on_headers(ec, content_length_,
|
||||||
|
has_on_headers<Derived>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
void call_on_body(error_code& ec,
|
void call_on_body(error_code& ec,
|
||||||
@@ -789,8 +875,16 @@ private:
|
|||||||
|
|
||||||
void call_on_body(error_code& ec, boost::string_ref const& s)
|
void call_on_body(error_code& ec, boost::string_ref const& s)
|
||||||
{
|
{
|
||||||
|
if(! b_max_ || s.size() <= b_left_)
|
||||||
|
{
|
||||||
|
b_left_ -= s.size();
|
||||||
call_on_body(ec, s, has_on_body<Derived>{});
|
call_on_body(ec, s, has_on_body<Derived>{});
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ec = parse_error::body_too_big;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void call_on_complete(error_code& ec, std::true_type)
|
void call_on_complete(error_code& ec, std::true_type)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,137 +17,6 @@ namespace beast {
|
|||||||
namespace http {
|
namespace http {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
// '0'...'9'
|
|
||||||
inline
|
|
||||||
bool
|
|
||||||
is_digit(char c)
|
|
||||||
{
|
|
||||||
return c >= '0' && c <= '9';
|
|
||||||
}
|
|
||||||
|
|
||||||
inline
|
|
||||||
bool
|
|
||||||
is_token(char c)
|
|
||||||
{
|
|
||||||
/* token = 1*<any CHAR except CTLs or separators>
|
|
||||||
CHAR = <any US-ASCII character (octets 0 - 127)>
|
|
||||||
sep = "(" | ")" | "<" | ">" | "@"
|
|
||||||
| "," | ";" | ":" | "\" | <">
|
|
||||||
| "/" | "[" | "]" | "?" | "="
|
|
||||||
| "{" | "}" | SP | HT
|
|
||||||
*/
|
|
||||||
static std::array<char, 256> constexpr tab = {{
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
|
|
||||||
0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48
|
|
||||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, // 112
|
|
||||||
}};
|
|
||||||
return tab[static_cast<std::uint8_t>(c)] != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline
|
|
||||||
bool
|
|
||||||
is_text(char c)
|
|
||||||
{
|
|
||||||
// TEXT = <any OCTET except CTLs, but including LWS>
|
|
||||||
static std::array<char, 256> constexpr tab = {{
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, // 0
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 32
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 48
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 112
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 128
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 144
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 160
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 176
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 192
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 208
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 224
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 240
|
|
||||||
}};
|
|
||||||
return tab[static_cast<std::uint8_t>(c)] != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// converts to lower case,
|
|
||||||
// returns 0 if not a valid token char
|
|
||||||
//
|
|
||||||
inline
|
|
||||||
char
|
|
||||||
to_field_char(char c)
|
|
||||||
{
|
|
||||||
/* token = 1*<any CHAR except CTLs or separators>
|
|
||||||
CHAR = <any US-ASCII character (octets 0 - 127)>
|
|
||||||
sep = "(" | ")" | "<" | ">" | "@"
|
|
||||||
| "," | ";" | ":" | "\" | <">
|
|
||||||
| "/" | "[" | "]" | "?" | "="
|
|
||||||
| "{" | "}" | SP | HT
|
|
||||||
*/
|
|
||||||
static std::array<char, 256> constexpr tab = {{
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, '!', 0, '#', '$', '%', '&', '\'', 0, 0, '*', '+', 0, '-', '.', 0,
|
|
||||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
|
|
||||||
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, '^', '_',
|
|
||||||
'`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
|
|
||||||
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, '|', 0, '~', 0
|
|
||||||
}};
|
|
||||||
return tab[static_cast<std::uint8_t>(c)];
|
|
||||||
}
|
|
||||||
|
|
||||||
// converts to lower case,
|
|
||||||
// returns 0 if not a valid text char
|
|
||||||
//
|
|
||||||
inline
|
|
||||||
char
|
|
||||||
to_value_char(char c)
|
|
||||||
{
|
|
||||||
// TEXT = <any OCTET except CTLs, but including LWS>
|
|
||||||
static std::array<std::uint8_t, 256> constexpr tab = {{
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, // 0
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
|
|
||||||
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, // 32
|
|
||||||
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, // 48
|
|
||||||
64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, // 64
|
|
||||||
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95, // 80
|
|
||||||
96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, // 96
|
|
||||||
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 0, // 112
|
|
||||||
128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, // 128
|
|
||||||
144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, // 144
|
|
||||||
160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, // 160
|
|
||||||
176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, // 176
|
|
||||||
192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, // 192
|
|
||||||
208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, // 208
|
|
||||||
224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, // 224
|
|
||||||
240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 // 240
|
|
||||||
}};
|
|
||||||
return static_cast<char>(tab[static_cast<std::uint8_t>(c)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline
|
|
||||||
std::int8_t
|
|
||||||
unhex(char c)
|
|
||||||
{
|
|
||||||
static std::array<std::int8_t, 256> constexpr tab = {{
|
|
||||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0
|
|
||||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 16
|
|
||||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 32
|
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, // 48
|
|
||||||
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 64
|
|
||||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 80
|
|
||||||
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 96
|
|
||||||
-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>
|
template<class = void>
|
||||||
struct parser_str_t
|
struct parser_str_t
|
||||||
{
|
{
|
||||||
@@ -196,6 +65,82 @@ parser_str_t<_>::transfer_encoding[18];
|
|||||||
|
|
||||||
using parser_str = parser_str_t<>;
|
using parser_str = parser_str_t<>;
|
||||||
|
|
||||||
|
class parser_base
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
enum state : std::uint8_t
|
||||||
|
{
|
||||||
|
s_dead = 1,
|
||||||
|
|
||||||
|
s_req_start,
|
||||||
|
s_req_method0,
|
||||||
|
s_req_method,
|
||||||
|
s_req_url0,
|
||||||
|
s_req_url,
|
||||||
|
s_req_http,
|
||||||
|
s_req_http_H,
|
||||||
|
s_req_http_HT,
|
||||||
|
s_req_http_HTT,
|
||||||
|
s_req_http_HTTP,
|
||||||
|
s_req_major,
|
||||||
|
s_req_dot,
|
||||||
|
s_req_minor,
|
||||||
|
s_req_cr,
|
||||||
|
s_req_lf,
|
||||||
|
|
||||||
|
s_res_start,
|
||||||
|
s_res_H,
|
||||||
|
s_res_HT,
|
||||||
|
s_res_HTT,
|
||||||
|
s_res_HTTP,
|
||||||
|
s_res_major,
|
||||||
|
s_res_dot,
|
||||||
|
s_res_minor,
|
||||||
|
s_res_space_1,
|
||||||
|
s_res_status0,
|
||||||
|
s_res_status1,
|
||||||
|
s_res_status2,
|
||||||
|
s_res_space_2,
|
||||||
|
s_res_reason0,
|
||||||
|
s_res_reason,
|
||||||
|
s_res_line_lf,
|
||||||
|
s_res_line_done,
|
||||||
|
|
||||||
|
s_header_name0,
|
||||||
|
s_header_name,
|
||||||
|
s_header_value0_lf,
|
||||||
|
s_header_value0_almost_done,
|
||||||
|
s_header_value0,
|
||||||
|
s_header_value,
|
||||||
|
s_header_value_lf,
|
||||||
|
s_header_value_almost_done,
|
||||||
|
s_header_value_unfold,
|
||||||
|
|
||||||
|
s_headers_almost_done,
|
||||||
|
s_headers_done,
|
||||||
|
|
||||||
|
s_chunk_size0,
|
||||||
|
s_chunk_size,
|
||||||
|
s_chunk_ext_name0,
|
||||||
|
s_chunk_ext_name,
|
||||||
|
s_chunk_ext_val,
|
||||||
|
s_chunk_size_lf,
|
||||||
|
s_chunk_data0,
|
||||||
|
s_chunk_data,
|
||||||
|
s_chunk_data_cr,
|
||||||
|
s_chunk_data_lf,
|
||||||
|
|
||||||
|
s_body_identity0,
|
||||||
|
s_body_identity,
|
||||||
|
s_body_identity_eof0,
|
||||||
|
s_body_identity_eof,
|
||||||
|
|
||||||
|
s_complete,
|
||||||
|
s_restart,
|
||||||
|
s_closed_complete
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
} // http
|
} // http
|
||||||
} // beast
|
} // beast
|
||||||
|
|||||||
384
src/beast/include/beast/http/detail/rfc7230.hpp
Normal file
384
src/beast/include/beast/http/detail/rfc7230.hpp
Normal file
@@ -0,0 +1,384 @@
|
|||||||
|
//
|
||||||
|
// 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_DETAIL_RFC7230_HPP
|
||||||
|
#define BEAST_HTTP_DETAIL_RFC7230_HPP
|
||||||
|
|
||||||
|
#include <boost/utility/string_ref.hpp>
|
||||||
|
#include <array>
|
||||||
|
#include <iterator>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
namespace http {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
inline
|
||||||
|
bool
|
||||||
|
is_digit(char c)
|
||||||
|
{
|
||||||
|
return c >= '0' && c <= '9';
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
bool
|
||||||
|
is_alpha(char c)
|
||||||
|
{
|
||||||
|
static std::array<char, 256> constexpr tab = {{
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 48
|
||||||
|
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 80
|
||||||
|
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 112
|
||||||
|
}};
|
||||||
|
return tab[static_cast<std::uint8_t>(c)] != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
bool
|
||||||
|
is_text(char c)
|
||||||
|
{
|
||||||
|
// TEXT = <any OCTET except CTLs, but including LWS>
|
||||||
|
static std::array<char, 256> constexpr tab = {{
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, // 0
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 32
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 48
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 112
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 128
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 144
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 160
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 176
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 192
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 208
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 224
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 240
|
||||||
|
}};
|
||||||
|
return tab[static_cast<std::uint8_t>(c)] != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
bool
|
||||||
|
is_tchar(char c)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
tchar = "!" | "#" | "$" | "%" | "&" |
|
||||||
|
"'" | "*" | "+" | "-" | "." |
|
||||||
|
"^" | "_" | "`" | "|" | "~" |
|
||||||
|
DIGIT | ALPHA
|
||||||
|
*/
|
||||||
|
static std::array<char, 256> constexpr tab = {{
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
|
||||||
|
0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48
|
||||||
|
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, // 112
|
||||||
|
}};
|
||||||
|
return tab[static_cast<std::uint8_t>(c)] != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
bool
|
||||||
|
is_qdchar(char c)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
qdtext = HTAB / SP / "!" / %x23-5B ; '#'-'[' / %x5D-7E ; ']'-'~' / obs-text
|
||||||
|
*/
|
||||||
|
static std::array<bool, 256> constexpr tab = {{
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, // 0
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
|
||||||
|
1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 32
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 48
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 80
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 112
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 128
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 144
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 160
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 176
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 192
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 208
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 224
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 240
|
||||||
|
}};
|
||||||
|
return tab[static_cast<std::uint8_t>(c)];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
bool
|
||||||
|
is_qpchar(char c)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
|
||||||
|
obs-text = %x80-FF
|
||||||
|
*/
|
||||||
|
static std::array<bool, 256> constexpr tab = {{
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, // 0
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 32
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 48
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 112
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 128
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 144
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 160
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 176
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 192
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 208
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 224
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 240
|
||||||
|
}};
|
||||||
|
return tab[static_cast<std::uint8_t>(c)];
|
||||||
|
}
|
||||||
|
|
||||||
|
// converts to lower case,
|
||||||
|
// returns 0 if not a valid token char
|
||||||
|
//
|
||||||
|
inline
|
||||||
|
char
|
||||||
|
to_field_char(char c)
|
||||||
|
{
|
||||||
|
/* token = 1*<any CHAR except CTLs or separators>
|
||||||
|
CHAR = <any US-ASCII character (octets 0 - 127)>
|
||||||
|
sep = "(" | ")" | "<" | ">" | "@"
|
||||||
|
| "," | ";" | ":" | "\" | <">
|
||||||
|
| "/" | "[" | "]" | "?" | "="
|
||||||
|
| "{" | "}" | SP | HT
|
||||||
|
*/
|
||||||
|
static std::array<char, 256> constexpr tab = {{
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, '!', 0, '#', '$', '%', '&', '\'', 0, 0, '*', '+', 0, '-', '.', 0,
|
||||||
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
|
||||||
|
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, '^', '_',
|
||||||
|
'`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
|
||||||
|
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, '|', 0, '~', 0
|
||||||
|
}};
|
||||||
|
return tab[static_cast<std::uint8_t>(c)];
|
||||||
|
}
|
||||||
|
|
||||||
|
// converts to lower case,
|
||||||
|
// returns 0 if not a valid text char
|
||||||
|
//
|
||||||
|
inline
|
||||||
|
char
|
||||||
|
to_value_char(char c)
|
||||||
|
{
|
||||||
|
// TEXT = <any OCTET except CTLs, but including LWS>
|
||||||
|
static std::array<std::uint8_t, 256> constexpr tab = {{
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, // 0
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
|
||||||
|
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, // 32
|
||||||
|
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, // 48
|
||||||
|
64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, // 64
|
||||||
|
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95, // 80
|
||||||
|
96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, // 96
|
||||||
|
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 0, // 112
|
||||||
|
128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, // 128
|
||||||
|
144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, // 144
|
||||||
|
160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, // 160
|
||||||
|
176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, // 176
|
||||||
|
192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, // 192
|
||||||
|
208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, // 208
|
||||||
|
224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, // 224
|
||||||
|
240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 // 240
|
||||||
|
}};
|
||||||
|
return static_cast<char>(tab[static_cast<std::uint8_t>(c)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
std::int8_t
|
||||||
|
unhex(char c)
|
||||||
|
{
|
||||||
|
static std::array<std::int8_t, 256> constexpr tab = {{
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 16
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 32
|
||||||
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, // 48
|
||||||
|
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 64
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 80
|
||||||
|
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 96
|
||||||
|
-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 FwdIt>
|
||||||
|
void
|
||||||
|
skip_ows(FwdIt& it, FwdIt const& end)
|
||||||
|
{
|
||||||
|
while(it != end)
|
||||||
|
{
|
||||||
|
auto const c = *it;
|
||||||
|
if(c != ' ' && c != '\t')
|
||||||
|
break;
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
boost::string_ref
|
||||||
|
trim(boost::string_ref const& s)
|
||||||
|
{
|
||||||
|
auto first = s.begin();
|
||||||
|
auto last = s.end();
|
||||||
|
skip_ows(first, last);
|
||||||
|
while(first != last)
|
||||||
|
{
|
||||||
|
auto const c = *std::prev(last);
|
||||||
|
if(c != ' ' && c != '\t')
|
||||||
|
break;
|
||||||
|
--last;
|
||||||
|
}
|
||||||
|
if(first == last)
|
||||||
|
return {};
|
||||||
|
return {&*first,
|
||||||
|
static_cast<std::size_t>(last - first)};
|
||||||
|
}
|
||||||
|
|
||||||
|
struct param_iter
|
||||||
|
{
|
||||||
|
using iter_type = boost::string_ref::const_iterator;
|
||||||
|
|
||||||
|
iter_type it;
|
||||||
|
iter_type begin;
|
||||||
|
iter_type end;
|
||||||
|
std::pair<boost::string_ref, boost::string_ref> v;
|
||||||
|
|
||||||
|
bool
|
||||||
|
empty() const
|
||||||
|
{
|
||||||
|
return begin == it;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class = void>
|
||||||
|
void
|
||||||
|
increment();
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class>
|
||||||
|
void
|
||||||
|
param_iter::
|
||||||
|
increment()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
ext-list = *( "," OWS ) ext *( OWS "," [ OWS ext ] )
|
||||||
|
ext = token param-list
|
||||||
|
param-list = *( OWS ";" OWS param )
|
||||||
|
param = token OWS "=" OWS ( token / quoted-string )
|
||||||
|
|
||||||
|
quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE
|
||||||
|
qdtext = HTAB / SP / "!" / %x23-5B ; '#'-'[' / %x5D-7E ; ']'-'~' / obs-text
|
||||||
|
quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
|
||||||
|
obs-text = %x80-FF
|
||||||
|
|
||||||
|
Example:
|
||||||
|
chunked;a=b;i=j,gzip;windowBits=12
|
||||||
|
x,y
|
||||||
|
*/
|
||||||
|
auto const err =
|
||||||
|
[&]
|
||||||
|
{
|
||||||
|
it = begin;
|
||||||
|
};
|
||||||
|
v.first.clear();
|
||||||
|
v.second.clear();
|
||||||
|
detail::skip_ows(it, end);
|
||||||
|
begin = it;
|
||||||
|
if(it == end)
|
||||||
|
return err();
|
||||||
|
if(*it != ';')
|
||||||
|
return err();
|
||||||
|
++it;
|
||||||
|
detail::skip_ows(it, end);
|
||||||
|
if(it == end)
|
||||||
|
return err();
|
||||||
|
// param
|
||||||
|
if(! detail::is_tchar(*it))
|
||||||
|
return err();
|
||||||
|
auto const p0 = it;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
++it;
|
||||||
|
if(it == end)
|
||||||
|
return err();
|
||||||
|
if(! detail::is_tchar(*it))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
auto const p1 = it;
|
||||||
|
detail::skip_ows(it, end);
|
||||||
|
if(it == end)
|
||||||
|
return err();
|
||||||
|
if(*it != '=')
|
||||||
|
return err();
|
||||||
|
++it;
|
||||||
|
detail::skip_ows(it, end);
|
||||||
|
if(it == end)
|
||||||
|
return err();
|
||||||
|
if(*it == '"')
|
||||||
|
{
|
||||||
|
// quoted-string
|
||||||
|
auto const p2 = it;
|
||||||
|
++it;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
if(it == end)
|
||||||
|
return err();
|
||||||
|
auto c = *it++;
|
||||||
|
if(c == '"')
|
||||||
|
break;
|
||||||
|
if(detail::is_qdchar(c))
|
||||||
|
continue;
|
||||||
|
if(c != '\\')
|
||||||
|
return err();
|
||||||
|
if(it == end)
|
||||||
|
return err();
|
||||||
|
c = *it++;
|
||||||
|
if(! detail::is_qpchar(c))
|
||||||
|
return err();
|
||||||
|
}
|
||||||
|
v.first = { &*p0, static_cast<std::size_t>(p1 - p0) };
|
||||||
|
v.second = { &*p2, static_cast<std::size_t>(it - p2) };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// token
|
||||||
|
if(! detail::is_tchar(*it))
|
||||||
|
return err();
|
||||||
|
auto const p2 = it;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
it++;
|
||||||
|
if(it == end)
|
||||||
|
break;
|
||||||
|
if(! detail::is_tchar(*it))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
v.first = { &*p0, static_cast<std::size_t>(p1 - p0) };
|
||||||
|
v.second = { &*p2, static_cast<std::size_t>(it - p2) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
} // http
|
||||||
|
} // beast
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -9,7 +9,6 @@
|
|||||||
#define BEAST_HTTP_EMPTY_BODY_HPP
|
#define BEAST_HTTP_EMPTY_BODY_HPP
|
||||||
|
|
||||||
#include <beast/http/body_type.hpp>
|
#include <beast/http/body_type.hpp>
|
||||||
#include <beast/core/streambuf.hpp>
|
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
#ifndef BEAST_HTTP_IMPL_BASIC_HEADERS_IPP
|
#ifndef BEAST_HTTP_IMPL_BASIC_HEADERS_IPP
|
||||||
#define BEAST_HTTP_IMPL_BASIC_HEADERS_IPP
|
#define BEAST_HTTP_IMPL_BASIC_HEADERS_IPP
|
||||||
|
|
||||||
|
#include <beast/http/detail/rfc7230.hpp>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace http {
|
namespace http {
|
||||||
|
|
||||||
@@ -257,12 +259,13 @@ template<class Allocator>
|
|||||||
void
|
void
|
||||||
basic_headers<Allocator>::
|
basic_headers<Allocator>::
|
||||||
insert(boost::string_ref const& name,
|
insert(boost::string_ref const& name,
|
||||||
boost::string_ref const& value)
|
boost::string_ref value)
|
||||||
{
|
{
|
||||||
|
value = detail::trim(value);
|
||||||
typename set_t::insert_commit_data d;
|
typename set_t::insert_commit_data d;
|
||||||
auto const result =
|
auto const result =
|
||||||
set_.insert_check(name, less{}, d);
|
set_.insert_check(name, less{}, d);
|
||||||
if (result.second)
|
if(result.second)
|
||||||
{
|
{
|
||||||
auto const p = alloc_traits::allocate(
|
auto const p = alloc_traits::allocate(
|
||||||
this->member(), 1);
|
this->member(), 1);
|
||||||
@@ -284,8 +287,9 @@ template<class Allocator>
|
|||||||
void
|
void
|
||||||
basic_headers<Allocator>::
|
basic_headers<Allocator>::
|
||||||
replace(boost::string_ref const& name,
|
replace(boost::string_ref const& name,
|
||||||
boost::string_ref const& value)
|
boost::string_ref value)
|
||||||
{
|
{
|
||||||
|
value = detail::trim(value);
|
||||||
erase(name);
|
erase(name);
|
||||||
insert(name, value);
|
insert(name, value);
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@
|
|||||||
#ifndef BEAST_HTTP_IMPL_MESSAGE_V1_IPP
|
#ifndef BEAST_HTTP_IMPL_MESSAGE_V1_IPP
|
||||||
#define BEAST_HTTP_IMPL_MESSAGE_V1_IPP
|
#define BEAST_HTTP_IMPL_MESSAGE_V1_IPP
|
||||||
|
|
||||||
#include <beast/http/rfc2616.hpp>
|
#include <beast/http/rfc7230.hpp>
|
||||||
#include <beast/http/detail/has_content_length.hpp>
|
#include <beast/http/detail/has_content_length.hpp>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
@@ -22,13 +22,11 @@ is_keep_alive(message_v1<isRequest, Body, Headers> const& msg)
|
|||||||
{
|
{
|
||||||
if(msg.version >= 11)
|
if(msg.version >= 11)
|
||||||
{
|
{
|
||||||
if(rfc2616::token_in_list(
|
if(token_list{msg.headers["Connection"]}.exists("close"))
|
||||||
msg.headers["Connection"], "close"))
|
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if(rfc2616::token_in_list(
|
if(token_list{msg.headers["Connection"]}.exists("keep-alive"))
|
||||||
msg.headers["Connection"], "keep-alive"))
|
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -39,8 +37,7 @@ is_upgrade(message_v1<isRequest, Body, Headers> const& msg)
|
|||||||
{
|
{
|
||||||
if(msg.version < 11)
|
if(msg.version < 11)
|
||||||
return false;
|
return false;
|
||||||
if(rfc2616::token_in_list(
|
if(token_list{msg.headers["Connection"]}.exists("upgrade"))
|
||||||
msg.headers["Connection"], "upgrade"))
|
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -129,8 +126,7 @@ prepare(message_v1<isRequest, Body, Headers>& msg,
|
|||||||
throw std::invalid_argument(
|
throw std::invalid_argument(
|
||||||
"prepare called with Content-Length field set");
|
"prepare called with Content-Length field set");
|
||||||
|
|
||||||
if(rfc2616::token_in_list(
|
if(token_list{msg.headers["Transfer-Encoding"]}.exists("chunked"))
|
||||||
msg.headers["Transfer-Encoding"], "chunked"))
|
|
||||||
throw std::invalid_argument(
|
throw std::invalid_argument(
|
||||||
"prepare called with Transfer-Encoding: chunked set");
|
"prepare called with Transfer-Encoding: chunked set");
|
||||||
|
|
||||||
@@ -175,8 +171,8 @@ prepare(message_v1<isRequest, Body, Headers>& msg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// rfc7230 6.7.
|
// rfc7230 6.7.
|
||||||
if(msg.version < 11 && rfc2616::token_in_list(
|
if(msg.version < 11 && token_list{
|
||||||
msg.headers["Connection"], "upgrade"))
|
msg.headers["Connection"]}.exists("upgrade"))
|
||||||
throw std::invalid_argument(
|
throw std::invalid_argument(
|
||||||
"invalid version for Connection: upgrade");
|
"invalid version for Connection: upgrade");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace http {
|
|||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template<class Stream,
|
template<class Stream,
|
||||||
class Streambuf, class Parser, class Handler>
|
class DynamicBuffer, class Parser, class Handler>
|
||||||
class parse_op
|
class parse_op
|
||||||
{
|
{
|
||||||
using alloc_type =
|
using alloc_type =
|
||||||
@@ -30,7 +30,7 @@ class parse_op
|
|||||||
struct data
|
struct data
|
||||||
{
|
{
|
||||||
Stream& s;
|
Stream& s;
|
||||||
Streambuf& sb;
|
DynamicBuffer& db;
|
||||||
Parser& p;
|
Parser& p;
|
||||||
Handler h;
|
Handler h;
|
||||||
bool started = false;
|
bool started = false;
|
||||||
@@ -39,9 +39,9 @@ class parse_op
|
|||||||
|
|
||||||
template<class DeducedHandler>
|
template<class DeducedHandler>
|
||||||
data(DeducedHandler&& h_, Stream& s_,
|
data(DeducedHandler&& h_, Stream& s_,
|
||||||
Streambuf& sb_, Parser& p_)
|
DynamicBuffer& sb_, Parser& p_)
|
||||||
: s(s_)
|
: s(s_)
|
||||||
, sb(sb_)
|
, db(sb_)
|
||||||
, p(p_)
|
, p(p_)
|
||||||
, h(std::forward<DeducedHandler>(h_))
|
, h(std::forward<DeducedHandler>(h_))
|
||||||
, cont(boost_asio_handler_cont_helpers::
|
, cont(boost_asio_handler_cont_helpers::
|
||||||
@@ -101,9 +101,9 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<class Stream,
|
template<class Stream,
|
||||||
class Streambuf, class Parser, class Handler>
|
class DynamicBuffer, class Parser, class Handler>
|
||||||
void
|
void
|
||||||
parse_op<Stream, Streambuf, Parser, Handler>::
|
parse_op<Stream, DynamicBuffer, Parser, Handler>::
|
||||||
operator()(error_code ec, std::size_t bytes_transferred, bool again)
|
operator()(error_code ec, std::size_t bytes_transferred, bool again)
|
||||||
{
|
{
|
||||||
auto& d = *d_;
|
auto& d = *d_;
|
||||||
@@ -115,7 +115,7 @@ operator()(error_code ec, std::size_t bytes_transferred, bool again)
|
|||||||
case 0:
|
case 0:
|
||||||
{
|
{
|
||||||
auto const used =
|
auto const used =
|
||||||
d.p.write(d.sb.data(), ec);
|
d.p.write(d.db.data(), ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
// call handler
|
// call handler
|
||||||
@@ -126,7 +126,7 @@ operator()(error_code ec, std::size_t bytes_transferred, bool again)
|
|||||||
}
|
}
|
||||||
if(used > 0)
|
if(used > 0)
|
||||||
d.started = true;
|
d.started = true;
|
||||||
d.sb.consume(used);
|
d.db.consume(used);
|
||||||
if(d.p.complete())
|
if(d.p.complete())
|
||||||
{
|
{
|
||||||
// call handler
|
// call handler
|
||||||
@@ -142,8 +142,8 @@ operator()(error_code ec, std::size_t bytes_transferred, bool again)
|
|||||||
case 1:
|
case 1:
|
||||||
// read
|
// read
|
||||||
d.state = 2;
|
d.state = 2;
|
||||||
d.s.async_read_some(d.sb.prepare(
|
d.s.async_read_some(d.db.prepare(
|
||||||
read_size_helper(d.sb, 65536)),
|
read_size_helper(d.db, 65536)),
|
||||||
std::move(*this));
|
std::move(*this));
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -172,8 +172,8 @@ operator()(error_code ec, std::size_t bytes_transferred, bool again)
|
|||||||
d.state = 99;
|
d.state = 99;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
d.sb.commit(bytes_transferred);
|
d.db.commit(bytes_transferred);
|
||||||
auto const used = d.p.write(d.sb.data(), ec);
|
auto const used = d.p.write(d.db.data(), ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
// call handler
|
// call handler
|
||||||
@@ -182,7 +182,7 @@ operator()(error_code ec, std::size_t bytes_transferred, bool again)
|
|||||||
}
|
}
|
||||||
if(used > 0)
|
if(used > 0)
|
||||||
d.started = true;
|
d.started = true;
|
||||||
d.sb.consume(used);
|
d.db.consume(used);
|
||||||
if(d.p.complete())
|
if(d.p.complete())
|
||||||
{
|
{
|
||||||
// call handler
|
// call handler
|
||||||
@@ -199,7 +199,7 @@ operator()(error_code ec, std::size_t bytes_transferred, bool again)
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class Stream, class Streambuf,
|
template<class Stream, class DynamicBuffer,
|
||||||
bool isRequest, class Body, class Headers,
|
bool isRequest, class Body, class Headers,
|
||||||
class Handler>
|
class Handler>
|
||||||
class read_op
|
class read_op
|
||||||
@@ -216,7 +216,7 @@ class read_op
|
|||||||
struct data
|
struct data
|
||||||
{
|
{
|
||||||
Stream& s;
|
Stream& s;
|
||||||
Streambuf& sb;
|
DynamicBuffer& db;
|
||||||
message_type& m;
|
message_type& m;
|
||||||
parser_type p;
|
parser_type p;
|
||||||
Handler h;
|
Handler h;
|
||||||
@@ -226,9 +226,9 @@ class read_op
|
|||||||
|
|
||||||
template<class DeducedHandler>
|
template<class DeducedHandler>
|
||||||
data(DeducedHandler&& h_, Stream& s_,
|
data(DeducedHandler&& h_, Stream& s_,
|
||||||
Streambuf& sb_, message_type& m_)
|
DynamicBuffer& sb_, message_type& m_)
|
||||||
: s(s_)
|
: s(s_)
|
||||||
, sb(sb_)
|
, db(sb_)
|
||||||
, m(m_)
|
, m(m_)
|
||||||
, h(std::forward<DeducedHandler>(h_))
|
, h(std::forward<DeducedHandler>(h_))
|
||||||
, cont(boost_asio_handler_cont_helpers::
|
, cont(boost_asio_handler_cont_helpers::
|
||||||
@@ -286,11 +286,11 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Stream, class Streambuf,
|
template<class Stream, class DynamicBuffer,
|
||||||
bool isRequest, class Body, class Headers,
|
bool isRequest, class Body, class Headers,
|
||||||
class Handler>
|
class Handler>
|
||||||
void
|
void
|
||||||
read_op<Stream, Streambuf, isRequest, Body, Headers, Handler>::
|
read_op<Stream, DynamicBuffer, isRequest, Body, Headers, Handler>::
|
||||||
operator()(error_code ec, bool again)
|
operator()(error_code ec, bool again)
|
||||||
{
|
{
|
||||||
auto& d = *d_;
|
auto& d = *d_;
|
||||||
@@ -301,7 +301,7 @@ operator()(error_code ec, bool again)
|
|||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
d.state = 1;
|
d.state = 1;
|
||||||
async_parse(d.s, d.sb, d.p, std::move(*this));
|
async_parse(d.s, d.db, d.p, std::move(*this));
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
@@ -318,49 +318,49 @@ operator()(error_code ec, bool again)
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class SyncReadStream, class Streambuf, class Parser>
|
template<class SyncReadStream, class DynamicBuffer, class Parser>
|
||||||
void
|
void
|
||||||
parse(SyncReadStream& stream,
|
parse(SyncReadStream& stream,
|
||||||
Streambuf& streambuf, Parser& parser)
|
DynamicBuffer& dynabuf, Parser& parser)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncReadStream<SyncReadStream>::value,
|
static_assert(is_SyncReadStream<SyncReadStream>::value,
|
||||||
"SyncReadStream requirements not met");
|
"SyncReadStream requirements not met");
|
||||||
static_assert(is_Streambuf<Streambuf>::value,
|
static_assert(is_DynamicBuffer<DynamicBuffer>::value,
|
||||||
"Streambuf requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
static_assert(is_Parser<Parser>::value,
|
static_assert(is_Parser<Parser>::value,
|
||||||
"Parser requirements not met");
|
"Parser requirements not met");
|
||||||
error_code ec;
|
error_code ec;
|
||||||
parse(stream, streambuf, parser, ec);
|
parse(stream, dynabuf, parser, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
throw boost::system::system_error{ec};
|
throw boost::system::system_error{ec};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class SyncReadStream, class Streambuf, class Parser>
|
template<class SyncReadStream, class DynamicBuffer, class Parser>
|
||||||
void
|
void
|
||||||
parse(SyncReadStream& stream, Streambuf& streambuf,
|
parse(SyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||||
Parser& parser, error_code& ec)
|
Parser& parser, error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncReadStream<SyncReadStream>::value,
|
static_assert(is_SyncReadStream<SyncReadStream>::value,
|
||||||
"SyncReadStream requirements not met");
|
"SyncReadStream requirements not met");
|
||||||
static_assert(is_Streambuf<Streambuf>::value,
|
static_assert(is_DynamicBuffer<DynamicBuffer>::value,
|
||||||
"Streambuf requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
static_assert(is_Parser<Parser>::value,
|
static_assert(is_Parser<Parser>::value,
|
||||||
"Parser requirements not met");
|
"Parser requirements not met");
|
||||||
bool started = false;
|
bool started = false;
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
auto used =
|
auto used =
|
||||||
parser.write(streambuf.data(), ec);
|
parser.write(dynabuf.data(), ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
return;
|
return;
|
||||||
streambuf.consume(used);
|
dynabuf.consume(used);
|
||||||
if(used > 0)
|
if(used > 0)
|
||||||
started = true;
|
started = true;
|
||||||
if(parser.complete())
|
if(parser.complete())
|
||||||
break;
|
break;
|
||||||
streambuf.commit(stream.read_some(
|
dynabuf.commit(stream.read_some(
|
||||||
streambuf.prepare(read_size_helper(
|
dynabuf.prepare(read_size_helper(
|
||||||
streambuf, 65536)), ec));
|
dynabuf, 65536)), ec));
|
||||||
if(ec && ec != boost::asio::error::eof)
|
if(ec && ec != boost::asio::error::eof)
|
||||||
return;
|
return;
|
||||||
if(ec == boost::asio::error::eof)
|
if(ec == boost::asio::error::eof)
|
||||||
@@ -379,86 +379,86 @@ parse(SyncReadStream& stream, Streambuf& streambuf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class AsyncReadStream,
|
template<class AsyncReadStream,
|
||||||
class Streambuf, class Parser, class ReadHandler>
|
class DynamicBuffer, class Parser, class ReadHandler>
|
||||||
typename async_completion<
|
typename async_completion<
|
||||||
ReadHandler, void(error_code)>::result_type
|
ReadHandler, void(error_code)>::result_type
|
||||||
async_parse(AsyncReadStream& stream,
|
async_parse(AsyncReadStream& stream,
|
||||||
Streambuf& streambuf, Parser& parser, ReadHandler&& handler)
|
DynamicBuffer& dynabuf, Parser& parser, ReadHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncReadStream<AsyncReadStream>::value,
|
static_assert(is_AsyncReadStream<AsyncReadStream>::value,
|
||||||
"AsyncReadStream requirements not met");
|
"AsyncReadStream requirements not met");
|
||||||
static_assert(is_Streambuf<Streambuf>::value,
|
static_assert(is_DynamicBuffer<DynamicBuffer>::value,
|
||||||
"Streambuf requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
static_assert(is_Parser<Parser>::value,
|
static_assert(is_Parser<Parser>::value,
|
||||||
"Parser requirements not met");
|
"Parser requirements not met");
|
||||||
beast::async_completion<ReadHandler,
|
beast::async_completion<ReadHandler,
|
||||||
void(error_code)> completion(handler);
|
void(error_code)> completion(handler);
|
||||||
detail::parse_op<AsyncReadStream, Streambuf,
|
detail::parse_op<AsyncReadStream, DynamicBuffer,
|
||||||
Parser, decltype(completion.handler)>{
|
Parser, decltype(completion.handler)>{
|
||||||
completion.handler, stream, streambuf, parser};
|
completion.handler, stream, dynabuf, parser};
|
||||||
return completion.result.get();
|
return completion.result.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class SyncReadStream, class Streambuf,
|
template<class SyncReadStream, class DynamicBuffer,
|
||||||
bool isRequest, class Body, class Headers>
|
bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
read(SyncReadStream& stream, Streambuf& streambuf,
|
read(SyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||||
message_v1<isRequest, Body, Headers>& msg)
|
message_v1<isRequest, Body, Headers>& msg)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncReadStream<SyncReadStream>::value,
|
static_assert(is_SyncReadStream<SyncReadStream>::value,
|
||||||
"SyncReadStream requirements not met");
|
"SyncReadStream requirements not met");
|
||||||
static_assert(is_Streambuf<Streambuf>::value,
|
static_assert(is_DynamicBuffer<DynamicBuffer>::value,
|
||||||
"Streambuf requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
static_assert(is_ReadableBody<Body>::value,
|
static_assert(is_ReadableBody<Body>::value,
|
||||||
"ReadableBody requirements not met");
|
"ReadableBody requirements not met");
|
||||||
error_code ec;
|
error_code ec;
|
||||||
read(stream, streambuf, msg, ec);
|
read(stream, dynabuf, msg, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
throw system_error{ec};
|
throw system_error{ec};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class SyncReadStream, class Streambuf,
|
template<class SyncReadStream, class DynamicBuffer,
|
||||||
bool isRequest, class Body, class Headers>
|
bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
read(SyncReadStream& stream, Streambuf& streambuf,
|
read(SyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||||
message_v1<isRequest, Body, Headers>& m,
|
message_v1<isRequest, Body, Headers>& m,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncReadStream<SyncReadStream>::value,
|
static_assert(is_SyncReadStream<SyncReadStream>::value,
|
||||||
"SyncReadStream requirements not met");
|
"SyncReadStream requirements not met");
|
||||||
static_assert(is_Streambuf<Streambuf>::value,
|
static_assert(is_DynamicBuffer<DynamicBuffer>::value,
|
||||||
"Streambuf requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
static_assert(is_ReadableBody<Body>::value,
|
static_assert(is_ReadableBody<Body>::value,
|
||||||
"ReadableBody requirements not met");
|
"ReadableBody requirements not met");
|
||||||
parser_v1<isRequest, Body, Headers> p;
|
parser_v1<isRequest, Body, Headers> p;
|
||||||
parse(stream, streambuf, p, ec);
|
parse(stream, dynabuf, p, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
return;
|
return;
|
||||||
assert(p.complete());
|
assert(p.complete());
|
||||||
m = p.release();
|
m = p.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class AsyncReadStream, class Streambuf,
|
template<class AsyncReadStream, class DynamicBuffer,
|
||||||
bool isRequest, class Body, class Headers,
|
bool isRequest, class Body, class Headers,
|
||||||
class ReadHandler>
|
class ReadHandler>
|
||||||
typename async_completion<
|
typename async_completion<
|
||||||
ReadHandler, void(error_code)>::result_type
|
ReadHandler, void(error_code)>::result_type
|
||||||
async_read(AsyncReadStream& stream, Streambuf& streambuf,
|
async_read(AsyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||||
message_v1<isRequest, Body, Headers>& m,
|
message_v1<isRequest, Body, Headers>& m,
|
||||||
ReadHandler&& handler)
|
ReadHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncReadStream<AsyncReadStream>::value,
|
static_assert(is_AsyncReadStream<AsyncReadStream>::value,
|
||||||
"AsyncReadStream requirements not met");
|
"AsyncReadStream requirements not met");
|
||||||
static_assert(is_Streambuf<Streambuf>::value,
|
static_assert(is_DynamicBuffer<DynamicBuffer>::value,
|
||||||
"Streambuf requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
static_assert(is_ReadableBody<Body>::value,
|
static_assert(is_ReadableBody<Body>::value,
|
||||||
"ReadableBody requirements not met");
|
"ReadableBody requirements not met");
|
||||||
beast::async_completion<ReadHandler,
|
beast::async_completion<ReadHandler,
|
||||||
void(error_code)> completion(handler);
|
void(error_code)> completion(handler);
|
||||||
detail::read_op<AsyncReadStream, Streambuf,
|
detail::read_op<AsyncReadStream, DynamicBuffer,
|
||||||
isRequest, Body, Headers, decltype(
|
isRequest, Body, Headers, decltype(
|
||||||
completion.handler)>{completion.handler,
|
completion.handler)>{completion.handler,
|
||||||
stream, streambuf, m};
|
stream, dynabuf, m};
|
||||||
return completion.result.get();
|
return completion.result.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
548
src/beast/include/beast/http/impl/rfc7230.ipp
Normal file
548
src/beast/include/beast/http/impl/rfc7230.ipp
Normal file
@@ -0,0 +1,548 @@
|
|||||||
|
//
|
||||||
|
// 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_IMPL_RFC7230_IPP
|
||||||
|
#define BEAST_HTTP_IMPL_RFC7230_IPP
|
||||||
|
|
||||||
|
#include <beast/core/detail/ci_char_traits.hpp>
|
||||||
|
#include <beast/http/detail/rfc7230.hpp>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
namespace http {
|
||||||
|
|
||||||
|
class param_list::const_iterator
|
||||||
|
{
|
||||||
|
using iter_type = boost::string_ref::const_iterator;
|
||||||
|
|
||||||
|
std::string s_;
|
||||||
|
detail::param_iter pi_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using value_type = param_list::value_type;
|
||||||
|
using pointer = value_type const*;
|
||||||
|
using reference = value_type const&;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using iterator_category = std::input_iterator_tag;
|
||||||
|
|
||||||
|
const_iterator() = default;
|
||||||
|
|
||||||
|
bool
|
||||||
|
operator==(const_iterator const& other) const
|
||||||
|
{
|
||||||
|
return
|
||||||
|
other.pi_.it == pi_.it &&
|
||||||
|
other.pi_.end == pi_.end &&
|
||||||
|
other.pi_.begin == pi_.begin;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
operator!=(const_iterator const& other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
reference
|
||||||
|
operator*() const
|
||||||
|
{
|
||||||
|
return pi_.v;
|
||||||
|
}
|
||||||
|
|
||||||
|
pointer
|
||||||
|
operator->() const
|
||||||
|
{
|
||||||
|
return &*(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator&
|
||||||
|
operator++()
|
||||||
|
{
|
||||||
|
increment();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator
|
||||||
|
operator++(int)
|
||||||
|
{
|
||||||
|
auto temp = *this;
|
||||||
|
++(*this);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class param_list;
|
||||||
|
|
||||||
|
const_iterator(iter_type begin, iter_type end)
|
||||||
|
{
|
||||||
|
pi_.it = begin;
|
||||||
|
pi_.begin = begin;
|
||||||
|
pi_.end = end;
|
||||||
|
increment();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class = void>
|
||||||
|
static
|
||||||
|
std::string
|
||||||
|
unquote(boost::string_ref const& sr);
|
||||||
|
|
||||||
|
template<class = void>
|
||||||
|
void
|
||||||
|
increment();
|
||||||
|
};
|
||||||
|
|
||||||
|
inline
|
||||||
|
auto
|
||||||
|
param_list::
|
||||||
|
begin() const ->
|
||||||
|
const_iterator
|
||||||
|
{
|
||||||
|
return const_iterator{s_.begin(), s_.end()};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
auto
|
||||||
|
param_list::
|
||||||
|
end() const ->
|
||||||
|
const_iterator
|
||||||
|
{
|
||||||
|
return const_iterator{s_.end(), s_.end()};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
auto
|
||||||
|
param_list::
|
||||||
|
cbegin() const ->
|
||||||
|
const_iterator
|
||||||
|
{
|
||||||
|
return const_iterator{s_.begin(), s_.end()};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
auto
|
||||||
|
param_list::
|
||||||
|
cend() const ->
|
||||||
|
const_iterator
|
||||||
|
{
|
||||||
|
return const_iterator{s_.end(), s_.end()};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class>
|
||||||
|
std::string
|
||||||
|
param_list::const_iterator::
|
||||||
|
unquote(boost::string_ref const& sr)
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
s.reserve(sr.size());
|
||||||
|
auto it = sr.begin() + 1;
|
||||||
|
auto end = sr.end() - 1;
|
||||||
|
while(it != end)
|
||||||
|
{
|
||||||
|
if(*it == '\\')
|
||||||
|
++it;
|
||||||
|
s.push_back(*it);
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class>
|
||||||
|
void
|
||||||
|
param_list::const_iterator::
|
||||||
|
increment()
|
||||||
|
{
|
||||||
|
s_.clear();
|
||||||
|
pi_.increment();
|
||||||
|
if(pi_.empty())
|
||||||
|
{
|
||||||
|
pi_.it = pi_.end;
|
||||||
|
pi_.begin = pi_.end;
|
||||||
|
}
|
||||||
|
else if(pi_.v.second.front() == '"')
|
||||||
|
{
|
||||||
|
s_ = unquote(pi_.v.second);
|
||||||
|
pi_.v.second = boost::string_ref{
|
||||||
|
s_.data(), s_.size()};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class ext_list::const_iterator
|
||||||
|
{
|
||||||
|
ext_list::value_type v_;
|
||||||
|
iter_type it_;
|
||||||
|
iter_type begin_;
|
||||||
|
iter_type end_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using value_type = ext_list::value_type;
|
||||||
|
using pointer = value_type const*;
|
||||||
|
using reference = value_type const&;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using iterator_category = std::forward_iterator_tag;
|
||||||
|
|
||||||
|
const_iterator() = default;
|
||||||
|
|
||||||
|
bool
|
||||||
|
operator==(const_iterator const& other) const
|
||||||
|
{
|
||||||
|
return
|
||||||
|
other.it_ == it_ &&
|
||||||
|
other.begin_ == begin_ &&
|
||||||
|
other.end_ == end_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
operator!=(const_iterator const& other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
reference
|
||||||
|
operator*() const
|
||||||
|
{
|
||||||
|
return v_;
|
||||||
|
}
|
||||||
|
|
||||||
|
pointer
|
||||||
|
operator->() const
|
||||||
|
{
|
||||||
|
return &*(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator&
|
||||||
|
operator++()
|
||||||
|
{
|
||||||
|
increment();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator
|
||||||
|
operator++(int)
|
||||||
|
{
|
||||||
|
auto temp = *this;
|
||||||
|
++(*this);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class ext_list;
|
||||||
|
|
||||||
|
const_iterator(iter_type begin, iter_type end)
|
||||||
|
{
|
||||||
|
it_ = begin;
|
||||||
|
begin_ = begin;
|
||||||
|
end_ = end;
|
||||||
|
increment();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class = void>
|
||||||
|
void
|
||||||
|
increment();
|
||||||
|
};
|
||||||
|
|
||||||
|
inline
|
||||||
|
auto
|
||||||
|
ext_list::
|
||||||
|
begin() const ->
|
||||||
|
const_iterator
|
||||||
|
{
|
||||||
|
return const_iterator{s_.begin(), s_.end()};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
auto
|
||||||
|
ext_list::
|
||||||
|
end() const ->
|
||||||
|
const_iterator
|
||||||
|
{
|
||||||
|
return const_iterator{s_.end(), s_.end()};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
auto
|
||||||
|
ext_list::
|
||||||
|
cbegin() const ->
|
||||||
|
const_iterator
|
||||||
|
{
|
||||||
|
return const_iterator{s_.begin(), s_.end()};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
auto
|
||||||
|
ext_list::
|
||||||
|
cend() const ->
|
||||||
|
const_iterator
|
||||||
|
{
|
||||||
|
return const_iterator{s_.end(), s_.end()};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
auto
|
||||||
|
ext_list::
|
||||||
|
find(T const& s) ->
|
||||||
|
const_iterator
|
||||||
|
{
|
||||||
|
return std::find_if(begin(), end(),
|
||||||
|
[&s](value_type const& v)
|
||||||
|
{
|
||||||
|
return beast::detail::ci_equal(s, v.first);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
bool
|
||||||
|
ext_list::
|
||||||
|
exists(T const& s)
|
||||||
|
{
|
||||||
|
return find(s) != end();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class>
|
||||||
|
void
|
||||||
|
ext_list::const_iterator::
|
||||||
|
increment()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
ext-list = *( "," OWS ) ext *( OWS "," [ OWS ext ] )
|
||||||
|
ext = token param-list
|
||||||
|
param-list = *( OWS ";" OWS param )
|
||||||
|
param = token OWS "=" OWS ( token / quoted-string )
|
||||||
|
|
||||||
|
chunked;a=b;i=j,gzip;windowBits=12
|
||||||
|
x,y
|
||||||
|
,,,,,chameleon
|
||||||
|
*/
|
||||||
|
auto const err =
|
||||||
|
[&]
|
||||||
|
{
|
||||||
|
it_ = end_;
|
||||||
|
begin_ = end_;
|
||||||
|
};
|
||||||
|
auto need_comma = it_ != begin_;
|
||||||
|
v_.first = {};
|
||||||
|
begin_ = it_;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
detail::skip_ows(it_, end_);
|
||||||
|
if(it_ == end_)
|
||||||
|
return err();
|
||||||
|
auto const c = *it_;
|
||||||
|
if(detail::is_tchar(c))
|
||||||
|
{
|
||||||
|
if(need_comma)
|
||||||
|
return err();
|
||||||
|
auto const p0 = it_;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
++it_;
|
||||||
|
if(it_ == end_)
|
||||||
|
break;
|
||||||
|
if(! detail::is_tchar(*it_))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
v_.first = boost::string_ref{&*p0,
|
||||||
|
static_cast<std::size_t>(it_ - p0)};
|
||||||
|
detail::param_iter pi;
|
||||||
|
pi.it = it_;
|
||||||
|
pi.begin = it_;
|
||||||
|
pi.end = end_;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
pi.increment();
|
||||||
|
if(pi.empty())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
v_.second = param_list{boost::string_ref{&*it_,
|
||||||
|
static_cast<std::size_t>(pi.it - it_)}};
|
||||||
|
it_ = pi.it;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(c != ',')
|
||||||
|
return err();
|
||||||
|
need_comma = false;
|
||||||
|
++it_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class token_list::const_iterator
|
||||||
|
{
|
||||||
|
token_list::value_type v_;
|
||||||
|
iter_type it_;
|
||||||
|
iter_type begin_;
|
||||||
|
iter_type end_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using value_type = token_list::value_type;
|
||||||
|
using pointer = value_type const*;
|
||||||
|
using reference = value_type const&;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using iterator_category = std::forward_iterator_tag;
|
||||||
|
|
||||||
|
const_iterator() = default;
|
||||||
|
|
||||||
|
bool
|
||||||
|
operator==(const_iterator const& other) const
|
||||||
|
{
|
||||||
|
return
|
||||||
|
other.it_ == it_ &&
|
||||||
|
other.begin_ == begin_ &&
|
||||||
|
other.end_ == end_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
operator!=(const_iterator const& other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
reference
|
||||||
|
operator*() const
|
||||||
|
{
|
||||||
|
return v_;
|
||||||
|
}
|
||||||
|
|
||||||
|
pointer
|
||||||
|
operator->() const
|
||||||
|
{
|
||||||
|
return &*(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator&
|
||||||
|
operator++()
|
||||||
|
{
|
||||||
|
increment();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator
|
||||||
|
operator++(int)
|
||||||
|
{
|
||||||
|
auto temp = *this;
|
||||||
|
++(*this);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class token_list;
|
||||||
|
|
||||||
|
const_iterator(iter_type begin, iter_type end)
|
||||||
|
{
|
||||||
|
it_ = begin;
|
||||||
|
begin_ = begin;
|
||||||
|
end_ = end;
|
||||||
|
increment();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class = void>
|
||||||
|
void
|
||||||
|
increment();
|
||||||
|
};
|
||||||
|
|
||||||
|
inline
|
||||||
|
auto
|
||||||
|
token_list::
|
||||||
|
begin() const ->
|
||||||
|
const_iterator
|
||||||
|
{
|
||||||
|
return const_iterator{s_.begin(), s_.end()};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
auto
|
||||||
|
token_list::
|
||||||
|
end() const ->
|
||||||
|
const_iterator
|
||||||
|
{
|
||||||
|
return const_iterator{s_.end(), s_.end()};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
auto
|
||||||
|
token_list::
|
||||||
|
cbegin() const ->
|
||||||
|
const_iterator
|
||||||
|
{
|
||||||
|
return const_iterator{s_.begin(), s_.end()};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
auto
|
||||||
|
token_list::
|
||||||
|
cend() const ->
|
||||||
|
const_iterator
|
||||||
|
{
|
||||||
|
return const_iterator{s_.end(), s_.end()};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class>
|
||||||
|
void
|
||||||
|
token_list::const_iterator::
|
||||||
|
increment()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
token-list = *( "," OWS ) token *( OWS "," [ OWS ext ] )
|
||||||
|
*/
|
||||||
|
auto const err =
|
||||||
|
[&]
|
||||||
|
{
|
||||||
|
it_ = end_;
|
||||||
|
begin_ = end_;
|
||||||
|
};
|
||||||
|
auto need_comma = it_ != begin_;
|
||||||
|
v_ = {};
|
||||||
|
begin_ = it_;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
detail::skip_ows(it_, end_);
|
||||||
|
if(it_ == end_)
|
||||||
|
return err();
|
||||||
|
auto const c = *it_;
|
||||||
|
if(detail::is_tchar(c))
|
||||||
|
{
|
||||||
|
if(need_comma)
|
||||||
|
return err();
|
||||||
|
auto const p0 = it_;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
++it_;
|
||||||
|
if(it_ == end_)
|
||||||
|
break;
|
||||||
|
if(! detail::is_tchar(*it_))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
v_ = boost::string_ref{&*p0,
|
||||||
|
static_cast<std::size_t>(it_ - p0)};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(c != ',')
|
||||||
|
return err();
|
||||||
|
need_comma = false;
|
||||||
|
++it_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
bool
|
||||||
|
token_list::
|
||||||
|
exists(T const& s)
|
||||||
|
{
|
||||||
|
return std::find_if(begin(), end(),
|
||||||
|
[&s](value_type const& v)
|
||||||
|
{
|
||||||
|
return beast::detail::ci_equal(s, v);
|
||||||
|
}
|
||||||
|
) != end();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // http
|
||||||
|
} // beast
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
#include <beast/core/handler_alloc.hpp>
|
#include <beast/core/handler_alloc.hpp>
|
||||||
#include <beast/core/stream_concepts.hpp>
|
#include <beast/core/stream_concepts.hpp>
|
||||||
#include <beast/core/streambuf.hpp>
|
#include <beast/core/streambuf.hpp>
|
||||||
#include <beast/core/write_streambuf.hpp>
|
#include <beast/core/write_dynabuf.hpp>
|
||||||
#include <boost/asio/write.hpp>
|
#include <boost/asio/write.hpp>
|
||||||
#include <boost/logic/tribool.hpp>
|
#include <boost/logic/tribool.hpp>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
@@ -32,51 +32,51 @@ namespace http {
|
|||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template<class Streambuf, class Body, class Headers>
|
template<class DynamicBuffer, class Body, class Headers>
|
||||||
void
|
void
|
||||||
write_firstline(Streambuf& streambuf,
|
write_firstline(DynamicBuffer& dynabuf,
|
||||||
message_v1<true, Body, Headers> const& msg)
|
message_v1<true, Body, Headers> const& msg)
|
||||||
{
|
{
|
||||||
write(streambuf, msg.method);
|
write(dynabuf, msg.method);
|
||||||
write(streambuf, " ");
|
write(dynabuf, " ");
|
||||||
write(streambuf, msg.url);
|
write(dynabuf, msg.url);
|
||||||
write(streambuf, " HTTP/");
|
write(dynabuf, " HTTP/");
|
||||||
write(streambuf, msg.version / 10);
|
write(dynabuf, msg.version / 10);
|
||||||
write(streambuf, ".");
|
write(dynabuf, ".");
|
||||||
write(streambuf, msg.version % 10);
|
write(dynabuf, msg.version % 10);
|
||||||
write(streambuf, "\r\n");
|
write(dynabuf, "\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Streambuf, class Body, class Headers>
|
template<class DynamicBuffer, class Body, class Headers>
|
||||||
void
|
void
|
||||||
write_firstline(Streambuf& streambuf,
|
write_firstline(DynamicBuffer& dynabuf,
|
||||||
message_v1<false, Body, Headers> const& msg)
|
message_v1<false, Body, Headers> const& msg)
|
||||||
{
|
{
|
||||||
write(streambuf, "HTTP/");
|
write(dynabuf, "HTTP/");
|
||||||
write(streambuf, msg.version / 10);
|
write(dynabuf, msg.version / 10);
|
||||||
write(streambuf, ".");
|
write(dynabuf, ".");
|
||||||
write(streambuf, msg.version % 10);
|
write(dynabuf, msg.version % 10);
|
||||||
write(streambuf, " ");
|
write(dynabuf, " ");
|
||||||
write(streambuf, msg.status);
|
write(dynabuf, msg.status);
|
||||||
write(streambuf, " ");
|
write(dynabuf, " ");
|
||||||
write(streambuf, msg.reason);
|
write(dynabuf, msg.reason);
|
||||||
write(streambuf, "\r\n");
|
write(dynabuf, "\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Streambuf, class FieldSequence>
|
template<class DynamicBuffer, class FieldSequence>
|
||||||
void
|
void
|
||||||
write_fields(Streambuf& streambuf, FieldSequence const& fields)
|
write_fields(DynamicBuffer& dynabuf, FieldSequence const& fields)
|
||||||
{
|
{
|
||||||
static_assert(is_Streambuf<Streambuf>::value,
|
static_assert(is_DynamicBuffer<DynamicBuffer>::value,
|
||||||
"Streambuf requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
//static_assert(is_FieldSequence<FieldSequence>::value,
|
//static_assert(is_FieldSequence<FieldSequence>::value,
|
||||||
// "FieldSequence requirements not met");
|
// "FieldSequence requirements not met");
|
||||||
for(auto const& field : fields)
|
for(auto const& field : fields)
|
||||||
{
|
{
|
||||||
write(streambuf, field.name());
|
write(dynabuf, field.name());
|
||||||
write(streambuf, ": ");
|
write(dynabuf, ": ");
|
||||||
write(streambuf, field.value());
|
write(dynabuf, field.value());
|
||||||
write(streambuf, "\r\n");
|
write(dynabuf, "\r\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,10 +97,10 @@ struct write_preparation
|
|||||||
message_v1<isRequest, Body, Headers> const& msg_)
|
message_v1<isRequest, Body, Headers> const& msg_)
|
||||||
: msg(msg_)
|
: msg(msg_)
|
||||||
, w(msg)
|
, w(msg)
|
||||||
, chunked(rfc2616::token_in_list(
|
, chunked(token_list{
|
||||||
msg.headers["Transfer-Encoding"], "chunked"))
|
msg.headers["Transfer-Encoding"]}.exists("chunked"))
|
||||||
, close(rfc2616::token_in_list(
|
, close(token_list{
|
||||||
msg.headers["Connection"], "close") ||
|
msg.headers["Connection"]}.exists("close") ||
|
||||||
(msg.version < 11 && ! msg.headers.exists(
|
(msg.version < 11 && ! msg.headers.exists(
|
||||||
"Content-Length")))
|
"Content-Length")))
|
||||||
{
|
{
|
||||||
@@ -378,17 +378,17 @@ operator()(error_code ec, std::size_t, bool again)
|
|||||||
d.copy = {};
|
d.copy = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class SyncWriteStream, class Streambuf>
|
template<class SyncWriteStream, class DynamicBuffer>
|
||||||
class writef0_lambda
|
class writef0_lambda
|
||||||
{
|
{
|
||||||
Streambuf const& sb_;
|
DynamicBuffer const& sb_;
|
||||||
SyncWriteStream& stream_;
|
SyncWriteStream& stream_;
|
||||||
bool chunked_;
|
bool chunked_;
|
||||||
error_code& ec_;
|
error_code& ec_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
writef0_lambda(SyncWriteStream& stream,
|
writef0_lambda(SyncWriteStream& stream,
|
||||||
Streambuf const& sb, bool chunked, error_code& ec)
|
DynamicBuffer const& sb, bool chunked, error_code& ec)
|
||||||
: sb_(sb)
|
: sb_(sb)
|
||||||
, stream_(stream)
|
, stream_(stream)
|
||||||
, chunked_(chunked)
|
, chunked_(chunked)
|
||||||
@@ -548,8 +548,7 @@ async_write(AsyncWriteStream& stream,
|
|||||||
message_v1<isRequest, Body, Headers> const& msg,
|
message_v1<isRequest, Body, Headers> const& msg,
|
||||||
WriteHandler&& handler)
|
WriteHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(
|
static_assert(is_AsyncWriteStream<AsyncWriteStream>::value,
|
||||||
is_AsyncWriteStream<AsyncWriteStream>::value,
|
|
||||||
"AsyncWriteStream requirements not met");
|
"AsyncWriteStream requirements not met");
|
||||||
static_assert(is_WritableBody<Body>::value,
|
static_assert(is_WritableBody<Body>::value,
|
||||||
"WritableBody requirements not met");
|
"WritableBody requirements not met");
|
||||||
|
|||||||
@@ -24,12 +24,30 @@ struct request_fields
|
|||||||
{
|
{
|
||||||
std::string method;
|
std::string method;
|
||||||
std::string url;
|
std::string url;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void
|
||||||
|
swap(request_fields& other)
|
||||||
|
{
|
||||||
|
using std::swap;
|
||||||
|
swap(method, other.method);
|
||||||
|
swap(url, other.url);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct response_fields
|
struct response_fields
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
std::string reason;
|
std::string reason;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void
|
||||||
|
swap(response_fields& other)
|
||||||
|
{
|
||||||
|
using std::swap;
|
||||||
|
swap(status, other.status);
|
||||||
|
swap(reason, other.reason);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
@@ -125,7 +143,14 @@ struct message
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Swap this message for another message.
|
||||||
|
void
|
||||||
|
swap(message& other);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
using base = typename std::conditional<isRequest,
|
||||||
|
detail::request_fields, detail::response_fields>::type;
|
||||||
|
|
||||||
template<class... Un, size_t... IUn>
|
template<class... Un, size_t... IUn>
|
||||||
message(std::piecewise_construct_t,
|
message(std::piecewise_construct_t,
|
||||||
std::tuple<Un...>& tu, beast::detail::index_sequence<IUn...>)
|
std::tuple<Un...>& tu, beast::detail::index_sequence<IUn...>)
|
||||||
@@ -145,7 +170,26 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#if ! GENERATING_DOCS
|
template<bool isRequest, class Body, class Headers>
|
||||||
|
void
|
||||||
|
message<isRequest, Body, Headers>::
|
||||||
|
swap(message& other)
|
||||||
|
{
|
||||||
|
using std::swap;
|
||||||
|
base::swap(other);
|
||||||
|
swap(headers, other.headers);
|
||||||
|
swap(body, other.body);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Swap one message for another message.
|
||||||
|
template<bool isRequest, class Body, class Headers>
|
||||||
|
inline
|
||||||
|
void
|
||||||
|
swap(message<isRequest, Body, Headers>& lhs,
|
||||||
|
message<isRequest, Body, Headers>& rhs)
|
||||||
|
{
|
||||||
|
lhs.swap(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
/// A typical HTTP request
|
/// A typical HTTP request
|
||||||
template<class Body,
|
template<class Body,
|
||||||
@@ -157,8 +201,6 @@ template<class Body,
|
|||||||
class Headers = basic_headers<std::allocator<char>>>
|
class Headers = basic_headers<std::allocator<char>>>
|
||||||
using response = message<false, Body, Headers>;
|
using response = message<false, Body, Headers>;
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // http
|
} // http
|
||||||
} // beast
|
} // beast
|
||||||
|
|
||||||
|
|||||||
@@ -48,9 +48,31 @@ struct message_v1 : message<isRequest, Body, Headers>
|
|||||||
std::forward<Argn>(argn)...)
|
std::forward<Argn>(argn)...)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Swap this message for another message.
|
||||||
|
void
|
||||||
|
swap(message_v1& other);
|
||||||
};
|
};
|
||||||
|
|
||||||
#if ! GENERATING_DOCS
|
template<bool isRequest, class Body, class Headers>
|
||||||
|
void
|
||||||
|
message_v1<isRequest, Body, Headers>::
|
||||||
|
swap(message_v1& other)
|
||||||
|
{
|
||||||
|
using std::swap;
|
||||||
|
message<isRequest, Body, Headers>::swap(other);
|
||||||
|
swap(version, other.version);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Swap one message for another message.
|
||||||
|
template<bool isRequest, class Body, class Headers>
|
||||||
|
inline
|
||||||
|
void
|
||||||
|
swap(message_v1<isRequest, Body, Headers>& lhs,
|
||||||
|
message_v1<isRequest, Body, Headers>& rhs)
|
||||||
|
{
|
||||||
|
lhs.swap(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
/// A typical HTTP/1 request
|
/// A typical HTTP/1 request
|
||||||
template<class Body,
|
template<class Body,
|
||||||
@@ -62,8 +84,6 @@ template<class Body,
|
|||||||
class Headers = basic_headers<std::allocator<char>>>
|
class Headers = basic_headers<std::allocator<char>>>
|
||||||
using response_v1 = message_v1<false, Body, Headers>;
|
using response_v1 = message_v1<false, Body, Headers>;
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// Returns `true` if a HTTP/1 message indicates a keep alive
|
/// Returns `true` if a HTTP/1 message indicates a keep alive
|
||||||
template<bool isRequest, class Body, class Headers>
|
template<bool isRequest, class Body, class Headers>
|
||||||
bool
|
bool
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ enum class parse_error
|
|||||||
bad_crlf,
|
bad_crlf,
|
||||||
bad_request,
|
bad_request,
|
||||||
|
|
||||||
bad_status_code,
|
|
||||||
bad_status,
|
bad_status,
|
||||||
|
bad_reason,
|
||||||
|
|
||||||
bad_field,
|
bad_field,
|
||||||
bad_value,
|
bad_value,
|
||||||
@@ -33,7 +33,11 @@ enum class parse_error
|
|||||||
bad_on_headers_rv,
|
bad_on_headers_rv,
|
||||||
|
|
||||||
invalid_chunk_size,
|
invalid_chunk_size,
|
||||||
|
invalid_ext_name,
|
||||||
|
invalid_ext_val,
|
||||||
|
|
||||||
|
headers_too_big,
|
||||||
|
body_too_big,
|
||||||
short_read,
|
short_read,
|
||||||
|
|
||||||
general
|
general
|
||||||
@@ -60,7 +64,7 @@ public:
|
|||||||
return "bad method";
|
return "bad method";
|
||||||
|
|
||||||
case parse_error::bad_uri:
|
case parse_error::bad_uri:
|
||||||
return "bad Request-URI";
|
return "bad request-target";
|
||||||
|
|
||||||
case parse_error::bad_version:
|
case parse_error::bad_version:
|
||||||
return "bad HTTP-Version";
|
return "bad HTTP-Version";
|
||||||
@@ -69,13 +73,13 @@ public:
|
|||||||
return "missing CRLF";
|
return "missing CRLF";
|
||||||
|
|
||||||
case parse_error::bad_request:
|
case parse_error::bad_request:
|
||||||
return "bad Request-Line";
|
return "bad reason-phrase";
|
||||||
|
|
||||||
case parse_error::bad_status_code:
|
|
||||||
return "bad Status-Code";
|
|
||||||
|
|
||||||
case parse_error::bad_status:
|
case parse_error::bad_status:
|
||||||
return "bad Status-Line";
|
return "bad status-code";
|
||||||
|
|
||||||
|
case parse_error::bad_reason:
|
||||||
|
return "bad reason-phrase";
|
||||||
|
|
||||||
case parse_error::bad_field:
|
case parse_error::bad_field:
|
||||||
return "bad field token";
|
return "bad field token";
|
||||||
@@ -95,6 +99,18 @@ public:
|
|||||||
case parse_error::invalid_chunk_size:
|
case parse_error::invalid_chunk_size:
|
||||||
return "invalid chunk size";
|
return "invalid chunk size";
|
||||||
|
|
||||||
|
case parse_error::invalid_ext_name:
|
||||||
|
return "invalid ext name";
|
||||||
|
|
||||||
|
case parse_error::invalid_ext_val:
|
||||||
|
return "invalid ext val";
|
||||||
|
|
||||||
|
case parse_error::headers_too_big:
|
||||||
|
return "headers size limit exceeded";
|
||||||
|
|
||||||
|
case parse_error::body_too_big:
|
||||||
|
return "body size limit exceeded";
|
||||||
|
|
||||||
case parse_error::short_read:
|
case parse_error::short_read:
|
||||||
return "unexpected end of data";
|
return "unexpected end of data";
|
||||||
|
|
||||||
|
|||||||
@@ -124,8 +124,6 @@ private:
|
|||||||
{
|
{
|
||||||
if(! value_.empty())
|
if(! value_.empty())
|
||||||
{
|
{
|
||||||
rfc2616::trim_right_in_place(value_);
|
|
||||||
// VFALCO could std::move
|
|
||||||
m_.headers.insert(field_, value_);
|
m_.headers.insert(field_, value_);
|
||||||
field_.clear();
|
field_.clear();
|
||||||
value_.clear();
|
value_.clear();
|
||||||
@@ -174,7 +172,7 @@ private:
|
|||||||
m_.reason = std::move(this->reason_);
|
m_.reason = std::move(this->reason_);
|
||||||
}
|
}
|
||||||
|
|
||||||
int on_headers(error_code&)
|
int on_headers(std::uint64_t, error_code&)
|
||||||
{
|
{
|
||||||
flush();
|
flush();
|
||||||
m_.version = 10 * this->http_major() + this->http_minor();
|
m_.version = 10 * this->http_major() + this->http_minor();
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
#include <beast/core/error.hpp>
|
#include <beast/core/error.hpp>
|
||||||
#include <beast/core/async_completion.hpp>
|
#include <beast/core/async_completion.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <boost/system/error_code.hpp>
|
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace http {
|
namespace http {
|
||||||
@@ -36,7 +35,7 @@ namespace http {
|
|||||||
@param stream The stream from which the data is to be read.
|
@param stream The stream from which the data is to be read.
|
||||||
The type must support the @b `SyncReadStream` concept.
|
The type must support the @b `SyncReadStream` concept.
|
||||||
|
|
||||||
@param streambuf A `Streambuf` holding additional bytes
|
@param dynabuf A @b `DynamicBuffer` holding additional bytes
|
||||||
read by the implementation from the stream. This is both
|
read by the implementation from the stream. This is both
|
||||||
an input and an output parameter; on entry, any data in the
|
an input and an output parameter; on entry, any data in the
|
||||||
stream buffer's input sequence will be given to the parser
|
stream buffer's input sequence will be given to the parser
|
||||||
@@ -47,10 +46,10 @@ namespace http {
|
|||||||
|
|
||||||
@throws boost::system::system_error on failure.
|
@throws boost::system::system_error on failure.
|
||||||
*/
|
*/
|
||||||
template<class SyncReadStream, class Streambuf, class Parser>
|
template<class SyncReadStream, class DynamicBuffer, class Parser>
|
||||||
void
|
void
|
||||||
parse(SyncReadStream& stream,
|
parse(SyncReadStream& stream,
|
||||||
Streambuf& streambuf, Parser& parser);
|
DynamicBuffer& dynabuf, Parser& parser);
|
||||||
|
|
||||||
/** Parse a HTTP/1 message from a stream.
|
/** Parse a HTTP/1 message from a stream.
|
||||||
|
|
||||||
@@ -71,7 +70,7 @@ parse(SyncReadStream& stream,
|
|||||||
@param stream The stream from which the data is to be read.
|
@param stream The stream from which the data is to be read.
|
||||||
The type must support the @b `SyncReadStream` concept.
|
The type must support the @b `SyncReadStream` concept.
|
||||||
|
|
||||||
@param streambuf A `Streambuf` holding additional bytes
|
@param dynabuf A @b `DynamicBuffer` holding additional bytes
|
||||||
read by the implementation from the stream. This is both
|
read by the implementation from the stream. This is both
|
||||||
an input and an output parameter; on entry, any data in the
|
an input and an output parameter; on entry, any data in the
|
||||||
stream buffer's input sequence will be given to the parser
|
stream buffer's input sequence will be given to the parser
|
||||||
@@ -82,10 +81,10 @@ parse(SyncReadStream& stream,
|
|||||||
|
|
||||||
@param ec Set to the error, if any occurred.
|
@param ec Set to the error, if any occurred.
|
||||||
*/
|
*/
|
||||||
template<class SyncReadStream, class Streambuf, class Parser>
|
template<class SyncReadStream, class DynamicBuffer, class Parser>
|
||||||
void
|
void
|
||||||
parse(SyncReadStream& stream,
|
parse(SyncReadStream& stream,
|
||||||
Streambuf& streambuf, Parser& parser, error_code& ec);
|
DynamicBuffer& dynabuf, Parser& parser, error_code& ec);
|
||||||
|
|
||||||
/** Start an asynchronous operation to parse a HTTP/1 message from a stream.
|
/** Start an asynchronous operation to parse a HTTP/1 message from a stream.
|
||||||
|
|
||||||
@@ -106,7 +105,7 @@ parse(SyncReadStream& stream,
|
|||||||
@param stream The stream from which the data is to be read.
|
@param stream The stream from which the data is to be read.
|
||||||
The type must support the @b `AsyncReadStream` concept.
|
The type must support the @b `AsyncReadStream` concept.
|
||||||
|
|
||||||
@param streambuf A `Streambuf` holding additional bytes
|
@param dynabuf A @b `DynamicBuffer` holding additional bytes
|
||||||
read by the implementation from the stream. This is both
|
read by the implementation from the stream. This is both
|
||||||
an input and an output parameter; on entry, any data in the
|
an input and an output parameter; on entry, any data in the
|
||||||
stream buffer's input sequence will be given to the parser
|
stream buffer's input sequence will be given to the parser
|
||||||
@@ -128,14 +127,14 @@ parse(SyncReadStream& stream,
|
|||||||
manner equivalent to using `boost::asio::io_service::post`.
|
manner equivalent to using `boost::asio::io_service::post`.
|
||||||
*/
|
*/
|
||||||
template<class AsyncReadStream,
|
template<class AsyncReadStream,
|
||||||
class Streambuf, class Parser, class ReadHandler>
|
class DynamicBuffer, class Parser, class ReadHandler>
|
||||||
#if GENERATING_DOCS
|
#if GENERATING_DOCS
|
||||||
void_or_deduced
|
void_or_deduced
|
||||||
#else
|
#else
|
||||||
typename async_completion<
|
typename async_completion<
|
||||||
ReadHandler, void(error_code)>::result_type
|
ReadHandler, void(error_code)>::result_type
|
||||||
#endif
|
#endif
|
||||||
async_parse(AsyncReadStream& stream, Streambuf& streambuf,
|
async_parse(AsyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||||
Parser& parser, ReadHandler&& handler);
|
Parser& parser, ReadHandler&& handler);
|
||||||
|
|
||||||
/** Read a HTTP/1 message from a stream.
|
/** Read a HTTP/1 message from a stream.
|
||||||
@@ -157,7 +156,7 @@ async_parse(AsyncReadStream& stream, Streambuf& streambuf,
|
|||||||
@param stream The stream from which the data is to be read.
|
@param stream The stream from which the data is to be read.
|
||||||
The type must support the @b `SyncReadStream` concept.
|
The type must support the @b `SyncReadStream` concept.
|
||||||
|
|
||||||
@param streambuf A `Streambuf` holding additional bytes
|
@param dynabuf A @b `DynamicBuffer` holding additional bytes
|
||||||
read by the implementation from the stream. This is both
|
read by the implementation from the stream. This is both
|
||||||
an input and an output parameter; on entry, any data in the
|
an input and an output parameter; on entry, any data in the
|
||||||
stream buffer's input sequence will be given to the parser
|
stream buffer's input sequence will be given to the parser
|
||||||
@@ -168,10 +167,10 @@ async_parse(AsyncReadStream& stream, Streambuf& streambuf,
|
|||||||
|
|
||||||
@throws boost::system::system_error Thrown on failure.
|
@throws boost::system::system_error Thrown on failure.
|
||||||
*/
|
*/
|
||||||
template<class SyncReadStream, class Streambuf,
|
template<class SyncReadStream, class DynamicBuffer,
|
||||||
bool isRequest, class Body, class Headers>
|
bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
read(SyncReadStream& stream, Streambuf& streambuf,
|
read(SyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||||
message_v1<isRequest, Body, Headers>& msg);
|
message_v1<isRequest, Body, Headers>& msg);
|
||||||
|
|
||||||
/** Read a HTTP/1 message from a stream.
|
/** Read a HTTP/1 message from a stream.
|
||||||
@@ -193,7 +192,7 @@ read(SyncReadStream& stream, Streambuf& streambuf,
|
|||||||
@param stream The stream from which the data is to be read.
|
@param stream The stream from which the data is to be read.
|
||||||
The type must support the @b `SyncReadStream` concept.
|
The type must support the @b `SyncReadStream` concept.
|
||||||
|
|
||||||
@param streambuf A `Streambuf` holding additional bytes
|
@param dynabuf A @b `DynamicBuffer` holding additional bytes
|
||||||
read by the implementation from the stream. This is both
|
read by the implementation from the stream. This is both
|
||||||
an input and an output parameter; on entry, any data in the
|
an input and an output parameter; on entry, any data in the
|
||||||
stream buffer's input sequence will be given to the parser
|
stream buffer's input sequence will be given to the parser
|
||||||
@@ -204,10 +203,10 @@ read(SyncReadStream& stream, Streambuf& streambuf,
|
|||||||
|
|
||||||
@param ec Set to the error, if any occurred.
|
@param ec Set to the error, if any occurred.
|
||||||
*/
|
*/
|
||||||
template<class SyncReadStream, class Streambuf,
|
template<class SyncReadStream, class DynamicBuffer,
|
||||||
bool isRequest, class Body, class Headers>
|
bool isRequest, class Body, class Headers>
|
||||||
void
|
void
|
||||||
read(SyncReadStream& stream, Streambuf& streambuf,
|
read(SyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||||
message_v1<isRequest, Body, Headers>& msg,
|
message_v1<isRequest, Body, Headers>& msg,
|
||||||
error_code& ec);
|
error_code& ec);
|
||||||
|
|
||||||
@@ -229,7 +228,7 @@ read(SyncReadStream& stream, Streambuf& streambuf,
|
|||||||
@param stream The stream to read the message from.
|
@param stream The stream to read the message from.
|
||||||
The type must support the @b `AsyncReadStream` concept.
|
The type must support the @b `AsyncReadStream` concept.
|
||||||
|
|
||||||
@param streambuf A `Streambuf` holding additional bytes
|
@param dynabuf A @b `DynamicBuffer` holding additional bytes
|
||||||
read by the implementation from the stream. This is both
|
read by the implementation from the stream. This is both
|
||||||
an input and an output parameter; on entry, any data in the
|
an input and an output parameter; on entry, any data in the
|
||||||
stream buffer's input sequence will be given to the parser
|
stream buffer's input sequence will be given to the parser
|
||||||
@@ -249,7 +248,7 @@ read(SyncReadStream& stream, Streambuf& streambuf,
|
|||||||
this function. Invocation of the handler will be performed in a
|
this function. Invocation of the handler will be performed in a
|
||||||
manner equivalent to using `boost::asio::io_service::post`.
|
manner equivalent to using `boost::asio::io_service::post`.
|
||||||
*/
|
*/
|
||||||
template<class AsyncReadStream, class Streambuf,
|
template<class AsyncReadStream, class DynamicBuffer,
|
||||||
bool isRequest, class Body, class Headers,
|
bool isRequest, class Body, class Headers,
|
||||||
class ReadHandler>
|
class ReadHandler>
|
||||||
#if GENERATING_DOCS
|
#if GENERATING_DOCS
|
||||||
@@ -258,7 +257,7 @@ void_or_deduced
|
|||||||
typename async_completion<
|
typename async_completion<
|
||||||
ReadHandler, void(error_code)>::result_type
|
ReadHandler, void(error_code)>::result_type
|
||||||
#endif
|
#endif
|
||||||
async_read(AsyncReadStream& stream, Streambuf& streambuf,
|
async_read(AsyncReadStream& stream, DynamicBuffer& dynabuf,
|
||||||
message_v1<isRequest, Body, Headers>& msg,
|
message_v1<isRequest, Body, Headers>& msg,
|
||||||
ReadHandler&& handler);
|
ReadHandler&& handler);
|
||||||
|
|
||||||
|
|||||||
@@ -1,464 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef BEAST_HTTP_RFC2616_HPP
|
|
||||||
#define BEAST_HTTP_RFC2616_HPP
|
|
||||||
|
|
||||||
#include <boost/range/algorithm/equal.hpp>
|
|
||||||
#include <boost/range/iterator_range.hpp>
|
|
||||||
#include <boost/utility/string_ref.hpp>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cctype>
|
|
||||||
#include <string>
|
|
||||||
#include <iterator>
|
|
||||||
#include <tuple> // for std::tie, remove ASAP
|
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
#if ! GENERATING_DOCS
|
|
||||||
|
|
||||||
/** Routines for performing RFC2616 compliance.
|
|
||||||
RFC2616:
|
|
||||||
Hypertext Transfer Protocol -- HTTP/1.1
|
|
||||||
http://www.w3.org/Protocols/rfc2616/rfc2616
|
|
||||||
*/
|
|
||||||
namespace rfc2616 {
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
struct ci_equal_pred
|
|
||||||
{
|
|
||||||
bool operator()(char c1, char c2)
|
|
||||||
{
|
|
||||||
// VFALCO TODO Use a table lookup here
|
|
||||||
return std::tolower(c1) == std::tolower(c2);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // detail
|
|
||||||
|
|
||||||
/** Returns `true` if `c` is linear white space.
|
|
||||||
|
|
||||||
This excludes the CRLF sequence allowed for line continuations.
|
|
||||||
*/
|
|
||||||
inline
|
|
||||||
bool
|
|
||||||
is_lws(char c)
|
|
||||||
{
|
|
||||||
return c == ' ' || c == '\t';
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns `true` if `c` is any whitespace character. */
|
|
||||||
inline
|
|
||||||
bool
|
|
||||||
is_white(char c)
|
|
||||||
{
|
|
||||||
switch (c)
|
|
||||||
{
|
|
||||||
case ' ': case '\f': case '\n':
|
|
||||||
case '\r': case '\t': case '\v':
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns `true` if `c` is a control character. */
|
|
||||||
inline
|
|
||||||
bool
|
|
||||||
is_control(char c)
|
|
||||||
{
|
|
||||||
return c <= 31 || c >= 127;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns `true` if `c` is a separator. */
|
|
||||||
inline
|
|
||||||
bool
|
|
||||||
is_separator(char c)
|
|
||||||
{
|
|
||||||
// VFALCO Could use a static table
|
|
||||||
switch (c)
|
|
||||||
{
|
|
||||||
case '(': case ')': case '<': case '>': case '@':
|
|
||||||
case ',': case ';': case ':': case '\\': case '"':
|
|
||||||
case '{': case '}': case ' ': case '\t':
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns `true` if `c` is a character. */
|
|
||||||
inline
|
|
||||||
bool
|
|
||||||
is_char(char c)
|
|
||||||
{
|
|
||||||
return c >= 0 && c <= 127;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class FwdIter>
|
|
||||||
FwdIter
|
|
||||||
trim_left (FwdIter first, FwdIter last)
|
|
||||||
{
|
|
||||||
return std::find_if_not (first, last,
|
|
||||||
is_white);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class FwdIter>
|
|
||||||
FwdIter
|
|
||||||
trim_right (FwdIter first, FwdIter last)
|
|
||||||
{
|
|
||||||
if (first == last)
|
|
||||||
return last;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
--last;
|
|
||||||
if (! is_white (*last))
|
|
||||||
return ++last;
|
|
||||||
}
|
|
||||||
while (last != first);
|
|
||||||
return first;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class CharT, class Traits, class Allocator>
|
|
||||||
void
|
|
||||||
trim_right_in_place (std::basic_string <
|
|
||||||
CharT, Traits, Allocator>& s)
|
|
||||||
{
|
|
||||||
s.resize (std::distance (s.begin(),
|
|
||||||
trim_right (s.begin(), s.end())));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class FwdIter>
|
|
||||||
std::pair <FwdIter, FwdIter>
|
|
||||||
trim (FwdIter first, FwdIter last)
|
|
||||||
{
|
|
||||||
first = trim_left (first, last);
|
|
||||||
last = trim_right (first, last);
|
|
||||||
return std::make_pair (first, last);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class String>
|
|
||||||
String
|
|
||||||
trim (String const& s)
|
|
||||||
{
|
|
||||||
using std::begin;
|
|
||||||
using std::end;
|
|
||||||
auto first = begin(s);
|
|
||||||
auto last = end(s);
|
|
||||||
std::tie (first, last) = trim (first, last);
|
|
||||||
return { first, last };
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class String>
|
|
||||||
String
|
|
||||||
trim_right (String const& s)
|
|
||||||
{
|
|
||||||
using std::begin;
|
|
||||||
using std::end;
|
|
||||||
auto first (begin(s));
|
|
||||||
auto last (end(s));
|
|
||||||
last = trim_right (first, last);
|
|
||||||
return { first, last };
|
|
||||||
}
|
|
||||||
|
|
||||||
inline
|
|
||||||
std::string
|
|
||||||
trim (std::string const& s)
|
|
||||||
{
|
|
||||||
return trim <std::string> (s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Parse a character sequence of values separated by commas.
|
|
||||||
Double quotes and escape sequences will be converted. Excess white
|
|
||||||
space, commas, double quotes, and empty elements are not copied.
|
|
||||||
Format:
|
|
||||||
#(token|quoted-string)
|
|
||||||
Reference:
|
|
||||||
http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2
|
|
||||||
*/
|
|
||||||
template <class FwdIt,
|
|
||||||
class Result = std::vector<
|
|
||||||
std::basic_string<typename
|
|
||||||
std::iterator_traits<FwdIt>::value_type>>,
|
|
||||||
class Char>
|
|
||||||
Result
|
|
||||||
split(FwdIt first, FwdIt last, Char delim)
|
|
||||||
{
|
|
||||||
Result result;
|
|
||||||
using string = typename Result::value_type;
|
|
||||||
FwdIt iter = first;
|
|
||||||
string e;
|
|
||||||
while (iter != last)
|
|
||||||
{
|
|
||||||
if (*iter == '"')
|
|
||||||
{
|
|
||||||
// quoted-string
|
|
||||||
++iter;
|
|
||||||
while (iter != last)
|
|
||||||
{
|
|
||||||
if (*iter == '"')
|
|
||||||
{
|
|
||||||
++iter;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*iter == '\\')
|
|
||||||
{
|
|
||||||
// quoted-pair
|
|
||||||
++iter;
|
|
||||||
if (iter != last)
|
|
||||||
e.append (1, *iter++);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// qdtext
|
|
||||||
e.append (1, *iter++);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (! e.empty())
|
|
||||||
{
|
|
||||||
result.emplace_back(std::move(e));
|
|
||||||
e.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (*iter == delim)
|
|
||||||
{
|
|
||||||
e = trim_right (e);
|
|
||||||
if (! e.empty())
|
|
||||||
{
|
|
||||||
result.emplace_back(std::move(e));
|
|
||||||
e.clear();
|
|
||||||
}
|
|
||||||
++iter;
|
|
||||||
}
|
|
||||||
else if (is_lws (*iter))
|
|
||||||
{
|
|
||||||
++iter;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
e.append (1, *iter++);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! e.empty())
|
|
||||||
{
|
|
||||||
e = trim_right (e);
|
|
||||||
if (! e.empty())
|
|
||||||
result.emplace_back(std::move(e));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class FwdIt,
|
|
||||||
class Result = std::vector<
|
|
||||||
std::basic_string<typename std::iterator_traits<
|
|
||||||
FwdIt>::value_type>>>
|
|
||||||
Result
|
|
||||||
split_commas(FwdIt first, FwdIt last)
|
|
||||||
{
|
|
||||||
return split(first, last, ',');
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Result = std::vector<std::string>>
|
|
||||||
Result
|
|
||||||
split_commas(boost::string_ref const& s)
|
|
||||||
{
|
|
||||||
return split_commas(s.begin(), s.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/** Iterates through a comma separated list.
|
|
||||||
|
|
||||||
Meets the requirements of ForwardIterator.
|
|
||||||
|
|
||||||
List defined in rfc2616 2.1.
|
|
||||||
|
|
||||||
@note Values returned may contain backslash escapes.
|
|
||||||
*/
|
|
||||||
class list_iterator
|
|
||||||
{
|
|
||||||
using iter_type = boost::string_ref::const_iterator;
|
|
||||||
|
|
||||||
iter_type it_;
|
|
||||||
iter_type end_;
|
|
||||||
boost::string_ref value_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
using value_type = boost::string_ref;
|
|
||||||
using pointer = value_type const*;
|
|
||||||
using reference = value_type const&;
|
|
||||||
using difference_type = std::ptrdiff_t;
|
|
||||||
using iterator_category =
|
|
||||||
std::forward_iterator_tag;
|
|
||||||
|
|
||||||
list_iterator(iter_type begin, iter_type end)
|
|
||||||
: it_(begin)
|
|
||||||
, end_(end)
|
|
||||||
{
|
|
||||||
if(it_ != end_)
|
|
||||||
increment();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
operator==(list_iterator const& other) const
|
|
||||||
{
|
|
||||||
return other.it_ == it_ && other.end_ == end_
|
|
||||||
&& other.value_.size() == value_.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
operator!=(list_iterator const& other) const
|
|
||||||
{
|
|
||||||
return !(*this == other);
|
|
||||||
}
|
|
||||||
|
|
||||||
reference
|
|
||||||
operator*() const
|
|
||||||
{
|
|
||||||
return value_;
|
|
||||||
}
|
|
||||||
|
|
||||||
pointer
|
|
||||||
operator->() const
|
|
||||||
{
|
|
||||||
return &*(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
list_iterator&
|
|
||||||
operator++()
|
|
||||||
{
|
|
||||||
increment();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
list_iterator
|
|
||||||
operator++(int)
|
|
||||||
{
|
|
||||||
auto temp = *this;
|
|
||||||
++(*this);
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
template<class = void>
|
|
||||||
void
|
|
||||||
increment();
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class>
|
|
||||||
void
|
|
||||||
list_iterator::increment()
|
|
||||||
{
|
|
||||||
value_.clear();
|
|
||||||
while(it_ != end_)
|
|
||||||
{
|
|
||||||
if(*it_ == '"')
|
|
||||||
{
|
|
||||||
// quoted-string
|
|
||||||
++it_;
|
|
||||||
if(it_ == end_)
|
|
||||||
return;
|
|
||||||
if(*it_ != '"')
|
|
||||||
{
|
|
||||||
auto start = it_;
|
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
++it_;
|
|
||||||
if(it_ == end_)
|
|
||||||
{
|
|
||||||
value_ = boost::string_ref(
|
|
||||||
&*start, std::distance(start, it_));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(*it_ == '"')
|
|
||||||
{
|
|
||||||
value_ = boost::string_ref(
|
|
||||||
&*start, std::distance(start, it_));
|
|
||||||
++it_;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
++it_;
|
|
||||||
}
|
|
||||||
else if(*it_ == ',')
|
|
||||||
{
|
|
||||||
it_++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if(is_lws(*it_))
|
|
||||||
{
|
|
||||||
++it_;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto start = it_;
|
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
++it_;
|
|
||||||
if(it_ == end_ ||
|
|
||||||
*it_ == ',' ||
|
|
||||||
is_lws(*it_))
|
|
||||||
{
|
|
||||||
value_ = boost::string_ref(
|
|
||||||
&*start, std::distance(start, it_));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns true if two strings are equal.
|
|
||||||
|
|
||||||
A case-insensitive comparison is used.
|
|
||||||
*/
|
|
||||||
inline
|
|
||||||
bool
|
|
||||||
ci_equal(boost::string_ref s1, boost::string_ref s2)
|
|
||||||
{
|
|
||||||
return boost::range::equal(s1, s2,
|
|
||||||
detail::ci_equal_pred{});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns a range representing the list. */
|
|
||||||
inline
|
|
||||||
boost::iterator_range<list_iterator>
|
|
||||||
make_list(boost::string_ref const& field)
|
|
||||||
{
|
|
||||||
return boost::iterator_range<list_iterator>{
|
|
||||||
list_iterator{field.begin(), field.end()},
|
|
||||||
list_iterator{field.end(), field.end()}};
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns true if the specified token exists in the list.
|
|
||||||
|
|
||||||
A case-insensitive comparison is used.
|
|
||||||
*/
|
|
||||||
template<class = void>
|
|
||||||
bool
|
|
||||||
token_in_list(boost::string_ref const& value,
|
|
||||||
boost::string_ref const& token)
|
|
||||||
{
|
|
||||||
for(auto const& item : make_list(value))
|
|
||||||
if(ci_equal(item, token))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // rfc2616
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // beast
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -8,16 +8,238 @@
|
|||||||
#ifndef BEAST_HTTP_RFC7230_HPP
|
#ifndef BEAST_HTTP_RFC7230_HPP
|
||||||
#define BEAST_HTTP_RFC7230_HPP
|
#define BEAST_HTTP_RFC7230_HPP
|
||||||
|
|
||||||
#include <array>
|
#include <beast/http/detail/rfc7230.hpp>
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace rfc7230 {
|
namespace http {
|
||||||
|
|
||||||
|
/** A list of parameters in a HTTP extension field value.
|
||||||
|
|
||||||
|
This container allows iteration of the parameter list
|
||||||
|
in a HTTP extension. The parameter list is a series
|
||||||
|
of "name = value" pairs with each pair starting with
|
||||||
|
a semicolon.
|
||||||
|
|
||||||
} // rfc7230
|
BNF:
|
||||||
|
@code
|
||||||
|
param-list = *( OWS ";" OWS param )
|
||||||
|
param = token OWS "=" OWS ( token / quoted-string )
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
If a parsing error is encountered while iterating the string,
|
||||||
|
the behavior of the container will be as if a string containing
|
||||||
|
only characters up to but excluding the first invalid character
|
||||||
|
was used to construct the list.
|
||||||
|
*/
|
||||||
|
class param_list
|
||||||
|
{
|
||||||
|
boost::string_ref s_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** The type of each element in the list.
|
||||||
|
|
||||||
|
The first string in the pair is the name of the
|
||||||
|
parameter, and the second string in the pair is its value.
|
||||||
|
*/
|
||||||
|
using value_type =
|
||||||
|
std::pair<boost::string_ref, boost::string_ref>;
|
||||||
|
|
||||||
|
/// A constant iterator to the list
|
||||||
|
#if GENERATING_DOCS
|
||||||
|
using const_iterator = implementation_defined;
|
||||||
|
#else
|
||||||
|
class const_iterator;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Default constructor.
|
||||||
|
param_list() = default;
|
||||||
|
|
||||||
|
/** Construct a list.
|
||||||
|
|
||||||
|
@param s A string containing the list contents. The string
|
||||||
|
must remain valid for the lifetime of the container.
|
||||||
|
*/
|
||||||
|
explicit
|
||||||
|
param_list(boost::string_ref const& s)
|
||||||
|
: s_(s)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return a const iterator to the beginning of the list
|
||||||
|
const_iterator begin() const;
|
||||||
|
|
||||||
|
/// Return a const iterator to the end of the list
|
||||||
|
const_iterator end() const;
|
||||||
|
|
||||||
|
/// Return a const iterator to the beginning of the list
|
||||||
|
const_iterator cbegin() const;
|
||||||
|
|
||||||
|
/// Return a const iterator to the end of the list
|
||||||
|
const_iterator cend() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/** A list of extensions in a comma separated HTTP field value.
|
||||||
|
|
||||||
|
This container allows iteration of the extensions in a HTTP
|
||||||
|
field value. The extension list is a comma separated list of
|
||||||
|
token parameter list pairs.
|
||||||
|
|
||||||
|
BNF:
|
||||||
|
@code
|
||||||
|
ext-list = *( "," OWS ) ext *( OWS "," [ OWS ext ] )
|
||||||
|
ext = token param-list
|
||||||
|
param-list = *( OWS ";" OWS param )
|
||||||
|
param = token OWS "=" OWS ( token / quoted-string )
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
If a parsing error is encountered while iterating the string,
|
||||||
|
the behavior of the container will be as if a string containing
|
||||||
|
only characters up to but excluding the first invalid character
|
||||||
|
was used to construct the list.
|
||||||
|
*/
|
||||||
|
class ext_list
|
||||||
|
{
|
||||||
|
using iter_type = boost::string_ref::const_iterator;
|
||||||
|
|
||||||
|
boost::string_ref s_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** The type of each element in the list.
|
||||||
|
|
||||||
|
The first element of the pair is the extension token, and the
|
||||||
|
second element of the pair is an iterable container holding the
|
||||||
|
extension's name/value parameters.
|
||||||
|
*/
|
||||||
|
using value_type = std::pair<boost::string_ref, param_list>;
|
||||||
|
|
||||||
|
/// A constant iterator to the list
|
||||||
|
#if GENERATING_DOCS
|
||||||
|
using const_iterator = implementation_defined;
|
||||||
|
#else
|
||||||
|
class const_iterator;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Construct a list.
|
||||||
|
|
||||||
|
@param s A string containing the list contents. The string
|
||||||
|
must remain valid for the lifetime of the container.
|
||||||
|
*/
|
||||||
|
explicit
|
||||||
|
ext_list(boost::string_ref const& s)
|
||||||
|
: s_(s)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return a const iterator to the beginning of the list
|
||||||
|
const_iterator begin() const;
|
||||||
|
|
||||||
|
/// Return a const iterator to the end of the list
|
||||||
|
const_iterator end() const;
|
||||||
|
|
||||||
|
/// Return a const iterator to the beginning of the list
|
||||||
|
const_iterator cbegin() const;
|
||||||
|
|
||||||
|
/// Return a const iterator to the end of the list
|
||||||
|
const_iterator cend() const;
|
||||||
|
|
||||||
|
/** Find a token in the list.
|
||||||
|
|
||||||
|
@param s The token to find. A case-insensitive comparison is used.
|
||||||
|
|
||||||
|
@return An iterator to the matching token, or `end()` if no
|
||||||
|
token exists.
|
||||||
|
*/
|
||||||
|
template<class T>
|
||||||
|
const_iterator
|
||||||
|
find(T const& s);
|
||||||
|
|
||||||
|
/** Return `true` if a token is present in the list.
|
||||||
|
|
||||||
|
@param s The token to find. A case-insensitive comparison is used.
|
||||||
|
*/
|
||||||
|
template<class T>
|
||||||
|
bool
|
||||||
|
exists(T const& s);
|
||||||
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/** A list of tokens in a comma separated HTTP field value.
|
||||||
|
|
||||||
|
This container allows iteration of the extensions in a HTTP
|
||||||
|
field value. The extension list is a comma separated list of
|
||||||
|
token parameter list pairs.
|
||||||
|
|
||||||
|
BNF:
|
||||||
|
@code
|
||||||
|
token-list = *( "," OWS ) token *( OWS "," [ OWS ext ] )
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
If a parsing error is encountered while iterating the string,
|
||||||
|
the behavior of the container will be as if a string containing
|
||||||
|
only characters up to but excluding the first invalid character
|
||||||
|
was used to construct the list.
|
||||||
|
*/
|
||||||
|
class token_list
|
||||||
|
{
|
||||||
|
using iter_type = boost::string_ref::const_iterator;
|
||||||
|
|
||||||
|
boost::string_ref s_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** The type of each element in the token list.
|
||||||
|
|
||||||
|
The first element of the pair is the extension token, and the
|
||||||
|
second element of the pair is an iterable container holding the
|
||||||
|
extension's name/value parameters.
|
||||||
|
*/
|
||||||
|
using value_type = boost::string_ref;
|
||||||
|
|
||||||
|
/// A constant iterator to the list
|
||||||
|
#if GENERATING_DOCS
|
||||||
|
using const_iterator = implementation_defined;
|
||||||
|
#else
|
||||||
|
class const_iterator;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Construct a list.
|
||||||
|
|
||||||
|
@param s A string containing the list contents. The string
|
||||||
|
must remain valid for the lifetime of the container.
|
||||||
|
*/
|
||||||
|
explicit
|
||||||
|
token_list(boost::string_ref const& s)
|
||||||
|
: s_(s)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return a const iterator to the beginning of the list
|
||||||
|
const_iterator begin() const;
|
||||||
|
|
||||||
|
/// Return a const iterator to the end of the list
|
||||||
|
const_iterator end() const;
|
||||||
|
|
||||||
|
/// Return a const iterator to the beginning of the list
|
||||||
|
const_iterator cbegin() const;
|
||||||
|
|
||||||
|
/// Return a const iterator to the end of the list
|
||||||
|
const_iterator cend() const;
|
||||||
|
|
||||||
|
/** Return `true` if a token is present in the list.
|
||||||
|
|
||||||
|
@param s The token to find. A case-insensitive comparison is used.
|
||||||
|
*/
|
||||||
|
template<class T>
|
||||||
|
bool
|
||||||
|
exists(T const& s);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // http
|
||||||
} // beast
|
} // beast
|
||||||
|
|
||||||
|
#include <beast/http/impl/rfc7230.ipp>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -8,91 +8,17 @@
|
|||||||
#ifndef BEAST_HTTP_STREAMBUF_BODY_HPP
|
#ifndef BEAST_HTTP_STREAMBUF_BODY_HPP
|
||||||
#define BEAST_HTTP_STREAMBUF_BODY_HPP
|
#define BEAST_HTTP_STREAMBUF_BODY_HPP
|
||||||
|
|
||||||
#include <beast/http/body_type.hpp>
|
#include <beast/http/basic_dynabuf_body.hpp>
|
||||||
#include <beast/core/buffer_cat.hpp>
|
|
||||||
#include <beast/core/streambuf.hpp>
|
#include <beast/core/streambuf.hpp>
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace http {
|
namespace http {
|
||||||
|
|
||||||
/** A message body represented by a Streambuf
|
/** A message body represented by a @ref streambuf
|
||||||
|
|
||||||
Meets the requirements of @b `Body`.
|
Meets the requirements of @b `Body`.
|
||||||
*/
|
*/
|
||||||
template<class Streambuf>
|
using streambuf_body = basic_dynabuf_body<streambuf>;
|
||||||
struct basic_streambuf_body
|
|
||||||
{
|
|
||||||
/// The type of the `message::body` member
|
|
||||||
using value_type = Streambuf;
|
|
||||||
|
|
||||||
#if GENERATING_DOCS
|
|
||||||
private:
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class reader
|
|
||||||
{
|
|
||||||
value_type& sb_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
template<bool isRequest, class Headers>
|
|
||||||
explicit
|
|
||||||
reader(message<isRequest,
|
|
||||||
basic_streambuf_body, Headers>& m) noexcept
|
|
||||||
: sb_(m.body)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
write(void const* data,
|
|
||||||
std::size_t size, error_code&) noexcept
|
|
||||||
{
|
|
||||||
using boost::asio::buffer;
|
|
||||||
using boost::asio::buffer_copy;
|
|
||||||
sb_.commit(buffer_copy(
|
|
||||||
sb_.prepare(size), buffer(data, size)));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class writer
|
|
||||||
{
|
|
||||||
Streambuf const& body_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
writer(writer const&) = delete;
|
|
||||||
writer& operator=(writer const&) = delete;
|
|
||||||
|
|
||||||
template<bool isRequest, class Headers>
|
|
||||||
explicit
|
|
||||||
writer(message<
|
|
||||||
isRequest, basic_streambuf_body, Headers> const& m)
|
|
||||||
: body_(m.body)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
init(error_code& ec)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::uint64_t
|
|
||||||
content_length() const
|
|
||||||
{
|
|
||||||
return body_.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Write>
|
|
||||||
boost::tribool
|
|
||||||
operator()(resume_context&&, error_code&, Write&& write)
|
|
||||||
{
|
|
||||||
write(body_.data());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
using streambuf_body = basic_streambuf_body<streambuf>;
|
|
||||||
|
|
||||||
} // http
|
} // http
|
||||||
} // beast
|
} // beast
|
||||||
|
|||||||
@@ -9,8 +9,7 @@
|
|||||||
#define BEAST_HTTP_STRING_BODY_HPP
|
#define BEAST_HTTP_STRING_BODY_HPP
|
||||||
|
|
||||||
#include <beast/http/body_type.hpp>
|
#include <beast/http/body_type.hpp>
|
||||||
#include <beast/core/buffer_cat.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <beast/core/streambuf.hpp>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
// BEAST_VERSION / 100 % 1000 is the minor version
|
// BEAST_VERSION / 100 % 1000 is the minor version
|
||||||
// BEAST_VERSION / 100000 is the major version
|
// BEAST_VERSION / 100000 is the major version
|
||||||
//
|
//
|
||||||
#define BEAST_VERSION 100000
|
#define BEAST_VERSION 100006
|
||||||
|
|
||||||
#define BEAST_VERSION_STRING "1.0.0-b5"
|
#define BEAST_VERSION_STRING "1.0.0-b6"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -117,11 +117,11 @@ is_valid(close_code::value code)
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Write frame header to streambuf
|
// Write frame header to dynamic buffer
|
||||||
//
|
//
|
||||||
template<class Streambuf>
|
template<class DynamicBuffer>
|
||||||
void
|
void
|
||||||
write(Streambuf& sb, frame_header const& fh)
|
write(DynamicBuffer& db, frame_header const& fh)
|
||||||
{
|
{
|
||||||
using boost::asio::buffer;
|
using boost::asio::buffer;
|
||||||
using boost::asio::buffer_copy;
|
using boost::asio::buffer_copy;
|
||||||
@@ -159,24 +159,24 @@ write(Streambuf& sb, frame_header const& fh)
|
|||||||
native_to_little_uint32(fh.key, &b[n]);
|
native_to_little_uint32(fh.key, &b[n]);
|
||||||
n += 4;
|
n += 4;
|
||||||
}
|
}
|
||||||
sb.commit(buffer_copy(
|
db.commit(buffer_copy(
|
||||||
sb.prepare(n), buffer(b)));
|
db.prepare(n), buffer(b)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read fixed frame header
|
// Read fixed frame header
|
||||||
// Requires at least 2 bytes
|
// Requires at least 2 bytes
|
||||||
//
|
//
|
||||||
template<class Streambuf>
|
template<class DynamicBuffer>
|
||||||
std::size_t
|
std::size_t
|
||||||
read_fh1(frame_header& fh, Streambuf& sb,
|
read_fh1(frame_header& fh, DynamicBuffer& db,
|
||||||
role_type role, close_code::value& code)
|
role_type role, close_code::value& code)
|
||||||
{
|
{
|
||||||
using boost::asio::buffer;
|
using boost::asio::buffer;
|
||||||
using boost::asio::buffer_copy;
|
using boost::asio::buffer_copy;
|
||||||
using boost::asio::buffer_size;
|
using boost::asio::buffer_size;
|
||||||
std::uint8_t b[2];
|
std::uint8_t b[2];
|
||||||
assert(buffer_size(sb.data()) >= sizeof(b));
|
assert(buffer_size(db.data()) >= sizeof(b));
|
||||||
sb.consume(buffer_copy(buffer(b), sb.data()));
|
db.consume(buffer_copy(buffer(b), db.data()));
|
||||||
std::size_t need;
|
std::size_t need;
|
||||||
fh.len = b[1] & 0x7f;
|
fh.len = b[1] & 0x7f;
|
||||||
switch(fh.len)
|
switch(fh.len)
|
||||||
@@ -236,9 +236,9 @@ read_fh1(frame_header& fh, Streambuf& sb,
|
|||||||
|
|
||||||
// Decode variable frame header from stream
|
// Decode variable frame header from stream
|
||||||
//
|
//
|
||||||
template<class Streambuf>
|
template<class DynamicBuffer>
|
||||||
void
|
void
|
||||||
read_fh2(frame_header& fh, Streambuf& sb,
|
read_fh2(frame_header& fh, DynamicBuffer& db,
|
||||||
role_type role, close_code::value& code)
|
role_type role, close_code::value& code)
|
||||||
{
|
{
|
||||||
using boost::asio::buffer;
|
using boost::asio::buffer;
|
||||||
@@ -250,8 +250,8 @@ read_fh2(frame_header& fh, Streambuf& sb,
|
|||||||
case 126:
|
case 126:
|
||||||
{
|
{
|
||||||
std::uint8_t b[2];
|
std::uint8_t b[2];
|
||||||
assert(buffer_size(sb.data()) >= sizeof(b));
|
assert(buffer_size(db.data()) >= sizeof(b));
|
||||||
sb.consume(buffer_copy(buffer(b), sb.data()));
|
db.consume(buffer_copy(buffer(b), db.data()));
|
||||||
fh.len = big_uint16_to_native(&b[0]);
|
fh.len = big_uint16_to_native(&b[0]);
|
||||||
// length not canonical
|
// length not canonical
|
||||||
if(fh.len < 126)
|
if(fh.len < 126)
|
||||||
@@ -264,8 +264,8 @@ read_fh2(frame_header& fh, Streambuf& sb,
|
|||||||
case 127:
|
case 127:
|
||||||
{
|
{
|
||||||
std::uint8_t b[8];
|
std::uint8_t b[8];
|
||||||
assert(buffer_size(sb.data()) >= sizeof(b));
|
assert(buffer_size(db.data()) >= sizeof(b));
|
||||||
sb.consume(buffer_copy(buffer(b), sb.data()));
|
db.consume(buffer_copy(buffer(b), db.data()));
|
||||||
fh.len = big_uint64_to_native(&b[0]);
|
fh.len = big_uint64_to_native(&b[0]);
|
||||||
// length not canonical
|
// length not canonical
|
||||||
if(fh.len < 65536)
|
if(fh.len < 65536)
|
||||||
@@ -279,8 +279,8 @@ read_fh2(frame_header& fh, Streambuf& sb,
|
|||||||
if(fh.mask)
|
if(fh.mask)
|
||||||
{
|
{
|
||||||
std::uint8_t b[4];
|
std::uint8_t b[4];
|
||||||
assert(buffer_size(sb.data()) >= sizeof(b));
|
assert(buffer_size(db.data()) >= sizeof(b));
|
||||||
sb.consume(buffer_copy(buffer(b), sb.data()));
|
db.consume(buffer_copy(buffer(b), db.data()));
|
||||||
fh.key = little_uint32_to_native(&b[0]);
|
fh.key = little_uint32_to_native(&b[0]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
#include <beast/http/empty_body.hpp>
|
#include <beast/http/empty_body.hpp>
|
||||||
#include <beast/http/message.hpp>
|
#include <beast/http/message.hpp>
|
||||||
#include <beast/http/string_body.hpp>
|
#include <beast/http/string_body.hpp>
|
||||||
#include <beast/core/streambuf.hpp>
|
|
||||||
#include <boost/asio/error.hpp>
|
#include <boost/asio/error.hpp>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@@ -107,15 +106,13 @@ protected:
|
|||||||
void
|
void
|
||||||
prepare_fh(close_code::value& code);
|
prepare_fh(close_code::value& code);
|
||||||
|
|
||||||
template<class Streambuf>
|
template<class DynamicBuffer>
|
||||||
void
|
void
|
||||||
write_close(Streambuf& sb,
|
write_close(DynamicBuffer& db, close_reason const& rc);
|
||||||
close_reason const& rc);
|
|
||||||
|
|
||||||
template<class Streambuf>
|
template<class DynamicBuffer>
|
||||||
void
|
void
|
||||||
write_ping(Streambuf& sb, opcode op,
|
write_ping(DynamicBuffer& db, opcode op, ping_data const& data);
|
||||||
ping_data const& data);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace websocket {
|
|||||||
// processes any received control frames.
|
// processes any received control frames.
|
||||||
//
|
//
|
||||||
template<class NextLayer>
|
template<class NextLayer>
|
||||||
template<class Streambuf, class Handler>
|
template<class DynamicBuffer, class Handler>
|
||||||
class stream<NextLayer>::read_frame_op
|
class stream<NextLayer>::read_frame_op
|
||||||
{
|
{
|
||||||
using alloc_type =
|
using alloc_type =
|
||||||
@@ -35,27 +35,27 @@ class stream<NextLayer>::read_frame_op
|
|||||||
using fmb_type =
|
using fmb_type =
|
||||||
typename fb_type::mutable_buffers_type;
|
typename fb_type::mutable_buffers_type;
|
||||||
|
|
||||||
using smb_type =
|
using dmb_type =
|
||||||
typename Streambuf::mutable_buffers_type;
|
typename DynamicBuffer::mutable_buffers_type;
|
||||||
|
|
||||||
struct data : op
|
struct data : op
|
||||||
{
|
{
|
||||||
stream<NextLayer>& ws;
|
stream<NextLayer>& ws;
|
||||||
frame_info& fi;
|
frame_info& fi;
|
||||||
Streambuf& sb;
|
DynamicBuffer& db;
|
||||||
Handler h;
|
Handler h;
|
||||||
fb_type fb;
|
fb_type fb;
|
||||||
boost::optional<smb_type> smb;
|
boost::optional<dmb_type> dmb;
|
||||||
boost::optional<fmb_type> fmb;
|
boost::optional<fmb_type> fmb;
|
||||||
bool cont;
|
bool cont;
|
||||||
int state = 0;
|
int state = 0;
|
||||||
|
|
||||||
template<class DeducedHandler>
|
template<class DeducedHandler>
|
||||||
data(DeducedHandler&& h_, stream<NextLayer>& ws_,
|
data(DeducedHandler&& h_, stream<NextLayer>& ws_,
|
||||||
frame_info& fi_, Streambuf& sb_)
|
frame_info& fi_, DynamicBuffer& sb_)
|
||||||
: ws(ws_)
|
: ws(ws_)
|
||||||
, fi(fi_)
|
, fi(fi_)
|
||||||
, sb(sb_)
|
, db(sb_)
|
||||||
, h(std::forward<DeducedHandler>(h_))
|
, h(std::forward<DeducedHandler>(h_))
|
||||||
, cont(boost_asio_handler_cont_helpers::
|
, cont(boost_asio_handler_cont_helpers::
|
||||||
is_continuation(h))
|
is_continuation(h))
|
||||||
@@ -127,9 +127,9 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer>
|
||||||
template<class Buffers, class Handler>
|
template<class DynamicBuffer, class Handler>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::read_frame_op<Buffers, Handler>::
|
stream<NextLayer>::read_frame_op<DynamicBuffer, Handler>::
|
||||||
operator()(error_code ec, std::size_t bytes_transferred)
|
operator()(error_code ec, std::size_t bytes_transferred)
|
||||||
{
|
{
|
||||||
auto& d = *d_;
|
auto& d = *d_;
|
||||||
@@ -139,9 +139,9 @@ operator()(error_code ec, std::size_t bytes_transferred)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer>
|
||||||
template<class Buffers, class Handler>
|
template<class DynamicBuffer, class Handler>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::read_frame_op<Buffers, Handler>::
|
stream<NextLayer>::read_frame_op<DynamicBuffer, Handler>::
|
||||||
operator()(error_code ec,std::size_t bytes_transferred, bool again)
|
operator()(error_code ec,std::size_t bytes_transferred, bool again)
|
||||||
{
|
{
|
||||||
enum
|
enum
|
||||||
@@ -187,18 +187,18 @@ operator()(error_code ec,std::size_t bytes_transferred, bool again)
|
|||||||
|
|
||||||
case do_read_payload:
|
case do_read_payload:
|
||||||
d.state = do_read_payload + 1;
|
d.state = do_read_payload + 1;
|
||||||
d.smb = d.sb.prepare(
|
d.dmb = d.db.prepare(
|
||||||
detail::clamp(d.ws.rd_need_));
|
detail::clamp(d.ws.rd_need_));
|
||||||
// receive payload data
|
// receive payload data
|
||||||
d.ws.stream_.async_read_some(
|
d.ws.stream_.async_read_some(
|
||||||
*d.smb, std::move(*this));
|
*d.dmb, std::move(*this));
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case do_read_payload + 1:
|
case do_read_payload + 1:
|
||||||
{
|
{
|
||||||
d.ws.rd_need_ -= bytes_transferred;
|
d.ws.rd_need_ -= bytes_transferred;
|
||||||
auto const pb = prepare_buffers(
|
auto const pb = prepare_buffers(
|
||||||
bytes_transferred, *d.smb);
|
bytes_transferred, *d.dmb);
|
||||||
if(d.ws.rd_fh_.mask)
|
if(d.ws.rd_fh_.mask)
|
||||||
detail::mask_inplace(pb, d.ws.rd_key_);
|
detail::mask_inplace(pb, d.ws.rd_key_);
|
||||||
if(d.ws.rd_opcode_ == opcode::text)
|
if(d.ws.rd_opcode_ == opcode::text)
|
||||||
@@ -213,7 +213,7 @@ operator()(error_code ec,std::size_t bytes_transferred, bool again)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
d.sb.commit(bytes_transferred);
|
d.db.commit(bytes_transferred);
|
||||||
if(d.ws.rd_need_ > 0)
|
if(d.ws.rd_need_ > 0)
|
||||||
{
|
{
|
||||||
d.state = do_read_payload;
|
d.state = do_read_payload;
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace websocket {
|
|||||||
// read an entire message
|
// read an entire message
|
||||||
//
|
//
|
||||||
template<class NextLayer>
|
template<class NextLayer>
|
||||||
template<class Streambuf, class Handler>
|
template<class DynamicBuffer, class Handler>
|
||||||
class stream<NextLayer>::read_op
|
class stream<NextLayer>::read_op
|
||||||
{
|
{
|
||||||
using alloc_type =
|
using alloc_type =
|
||||||
@@ -27,7 +27,7 @@ class stream<NextLayer>::read_op
|
|||||||
{
|
{
|
||||||
stream<NextLayer>& ws;
|
stream<NextLayer>& ws;
|
||||||
opcode& op;
|
opcode& op;
|
||||||
Streambuf& sb;
|
DynamicBuffer& db;
|
||||||
Handler h;
|
Handler h;
|
||||||
frame_info fi;
|
frame_info fi;
|
||||||
bool cont;
|
bool cont;
|
||||||
@@ -36,10 +36,10 @@ class stream<NextLayer>::read_op
|
|||||||
template<class DeducedHandler>
|
template<class DeducedHandler>
|
||||||
data(DeducedHandler&& h_,
|
data(DeducedHandler&& h_,
|
||||||
stream<NextLayer>& ws_, opcode& op_,
|
stream<NextLayer>& ws_, opcode& op_,
|
||||||
Streambuf& sb_)
|
DynamicBuffer& sb_)
|
||||||
: ws(ws_)
|
: ws(ws_)
|
||||||
, op(op_)
|
, op(op_)
|
||||||
, sb(sb_)
|
, db(sb_)
|
||||||
, h(std::forward<DeducedHandler>(h_))
|
, h(std::forward<DeducedHandler>(h_))
|
||||||
, cont(boost_asio_handler_cont_helpers::
|
, cont(boost_asio_handler_cont_helpers::
|
||||||
is_continuation(h))
|
is_continuation(h))
|
||||||
@@ -98,9 +98,9 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer>
|
||||||
template<class Streambuf, class Handler>
|
template<class DynamicBuffer, class Handler>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::read_op<Streambuf, Handler>::
|
stream<NextLayer>::read_op<DynamicBuffer, Handler>::
|
||||||
operator()(error_code const& ec, bool again)
|
operator()(error_code const& ec, bool again)
|
||||||
{
|
{
|
||||||
auto& d = *d_;
|
auto& d = *d_;
|
||||||
@@ -117,9 +117,9 @@ operator()(error_code const& ec, bool again)
|
|||||||
// the handler is moved from the data block
|
// the handler is moved from the data block
|
||||||
// before asio_handler_deallocate is called.
|
// before asio_handler_deallocate is called.
|
||||||
d.ws.async_read_frame(
|
d.ws.async_read_frame(
|
||||||
d.fi, d.sb, std::move(*this));
|
d.fi, d.db, std::move(*this));
|
||||||
#else
|
#else
|
||||||
d.ws.async_read_frame(d.fi, d.sb, *this);
|
d.ws.async_read_frame(d.fi, d.db, *this);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@@ -22,14 +22,13 @@
|
|||||||
#include <beast/http/read.hpp>
|
#include <beast/http/read.hpp>
|
||||||
#include <beast/http/write.hpp>
|
#include <beast/http/write.hpp>
|
||||||
#include <beast/http/reason.hpp>
|
#include <beast/http/reason.hpp>
|
||||||
#include <beast/http/rfc2616.hpp>
|
#include <beast/http/rfc7230.hpp>
|
||||||
#include <beast/core/buffer_cat.hpp>
|
#include <beast/core/buffer_cat.hpp>
|
||||||
#include <beast/core/buffer_concepts.hpp>
|
#include <beast/core/buffer_concepts.hpp>
|
||||||
#include <beast/core/consuming_buffers.hpp>
|
#include <beast/core/consuming_buffers.hpp>
|
||||||
#include <beast/core/prepare_buffers.hpp>
|
#include <beast/core/prepare_buffers.hpp>
|
||||||
#include <beast/core/static_streambuf.hpp>
|
#include <beast/core/static_streambuf.hpp>
|
||||||
#include <beast/core/stream_concepts.hpp>
|
#include <beast/core/stream_concepts.hpp>
|
||||||
#include <beast/core/streambuf.hpp>
|
|
||||||
#include <boost/endian/buffers.hpp>
|
#include <boost/endian/buffers.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@@ -94,10 +93,10 @@ stream_base::prepare_fh(close_code::value& code)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Streambuf>
|
template<class DynamicBuffer>
|
||||||
void
|
void
|
||||||
stream_base::write_close(
|
stream_base::write_close(
|
||||||
Streambuf& sb, close_reason const& cr)
|
DynamicBuffer& db, close_reason const& cr)
|
||||||
{
|
{
|
||||||
using namespace boost::endian;
|
using namespace boost::endian;
|
||||||
frame_header fh;
|
frame_header fh;
|
||||||
@@ -111,7 +110,7 @@ stream_base::write_close(
|
|||||||
fh.mask = role_ == detail::role_type::client;
|
fh.mask = role_ == detail::role_type::client;
|
||||||
if(fh.mask)
|
if(fh.mask)
|
||||||
fh.key = maskgen_();
|
fh.key = maskgen_();
|
||||||
detail::write(sb, fh);
|
detail::write(db, fh);
|
||||||
if(cr.code != close_code::none)
|
if(cr.code != close_code::none)
|
||||||
{
|
{
|
||||||
detail::prepared_key_type key;
|
detail::prepared_key_type key;
|
||||||
@@ -121,29 +120,29 @@ stream_base::write_close(
|
|||||||
std::uint8_t b[2];
|
std::uint8_t b[2];
|
||||||
::new(&b[0]) big_uint16_buf_t{
|
::new(&b[0]) big_uint16_buf_t{
|
||||||
(std::uint16_t)cr.code};
|
(std::uint16_t)cr.code};
|
||||||
auto d = sb.prepare(2);
|
auto d = db.prepare(2);
|
||||||
boost::asio::buffer_copy(d,
|
boost::asio::buffer_copy(d,
|
||||||
boost::asio::buffer(b));
|
boost::asio::buffer(b));
|
||||||
if(fh.mask)
|
if(fh.mask)
|
||||||
detail::mask_inplace(d, key);
|
detail::mask_inplace(d, key);
|
||||||
sb.commit(2);
|
db.commit(2);
|
||||||
}
|
}
|
||||||
if(! cr.reason.empty())
|
if(! cr.reason.empty())
|
||||||
{
|
{
|
||||||
auto d = sb.prepare(cr.reason.size());
|
auto d = db.prepare(cr.reason.size());
|
||||||
boost::asio::buffer_copy(d,
|
boost::asio::buffer_copy(d,
|
||||||
boost::asio::const_buffer(
|
boost::asio::const_buffer(
|
||||||
cr.reason.data(), cr.reason.size()));
|
cr.reason.data(), cr.reason.size()));
|
||||||
if(fh.mask)
|
if(fh.mask)
|
||||||
detail::mask_inplace(d, key);
|
detail::mask_inplace(d, key);
|
||||||
sb.commit(cr.reason.size());
|
db.commit(cr.reason.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Streambuf>
|
template<class DynamicBuffer>
|
||||||
void
|
void
|
||||||
stream_base::write_ping(Streambuf& sb,
|
stream_base::write_ping(DynamicBuffer& db,
|
||||||
opcode op, ping_data const& data)
|
opcode op, ping_data const& data)
|
||||||
{
|
{
|
||||||
frame_header fh;
|
frame_header fh;
|
||||||
@@ -156,19 +155,19 @@ stream_base::write_ping(Streambuf& sb,
|
|||||||
fh.mask = role_ == role_type::client;
|
fh.mask = role_ == role_type::client;
|
||||||
if(fh.mask)
|
if(fh.mask)
|
||||||
fh.key = maskgen_();
|
fh.key = maskgen_();
|
||||||
detail::write(sb, fh);
|
detail::write(db, fh);
|
||||||
if(data.empty())
|
if(data.empty())
|
||||||
return;
|
return;
|
||||||
detail::prepared_key_type key;
|
detail::prepared_key_type key;
|
||||||
if(fh.mask)
|
if(fh.mask)
|
||||||
detail::prepare_key(key, fh.key);
|
detail::prepare_key(key, fh.key);
|
||||||
auto d = sb.prepare(data.size());
|
auto d = db.prepare(data.size());
|
||||||
boost::asio::buffer_copy(d,
|
boost::asio::buffer_copy(d,
|
||||||
boost::asio::const_buffers_1(
|
boost::asio::const_buffers_1(
|
||||||
data.data(), data.size()));
|
data.data(), data.size()));
|
||||||
if(fh.mask)
|
if(fh.mask)
|
||||||
detail::mask_inplace(d, key);
|
detail::mask_inplace(d, key);
|
||||||
sb.commit(data.size());
|
db.commit(data.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
@@ -453,10 +452,10 @@ void
|
|||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
ping(ping_data const& payload, error_code& ec)
|
ping(ping_data const& payload, error_code& ec)
|
||||||
{
|
{
|
||||||
detail::frame_streambuf sb;
|
detail::frame_streambuf db;
|
||||||
write_ping<static_streambuf>(
|
write_ping<static_streambuf>(
|
||||||
sb, opcode::ping, payload);
|
db, opcode::ping, payload);
|
||||||
boost::asio::write(stream_, sb.data(), ec);
|
boost::asio::write(stream_, db.data(), ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer>
|
||||||
@@ -477,31 +476,35 @@ async_ping(ping_data const& payload, PingHandler&& handler)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer>
|
||||||
template<class Streambuf>
|
template<class DynamicBuffer>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
read(opcode& op, Streambuf& streambuf)
|
read(opcode& op, DynamicBuffer& dynabuf)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_SyncStream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
|
static_assert(beast::is_DynamicBuffer<DynamicBuffer>::value,
|
||||||
|
"DynamicBuffer requirements not met");
|
||||||
error_code ec;
|
error_code ec;
|
||||||
read(op, streambuf, ec);
|
read(op, dynabuf, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
throw system_error{ec};
|
throw system_error{ec};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer>
|
||||||
template<class Streambuf>
|
template<class DynamicBuffer>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
read(opcode& op, Streambuf& streambuf, error_code& ec)
|
read(opcode& op, DynamicBuffer& dynabuf, error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_SyncStream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
|
static_assert(beast::is_DynamicBuffer<DynamicBuffer>::value,
|
||||||
|
"DynamicBuffer requirements not met");
|
||||||
frame_info fi;
|
frame_info fi;
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
read_frame(fi, streambuf, ec);
|
read_frame(fi, dynabuf, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
break;
|
break;
|
||||||
op = fi.op;
|
op = fi.op;
|
||||||
@@ -511,47 +514,51 @@ read(opcode& op, Streambuf& streambuf, error_code& ec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer>
|
||||||
template<class Streambuf, class ReadHandler>
|
template<class DynamicBuffer, class ReadHandler>
|
||||||
typename async_completion<
|
typename async_completion<
|
||||||
ReadHandler, void(error_code)>::result_type
|
ReadHandler, void(error_code)>::result_type
|
||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
async_read(opcode& op,
|
async_read(opcode& op,
|
||||||
Streambuf& streambuf, ReadHandler&& handler)
|
DynamicBuffer& dynabuf, ReadHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
static_assert(is_AsyncStream<next_layer_type>::value,
|
||||||
"AsyncStream requirements requirements not met");
|
"AsyncStream requirements requirements not met");
|
||||||
static_assert(beast::is_Streambuf<Streambuf>::value,
|
static_assert(beast::is_DynamicBuffer<DynamicBuffer>::value,
|
||||||
"Streambuf requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
beast::async_completion<
|
beast::async_completion<
|
||||||
ReadHandler, void(error_code)
|
ReadHandler, void(error_code)
|
||||||
> completion(handler);
|
> completion(handler);
|
||||||
read_op<Streambuf, decltype(completion.handler)>{
|
read_op<DynamicBuffer, decltype(completion.handler)>{
|
||||||
completion.handler, *this, op, streambuf};
|
completion.handler, *this, op, dynabuf};
|
||||||
return completion.result.get();
|
return completion.result.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer>
|
||||||
template<class Streambuf>
|
template<class DynamicBuffer>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
read_frame(frame_info& fi, Streambuf& streambuf)
|
read_frame(frame_info& fi, DynamicBuffer& dynabuf)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_SyncStream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
|
static_assert(beast::is_DynamicBuffer<DynamicBuffer>::value,
|
||||||
|
"DynamicBuffer requirements not met");
|
||||||
error_code ec;
|
error_code ec;
|
||||||
read_frame(fi, streambuf, ec);
|
read_frame(fi, dynabuf, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
throw system_error{ec};
|
throw system_error{ec};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer>
|
||||||
template<class Streambuf>
|
template<class DynamicBuffer>
|
||||||
void
|
void
|
||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
read_frame(frame_info& fi, Streambuf& streambuf, error_code& ec)
|
read_frame(frame_info& fi, DynamicBuffer& dynabuf, error_code& ec)
|
||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_SyncStream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
|
static_assert(beast::is_DynamicBuffer<DynamicBuffer>::value,
|
||||||
|
"DynamicBuffer requirements not met");
|
||||||
close_code::value code{};
|
close_code::value code{};
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
@@ -630,7 +637,7 @@ read_frame(frame_info& fi, Streambuf& streambuf, error_code& ec)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// read payload
|
// read payload
|
||||||
auto smb = streambuf.prepare(
|
auto smb = dynabuf.prepare(
|
||||||
detail::clamp(rd_need_));
|
detail::clamp(rd_need_));
|
||||||
auto const bytes_transferred =
|
auto const bytes_transferred =
|
||||||
stream_.read_some(smb, ec);
|
stream_.read_some(smb, ec);
|
||||||
@@ -652,7 +659,7 @@ read_frame(frame_info& fi, Streambuf& streambuf, error_code& ec)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
streambuf.commit(bytes_transferred);
|
dynabuf.commit(bytes_transferred);
|
||||||
fi.op = rd_opcode_;
|
fi.op = rd_opcode_;
|
||||||
fi.fin = rd_fh_.fin && rd_need_ == 0;
|
fi.fin = rd_fh_.fin && rd_need_ == 0;
|
||||||
return;
|
return;
|
||||||
@@ -686,21 +693,21 @@ read_frame(frame_info& fi, Streambuf& streambuf, error_code& ec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer>
|
||||||
template<class Streambuf, class ReadHandler>
|
template<class DynamicBuffer, class ReadHandler>
|
||||||
typename async_completion<
|
typename async_completion<
|
||||||
ReadHandler, void(error_code)>::result_type
|
ReadHandler, void(error_code)>::result_type
|
||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
async_read_frame(frame_info& fi,
|
async_read_frame(frame_info& fi,
|
||||||
Streambuf& streambuf, ReadHandler&& handler)
|
DynamicBuffer& dynabuf, ReadHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
static_assert(is_AsyncStream<next_layer_type>::value,
|
||||||
"AsyncStream requirements requirements not met");
|
"AsyncStream requirements requirements not met");
|
||||||
static_assert(beast::is_Streambuf<Streambuf>::value,
|
static_assert(beast::is_DynamicBuffer<DynamicBuffer>::value,
|
||||||
"Streambuf requirements not met");
|
"DynamicBuffer requirements not met");
|
||||||
beast::async_completion<
|
beast::async_completion<
|
||||||
ReadHandler, void(error_code)> completion(handler);
|
ReadHandler, void(error_code)> completion(handler);
|
||||||
read_frame_op<Streambuf, decltype(completion.handler)>{
|
read_frame_op<DynamicBuffer, decltype(completion.handler)>{
|
||||||
completion.handler, *this, fi, streambuf};
|
completion.handler, *this, fi, dynabuf};
|
||||||
return completion.result.get();
|
return completion.result.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -712,6 +719,9 @@ write(ConstBufferSequence const& buffers)
|
|||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_SyncStream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
|
static_assert(beast::is_ConstBufferSequence<
|
||||||
|
ConstBufferSequence>::value,
|
||||||
|
"ConstBufferSequence requirements not met");
|
||||||
error_code ec;
|
error_code ec;
|
||||||
write(buffers, ec);
|
write(buffers, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
@@ -774,6 +784,9 @@ write_frame(bool fin, ConstBufferSequence const& buffers)
|
|||||||
{
|
{
|
||||||
static_assert(is_SyncStream<next_layer_type>::value,
|
static_assert(is_SyncStream<next_layer_type>::value,
|
||||||
"SyncStream requirements not met");
|
"SyncStream requirements not met");
|
||||||
|
static_assert(beast::is_ConstBufferSequence<
|
||||||
|
ConstBufferSequence>::value,
|
||||||
|
"ConstBufferSequence requirements not met");
|
||||||
error_code ec;
|
error_code ec;
|
||||||
write_frame(fin, buffers, ec);
|
write_frame(fin, buffers, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
@@ -951,8 +964,7 @@ build_response(http::request_v1<Body, Headers> const& req)
|
|||||||
return err("Missing Host");
|
return err("Missing Host");
|
||||||
if(! req.headers.exists("Sec-WebSocket-Key"))
|
if(! req.headers.exists("Sec-WebSocket-Key"))
|
||||||
return err("Missing Sec-WebSocket-Key");
|
return err("Missing Sec-WebSocket-Key");
|
||||||
if(! rfc2616::token_in_list(
|
if(! http::token_list{req.headers["Upgrade"]}.exists("websocket"))
|
||||||
req.headers["Upgrade"], "websocket"))
|
|
||||||
return err("Missing websocket Upgrade token");
|
return err("Missing websocket Upgrade token");
|
||||||
{
|
{
|
||||||
auto const version =
|
auto const version =
|
||||||
@@ -1005,8 +1017,7 @@ do_response(http::response_v1<Body, Headers> const& res,
|
|||||||
return fail();
|
return fail();
|
||||||
if(! is_upgrade(res))
|
if(! is_upgrade(res))
|
||||||
return fail();
|
return fail();
|
||||||
if(! rfc2616::ci_equal(
|
if(! http::token_list{res.headers["Upgrade"]}.exists("websocket"))
|
||||||
res.headers["Upgrade"], "websocket"))
|
|
||||||
return fail();
|
return fail();
|
||||||
if(! res.headers.exists("Sec-WebSocket-Accept"))
|
if(! res.headers.exists("Sec-WebSocket-Accept"))
|
||||||
return fail();
|
return fail();
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ decorate(Decorator&& d)
|
|||||||
This setting only affects the behavior of HTTP requests that
|
This setting only affects the behavior of HTTP requests that
|
||||||
implicitly or explicitly ask for a keepalive. For HTTP requests
|
implicitly or explicitly ask for a keepalive. For HTTP requests
|
||||||
that indicate the connection should be closed, the connection is
|
that indicate the connection should be closed, the connection is
|
||||||
closed as per rfc2616.
|
closed as per rfc7230.
|
||||||
|
|
||||||
The default setting is to close connections after a failed
|
The default setting is to close connections after a failed
|
||||||
upgrade request.
|
upgrade request.
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#include <beast/websocket/detail/stream_base.hpp>
|
#include <beast/websocket/detail/stream_base.hpp>
|
||||||
#include <beast/http/message_v1.hpp>
|
#include <beast/http/message_v1.hpp>
|
||||||
#include <beast/http/string_body.hpp>
|
#include <beast/http/string_body.hpp>
|
||||||
#include <beast/core/streambuf_readstream.hpp>
|
#include <beast/core/dynabuf_readstream.hpp>
|
||||||
#include <beast/core/async_completion.hpp>
|
#include <beast/core/async_completion.hpp>
|
||||||
#include <beast/core/detail/get_lowest_layer.hpp>
|
#include <beast/core/detail/get_lowest_layer.hpp>
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
@@ -78,7 +78,7 @@ struct frame_info
|
|||||||
@par Concepts
|
@par Concepts
|
||||||
@b `AsyncStream`,
|
@b `AsyncStream`,
|
||||||
@b `Decorator`,
|
@b `Decorator`,
|
||||||
@b `Streambuf`,
|
@b `DynamicBuffer`,
|
||||||
@b `SyncStream`
|
@b `SyncStream`
|
||||||
*/
|
*/
|
||||||
template<class NextLayer>
|
template<class NextLayer>
|
||||||
@@ -86,7 +86,7 @@ class stream : public detail::stream_base
|
|||||||
{
|
{
|
||||||
friend class stream_test;
|
friend class stream_test;
|
||||||
|
|
||||||
streambuf_readstream<NextLayer, streambuf> stream_;
|
dynabuf_readstream<NextLayer, streambuf> stream_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// The type of the next layer.
|
/// The type of the next layer.
|
||||||
@@ -95,12 +95,12 @@ public:
|
|||||||
|
|
||||||
/// The type of the lowest layer.
|
/// The type of the lowest layer.
|
||||||
using lowest_layer_type =
|
using lowest_layer_type =
|
||||||
#if GENERATING_DOCS
|
#if GENERATING_DOCS
|
||||||
implementation_defined;
|
implementation_defined;
|
||||||
#else
|
#else
|
||||||
typename beast::detail::get_lowest_layer<
|
typename beast::detail::get_lowest_layer<
|
||||||
next_layer_type>::type;
|
next_layer_type>::type;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** Move-construct a stream.
|
/** Move-construct a stream.
|
||||||
|
|
||||||
@@ -404,12 +404,12 @@ public:
|
|||||||
manner equivalent to using `boost::asio::io_service::post`.
|
manner equivalent to using `boost::asio::io_service::post`.
|
||||||
*/
|
*/
|
||||||
template<class AcceptHandler>
|
template<class AcceptHandler>
|
||||||
#if GENERATING_DOCS
|
#if GENERATING_DOCS
|
||||||
void_or_deduced
|
void_or_deduced
|
||||||
#else
|
#else
|
||||||
typename async_completion<
|
typename async_completion<
|
||||||
AcceptHandler, void(error_code)>::result_type
|
AcceptHandler, void(error_code)>::result_type
|
||||||
#endif
|
#endif
|
||||||
async_accept(AcceptHandler&& handler);
|
async_accept(AcceptHandler&& handler);
|
||||||
|
|
||||||
/** Read and respond to a WebSocket HTTP Upgrade request.
|
/** Read and respond to a WebSocket HTTP Upgrade request.
|
||||||
@@ -530,12 +530,12 @@ public:
|
|||||||
manner equivalent to using `boost::asio::io_service::post`.
|
manner equivalent to using `boost::asio::io_service::post`.
|
||||||
*/
|
*/
|
||||||
template<class ConstBufferSequence, class AcceptHandler>
|
template<class ConstBufferSequence, class AcceptHandler>
|
||||||
#if GENERATING_DOCS
|
#if GENERATING_DOCS
|
||||||
void_or_deduced
|
void_or_deduced
|
||||||
#else
|
#else
|
||||||
typename async_completion<
|
typename async_completion<
|
||||||
AcceptHandler, void(error_code)>::result_type
|
AcceptHandler, void(error_code)>::result_type
|
||||||
#endif
|
#endif
|
||||||
async_accept(ConstBufferSequence const& buffers,
|
async_accept(ConstBufferSequence const& buffers,
|
||||||
AcceptHandler&& handler);
|
AcceptHandler&& handler);
|
||||||
|
|
||||||
@@ -567,7 +567,7 @@ public:
|
|||||||
|
|
||||||
@throws boost::system::system_error Thrown on failure.
|
@throws boost::system::system_error Thrown on failure.
|
||||||
*/
|
*/
|
||||||
// VFALCO TODO This should also take a streambuf with any leftover bytes.
|
// VFALCO TODO This should also take a DynamicBuffer with any leftover bytes.
|
||||||
template<class Body, class Headers>
|
template<class Body, class Headers>
|
||||||
void
|
void
|
||||||
accept(http::request_v1<Body, Headers> const& request);
|
accept(http::request_v1<Body, Headers> const& request);
|
||||||
@@ -647,12 +647,12 @@ public:
|
|||||||
manner equivalent to using `boost::asio::io_service::post`.
|
manner equivalent to using `boost::asio::io_service::post`.
|
||||||
*/
|
*/
|
||||||
template<class Body, class Headers, class AcceptHandler>
|
template<class Body, class Headers, class AcceptHandler>
|
||||||
#if GENERATING_DOCS
|
#if GENERATING_DOCS
|
||||||
void_or_deduced
|
void_or_deduced
|
||||||
#else
|
#else
|
||||||
typename async_completion<
|
typename async_completion<
|
||||||
AcceptHandler, void(error_code)>::result_type
|
AcceptHandler, void(error_code)>::result_type
|
||||||
#endif
|
#endif
|
||||||
async_accept(http::request_v1<Body, Headers> const& request,
|
async_accept(http::request_v1<Body, Headers> const& request,
|
||||||
AcceptHandler&& handler);
|
AcceptHandler&& handler);
|
||||||
|
|
||||||
@@ -784,12 +784,12 @@ public:
|
|||||||
manner equivalent to using `boost::asio::io_service::post`.
|
manner equivalent to using `boost::asio::io_service::post`.
|
||||||
*/
|
*/
|
||||||
template<class HandshakeHandler>
|
template<class HandshakeHandler>
|
||||||
#if GENERATING_DOCS
|
#if GENERATING_DOCS
|
||||||
void_or_deduced
|
void_or_deduced
|
||||||
#else
|
#else
|
||||||
typename async_completion<
|
typename async_completion<
|
||||||
HandshakeHandler, void(error_code)>::result_type
|
HandshakeHandler, void(error_code)>::result_type
|
||||||
#endif
|
#endif
|
||||||
async_handshake(boost::string_ref const& host,
|
async_handshake(boost::string_ref const& host,
|
||||||
boost::string_ref const& resource, HandshakeHandler&& h);
|
boost::string_ref const& resource, HandshakeHandler&& h);
|
||||||
|
|
||||||
@@ -895,12 +895,12 @@ public:
|
|||||||
manner equivalent to using `boost::asio::io_service::post`.
|
manner equivalent to using `boost::asio::io_service::post`.
|
||||||
*/
|
*/
|
||||||
template<class CloseHandler>
|
template<class CloseHandler>
|
||||||
#if GENERATING_DOCS
|
#if GENERATING_DOCS
|
||||||
void_or_deduced
|
void_or_deduced
|
||||||
#else
|
#else
|
||||||
typename async_completion<
|
typename async_completion<
|
||||||
CloseHandler, void(error_code)>::result_type
|
CloseHandler, void(error_code)>::result_type
|
||||||
#endif
|
#endif
|
||||||
async_close(close_reason const& cr, CloseHandler&& handler);
|
async_close(close_reason const& cr, CloseHandler&& handler);
|
||||||
|
|
||||||
/** Send a WebSocket ping frame.
|
/** Send a WebSocket ping frame.
|
||||||
@@ -973,12 +973,12 @@ public:
|
|||||||
manner equivalent to using `boost::asio::io_service::post`.
|
manner equivalent to using `boost::asio::io_service::post`.
|
||||||
*/
|
*/
|
||||||
template<class PingHandler>
|
template<class PingHandler>
|
||||||
#if GENERATING_DOCS
|
#if GENERATING_DOCS
|
||||||
void_or_deduced
|
void_or_deduced
|
||||||
#else
|
#else
|
||||||
typename async_completion<
|
typename async_completion<
|
||||||
PingHandler, void(error_code)>::result_type
|
PingHandler, void(error_code)>::result_type
|
||||||
#endif
|
#endif
|
||||||
async_ping(ping_data const& payload, PingHandler&& handler);
|
async_ping(ping_data const& payload, PingHandler&& handler);
|
||||||
|
|
||||||
/** Read a message from the stream.
|
/** Read a message from the stream.
|
||||||
@@ -1007,14 +1007,14 @@ public:
|
|||||||
@param op A value to receive the message type.
|
@param op A value to receive the message type.
|
||||||
This object must remain valid until the handler is called.
|
This object must remain valid until the handler is called.
|
||||||
|
|
||||||
@param streambuf A stream buffer to hold the message data.
|
@param dynabuf A dynamic buffer to hold the message data after
|
||||||
This object must remain valid until the handler is called.
|
any masking or decompression has been applied.
|
||||||
|
|
||||||
@throws boost::system::system_error Thrown on failure.
|
@throws boost::system::system_error Thrown on failure.
|
||||||
*/
|
*/
|
||||||
template<class Streambuf>
|
template<class DynamicBuffer>
|
||||||
void
|
void
|
||||||
read(opcode& op, Streambuf& streambuf);
|
read(opcode& op, DynamicBuffer& dynabuf);
|
||||||
|
|
||||||
/** Read a message from the stream.
|
/** Read a message from the stream.
|
||||||
|
|
||||||
@@ -1042,15 +1042,14 @@ public:
|
|||||||
@param op A value to receive the message type.
|
@param op A value to receive the message type.
|
||||||
This object must remain valid until the handler is called.
|
This object must remain valid until the handler is called.
|
||||||
|
|
||||||
@param streambuf A stream buffer to hold the message data.
|
@param dynabuf A dynamic buffer to hold the message data after
|
||||||
This object must remain valid until the handler is called.
|
any masking or decompression has been applied.
|
||||||
|
|
||||||
@param ec Set to indicate what error occurred, if any.
|
@param ec Set to indicate what error occurred, if any.
|
||||||
*/
|
*/
|
||||||
template<class Streambuf>
|
template<class DynamicBuffer>
|
||||||
void
|
void
|
||||||
read(opcode& op,
|
read(opcode& op, DynamicBuffer& dynabuf, error_code& ec);
|
||||||
Streambuf& streambuf, error_code& ec);
|
|
||||||
|
|
||||||
/** Start an asynchronous operation to read a message from the stream.
|
/** Start an asynchronous operation to read a message from the stream.
|
||||||
|
|
||||||
@@ -1086,8 +1085,9 @@ public:
|
|||||||
@param op A value to receive the message type.
|
@param op A value to receive the message type.
|
||||||
This object must remain valid until the handler is called.
|
This object must remain valid until the handler is called.
|
||||||
|
|
||||||
@param streambuf A stream buffer to hold the message data.
|
@param dynabuf A dynamic buffer to hold the message data after
|
||||||
This object must remain valid until the handler is called.
|
any masking or decompression has been applied. This object must
|
||||||
|
remain valid until the handler is called.
|
||||||
|
|
||||||
@param handler The handler to be called when the read operation
|
@param handler The handler to be called when the read operation
|
||||||
completes. Copies will be made of the handler as required. The
|
completes. Copies will be made of the handler as required. The
|
||||||
@@ -1102,15 +1102,14 @@ public:
|
|||||||
this function. Invocation of the handler will be performed in a
|
this function. Invocation of the handler will be performed in a
|
||||||
manner equivalent to using `boost::asio::io_service::post`.
|
manner equivalent to using `boost::asio::io_service::post`.
|
||||||
*/
|
*/
|
||||||
template<class Streambuf, class ReadHandler>
|
template<class DynamicBuffer, class ReadHandler>
|
||||||
#if GENERATING_DOCS
|
#if GENERATING_DOCS
|
||||||
void_or_deduced
|
void_or_deduced
|
||||||
#else
|
#else
|
||||||
typename async_completion<
|
typename async_completion<
|
||||||
ReadHandler, void(error_code)>::result_type
|
ReadHandler, void(error_code)>::result_type
|
||||||
#endif
|
#endif
|
||||||
async_read(opcode& op,
|
async_read(opcode& op, DynamicBuffer& dynabuf, ReadHandler&& handler);
|
||||||
Streambuf& streambuf, ReadHandler&& handler);
|
|
||||||
|
|
||||||
/** Read a message frame from the stream.
|
/** Read a message frame from the stream.
|
||||||
|
|
||||||
@@ -1141,13 +1140,14 @@ public:
|
|||||||
|
|
||||||
@param fi An object to store metadata about the message.
|
@param fi An object to store metadata about the message.
|
||||||
|
|
||||||
@param streambuf A stream buffer to hold the message data.
|
@param dynabuf A dynamic buffer to hold the message data after
|
||||||
|
any masking or decompression has been applied.
|
||||||
|
|
||||||
@throws boost::system::system_error Thrown on failure.
|
@throws boost::system::system_error Thrown on failure.
|
||||||
*/
|
*/
|
||||||
template<class Streambuf>
|
template<class DynamicBuffer>
|
||||||
void
|
void
|
||||||
read_frame(frame_info& fi, Streambuf& streambuf);
|
read_frame(frame_info& fi, DynamicBuffer& dynabuf);
|
||||||
|
|
||||||
/** Read a message frame from the stream.
|
/** Read a message frame from the stream.
|
||||||
|
|
||||||
@@ -1178,13 +1178,14 @@ public:
|
|||||||
|
|
||||||
@param fi An object to store metadata about the message.
|
@param fi An object to store metadata about the message.
|
||||||
|
|
||||||
@param streambuf A stream buffer to hold the message data.
|
@param dynabuf A dynamic buffer to hold the message data after
|
||||||
|
any masking or decompression has been applied.
|
||||||
|
|
||||||
@param ec Set to indicate what error occurred, if any.
|
@param ec Set to indicate what error occurred, if any.
|
||||||
*/
|
*/
|
||||||
template<class Streambuf>
|
template<class DynamicBuffer>
|
||||||
void
|
void
|
||||||
read_frame(frame_info& fi, Streambuf& streambuf, error_code& ec);
|
read_frame(frame_info& fi, DynamicBuffer& dynabuf, error_code& ec);
|
||||||
|
|
||||||
/** Start an asynchronous operation to read a message frame from the stream.
|
/** Start an asynchronous operation to read a message frame from the stream.
|
||||||
|
|
||||||
@@ -1225,7 +1226,7 @@ public:
|
|||||||
@param fi An object to store metadata about the message.
|
@param fi An object to store metadata about the message.
|
||||||
This object must remain valid until the handler is called.
|
This object must remain valid until the handler is called.
|
||||||
|
|
||||||
@param streambuf A stream buffer to hold the message data after
|
@param dynabuf A dynamic buffer to hold the message data after
|
||||||
any masking or decompression has been applied. This object must
|
any masking or decompression has been applied. This object must
|
||||||
remain valid until the handler is called.
|
remain valid until the handler is called.
|
||||||
|
|
||||||
@@ -1242,15 +1243,15 @@ public:
|
|||||||
this function. Invocation of the handler will be performed in a
|
this function. Invocation of the handler will be performed in a
|
||||||
manner equivalent to using boost::asio::io_service::post().
|
manner equivalent to using boost::asio::io_service::post().
|
||||||
*/
|
*/
|
||||||
template<class Streambuf, class ReadHandler>
|
template<class DynamicBuffer, class ReadHandler>
|
||||||
#if GENERATING_DOCS
|
#if GENERATING_DOCS
|
||||||
void_or_deduced
|
void_or_deduced
|
||||||
#else
|
#else
|
||||||
typename async_completion<
|
typename async_completion<
|
||||||
ReadHandler, void(error_code)>::result_type
|
ReadHandler, void(error_code)>::result_type
|
||||||
#endif
|
#endif
|
||||||
async_read_frame(frame_info& fi,
|
async_read_frame(frame_info& fi,
|
||||||
Streambuf& streambuf, ReadHandler&& handler);
|
DynamicBuffer& dynabuf, ReadHandler&& handler);
|
||||||
|
|
||||||
/** Write a message to the stream.
|
/** Write a message to the stream.
|
||||||
|
|
||||||
@@ -1369,12 +1370,12 @@ public:
|
|||||||
manner equivalent to using `boost::asio::io_service::post`.
|
manner equivalent to using `boost::asio::io_service::post`.
|
||||||
*/
|
*/
|
||||||
template<class ConstBufferSequence, class WriteHandler>
|
template<class ConstBufferSequence, class WriteHandler>
|
||||||
#if GENERATING_DOCS
|
#if GENERATING_DOCS
|
||||||
void_or_deduced
|
void_or_deduced
|
||||||
#else
|
#else
|
||||||
typename async_completion<
|
typename async_completion<
|
||||||
WriteHandler, void(error_code)>::result_type
|
WriteHandler, void(error_code)>::result_type
|
||||||
#endif
|
#endif
|
||||||
async_write(ConstBufferSequence const& buffers,
|
async_write(ConstBufferSequence const& buffers,
|
||||||
WriteHandler&& handler);
|
WriteHandler&& handler);
|
||||||
|
|
||||||
@@ -1478,12 +1479,12 @@ public:
|
|||||||
); @endcode
|
); @endcode
|
||||||
*/
|
*/
|
||||||
template<class ConstBufferSequence, class WriteHandler>
|
template<class ConstBufferSequence, class WriteHandler>
|
||||||
#if GENERATING_DOCS
|
#if GENERATING_DOCS
|
||||||
void_or_deduced
|
void_or_deduced
|
||||||
#else
|
#else
|
||||||
typename async_completion<
|
typename async_completion<
|
||||||
WriteHandler, void(error_code)>::result_type
|
WriteHandler, void(error_code)>::result_type
|
||||||
#endif
|
#endif
|
||||||
async_write_frame(bool fin,
|
async_write_frame(bool fin,
|
||||||
ConstBufferSequence const& buffers, WriteHandler&& handler);
|
ConstBufferSequence const& buffers, WriteHandler&& handler);
|
||||||
|
|
||||||
@@ -1495,8 +1496,8 @@ private:
|
|||||||
template<class Handler> class response_op;
|
template<class Handler> class response_op;
|
||||||
template<class Buffers, class Handler> class write_op;
|
template<class Buffers, class Handler> class write_op;
|
||||||
template<class Buffers, class Handler> class write_frame_op;
|
template<class Buffers, class Handler> class write_frame_op;
|
||||||
template<class Streambuf, class Handler> class read_op;
|
template<class DynamicBuffer, class Handler> class read_op;
|
||||||
template<class Streambuf, class Handler> class read_frame_op;
|
template<class DynamicBuffer, class Handler> class read_frame_op;
|
||||||
|
|
||||||
void
|
void
|
||||||
reset();
|
reset();
|
||||||
|
|||||||
39
src/beast/scripts/blacklist.supp
Normal file
39
src/beast/scripts/blacklist.supp
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# Remember that this blacklist file is GLOBAL to all sanitizers
|
||||||
|
# Be therefore extremely careful when considering to add a sanitizer
|
||||||
|
# filter here instead of using a runtime suppression
|
||||||
|
#
|
||||||
|
# Remember also that filters here quite literally completely
|
||||||
|
# remove instrumentation altogether, so filtering here means
|
||||||
|
# that sanitizers such as tsan will false positive on problems
|
||||||
|
# introduced by code filtered here.
|
||||||
|
#
|
||||||
|
# The main use for this file is ubsan, as it's the only sanitizer
|
||||||
|
# without a runtime suppression facility.
|
||||||
|
#
|
||||||
|
# Be ESPECIALLY careful when filtering out entire source files!
|
||||||
|
# Try if at all possible to filter only functions using fun:regex
|
||||||
|
# Remember you must use mangled symbol names with fun:regex
|
||||||
|
|
||||||
|
|
||||||
|
#### Compile time filters for ubsan ####
|
||||||
|
|
||||||
|
## The well known ubsan failure in libstdc++ extant for years :)
|
||||||
|
# Line 96:24: runtime error: load of value 4294967221, which is not a valid value for type 'std::_Ios_Fmtflags'
|
||||||
|
fun:*_Ios_Fmtflags*
|
||||||
|
|
||||||
|
# boost/any.hpp:259:16: runtime error: downcast of address 0x000004392e70 which does not point to an object of type 'any::holder<int>'
|
||||||
|
fun:*any_cast*
|
||||||
|
|
||||||
|
# boost/lexical_cast.hpp:1625:43: runtime error: downcast of address 0x7fbb4fffbce8 which does not point to an object of type 'buffer_t' (aka 'parser_buf<std::basic_streambuf<char, char_traits<char> >, char>')
|
||||||
|
fun:*shl_input_streamable*
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### Compile time filters for asan ####
|
||||||
|
|
||||||
|
|
||||||
|
#### Compile time filters for msan ####
|
||||||
|
|
||||||
|
|
||||||
|
#### Compile time filters for tsan ####
|
||||||
@@ -1,8 +1,11 @@
|
|||||||
#!/bin/bash -u
|
#!/usr/bin/env bash
|
||||||
# We use set -e and bash with -u to bail on first non zero exit code of any
|
# We use set -e to bail on first non zero exit code of any processes launched
|
||||||
# processes launched or upon any unbound variable
|
# and -x to exit upon any unbound variable. -x will output command lines used
|
||||||
|
# (with variable expansion)
|
||||||
|
set -eux
|
||||||
|
|
||||||
|
# brew install bash (4) to get this working on OSX!
|
||||||
shopt -s globstar
|
shopt -s globstar
|
||||||
set -ex
|
|
||||||
|
|
||||||
################################## ENVIRONMENT #################################
|
################################## ENVIRONMENT #################################
|
||||||
|
|
||||||
@@ -17,36 +20,90 @@ else
|
|||||||
export PATH=$VALGRIND_ROOT/bin:$LCOV_ROOT/usr/bin:$PATH
|
export PATH=$VALGRIND_ROOT/bin:$LCOV_ROOT/usr/bin:$PATH
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
MAIN_BRANCH="0"
|
||||||
|
# For builds not triggered by a pull request TRAVIS_BRANCH is the name of the
|
||||||
|
# branch currently being built; whereas for builds triggered by a pull request
|
||||||
|
# it is the name of the branch targeted by the pull request (in many cases this
|
||||||
|
# will be master).
|
||||||
|
if [[ $TRAVIS_BRANCH == "master" || $TRAVIS_BRANCH == "develop" ]]; then
|
||||||
|
MAIN_BRANCH="1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
num_jobs="1"
|
||||||
|
if [[ $(uname) == "Darwin" ]]; then
|
||||||
|
num_jobs=$(sysctl -n hw.physicalcpu)
|
||||||
|
elif [[ $(uname -s) == "Linux" ]]; then
|
||||||
|
# CircleCI returns 32 phys procs, but 2 virt proc
|
||||||
|
num_proc_units=$(nproc)
|
||||||
|
# Physical cores
|
||||||
|
num_jobs=$(lscpu -p | grep -v '^#' | sort -u -t, -k 2,4 | wc -l)
|
||||||
|
if (("$num_proc_units" < "$num_jobs")); then
|
||||||
|
num_jobs=$num_proc_units
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
echo "using toolset: $CC"
|
echo "using toolset: $CC"
|
||||||
echo "using variant: $VARIANT"
|
echo "using variant: $VARIANT"
|
||||||
echo "using address-model: $ADDRESS_MODEL"
|
echo "using address-model: $ADDRESS_MODEL"
|
||||||
echo "using PATH: $PATH"
|
echo "using PATH: $PATH"
|
||||||
|
echo "using MAIN_BRANCH: $MAIN_BRANCH"
|
||||||
|
echo "using BOOST_ROOT: $BOOST_ROOT"
|
||||||
|
|
||||||
#################################### HELPERS ###################################
|
#################################### HELPERS ###################################
|
||||||
|
|
||||||
function run_tests_with_gdb {
|
function run_tests_with_debugger {
|
||||||
for x in bin/**/*-tests; do scripts/run-with-gdb.sh "$x"; done
|
for x in bin/**/$VARIANT/**/*-tests; do
|
||||||
|
scripts/run-with-debugger.sh "$x"
|
||||||
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
function run_tests {
|
function run_tests {
|
||||||
for x in bin/**/*-tests; do "$x"; done
|
for x in bin/**/$VARIANT/**/*-tests; do
|
||||||
|
$x
|
||||||
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
num_procs=1
|
function run_tests_with_valgrind {
|
||||||
if [[ $(uname) == "Darwin" ]]; then
|
for x in bin/**/$VARIANT/**/*-tests; do
|
||||||
num_procs=$(sysctl -n hw.ncpu)
|
if [[ $(basename $x) == "bench-tests" ]]; then
|
||||||
elif [[ $(uname -s) == "Linux" ]]; then
|
$x
|
||||||
num_procs=$(lscpu -p | grep -v '^#' | sort -u -t, -k 2,4 | wc -l) # physical cores
|
else
|
||||||
virt_num_procs=$(nproc) # CircleCI returns 32 phys procs, but 1 virt proc
|
# TODO --max-stackframe=8388608
|
||||||
if (("$virt_num_procs" < "$num_procs")); then
|
# see: https://travis-ci.org/vinniefalco/Beast/jobs/132486245
|
||||||
num_procs=$virt_num_procs
|
valgrind --error-exitcode=1 "$x"
|
||||||
fi
|
fi
|
||||||
fi
|
done
|
||||||
|
}
|
||||||
|
|
||||||
function build_beast {
|
function build_beast {
|
||||||
$BOOST_ROOT/bjam toolset=$CC \
|
$BOOST_ROOT/bjam toolset=$CC \
|
||||||
variant=$VARIANT \
|
variant=$VARIANT \
|
||||||
address-model=$ADDRESS_MODEL -j${num_procs}
|
address-model=$ADDRESS_MODEL \
|
||||||
|
-j${num_jobs}
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_autobahn_test_suite {
|
||||||
|
# Run autobahn tests
|
||||||
|
wsecho=$(find bin -name "websocket-echo" | grep /$VARIANT/)
|
||||||
|
nohup $wsecho&
|
||||||
|
|
||||||
|
# We need to wait a while so wstest can connect!
|
||||||
|
sleep 5
|
||||||
|
cd scripts && wstest -m fuzzingclient
|
||||||
|
cd ..
|
||||||
|
# Show the output
|
||||||
|
cat nohup.out
|
||||||
|
rm nohup.out
|
||||||
|
# Show what jobs are running
|
||||||
|
jobs
|
||||||
|
# Wait a while for things to wind down before issuing a kill
|
||||||
|
sleep 5
|
||||||
|
# Kill it gracefully
|
||||||
|
kill -INT %1
|
||||||
|
# Wait for all the jobs to finish
|
||||||
|
wait
|
||||||
|
# Parse the test results, with python>=2.5<3 script
|
||||||
|
python scripts/parseautobahn.py scripts/autoresults/index.json
|
||||||
}
|
}
|
||||||
|
|
||||||
##################################### BUILD ####################################
|
##################################### BUILD ####################################
|
||||||
@@ -62,24 +119,12 @@ if [[ $VARIANT == "coverage" ]]; then
|
|||||||
lcov --no-external -c -i -d . -o baseline.info > /dev/null
|
lcov --no-external -c -i -d . -o baseline.info > /dev/null
|
||||||
|
|
||||||
# Perform test
|
# Perform test
|
||||||
|
if [[ $MAIN_BRANCH == "1" ]]; then
|
||||||
|
run_tests_with_valgrind
|
||||||
|
run_autobahn_test_suite
|
||||||
|
else
|
||||||
run_tests
|
run_tests
|
||||||
|
fi
|
||||||
# Run autobahn tests
|
|
||||||
export SERVER=$(find . -name "websocket-echo")
|
|
||||||
nohup $SERVER&
|
|
||||||
|
|
||||||
# We need to wait a while so wstest can connect!
|
|
||||||
sleep 5
|
|
||||||
cd scripts && wstest -m fuzzingclient
|
|
||||||
cd ..
|
|
||||||
# Show the output
|
|
||||||
cat nohup.out
|
|
||||||
rm nohup.out
|
|
||||||
jobs
|
|
||||||
sleep 5
|
|
||||||
# Kill it gracefully
|
|
||||||
kill -INT %1
|
|
||||||
wait
|
|
||||||
|
|
||||||
# Create test coverage data file
|
# Create test coverage data file
|
||||||
lcov --no-external -c -d . -o testrun.info > /dev/null
|
lcov --no-external -c -d . -o testrun.info > /dev/null
|
||||||
@@ -88,20 +133,13 @@ if [[ $VARIANT == "coverage" ]]; then
|
|||||||
lcov -a baseline.info -a testrun.info -o lcov-all.info > /dev/null
|
lcov -a baseline.info -a testrun.info -o lcov-all.info > /dev/null
|
||||||
|
|
||||||
# Extract only include/beast, and don\'t report on examples/test
|
# Extract only include/beast, and don\'t report on examples/test
|
||||||
lcov -e "lcov-all.info" "*/include/beast/*" -o lcov.info > /dev/null
|
lcov -e "lcov-all.info" "$PWD/include/beast/*" -o lcov.info > /dev/null
|
||||||
|
|
||||||
~/.local/bin/codecov -X gcov
|
~/.local/bin/codecov -X gcov
|
||||||
else
|
cat lcov.info | node_modules/.bin/coveralls
|
||||||
# TODO: make a function
|
|
||||||
run_tests_with_gdb
|
|
||||||
|
|
||||||
if [[ $VARIANT == "debug" ]]; then
|
# Clean up these stragglers so BOOST_ROOT cache is clean
|
||||||
for x in bin/**/*-tests; do
|
find $BOOST_ROOT/bin.v2 -name "*.gcda" | xargs rm -f
|
||||||
# if [[ $x != "bench-tests" ]]; then
|
else
|
||||||
valgrind --error-exitcode=1 "$x"
|
run_tests_with_debugger
|
||||||
## declare -i RESULT=$RESULT + $?
|
|
||||||
# fi
|
|
||||||
done
|
|
||||||
echo
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/bash -u
|
#!/usr/bin/env bash
|
||||||
# Assumptions:
|
# Assumptions:
|
||||||
# 1) BOOST_ROOT and BOOST_URL are already defined,
|
# 1) BOOST_ROOT and BOOST_URL are already defined,
|
||||||
# and contain valid values.
|
# and contain valid values.
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
# folder name internal to boost's .tar.gz
|
# folder name internal to boost's .tar.gz
|
||||||
# When testing you can force a boost build by clearing travis caches:
|
# When testing you can force a boost build by clearing travis caches:
|
||||||
# https://travis-ci.org/ripple/rippled/caches
|
# https://travis-ci.org/ripple/rippled/caches
|
||||||
set -e
|
set -eu
|
||||||
if [ ! -d "$BOOST_ROOT/lib" ]
|
if [ ! -d "$BOOST_ROOT/lib" ]
|
||||||
then
|
then
|
||||||
wget $BOOST_URL -O /tmp/boost.tar.gz
|
wget $BOOST_URL -O /tmp/boost.tar.gz
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
#!/bin/bash -u
|
#!/usr/bin/env bash
|
||||||
# Exit if anything fails.
|
# Exit if anything fails.
|
||||||
set -e
|
set -eux
|
||||||
|
|
||||||
|
HERE=$PWD
|
||||||
|
|
||||||
# Override gcc version to $GCC_VER.
|
# Override gcc version to $GCC_VER.
|
||||||
# Put an appropriate symlink at the front of the path.
|
# Put an appropriate symlink at the front of the path.
|
||||||
mkdir -v $HOME/bin
|
mkdir -v $HOME/bin
|
||||||
@@ -44,3 +47,8 @@ tar xfvz lcov-1.12.tar.gz -C $HOME
|
|||||||
# Set install path
|
# Set install path
|
||||||
mkdir -p $LCOV_ROOT
|
mkdir -p $LCOV_ROOT
|
||||||
cd $HOME/lcov-1.12 && make install PREFIX=$LCOV_ROOT
|
cd $HOME/lcov-1.12 && make install PREFIX=$LCOV_ROOT
|
||||||
|
|
||||||
|
# Install coveralls reporter
|
||||||
|
cd $HERE
|
||||||
|
mkdir -p node_modules
|
||||||
|
npm install coveralls
|
||||||
|
|||||||
4
src/beast/scripts/install-valgrind.sh
Normal file → Executable file
4
src/beast/scripts/install-valgrind.sh
Normal file → Executable file
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash -u
|
#!/usr/bin/env bash
|
||||||
# Assumptions:
|
# Assumptions:
|
||||||
# 1) VALGRIND_ROOT is already defined, and contains a valid values
|
# 1) VALGRIND_ROOT is already defined, and contains a valid values
|
||||||
set -e
|
set -eu
|
||||||
if [ ! -d "$VALGRIND_ROOT/bin" ]
|
if [ ! -d "$VALGRIND_ROOT/bin" ]
|
||||||
then
|
then
|
||||||
# These are specified in the addons/apt section of .travis.yml
|
# These are specified in the addons/apt section of .travis.yml
|
||||||
|
|||||||
43
src/beast/scripts/parseautobahn.py
Normal file
43
src/beast/scripts/parseautobahn.py
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import os
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
|
||||||
|
VARIANT = os.environ.get('VARIANT', 'release')
|
||||||
|
EXPECTED_BEHAVIOR = ('OK', 'UNIMPLEMENTED', 'INFORMATIONAL')
|
||||||
|
EXPECTED_BEHAVIOR_CLOSE = ('OK', 'INFORMATIONAL')
|
||||||
|
WARNINGS = ("peer did not respond (in time) in closing handshake", )
|
||||||
|
|
||||||
|
args = sys.argv[1:]
|
||||||
|
fn = os.path.abspath(args[0])
|
||||||
|
indexPath = os.path.dirname(fn)
|
||||||
|
relativeToIndex = lambda f: os.path.join(indexPath, f)
|
||||||
|
print "index", fn
|
||||||
|
|
||||||
|
|
||||||
|
failures = []
|
||||||
|
warnings = []
|
||||||
|
|
||||||
|
with open(fn, 'r') as fh:
|
||||||
|
index = json.load(fh)
|
||||||
|
for servername, serverResults in index.items():
|
||||||
|
for test in serverResults:
|
||||||
|
result = serverResults[test]
|
||||||
|
if ((result['behavior'] not in EXPECTED_BEHAVIOR) or
|
||||||
|
result['behaviorClose'] not in EXPECTED_BEHAVIOR_CLOSE):
|
||||||
|
with open(relativeToIndex(result['reportfile'])) as rh:
|
||||||
|
report = json.load(rh)
|
||||||
|
if (report.get('wasNotCleanReason', '') in WARNINGS and
|
||||||
|
VARIANT != 'release'):
|
||||||
|
warnings.append(report)
|
||||||
|
else:
|
||||||
|
failures.append(report)
|
||||||
|
|
||||||
|
|
||||||
|
if warnings:
|
||||||
|
print >> sys.stderr, json.dumps(warnings, indent=2)
|
||||||
|
print >> sys.stderr, 'there was %s warnings' % len(warnings)
|
||||||
|
|
||||||
|
if failures:
|
||||||
|
print >> sys.stderr, json.dumps(failures, indent=2)
|
||||||
|
print >> sys.stderr, 'there was %s failures' % len(failures)
|
||||||
|
sys.exit(1)
|
||||||
22
src/beast/scripts/run-with-debugger.sh
Executable file
22
src/beast/scripts/run-with-debugger.sh
Executable file
@@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
if [[ $(uname) == "Darwin" ]]; then
|
||||||
|
# -o runs after loading the binary
|
||||||
|
# -k runs after any crash
|
||||||
|
# We use a ghetto appromixation of --return-child-result, exiting with
|
||||||
|
# 1 on a crash
|
||||||
|
lldb --batch \
|
||||||
|
-o 'run' \
|
||||||
|
-k 'thread backtrace all' \
|
||||||
|
-k 'script import os; os._exit(1)' \
|
||||||
|
$@
|
||||||
|
else
|
||||||
|
gdb --silent \
|
||||||
|
--batch \
|
||||||
|
--return-child-result \
|
||||||
|
-ex="set print thread-events off" \
|
||||||
|
-ex=run \
|
||||||
|
-ex="thread apply all bt full" \
|
||||||
|
--args $@
|
||||||
|
fi
|
||||||
@@ -21,6 +21,7 @@ unit-test core-tests :
|
|||||||
core/buffer_concepts.cpp
|
core/buffer_concepts.cpp
|
||||||
core/buffers_adapter.cpp
|
core/buffers_adapter.cpp
|
||||||
core/consuming_buffers.cpp
|
core/consuming_buffers.cpp
|
||||||
|
core/dynabuf_readstream.cpp
|
||||||
core/error.cpp
|
core/error.cpp
|
||||||
core/handler_alloc.cpp
|
core/handler_alloc.cpp
|
||||||
core/handler_concepts.cpp
|
core/handler_concepts.cpp
|
||||||
@@ -30,9 +31,8 @@ unit-test core-tests :
|
|||||||
core/static_string.cpp
|
core/static_string.cpp
|
||||||
core/stream_concepts.cpp
|
core/stream_concepts.cpp
|
||||||
core/streambuf.cpp
|
core/streambuf.cpp
|
||||||
core/streambuf_readstream.cpp
|
|
||||||
core/to_string.cpp
|
core/to_string.cpp
|
||||||
core/write_streambuf.cpp
|
core/write_dynabuf.cpp
|
||||||
core/detail/base64.cpp
|
core/detail/base64.cpp
|
||||||
core/detail/empty_base_optimization.cpp
|
core/detail/empty_base_optimization.cpp
|
||||||
core/detail/get_lowest_layer.cpp
|
core/detail/get_lowest_layer.cpp
|
||||||
@@ -41,6 +41,7 @@ unit-test core-tests :
|
|||||||
|
|
||||||
unit-test http-tests :
|
unit-test http-tests :
|
||||||
../extras/beast/unit_test/main.cpp
|
../extras/beast/unit_test/main.cpp
|
||||||
|
http/basic_dynabuf_body.cpp
|
||||||
http/basic_headers.cpp
|
http/basic_headers.cpp
|
||||||
http/basic_parser_v1.cpp
|
http/basic_parser_v1.cpp
|
||||||
http/body_type.cpp
|
http/body_type.cpp
|
||||||
@@ -54,7 +55,6 @@ unit-test http-tests :
|
|||||||
http/read.cpp
|
http/read.cpp
|
||||||
http/reason.cpp
|
http/reason.cpp
|
||||||
http/resume_context.cpp
|
http/resume_context.cpp
|
||||||
http/rfc2616.cpp
|
|
||||||
http/rfc7230.cpp
|
http/rfc7230.cpp
|
||||||
http/status.cpp
|
http/status.cpp
|
||||||
http/streambuf_body.cpp
|
http/streambuf_body.cpp
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ add_executable (core-tests
|
|||||||
buffer_concepts.cpp
|
buffer_concepts.cpp
|
||||||
buffers_adapter.cpp
|
buffers_adapter.cpp
|
||||||
consuming_buffers.cpp
|
consuming_buffers.cpp
|
||||||
|
dynabuf_readstream.cpp
|
||||||
error.cpp
|
error.cpp
|
||||||
handler_alloc.cpp
|
handler_alloc.cpp
|
||||||
handler_concepts.cpp
|
handler_concepts.cpp
|
||||||
@@ -24,9 +25,8 @@ add_executable (core-tests
|
|||||||
static_string.cpp
|
static_string.cpp
|
||||||
stream_concepts.cpp
|
stream_concepts.cpp
|
||||||
streambuf.cpp
|
streambuf.cpp
|
||||||
streambuf_readstream.cpp
|
|
||||||
to_string.cpp
|
to_string.cpp
|
||||||
write_streambuf.cpp
|
write_dynabuf.cpp
|
||||||
detail/base64.cpp
|
detail/base64.cpp
|
||||||
detail/empty_base_optimization.cpp
|
detail/empty_base_optimization.cpp
|
||||||
detail/get_lowest_layer.cpp
|
detail/get_lowest_layer.cpp
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
// Test that header file is self-contained.
|
// Test that header file is self-contained.
|
||||||
#include <beast/core/streambuf_readstream.hpp>
|
#include <beast/core/dynabuf_readstream.hpp>
|
||||||
|
|
||||||
#include <beast/core/streambuf.hpp>
|
#include <beast/core/streambuf.hpp>
|
||||||
#include <beast/test/fail_stream.hpp>
|
#include <beast/test/fail_stream.hpp>
|
||||||
@@ -17,11 +17,11 @@
|
|||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
class streambuf_readstream_test
|
class dynabuf_readstream_test
|
||||||
: public unit_test::suite
|
: public unit_test::suite
|
||||||
, public test::enable_yield_to
|
, public test::enable_yield_to
|
||||||
{
|
{
|
||||||
using self = streambuf_readstream_test;
|
using self = dynabuf_readstream_test;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void testSpecialMembers()
|
void testSpecialMembers()
|
||||||
@@ -29,16 +29,16 @@ public:
|
|||||||
using socket_type = boost::asio::ip::tcp::socket;
|
using socket_type = boost::asio::ip::tcp::socket;
|
||||||
boost::asio::io_service ios;
|
boost::asio::io_service ios;
|
||||||
{
|
{
|
||||||
streambuf_readstream<socket_type, streambuf> srs(ios);
|
dynabuf_readstream<socket_type, streambuf> srs(ios);
|
||||||
streambuf_readstream<socket_type, streambuf> srs2(std::move(srs));
|
dynabuf_readstream<socket_type, streambuf> srs2(std::move(srs));
|
||||||
srs = std::move(srs2);
|
srs = std::move(srs2);
|
||||||
expect(&srs.get_io_service() == &ios);
|
expect(&srs.get_io_service() == &ios);
|
||||||
expect(&srs.get_io_service() == &srs2.get_io_service());
|
expect(&srs.get_io_service() == &srs2.get_io_service());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
socket_type sock(ios);
|
socket_type sock(ios);
|
||||||
streambuf_readstream<socket_type&, streambuf> srs(sock);
|
dynabuf_readstream<socket_type&, streambuf> srs(sock);
|
||||||
streambuf_readstream<socket_type&, streambuf> srs2(std::move(srs));
|
dynabuf_readstream<socket_type&, streambuf> srs2(std::move(srs));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ public:
|
|||||||
{
|
{
|
||||||
test::fail_stream<
|
test::fail_stream<
|
||||||
test::string_stream> fs(n, ios_, ", world!");
|
test::string_stream> fs(n, ios_, ", world!");
|
||||||
streambuf_readstream<
|
dynabuf_readstream<
|
||||||
decltype(fs)&, streambuf> srs(fs);
|
decltype(fs)&, streambuf> srs(fs);
|
||||||
srs.buffer().commit(buffer_copy(
|
srs.buffer().commit(buffer_copy(
|
||||||
srs.buffer().prepare(5), buffer("Hello", 5)));
|
srs.buffer().prepare(5), buffer("Hello", 5)));
|
||||||
@@ -73,7 +73,7 @@ public:
|
|||||||
{
|
{
|
||||||
test::fail_stream<
|
test::fail_stream<
|
||||||
test::string_stream> fs(n, ios_, ", world!");
|
test::string_stream> fs(n, ios_, ", world!");
|
||||||
streambuf_readstream<
|
dynabuf_readstream<
|
||||||
decltype(fs)&, streambuf> srs(fs);
|
decltype(fs)&, streambuf> srs(fs);
|
||||||
srs.capacity(3);
|
srs.capacity(3);
|
||||||
srs.buffer().commit(buffer_copy(
|
srs.buffer().commit(buffer_copy(
|
||||||
@@ -92,7 +92,7 @@ public:
|
|||||||
{
|
{
|
||||||
test::fail_stream<
|
test::fail_stream<
|
||||||
test::string_stream> fs(n, ios_, ", world!");
|
test::string_stream> fs(n, ios_, ", world!");
|
||||||
streambuf_readstream<
|
dynabuf_readstream<
|
||||||
decltype(fs)&, streambuf> srs(fs);
|
decltype(fs)&, streambuf> srs(fs);
|
||||||
srs.buffer().commit(buffer_copy(
|
srs.buffer().commit(buffer_copy(
|
||||||
srs.buffer().prepare(5), buffer("Hello", 5)));
|
srs.buffer().prepare(5), buffer("Hello", 5)));
|
||||||
@@ -111,7 +111,7 @@ public:
|
|||||||
{
|
{
|
||||||
test::fail_stream<
|
test::fail_stream<
|
||||||
test::string_stream> fs(n, ios_, ", world!");
|
test::string_stream> fs(n, ios_, ", world!");
|
||||||
streambuf_readstream<
|
dynabuf_readstream<
|
||||||
decltype(fs)&, streambuf> srs(fs);
|
decltype(fs)&, streambuf> srs(fs);
|
||||||
srs.capacity(3);
|
srs.capacity(3);
|
||||||
srs.buffer().commit(buffer_copy(
|
srs.buffer().commit(buffer_copy(
|
||||||
@@ -137,7 +137,7 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
BEAST_DEFINE_TESTSUITE(streambuf_readstream,core,beast);
|
BEAST_DEFINE_TESTSUITE(dynabuf_readstream,core,beast);
|
||||||
|
|
||||||
} // beast
|
} // beast
|
||||||
|
|
||||||
@@ -6,14 +6,14 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
// Test that header file is self-contained.
|
// Test that header file is self-contained.
|
||||||
#include <beast/core/write_streambuf.hpp>
|
#include <beast/core/write_dynabuf.hpp>
|
||||||
|
|
||||||
#include <beast/core/streambuf.hpp>
|
#include <beast/core/streambuf.hpp>
|
||||||
#include <beast/unit_test/suite.hpp>
|
#include <beast/unit_test/suite.hpp>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
class write_streambuf_test : public beast::unit_test::suite
|
class write_dynabuf_test : public beast::unit_test::suite
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void run() override
|
void run() override
|
||||||
@@ -31,6 +31,6 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
BEAST_DEFINE_TESTSUITE(write_streambuf,core,beast);
|
BEAST_DEFINE_TESTSUITE(write_dynabuf,core,beast);
|
||||||
|
|
||||||
} // beast
|
} // beast
|
||||||
@@ -6,7 +6,10 @@ GroupSources(test/http "/")
|
|||||||
|
|
||||||
add_executable (http-tests
|
add_executable (http-tests
|
||||||
${BEAST_INCLUDES}
|
${BEAST_INCLUDES}
|
||||||
|
message_fuzz.hpp
|
||||||
|
fail_parser.hpp
|
||||||
../../extras/beast/unit_test/main.cpp
|
../../extras/beast/unit_test/main.cpp
|
||||||
|
basic_dynabuf_body.cpp
|
||||||
basic_headers.cpp
|
basic_headers.cpp
|
||||||
basic_parser_v1.cpp
|
basic_parser_v1.cpp
|
||||||
body_type.cpp
|
body_type.cpp
|
||||||
@@ -20,7 +23,6 @@ add_executable (http-tests
|
|||||||
read.cpp
|
read.cpp
|
||||||
reason.cpp
|
reason.cpp
|
||||||
resume_context.cpp
|
resume_context.cpp
|
||||||
rfc2616.cpp
|
|
||||||
rfc7230.cpp
|
rfc7230.cpp
|
||||||
status.cpp
|
status.cpp
|
||||||
streambuf_body.cpp
|
streambuf_body.cpp
|
||||||
@@ -35,6 +37,7 @@ endif()
|
|||||||
|
|
||||||
add_executable (bench-tests
|
add_executable (bench-tests
|
||||||
${BEAST_INCLUDES}
|
${BEAST_INCLUDES}
|
||||||
|
nodejs_parser.hpp
|
||||||
../../extras/beast/unit_test/main.cpp
|
../../extras/beast/unit_test/main.cpp
|
||||||
nodejs_parser.cpp
|
nodejs_parser.cpp
|
||||||
parser_bench.cpp
|
parser_bench.cpp
|
||||||
|
|||||||
9
src/beast/test/http/basic_dynabuf_body.cpp
Normal file
9
src/beast/test/http/basic_dynabuf_body.cpp
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
// Test that header file is self-contained.
|
||||||
|
#include <beast/http/basic_dynabuf_body.hpp>
|
||||||
File diff suppressed because it is too large
Load Diff
112
src/beast/test/http/fail_parser.hpp
Normal file
112
src/beast/test/http/fail_parser.hpp
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
//
|
||||||
|
// 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_TEST_FAIL_PARSER_HPP
|
||||||
|
#define BEAST_HTTP_TEST_FAIL_PARSER_HPP
|
||||||
|
|
||||||
|
#include <beast/http/basic_parser_v1.hpp>
|
||||||
|
#include <beast/test/fail_counter.hpp>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
namespace http {
|
||||||
|
|
||||||
|
template<bool isRequest>
|
||||||
|
class fail_parser
|
||||||
|
: public basic_parser_v1<isRequest, fail_parser<isRequest>>
|
||||||
|
{
|
||||||
|
test::fail_counter& fc_;
|
||||||
|
std::uint64_t content_length_ = no_content_length;
|
||||||
|
int body_rv_ = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::string body;
|
||||||
|
|
||||||
|
template<class... Args>
|
||||||
|
explicit
|
||||||
|
fail_parser(test::fail_counter& fc, Args&&... args)
|
||||||
|
: fc_(fc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
on_body_rv(int rv)
|
||||||
|
{
|
||||||
|
body_rv_ = rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
// valid on successful parse
|
||||||
|
std::uint64_t
|
||||||
|
content_length() const
|
||||||
|
{
|
||||||
|
return content_length_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_start(error_code& ec)
|
||||||
|
{
|
||||||
|
fc_.fail(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_method(boost::string_ref const&, error_code& ec)
|
||||||
|
{
|
||||||
|
fc_.fail(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_uri(boost::string_ref const&, error_code& ec)
|
||||||
|
{
|
||||||
|
fc_.fail(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_reason(boost::string_ref const&, error_code& ec)
|
||||||
|
{
|
||||||
|
fc_.fail(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_request(error_code& ec)
|
||||||
|
{
|
||||||
|
fc_.fail(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_response(error_code& ec)
|
||||||
|
{
|
||||||
|
fc_.fail(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_field(boost::string_ref const&, error_code& ec)
|
||||||
|
{
|
||||||
|
fc_.fail(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_value(boost::string_ref const&, error_code& ec)
|
||||||
|
{
|
||||||
|
fc_.fail(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
int on_headers(std::uint64_t content_length, error_code& ec)
|
||||||
|
{
|
||||||
|
if(fc_.fail(ec))
|
||||||
|
return 0;
|
||||||
|
content_length_ = content_length;
|
||||||
|
return body_rv_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_body(boost::string_ref const& s, error_code& ec)
|
||||||
|
{
|
||||||
|
if(fc_.fail(ec))
|
||||||
|
return;
|
||||||
|
body.append(s.data(), s.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_complete(error_code& ec)
|
||||||
|
{
|
||||||
|
fc_.fail(ec);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // http
|
||||||
|
} // beast
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <beast/http/message.hpp>
|
#include <beast/http/message.hpp>
|
||||||
|
|
||||||
#include <beast/http/headers.hpp>
|
#include <beast/http/headers.hpp>
|
||||||
|
#include <beast/http/string_body.hpp>
|
||||||
#include <beast/unit_test/suite.hpp>
|
#include <beast/unit_test/suite.hpp>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
@@ -126,9 +127,30 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void testSwap()
|
||||||
|
{
|
||||||
|
message<true, string_body, headers> m1;
|
||||||
|
message<true, string_body, headers> m2;
|
||||||
|
m1.url = "u";
|
||||||
|
m1.body = "1";
|
||||||
|
m1.headers.insert("h", "v");
|
||||||
|
m2.method = "G";
|
||||||
|
m2.body = "2";
|
||||||
|
swap(m1, m2);
|
||||||
|
expect(m1.method == "G");
|
||||||
|
expect(m2.method.empty());
|
||||||
|
expect(m1.url.empty());
|
||||||
|
expect(m2.url == "u");
|
||||||
|
expect(m1.body == "2");
|
||||||
|
expect(m2.body == "1");
|
||||||
|
expect(! m1.headers.exists("h"));
|
||||||
|
expect(m2.headers.exists("h"));
|
||||||
|
}
|
||||||
|
|
||||||
void run() override
|
void run() override
|
||||||
{
|
{
|
||||||
testConstruction();
|
testConstruction();
|
||||||
|
testSwap();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#ifndef BEAST_HTTP_TEST_MESSAGE_FUZZ_HPP
|
#ifndef BEAST_HTTP_TEST_MESSAGE_FUZZ_HPP
|
||||||
#define BEAST_HTTP_TEST_MESSAGE_FUZZ_HPP
|
#define BEAST_HTTP_TEST_MESSAGE_FUZZ_HPP
|
||||||
|
|
||||||
#include <beast/core/write_streambuf.hpp>
|
#include <beast/core/write_dynabuf.hpp>
|
||||||
#include <beast/http/detail/basic_parser_v1.hpp>
|
#include <beast/http/detail/basic_parser_v1.hpp>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
// Test that header file is self-contained.
|
// Test that header file is self-contained.
|
||||||
#include <beast/http/message_v1.hpp>
|
#include <beast/http/message_v1.hpp>
|
||||||
|
|
||||||
|
#include <beast/http/headers.hpp>
|
||||||
|
#include <beast/http/string_body.hpp>
|
||||||
#include <beast/unit_test/suite.hpp>
|
#include <beast/unit_test/suite.hpp>
|
||||||
#include <beast/http/empty_body.hpp>
|
#include <beast/http/empty_body.hpp>
|
||||||
|
|
||||||
@@ -78,10 +80,36 @@ public:
|
|||||||
expect(! is_keep_alive(m));
|
expect(! is_keep_alive(m));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void testSwap()
|
||||||
|
{
|
||||||
|
message_v1<false, string_body, headers> m1;
|
||||||
|
message_v1<false, string_body, headers> m2;
|
||||||
|
m1.status = 200;
|
||||||
|
m1.version = 10;
|
||||||
|
m1.body = "1";
|
||||||
|
m1.headers.insert("h", "v");
|
||||||
|
m2.status = 404;
|
||||||
|
m2.reason = "OK";
|
||||||
|
m2.body = "2";
|
||||||
|
m2.version = 11;
|
||||||
|
swap(m1, m2);
|
||||||
|
expect(m1.status == 404);
|
||||||
|
expect(m2.status == 200);
|
||||||
|
expect(m1.reason == "OK");
|
||||||
|
expect(m2.reason.empty());
|
||||||
|
expect(m1.version == 11);
|
||||||
|
expect(m2.version == 10);
|
||||||
|
expect(m1.body == "2");
|
||||||
|
expect(m2.body == "1");
|
||||||
|
expect(! m1.headers.exists("h"));
|
||||||
|
expect(m2.headers.exists("h"));
|
||||||
|
}
|
||||||
|
|
||||||
void run() override
|
void run() override
|
||||||
{
|
{
|
||||||
testFreeFunctions();
|
testFreeFunctions();
|
||||||
testPrepare();
|
testPrepare();
|
||||||
|
testSwap();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
#include "nodejs-parser/http_parser.h"
|
#include "nodejs-parser/http_parser.h"
|
||||||
|
|
||||||
#include <beast/http/message_v1.hpp>
|
#include <beast/http/message_v1.hpp>
|
||||||
#include <beast/http/rfc2616.hpp>
|
#include <beast/http/rfc7230.hpp>
|
||||||
#include <beast/core/buffer_concepts.hpp>
|
#include <beast/core/buffer_concepts.hpp>
|
||||||
#include <beast/core/error.hpp>
|
#include <beast/core/error.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
@@ -611,7 +611,7 @@ nodejs_basic_parser<Derived>::check_header()
|
|||||||
{
|
{
|
||||||
if (! value_.empty())
|
if (! value_.empty())
|
||||||
{
|
{
|
||||||
rfc2616::trim_right_in_place(value_);
|
//detail::trim(value_);
|
||||||
call_on_field(field_, value_,
|
call_on_field(field_, value_,
|
||||||
has_on_field<Derived>{});
|
has_on_field<Derived>{});
|
||||||
field_.clear();
|
field_.clear();
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ public:
|
|||||||
check("http", parse_error::bad_version);
|
check("http", parse_error::bad_version);
|
||||||
check("http", parse_error::bad_crlf);
|
check("http", parse_error::bad_crlf);
|
||||||
check("http", parse_error::bad_request);
|
check("http", parse_error::bad_request);
|
||||||
check("http", parse_error::bad_status_code);
|
|
||||||
check("http", parse_error::bad_status);
|
check("http", parse_error::bad_status);
|
||||||
|
check("http", parse_error::bad_reason);
|
||||||
check("http", parse_error::bad_field);
|
check("http", parse_error::bad_field);
|
||||||
check("http", parse_error::bad_value);
|
check("http", parse_error::bad_value);
|
||||||
check("http", parse_error::bad_content_length);
|
check("http", parse_error::bad_content_length);
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
// Test that header file is self-contained.
|
// Test that header file is self-contained.
|
||||||
#include <beast/http/read.hpp>
|
#include <beast/http/read.hpp>
|
||||||
|
|
||||||
|
#include "fail_parser.hpp"
|
||||||
|
|
||||||
#include <beast/http/headers.hpp>
|
#include <beast/http/headers.hpp>
|
||||||
#include <beast/http/streambuf_body.hpp>
|
#include <beast/http/streambuf_body.hpp>
|
||||||
#include <beast/test/fail_stream.hpp>
|
#include <beast/test/fail_stream.hpp>
|
||||||
@@ -24,77 +26,6 @@ class read_test
|
|||||||
, public test::enable_yield_to
|
, public test::enable_yield_to
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
template<bool isRequest>
|
|
||||||
class fail_parser
|
|
||||||
: public basic_parser_v1<isRequest, fail_parser<isRequest>>
|
|
||||||
{
|
|
||||||
test::fail_counter& fc_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
template<class... Args>
|
|
||||||
explicit
|
|
||||||
fail_parser(test::fail_counter& fc, Args&&... args)
|
|
||||||
: fc_(fc)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_start(error_code& ec)
|
|
||||||
{
|
|
||||||
fc_.fail(ec);
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_method(boost::string_ref const&, error_code& ec)
|
|
||||||
{
|
|
||||||
fc_.fail(ec);
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_uri(boost::string_ref const&, error_code& ec)
|
|
||||||
{
|
|
||||||
fc_.fail(ec);
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_reason(boost::string_ref const&, error_code& ec)
|
|
||||||
{
|
|
||||||
fc_.fail(ec);
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_request(error_code& ec)
|
|
||||||
{
|
|
||||||
fc_.fail(ec);
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_response(error_code& ec)
|
|
||||||
{
|
|
||||||
fc_.fail(ec);
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_field(boost::string_ref const&, error_code& ec)
|
|
||||||
{
|
|
||||||
fc_.fail(ec);
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_value(boost::string_ref const&, error_code& ec)
|
|
||||||
{
|
|
||||||
fc_.fail(ec);
|
|
||||||
}
|
|
||||||
|
|
||||||
int on_headers(error_code& ec)
|
|
||||||
{
|
|
||||||
fc_.fail(ec);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_body(boost::string_ref const&, error_code& ec)
|
|
||||||
{
|
|
||||||
fc_.fail(ec);
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_complete(error_code& ec)
|
|
||||||
{
|
|
||||||
fc_.fail(ec);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<bool isRequest>
|
template<bool isRequest>
|
||||||
void failMatrix(const char* s, yield_context do_yield)
|
void failMatrix(const char* s, yield_context do_yield)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,115 +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)
|
|
||||||
//
|
|
||||||
|
|
||||||
// Test that header file is self-contained.
|
|
||||||
#include <beast/http/rfc2616.hpp>
|
|
||||||
|
|
||||||
#include <beast/unit_test/suite.hpp>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
namespace rfc2616 {
|
|
||||||
namespace test {
|
|
||||||
|
|
||||||
class rfc2616_test : public beast::unit_test::suite
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void
|
|
||||||
checkSplit(std::string const& s,
|
|
||||||
std::vector <std::string> const& expected)
|
|
||||||
{
|
|
||||||
auto const parsed = split_commas(s.begin(), s.end());
|
|
||||||
expect (parsed == expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
void testSplit()
|
|
||||||
{
|
|
||||||
checkSplit("", {});
|
|
||||||
checkSplit(" ", {});
|
|
||||||
checkSplit(" ", {});
|
|
||||||
checkSplit("\t", {});
|
|
||||||
checkSplit(" \t ", {});
|
|
||||||
checkSplit(",", {});
|
|
||||||
checkSplit(",,", {});
|
|
||||||
checkSplit(" ,", {});
|
|
||||||
checkSplit(" , ,", {});
|
|
||||||
checkSplit("x", {"x"});
|
|
||||||
checkSplit(" x", {"x"});
|
|
||||||
checkSplit(" \t x", {"x"});
|
|
||||||
checkSplit("x ", {"x"});
|
|
||||||
checkSplit("x \t", {"x"});
|
|
||||||
checkSplit(" \t x \t ", {"x"});
|
|
||||||
checkSplit("\"\"", {});
|
|
||||||
checkSplit(" \"\"", {});
|
|
||||||
checkSplit("\"\" ", {});
|
|
||||||
checkSplit("\"x\"", {"x"});
|
|
||||||
checkSplit("\" \"", {" "});
|
|
||||||
checkSplit("\" x\"", {" x"});
|
|
||||||
checkSplit("\"x \"", {"x "});
|
|
||||||
checkSplit("\" x \"", {" x "});
|
|
||||||
checkSplit("\"\tx \"", {"\tx "});
|
|
||||||
checkSplit("x,y", {"x", "y"});
|
|
||||||
checkSplit("x ,\ty ", {"x", "y"});
|
|
||||||
checkSplit("x, y, z", {"x","y","z"});
|
|
||||||
checkSplit("x, \"y\", z", {"x","y","z"});
|
|
||||||
checkSplit(",,x,,\"y\",,", {"x","y"});
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
checkIter(std::string const& s,
|
|
||||||
std::vector<std::string> const& expected)
|
|
||||||
{
|
|
||||||
std::vector<std::string> got;
|
|
||||||
for(auto const& v : make_list(s))
|
|
||||||
got.emplace_back(v);
|
|
||||||
expect(got == expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
testIter()
|
|
||||||
{
|
|
||||||
checkIter("x", {"x"});
|
|
||||||
checkIter(" x", {"x"});
|
|
||||||
checkIter("x\t", {"x"});
|
|
||||||
checkIter("\tx ", {"x"});
|
|
||||||
checkIter(",x", {"x"});
|
|
||||||
checkIter("x,", {"x"});
|
|
||||||
checkIter(",x,", {"x"});
|
|
||||||
checkIter(" , x\t,\t", {"x"});
|
|
||||||
checkIter("x,y", {"x", "y"});
|
|
||||||
checkIter("x, ,y ", {"x", "y"});
|
|
||||||
checkIter("\"x\"", {"x"});
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
testList()
|
|
||||||
{
|
|
||||||
expect(token_in_list("x", "x"));
|
|
||||||
expect(token_in_list("x,y", "x"));
|
|
||||||
expect(token_in_list("x,y", "y"));
|
|
||||||
expect(token_in_list("x, y ", "y"));
|
|
||||||
expect(token_in_list("x", "X"));
|
|
||||||
expect(token_in_list("Y", "y"));
|
|
||||||
expect(token_in_list("close, keepalive", "close"));
|
|
||||||
expect(token_in_list("close, keepalive", "keepalive"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
run()
|
|
||||||
{
|
|
||||||
testSplit();
|
|
||||||
testIter();
|
|
||||||
testList();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
BEAST_DEFINE_TESTSUITE(rfc2616,http,beast);
|
|
||||||
|
|
||||||
} // test
|
|
||||||
} // rfc2616
|
|
||||||
} // beast
|
|
||||||
@@ -7,3 +7,240 @@
|
|||||||
|
|
||||||
// Test that header file is self-contained.
|
// Test that header file is self-contained.
|
||||||
#include <beast/http/rfc7230.hpp>
|
#include <beast/http/rfc7230.hpp>
|
||||||
|
|
||||||
|
#include <beast/http/detail/rfc7230.hpp>
|
||||||
|
#include <beast/unit_test/suite.hpp>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
namespace http {
|
||||||
|
namespace test {
|
||||||
|
|
||||||
|
class rfc7230_test : public beast::unit_test::suite
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static
|
||||||
|
std::string
|
||||||
|
fmt(std::string const& s)
|
||||||
|
{
|
||||||
|
return '\'' + s + '\'';
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
std::string
|
||||||
|
str(boost::string_ref const& s)
|
||||||
|
{
|
||||||
|
return std::string(s.data(), s.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
std::string
|
||||||
|
str(param_list const& c)
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
for(auto const& p : c)
|
||||||
|
{
|
||||||
|
s.push_back(';');
|
||||||
|
s.append(str(p.first));
|
||||||
|
s.push_back('=');
|
||||||
|
s.append(str(p.second));
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
testParamList()
|
||||||
|
{
|
||||||
|
auto const ce =
|
||||||
|
[&](std::string const& s)
|
||||||
|
{
|
||||||
|
auto const got = str(param_list{s});
|
||||||
|
expect(got == s, fmt(got));
|
||||||
|
};
|
||||||
|
auto const cs =
|
||||||
|
[&](std::string const& s, std::string const& good)
|
||||||
|
{
|
||||||
|
ce(good);
|
||||||
|
auto const got = str(param_list{s});
|
||||||
|
ce(got);
|
||||||
|
expect(got == good, fmt(got));
|
||||||
|
};
|
||||||
|
auto const cq =
|
||||||
|
[&](std::string const& s, std::string const& good)
|
||||||
|
{
|
||||||
|
auto const got = str(param_list{s});
|
||||||
|
expect(got == good, fmt(got));
|
||||||
|
};
|
||||||
|
|
||||||
|
ce("");
|
||||||
|
cs(" ;\t i =\t 1 \t", ";i=1");
|
||||||
|
cq("\t; \t xyz=1 ; ijk=\"q\\\"t\"", ";xyz=1;ijk=q\"t");
|
||||||
|
|
||||||
|
// invalid strings
|
||||||
|
cs(";", "");
|
||||||
|
cs(";,", "");
|
||||||
|
cs(";xy", "");
|
||||||
|
cs(";xy", "");
|
||||||
|
cs(";xy ", "");
|
||||||
|
cs(";xy,", "");
|
||||||
|
|
||||||
|
cq(";x=,", "");
|
||||||
|
cq(";xy=\"", "");
|
||||||
|
cq(";xy=\"\x7f", "");
|
||||||
|
cq(";xy=\"\\", "");
|
||||||
|
cq(";xy=\"\\\x01\"", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
std::string
|
||||||
|
str(ext_list const& ex)
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
for(auto const& e : ex)
|
||||||
|
{
|
||||||
|
if(! s.empty())
|
||||||
|
s += ',';
|
||||||
|
s.append(str(e.first));
|
||||||
|
s += str(e.second);
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
testExtList()
|
||||||
|
{
|
||||||
|
auto const ce =
|
||||||
|
[&](std::string const& s)
|
||||||
|
{
|
||||||
|
auto const got = str(ext_list{s});
|
||||||
|
expect(got == s, fmt(got));
|
||||||
|
};
|
||||||
|
auto const cs =
|
||||||
|
[&](std::string const& s, std::string const& good)
|
||||||
|
{
|
||||||
|
ce(good);
|
||||||
|
auto const got = str(ext_list{s});
|
||||||
|
ce(got);
|
||||||
|
expect(got == good, fmt(got));
|
||||||
|
};
|
||||||
|
auto const cq =
|
||||||
|
[&](std::string const& s, std::string const& good)
|
||||||
|
{
|
||||||
|
auto const got = str(ext_list{s});
|
||||||
|
expect(got == good, fmt(got));
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
ext-list = *( "," OWS ) ext *( OWS "," [ OWS ext ] )
|
||||||
|
ext = token param-list
|
||||||
|
param-list = *( OWS ";" OWS param )
|
||||||
|
param = token OWS "=" OWS ( token / quoted-string )
|
||||||
|
*/
|
||||||
|
ce("");
|
||||||
|
cs(",", "");
|
||||||
|
cs(", ", "");
|
||||||
|
cs(",\t", "");
|
||||||
|
cs(", \t", "");
|
||||||
|
cs(" ", "");
|
||||||
|
cs(" ,", "");
|
||||||
|
cs("\t,", "");
|
||||||
|
cs("\t , \t", "");
|
||||||
|
cs(",,", "");
|
||||||
|
cs(" , \t,, \t,", "");
|
||||||
|
|
||||||
|
ce("a");
|
||||||
|
ce("ab");
|
||||||
|
ce("a,b");
|
||||||
|
cs(" a ", "a");
|
||||||
|
cs("\t a, b\t , c\t", "a,b,c");
|
||||||
|
|
||||||
|
cs("a; \t i\t=\t \t1\t ", "a;i=1");
|
||||||
|
ce("a;i=1;j=2;k=3");
|
||||||
|
ce("a;i=1;j=2;k=3,b;i=4;j=5;k=6");
|
||||||
|
|
||||||
|
cq("ab;x=\" \"", "ab;x= ");
|
||||||
|
cq("ab;x=\"\\\"\"", "ab;x=\"");
|
||||||
|
|
||||||
|
expect(ext_list{"a,b;i=1,c;j=2;k=3"}.exists("A"));
|
||||||
|
expect(ext_list{"a,b;i=1,c;j=2;k=3"}.exists("b"));
|
||||||
|
expect(! ext_list{"a,b;i=1,c;j=2;k=3"}.exists("d"));
|
||||||
|
|
||||||
|
// invalid strings
|
||||||
|
cs("i j", "i");
|
||||||
|
cs(";", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
std::string
|
||||||
|
str(token_list const& c)
|
||||||
|
{
|
||||||
|
bool first = true;
|
||||||
|
std::string s;
|
||||||
|
for(auto const& p : c)
|
||||||
|
{
|
||||||
|
if(! first)
|
||||||
|
s.push_back(',');
|
||||||
|
s.append(str(p));
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
testTokenList()
|
||||||
|
{
|
||||||
|
auto const ce =
|
||||||
|
[&](std::string const& s)
|
||||||
|
{
|
||||||
|
auto const got = str(token_list{s});
|
||||||
|
expect(got == s, fmt(got));
|
||||||
|
};
|
||||||
|
auto const cs =
|
||||||
|
[&](std::string const& s, std::string const& good)
|
||||||
|
{
|
||||||
|
ce(good);
|
||||||
|
auto const got = str(token_list{s});
|
||||||
|
ce(got);
|
||||||
|
expect(got == good, fmt(got));
|
||||||
|
};
|
||||||
|
|
||||||
|
cs("", "");
|
||||||
|
cs(" ", "");
|
||||||
|
cs(" ", "");
|
||||||
|
cs("\t", "");
|
||||||
|
cs(" \t ", "");
|
||||||
|
cs(",", "");
|
||||||
|
cs(",,", "");
|
||||||
|
cs(" ,", "");
|
||||||
|
cs(" , ,", "");
|
||||||
|
cs(" x", "x");
|
||||||
|
cs(" \t x", "x");
|
||||||
|
cs("x ", "x");
|
||||||
|
cs("x \t", "x");
|
||||||
|
cs(" \t x \t ", "x");
|
||||||
|
ce("x,y");
|
||||||
|
cs("x ,\ty ", "x,y");
|
||||||
|
cs("x, y, z", "x,y,z");
|
||||||
|
|
||||||
|
expect(token_list{"a,b,c"}.exists("A"));
|
||||||
|
expect(token_list{"a,b,c"}.exists("b"));
|
||||||
|
expect(! token_list{"a,b,c"}.exists("d"));
|
||||||
|
|
||||||
|
// invalid
|
||||||
|
cs("x y", "x");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
run()
|
||||||
|
{
|
||||||
|
testParamList();
|
||||||
|
testExtList();
|
||||||
|
testTokenList();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BEAST_DEFINE_TESTSUITE(rfc7230,http,beast);
|
||||||
|
|
||||||
|
} // test
|
||||||
|
} // http
|
||||||
|
} // beast
|
||||||
|
|||||||
Reference in New Issue
Block a user