diff --git a/.travis.yml b/.travis.yml index 32dc14ad..976ad56a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -118,6 +118,9 @@ matrix: - TOOLSET=clang - COMPILER=clang++ - CXXSTD=14 + before_install: + - brew install openssl + - export OPENSSL_ROOT=$(brew --prefix openssl) install: - export BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true @@ -198,10 +201,13 @@ install: script: - |- - echo "using $TOOLSET : : $COMPILER ;" > ~/user-config.jam + cp libs/beast/tools/user-config.jam ~/user-config.jam + - |- + echo "using $TOOLSET : : $COMPILER ;" >> ~/user-config.jam - cd ../boost-root - libs/beast/tools/retry.sh libs/beast/tools/build-and-test.sh + after_script: - cat nohup.out || echo "nohup.out already deleted" diff --git a/CHANGELOG.md b/CHANGELOG.md index 80c32296..80364f46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +Version 208: + +* Add get_lowest_layer free function +* Add lowest_layer_type metafunction + +-------------------------------------------------------------------------------- + Version 207 * Send from the strand diff --git a/CMakeLists.txt b/CMakeLists.txt index 3208090e..3a15e7bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,7 @@ # cmake_minimum_required (VERSION 3.5.1) +cmake_policy (SET CMP0074 NEW) project (Beast VERSION 207) diff --git a/Jamfile b/Jamfile index 02768170..4b544335 100644 --- a/Jamfile +++ b/Jamfile @@ -1,5 +1,5 @@ # -# Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com) +# Copyright (c) 2019 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) @@ -7,6 +7,7 @@ # Official repository: https://github.com/boostorg/beast # +import ac ; import os ; import feature ; import boost ; @@ -16,39 +17,19 @@ import ../../config/checks/config : requires ; boost.use-project ; -if [ os.name ] = SOLARIS -{ - lib socket ; - lib nsl ; -} -else if [ os.name ] = NT -{ - lib ws2_32 ; - lib mswsock ; -} -else if [ os.name ] = HPUX -{ - lib ipv6 ; -} -else if [ os.name ] = QNXNTO -{ - lib socket ; -} -else if [ os.name ] = HAIKU -{ - lib network ; -} +lib socket ; # SOLARIS, QNXNTO +lib nsl ; # SOLARIS +lib ws2_32 ; # NT +lib mswsock ; # NT +lib ipv6 ; # HPUX +lib network ; # HAIKU -if [ os.name ] = NT -{ - lib ssl : : ssleay32 ; - lib crypto : : libeay32 ; -} -else -{ - lib ssl ; - lib crypto ; -} +lib ssl ; +lib crypto ; +lib crypt32 ; + +lib ssl : : windows ssleay32 ; +lib crypto : : windows libeay32 ; variant coverage : debug @@ -87,21 +68,24 @@ lib static_asio BOOST_ASIO_DISABLE_BOOST_REGEX=1 BOOST_ASIO_SEPARATE_COMPILATION BOOST_COROUTINES_NO_DEPRECATION_WARNING=1 - NT:_WIN32_WINNT=0x0601 + windows:_WIN32_WINNT=0x0501 static ; project /boost/beast : requirements - /boost//headers . ./test/extras/include /boost/coroutine//boost_coroutine /boost/filesystem//boost_filesystem static_asio + /boost//headers multi - shared on + shared + [ ac.check-library /boost/beast//ssl : /boost/beast//ssl : no ] + /boost/beast//crypto + BOOST_ALL_NO_LIB=1 BOOST_ASIO_NO_DEPRECATED=1 BOOST_ASIO_DISABLE_BOOST_ARRAY=1 @@ -116,13 +100,23 @@ project /boost/beast msvc:_SILENCE_CXX17_ALLOCATOR_VOID_DEPRECATION_WARNING msvc:_SILENCE_CXX17_ADAPTOR_TYPEDEFS_DEPRECATION_WARNING msvc,release:"/Ob2 /Oi /Ot" - SOLARIS:socket - SOLARIS:nsl - NT:_WIN32_WINNT=0x0601 - NT,cw:ws2_32 - NT,cw:mswsock - NT,gcc:ws2_32 - NT,gcc:mswsock - NT,gcc-cygwin:__USE_W32_SOCKETS + + linux:_XOPEN_SOURCE=600 + linux:_GNU_SOURCE=1 + solaris:_XOPEN_SOURCE=500 + solaris:__EXTENSIONS__ + solaris:socket + solaris:nsl + windows:_WIN32_WINNT=0x0501 + windows,cw:ws2_32 + windows,cw:mswsock + windows,gcc:ws2_32 + windows,gcc:mswsock + windows,gcc-cygwin:__USE_W32_SOCKETS + hpux,gcc:_XOPEN_SOURCE_EXTENDED + hpux:ipv6 + qnxnto:socket + haiku:network + : usage-requirements ; diff --git a/doc/qbk/00_main.qbk b/doc/qbk/00_main.qbk index 47d6dd9c..44a39749 100644 --- a/doc/qbk/00_main.qbk +++ b/doc/qbk/00_main.qbk @@ -109,6 +109,7 @@ [def __serializer__ [link beast.ref.boost__beast__http__serializer `serializer`]] [def __flat_static_buffer__ [link beast.ref.boost__beast__flat_static_buffer `flat_static_buffer`]] [def __flat_static_buffer_base__ [link beast.ref.boost__beast__flat_static_buffer_base `flat_static_buffer_base`]] +[def __websocket_stream__ [link beast.ref.boost__beast__websocket__stream `websocket::stream`]] [import ../../example/common/detect_ssl.hpp] [import ../../example/doc/http_examples.hpp] @@ -120,6 +121,7 @@ [import ../../test/doc/exemplars.cpp] [import ../../test/doc/core_snippets.cpp] +[import ../../test/doc/core_3_layers.cpp] [import ../../test/doc/http_snippets.cpp] [import ../../test/doc/websocket_snippets.cpp] diff --git a/doc/qbk/03_core.qbk b/doc/qbk/03_core.qbk index 5a823423..dd33983c 100644 --- a/doc/qbk/03_core.qbk +++ b/doc/qbk/03_core.qbk @@ -94,9 +94,10 @@ effect: [include 03_core/1_refresher.qbk] [include 03_core/2_streams.qbk] -[include 03_core/3_buffers.qbk] -[include 03_core/4_files.qbk] -[include 03_core/5_composed.qbk] -[include 03_core/6_detect_ssl.qbk] +[include 03_core/3_layers.qbk] +[include 03_core/4_buffers.qbk] +[include 03_core/5_files.qbk] +[include 03_core/6_composed.qbk] +[include 03_core/7_detect_ssl.qbk] [endsect] diff --git a/doc/qbk/03_core/3_layers.qbk b/doc/qbk/03_core/3_layers.qbk new file mode 100644 index 00000000..8778e000 --- /dev/null +++ b/doc/qbk/03_core/3_layers.qbk @@ -0,0 +1,115 @@ +[/ + Copyright (c) 2016-2017 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) + + Official repository: https://github.com/boostorg/beast +] + +[section Layered Streams] + +Networking's __ssl_stream__ is a class template meeting the requirements +of both synchronous and asynchronous read and write streams, implemented +in terms of a "next layer" object whose type is determined by a class +template parameter. The SSL stream constructs an instance of the next +layer object internally, while allowing external access through the +observer `net::ssl::stream::next_layer()`. This declares an SSL stream +which uses a regular TCP/IP socket as the next layer: + +[code_core_3_layers_1] + +Objects using this design pattern are referred to in networking as "a +stack of stream layers". In Beast we use the term ['layered stream], +although the property of having a next layer is not exclusive to streams. +As with the SSL stream, __websocket_stream__ is a class template +parameterized on a next layer object. This declares a websocket +stream which uses a regular TCP/IP socket as the next layer: + +[code_core_3_layers_2] + +If a Secure WebSockets stream is desired, this is accomplished simply +by changing the type of the next layer and adjusting the constructor +arguments to match: + +[code_core_3_layers_3] + +Higher level abstractions can be developed in this fashion by nesting +stream layers to arbitrary degree. The stack of stream layers effectively +forms a compile-time singly linked list. The object at the end of +this list is called the ['lowest layer], and is special from the +others because it typically represents the underlying socket. + +Beast comes with several layered stream wrappers, as well as +facilities for authoring and working with layered streams: + +[table Layered Stream Algorithms and Types +[[Name][Description]] +[[ + [link beast.ref.boost__beast__timeout_stream `timeout_stream`] + [link beast.ref.boost__beast__basic_timeout_stream `basic_timeout_stream`] +][ + A timeout stream meets the requirements for synchronous and asynchronous + read and write streams, and additionally provides configurable timeouts + for logical operations that include reading, writing, and/or connecting. +]] +[[ + [link beast.ref.boost__beast__buffered_read_stream `buffered_read_stream`] +][ + A timeout stream meets the requirements for synchronous and asynchronous + read and write streams, and additionally implements configurable buffering + for reads. +]] +[[ + [link beast.ref.boost__beast__flat_stream `flat_stream`] +][ + A flat stream operates as a transparent stream which helps to work around + a limitation of `net::ssl::stream`. It is used in the implementation + of [link beast.ref.boost__beast__ssl_stream `ssl_stream`]. +]] +[[ + [link beast.ref.boost__beast__http__icy_stream `http::icy_stream`] +][ + An ICY stream transparently converts the non-standard "ICY 200 OK" + HTTP response from Shoutcast servers into a conforming 200 level + HTTP response. +]] +[[ + [link beast.ref.boost__beast__ssl_stream `ssl_stream`] +][ + The SSL stream is a drop-in replacement for `net::ssl::stream` which + allows for move-construction and move-assignment, and also implements + a work-around for a performance limitation in the original SSL stream. +]] +[[ + [link beast.ref.boost__beast__get_lowest_layer `get_lowest_layer`] +][ + Returns the lowest layer in a stack of stream layers by recursively + calling the `next_layer` member function on each object until reaching + an object which lacks the member. This example + puts a layered stream into non-blocking mode by retrieving the + TCP/IP socket in the lowest layer and changing the socket option: + + [code_core_3_layers_4] +]] +[[ + [link beast.ref.boost__beast__lowest_layer_type `lowest_layer_type`] +][ + A metafunction to return the type of the lowest layer used in + a type representing a stack of stream layers. This is the type + of reference returned by + [link beast.ref.boost__beast__get_lowest_layer `get_lowest_layer`] +]] +] + +[heading Example] + +This example shows the definition of a layered stream which keeps individual +counts of the total number of bytes read from and written to the next layer. +It meets the requirements for synchronous and asynchronous read and write +streams: + +[code_core_3_layers_5] + +[endsect] + diff --git a/doc/qbk/03_core/3_buffers.qbk b/doc/qbk/03_core/4_buffers.qbk similarity index 100% rename from doc/qbk/03_core/3_buffers.qbk rename to doc/qbk/03_core/4_buffers.qbk diff --git a/doc/qbk/03_core/4_files.qbk b/doc/qbk/03_core/5_files.qbk similarity index 100% rename from doc/qbk/03_core/4_files.qbk rename to doc/qbk/03_core/5_files.qbk diff --git a/doc/qbk/03_core/5_composed.qbk b/doc/qbk/03_core/6_composed.qbk similarity index 100% rename from doc/qbk/03_core/5_composed.qbk rename to doc/qbk/03_core/6_composed.qbk diff --git a/doc/qbk/03_core/6_detect_ssl.qbk b/doc/qbk/03_core/7_detect_ssl.qbk similarity index 100% rename from doc/qbk/03_core/6_detect_ssl.qbk rename to doc/qbk/03_core/7_detect_ssl.qbk diff --git a/doc/qbk/07_concepts/DynamicBuffer.qbk b/doc/qbk/07_concepts/DynamicBuffer.qbk index cb22dd60..4b2d6a5f 100644 --- a/doc/qbk/07_concepts/DynamicBuffer.qbk +++ b/doc/qbk/07_concepts/DynamicBuffer.qbk @@ -33,7 +33,7 @@ implementation strategies: size of the character sequence. This is the implementation approach currently offered by __multi_buffer__. -[heading Associated Types] +[heading Associated With] * `boost::asio::is_dynamic_buffer` * __ConstBufferSequence__ diff --git a/doc/qbk/07_concepts/Streams.qbk b/doc/qbk/07_concepts/Streams.qbk index 29a3cf5e..63ddd8d9 100644 --- a/doc/qbk/07_concepts/Streams.qbk +++ b/doc/qbk/07_concepts/Streams.qbk @@ -12,8 +12,8 @@ A stream in the context of Beast and networking, represents a full-duplex connection between two programs or hosts, where data represented as bytes may be received reliably in the same order they were written. -Streams can be support synchronous transfers, asynchronous transfers, -or both. +Streams may support any combination of synchronous and/or asynchronous +reading and writing. Stream concepts are based on named requirements in networking: diff --git a/doc/qbk/quickref.xml b/doc/qbk/quickref.xml index 27de1ccb..cad0d9cd 100644 --- a/doc/qbk/quickref.xml +++ b/doc/qbk/quickref.xml @@ -234,7 +234,9 @@ buffers_range buffers_range_ref buffers_to_string + close_socket generic_category + get_lowest_layer iequals make_printable ostream @@ -248,6 +250,7 @@ buffers_type buffers_iterator_type + lowest_layer_type has_get_executor is_async_read_stream is_async_write_stream diff --git a/example/advanced/Jamfile b/example/advanced/Jamfile index 2524238b..d1053a90 100644 --- a/example/advanced/Jamfile +++ b/example/advanced/Jamfile @@ -9,5 +9,5 @@ build-project server ; -# VFALCO How do I make this work on Windows and if OpenSSL is not available? -#build-project server-flex ; +# SSL +build-project server-flex ; diff --git a/example/advanced/server-flex/CMakeLists.txt b/example/advanced/server-flex/CMakeLists.txt index 981ce6b5..094f9acb 100644 --- a/example/advanced/server-flex/CMakeLists.txt +++ b/example/advanced/server-flex/CMakeLists.txt @@ -23,7 +23,7 @@ if (OPENSSL_FOUND) set_property(TARGET advanced-server-flex PROPERTY FOLDER "example-advanced-server") target_link_libraries (advanced-server-flex - ${OPENSSL_LIBRARIES} + OpenSSL::SSL OpenSSL::Crypto ) endif() diff --git a/example/advanced/server-flex/Jamfile b/example/advanced/server-flex/Jamfile index dfa18256..52fe55d3 100644 --- a/example/advanced/server-flex/Jamfile +++ b/example/advanced/server-flex/Jamfile @@ -7,10 +7,12 @@ # Official repository: https://github.com/boostorg/beast # +import ac ; + project : requirements - ssl - crypto + [ ac.check-library /boost/beast//ssl : /boost/beast//ssl : no ] + /boost/beast//crypto ; exe advanced-server-flex : diff --git a/example/http/client/Jamfile b/example/http/client/Jamfile index c5d71aab..11dd77ee 100644 --- a/example/http/client/Jamfile +++ b/example/http/client/Jamfile @@ -12,7 +12,7 @@ build-project coro ; build-project crawl ; build-project sync ; -# VFALCO How do I make this work on Windows and if OpenSSL is not available? -#build-project async-ssl ; -#build-project coro-ssl ; -#build-project sync-ssl ; +# SSL +build-project async-ssl ; +build-project coro-ssl ; +build-project sync-ssl ; diff --git a/example/http/client/async-ssl/CMakeLists.txt b/example/http/client/async-ssl/CMakeLists.txt index 87eb2fed..f7c88a12 100644 --- a/example/http/client/async-ssl/CMakeLists.txt +++ b/example/http/client/async-ssl/CMakeLists.txt @@ -22,7 +22,7 @@ if (OPENSSL_FOUND) set_property(TARGET http-client-async-ssl PROPERTY FOLDER "example-http-client") target_link_libraries (http-client-async-ssl - ${OPENSSL_LIBRARIES} + OpenSSL::SSL OpenSSL::Crypto ) endif() diff --git a/example/http/client/async-ssl/Jamfile b/example/http/client/async-ssl/Jamfile index ed5596af..3cabd04f 100644 --- a/example/http/client/async-ssl/Jamfile +++ b/example/http/client/async-ssl/Jamfile @@ -7,10 +7,12 @@ # Official repository: https://github.com/boostorg/beast # +import ac ; + project : requirements - ssl - crypto + [ ac.check-library /boost/beast//ssl : /boost/beast//ssl : no ] + /boost/beast//crypto ; exe http-client-async-ssl : diff --git a/example/http/client/coro-ssl/CMakeLists.txt b/example/http/client/coro-ssl/CMakeLists.txt index 3ff78360..f8ed33ed 100644 --- a/example/http/client/coro-ssl/CMakeLists.txt +++ b/example/http/client/coro-ssl/CMakeLists.txt @@ -22,7 +22,7 @@ if (OPENSSL_FOUND) set_property(TARGET http-client-coro-ssl PROPERTY FOLDER "example-http-client") target_link_libraries (http-client-coro-ssl - ${OPENSSL_LIBRARIES} + OpenSSL::SSL OpenSSL::Crypto ) endif() diff --git a/example/http/client/coro-ssl/Jamfile b/example/http/client/coro-ssl/Jamfile index 8ed87bf1..24904127 100644 --- a/example/http/client/coro-ssl/Jamfile +++ b/example/http/client/coro-ssl/Jamfile @@ -7,10 +7,12 @@ # Official repository: https://github.com/boostorg/beast # +import ac ; + project : requirements - ssl - crypto + [ ac.check-library /boost/beast//ssl : /boost/beast//ssl : no ] + /boost/beast//crypto ; exe http-client-coro-ssl : diff --git a/example/http/client/sync-ssl/CMakeLists.txt b/example/http/client/sync-ssl/CMakeLists.txt index 9683e62d..0997d37f 100644 --- a/example/http/client/sync-ssl/CMakeLists.txt +++ b/example/http/client/sync-ssl/CMakeLists.txt @@ -22,7 +22,7 @@ if (OPENSSL_FOUND) set_property(TARGET http-client-sync-ssl PROPERTY FOLDER "example-http-client") target_link_libraries (http-client-sync-ssl - ${OPENSSL_LIBRARIES} + OpenSSL::SSL OpenSSL::Crypto ) endif() diff --git a/example/http/client/sync-ssl/Jamfile b/example/http/client/sync-ssl/Jamfile index 26fa582f..f2726f4c 100644 --- a/example/http/client/sync-ssl/Jamfile +++ b/example/http/client/sync-ssl/Jamfile @@ -7,10 +7,12 @@ # Official repository: https://github.com/boostorg/beast # +import ac ; + project : requirements - ssl - crypto + [ ac.check-library /boost/beast//ssl : /boost/beast//ssl : no ] + /boost/beast//crypto ; exe http-client-sync-ssl : diff --git a/example/http/server/Jamfile b/example/http/server/Jamfile index d5c0fdc7..cb8ab104 100644 --- a/example/http/server/Jamfile +++ b/example/http/server/Jamfile @@ -14,9 +14,9 @@ build-project small ; build-project stackless ; build-project sync ; -# VFALCO How do I make this work on Windows and if OpenSSL is not available? -#build-project async-ssl ; -#build-project coro-ssl ; -#build-project flex ; -#build-project stackless-ssl ; -#build-project sync-ssl ; +# SSL +build-project async-ssl ; +build-project coro-ssl ; +build-project flex ; +build-project stackless-ssl ; +build-project sync-ssl ; diff --git a/example/http/server/async-ssl/CMakeLists.txt b/example/http/server/async-ssl/CMakeLists.txt index 130f4550..40d52195 100644 --- a/example/http/server/async-ssl/CMakeLists.txt +++ b/example/http/server/async-ssl/CMakeLists.txt @@ -22,7 +22,7 @@ if (OPENSSL_FOUND) set_property(TARGET http-server-async-ssl PROPERTY FOLDER "example-http-server") target_link_libraries (http-server-async-ssl - ${OPENSSL_LIBRARIES} + OpenSSL::SSL OpenSSL::Crypto ) endif() diff --git a/example/http/server/async-ssl/Jamfile b/example/http/server/async-ssl/Jamfile index 875bacd7..baeccc20 100644 --- a/example/http/server/async-ssl/Jamfile +++ b/example/http/server/async-ssl/Jamfile @@ -7,10 +7,12 @@ # Official repository: https://github.com/boostorg/beast # +import ac ; + project : requirements - ssl - crypto + [ ac.check-library /boost/beast//ssl : /boost/beast//ssl : no ] + /boost/beast//crypto ; exe http-server-async-ssl : diff --git a/example/http/server/coro-ssl/CMakeLists.txt b/example/http/server/coro-ssl/CMakeLists.txt index b5787459..63322bfe 100644 --- a/example/http/server/coro-ssl/CMakeLists.txt +++ b/example/http/server/coro-ssl/CMakeLists.txt @@ -22,7 +22,7 @@ if (OPENSSL_FOUND) set_property(TARGET http-server-coro-ssl PROPERTY FOLDER "example-http-server") target_link_libraries (http-server-coro-ssl - ${OPENSSL_LIBRARIES} + OpenSSL::SSL OpenSSL::Crypto ) endif() diff --git a/example/http/server/coro-ssl/Jamfile b/example/http/server/coro-ssl/Jamfile index 838e7cd7..2cc5c914 100644 --- a/example/http/server/coro-ssl/Jamfile +++ b/example/http/server/coro-ssl/Jamfile @@ -7,10 +7,12 @@ # Official repository: https://github.com/boostorg/beast # +import ac ; + project : requirements - ssl - crypto + [ ac.check-library /boost/beast//ssl : /boost/beast//ssl : no ] + /boost/beast//crypto ; exe http-server-coro-ssl : diff --git a/example/http/server/flex/CMakeLists.txt b/example/http/server/flex/CMakeLists.txt index 3011e6df..f14d0379 100644 --- a/example/http/server/flex/CMakeLists.txt +++ b/example/http/server/flex/CMakeLists.txt @@ -23,7 +23,7 @@ if (OPENSSL_FOUND) set_property(TARGET http-server-flex PROPERTY FOLDER "example-http-server") target_link_libraries (http-server-flex - ${OPENSSL_LIBRARIES} + OpenSSL::SSL OpenSSL::Crypto ) endif() diff --git a/example/http/server/flex/Jamfile b/example/http/server/flex/Jamfile index 875bacd7..5f6ae1bf 100644 --- a/example/http/server/flex/Jamfile +++ b/example/http/server/flex/Jamfile @@ -7,14 +7,16 @@ # Official repository: https://github.com/boostorg/beast # +import ac ; + project : requirements - ssl - crypto + [ ac.check-library /boost/beast//ssl : /boost/beast//ssl : no ] + /boost/beast//crypto ; -exe http-server-async-ssl : - http_server_async_ssl.cpp +exe http-server-flex : + http_server_flex.cpp : coverage:no ubasan:no diff --git a/example/http/server/stackless-ssl/CMakeLists.txt b/example/http/server/stackless-ssl/CMakeLists.txt index edf31338..fe7102d0 100644 --- a/example/http/server/stackless-ssl/CMakeLists.txt +++ b/example/http/server/stackless-ssl/CMakeLists.txt @@ -22,7 +22,7 @@ if (OPENSSL_FOUND) set_property(TARGET http-server-stackless-ssl PROPERTY FOLDER "example-http-server") target_link_libraries (http-server-stackless-ssl - ${OPENSSL_LIBRARIES} + OpenSSL::SSL OpenSSL::Crypto ) endif() diff --git a/example/http/server/stackless-ssl/Jamfile b/example/http/server/stackless-ssl/Jamfile index 875bacd7..33d57e9b 100644 --- a/example/http/server/stackless-ssl/Jamfile +++ b/example/http/server/stackless-ssl/Jamfile @@ -7,14 +7,16 @@ # Official repository: https://github.com/boostorg/beast # +import ac ; + project : requirements - ssl - crypto + [ ac.check-library /boost/beast//ssl : /boost/beast//ssl : no ] + /boost/beast//crypto ; -exe http-server-async-ssl : - http_server_async_ssl.cpp +exe http-server-stackless-ssl : + http_server_stackless_ssl.cpp : coverage:no ubasan:no diff --git a/example/http/server/sync-ssl/CMakeLists.txt b/example/http/server/sync-ssl/CMakeLists.txt index 792cef82..7dae7367 100644 --- a/example/http/server/sync-ssl/CMakeLists.txt +++ b/example/http/server/sync-ssl/CMakeLists.txt @@ -22,7 +22,7 @@ if (OPENSSL_FOUND) set_property(TARGET http-server-sync-ssl PROPERTY FOLDER "example-http-server") target_link_libraries (http-server-sync-ssl - ${OPENSSL_LIBRARIES} + OpenSSL::SSL OpenSSL::Crypto ) endif() diff --git a/example/http/server/sync-ssl/Jamfile b/example/http/server/sync-ssl/Jamfile index d7a5ca72..d438549e 100644 --- a/example/http/server/sync-ssl/Jamfile +++ b/example/http/server/sync-ssl/Jamfile @@ -7,10 +7,12 @@ # Official repository: https://github.com/boostorg/beast # +import ac ; + project : requirements - ssl - crypto + [ ac.check-library /boost/beast//ssl : /boost/beast//ssl : no ] + /boost/beast//crypto ; exe http-server-sync-ssl : diff --git a/example/websocket/client/Jamfile b/example/websocket/client/Jamfile index f2a7a337..bfdb89e8 100644 --- a/example/websocket/client/Jamfile +++ b/example/websocket/client/Jamfile @@ -11,7 +11,7 @@ build-project async ; build-project coro ; build-project sync ; -# VFALCO How do I make this work on Windows and if OpenSSL is not available? -#build-project async-ssl ; -#build-project coro-ssl ; -#build-project sync-ssl ; +# SSL +build-project async-ssl ; +build-project coro-ssl ; +build-project sync-ssl ; diff --git a/example/websocket/client/async-ssl/CMakeLists.txt b/example/websocket/client/async-ssl/CMakeLists.txt index c02f4d06..84a09c9c 100644 --- a/example/websocket/client/async-ssl/CMakeLists.txt +++ b/example/websocket/client/async-ssl/CMakeLists.txt @@ -22,7 +22,7 @@ if (OPENSSL_FOUND) set_property(TARGET websocket-client-async-ssl PROPERTY FOLDER "example-websocket-client") target_link_libraries (websocket-client-async-ssl - ${OPENSSL_LIBRARIES} + OpenSSL::SSL OpenSSL::Crypto ) endif() diff --git a/example/websocket/client/async-ssl/Jamfile b/example/websocket/client/async-ssl/Jamfile index 35d1b50a..d9f3ad78 100644 --- a/example/websocket/client/async-ssl/Jamfile +++ b/example/websocket/client/async-ssl/Jamfile @@ -7,10 +7,12 @@ # Official repository: https://github.com/boostorg/beast # +import ac ; + project : requirements - ssl - crypto + [ ac.check-library /boost/beast//ssl : /boost/beast//ssl : no ] + /boost/beast//crypto ; exe websocket-client-async-ssl : diff --git a/example/websocket/client/coro-ssl/CMakeLists.txt b/example/websocket/client/coro-ssl/CMakeLists.txt index 7b9f167a..78db6890 100644 --- a/example/websocket/client/coro-ssl/CMakeLists.txt +++ b/example/websocket/client/coro-ssl/CMakeLists.txt @@ -22,7 +22,7 @@ if (OPENSSL_FOUND) set_property(TARGET websocket-client-coro-ssl PROPERTY FOLDER "example-websocket-client") target_link_libraries (websocket-client-coro-ssl - ${OPENSSL_LIBRARIES} + OpenSSL::SSL OpenSSL::Crypto ) endif() diff --git a/example/websocket/client/coro-ssl/Jamfile b/example/websocket/client/coro-ssl/Jamfile index 5a48576c..f6d895d6 100644 --- a/example/websocket/client/coro-ssl/Jamfile +++ b/example/websocket/client/coro-ssl/Jamfile @@ -7,10 +7,12 @@ # Official repository: https://github.com/boostorg/beast # +import ac ; + project : requirements - ssl - crypto + [ ac.check-library /boost/beast//ssl : /boost/beast//ssl : no ] + /boost/beast//crypto ; exe websocket-client-coro-ssl : diff --git a/example/websocket/client/sync-ssl/CMakeLists.txt b/example/websocket/client/sync-ssl/CMakeLists.txt index 11c5f030..435996da 100644 --- a/example/websocket/client/sync-ssl/CMakeLists.txt +++ b/example/websocket/client/sync-ssl/CMakeLists.txt @@ -22,7 +22,7 @@ if (OPENSSL_FOUND) set_property(TARGET websocket-client-sync-ssl PROPERTY FOLDER "example-websocket-client") target_link_libraries (websocket-client-sync-ssl - ${OPENSSL_LIBRARIES} + OpenSSL::SSL OpenSSL::Crypto ) endif() diff --git a/example/websocket/client/sync-ssl/Jamfile b/example/websocket/client/sync-ssl/Jamfile index dca65102..010703dc 100644 --- a/example/websocket/client/sync-ssl/Jamfile +++ b/example/websocket/client/sync-ssl/Jamfile @@ -7,10 +7,12 @@ # Official repository: https://github.com/boostorg/beast # +import ac ; + project : requirements - ssl - crypto + [ ac.check-library /boost/beast//ssl : /boost/beast//ssl : no ] + /boost/beast//crypto ; exe websocket-client-sync-ssl : diff --git a/example/websocket/server/Jamfile b/example/websocket/server/Jamfile index 131185c4..ccfd63fa 100644 --- a/example/websocket/server/Jamfile +++ b/example/websocket/server/Jamfile @@ -14,8 +14,8 @@ build-project fast ; build-project stackless ; build-project sync ; -# VFALCO How do I make this work on Windows and if OpenSSL is not available? -#build-project async-ssl ; -#build-project coro-ssl ; -#build-project stackless-ssl ; -#build-project sync-ssl ; +# SSL +build-project async-ssl ; +build-project coro-ssl ; +build-project stackless-ssl ; +build-project sync-ssl ; diff --git a/example/websocket/server/async-ssl/CMakeLists.txt b/example/websocket/server/async-ssl/CMakeLists.txt index 09496800..62ec5219 100644 --- a/example/websocket/server/async-ssl/CMakeLists.txt +++ b/example/websocket/server/async-ssl/CMakeLists.txt @@ -22,7 +22,7 @@ if (OPENSSL_FOUND) set_property(TARGET websocket-server-async-ssl PROPERTY FOLDER "example-websocket-server") target_link_libraries (websocket-server-async-ssl - ${OPENSSL_LIBRARIES} + OpenSSL::SSL OpenSSL::Crypto ) endif() diff --git a/example/websocket/server/async-ssl/Jamfile b/example/websocket/server/async-ssl/Jamfile index 16bc5dea..78cb6700 100644 --- a/example/websocket/server/async-ssl/Jamfile +++ b/example/websocket/server/async-ssl/Jamfile @@ -7,10 +7,12 @@ # Official repository: https://github.com/boostorg/beast # +import ac ; + project : requirements - ssl - crypto + [ ac.check-library /boost/beast//ssl : /boost/beast//ssl : no ] + /boost/beast//crypto ; exe websocket-server-async-ssl : diff --git a/example/websocket/server/coro-ssl/CMakeLists.txt b/example/websocket/server/coro-ssl/CMakeLists.txt index 2d9d7120..292669c2 100644 --- a/example/websocket/server/coro-ssl/CMakeLists.txt +++ b/example/websocket/server/coro-ssl/CMakeLists.txt @@ -22,7 +22,7 @@ if (OPENSSL_FOUND) set_property(TARGET websocket-server-coro-ssl PROPERTY FOLDER "example-websocket-server") target_link_libraries (websocket-server-coro-ssl - ${OPENSSL_LIBRARIES} + OpenSSL::SSL OpenSSL::Crypto ) endif() diff --git a/example/websocket/server/coro-ssl/Jamfile b/example/websocket/server/coro-ssl/Jamfile index f967994f..1509f072 100644 --- a/example/websocket/server/coro-ssl/Jamfile +++ b/example/websocket/server/coro-ssl/Jamfile @@ -7,10 +7,12 @@ # Official repository: https://github.com/boostorg/beast # +import ac ; + project : requirements - ssl - crypto + [ ac.check-library /boost/beast//ssl : /boost/beast//ssl : no ] + /boost/beast//crypto ; exe websocket-server-coro-ssl : diff --git a/example/websocket/server/stackless-ssl/CMakeLists.txt b/example/websocket/server/stackless-ssl/CMakeLists.txt index bd0e8828..6dca1e84 100644 --- a/example/websocket/server/stackless-ssl/CMakeLists.txt +++ b/example/websocket/server/stackless-ssl/CMakeLists.txt @@ -22,7 +22,7 @@ if (OPENSSL_FOUND) set_property(TARGET websocket-server-stackless-ssl PROPERTY FOLDER "example-websocket-server") target_link_libraries (websocket-server-stackless-ssl - ${OPENSSL_LIBRARIES} + OpenSSL::SSL OpenSSL::Crypto ) endif() diff --git a/example/websocket/server/stackless-ssl/Jamfile b/example/websocket/server/stackless-ssl/Jamfile index fb56a416..7e2e8c4c 100644 --- a/example/websocket/server/stackless-ssl/Jamfile +++ b/example/websocket/server/stackless-ssl/Jamfile @@ -7,10 +7,12 @@ # Official repository: https://github.com/boostorg/beast # +import ac ; + project : requirements - ssl - crypto + [ ac.check-library /boost/beast//ssl : /boost/beast//ssl : no ] + /boost/beast//crypto ; exe websocket-server-stackless-ssl : diff --git a/example/websocket/server/sync-ssl/CMakeLists.txt b/example/websocket/server/sync-ssl/CMakeLists.txt index 3a7e32fe..01498af4 100644 --- a/example/websocket/server/sync-ssl/CMakeLists.txt +++ b/example/websocket/server/sync-ssl/CMakeLists.txt @@ -22,7 +22,7 @@ if (OPENSSL_FOUND) set_property(TARGET websocket-server-sync-ssl PROPERTY FOLDER "example-websocket-server") target_link_libraries (websocket-server-sync-ssl - ${OPENSSL_LIBRARIES} + OpenSSL::SSL OpenSSL::Crypto ) endif() diff --git a/example/websocket/server/sync-ssl/Jamfile b/example/websocket/server/sync-ssl/Jamfile index ccdca116..88074c91 100644 --- a/example/websocket/server/sync-ssl/Jamfile +++ b/example/websocket/server/sync-ssl/Jamfile @@ -7,10 +7,12 @@ # Official repository: https://github.com/boostorg/beast # +import ac ; + project : requirements - ssl - crypto + [ ac.check-library /boost/beast//ssl : /boost/beast//ssl : no ] + /boost/beast//crypto ; exe websocket-server-sync-ssl : diff --git a/include/boost/beast/core.hpp b/include/boost/beast/core.hpp index 21b4134a..fca13c09 100644 --- a/include/boost/beast/core.hpp +++ b/include/boost/beast/core.hpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -30,6 +31,7 @@ #include #include #include +#include #include #include #include diff --git a/include/boost/beast/core/close_socket.hpp b/include/boost/beast/core/close_socket.hpp new file mode 100644 index 00000000..3dcf2be8 --- /dev/null +++ b/include/boost/beast/core/close_socket.hpp @@ -0,0 +1,47 @@ +// +// Copyright (c) 2018 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) +// +// Official repository: https://github.com/boostorg/beast +// + +#ifndef BOOST_BEAST_CLOSE_SOCKET_HPP +#define BOOST_BEAST_CLOSE_SOCKET_HPP + +#include +#include + +namespace boost { +namespace beast { + +namespace detail { + +template +void +beast_close_socket( + net::basic_socket& sock) +{ + boost::system::error_code ec; + sock.close(ec); +} + +} // detail + +/** Close a socket. + + @param sock The socket to close. +*/ +template +void +close_socket(Socket& sock) +{ + using detail::beast_close_socket; + beast_close_socket(sock); +} + +} // beast +} // boost + +#endif diff --git a/include/boost/beast/core/detail/get_lowest_layer.hpp b/include/boost/beast/core/detail/get_lowest_layer.hpp new file mode 100644 index 00000000..8d71f304 --- /dev/null +++ b/include/boost/beast/core/detail/get_lowest_layer.hpp @@ -0,0 +1,73 @@ +// +// Copyright (c) 2018 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) +// +// Official repository: https://github.com/boostorg/beast +// + +#ifndef BOOST_BEAST_DETAIL_GET_LOWEST_LAYER_HPP +#define BOOST_BEAST_DETAIL_GET_LOWEST_LAYER_HPP + +#include +#include + +namespace boost { +namespace beast { +namespace detail { + +template +struct has_next_layer : std::false_type +{ +}; + +template +struct has_next_layer().next_layer())>> + : std::true_type +{ +}; + +template +struct lowest_layer_type_impl +{ + using type = typename std::remove_reference::type; +}; + +template +struct lowest_layer_type_impl().next_layer())>> +{ + using type = typename lowest_layer_type_impl< + decltype(std::declval().next_layer())>::type; +}; + +template +using lowest_layer_type = typename + lowest_layer_type_impl::type; + +template +lowest_layer_type& +get_lowest_layer_impl( + T& t, std::true_type) noexcept +{ + using type = typename std::decay< + decltype(t.next_layer())>::type; + return get_lowest_layer_impl(t.next_layer(), + has_next_layer{}); +} + +template +T& +get_lowest_layer_impl( + T& t, std::false_type) noexcept +{ + return t; +} + +} // detail +} // beast +} // boost + +#endif diff --git a/include/boost/beast/core/get_lowest_layer.hpp b/include/boost/beast/core/get_lowest_layer.hpp new file mode 100644 index 00000000..6cf92469 --- /dev/null +++ b/include/boost/beast/core/get_lowest_layer.hpp @@ -0,0 +1,88 @@ +// +// Copyright (c) 2018 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) +// +// Official repository: https://github.com/boostorg/beast +// + +#ifndef BOOST_BEAST_GET_LOWEST_LAYER_HPP +#define BOOST_BEAST_GET_LOWEST_LAYER_HPP + +#include +#include + +namespace boost { +namespace beast { + +/** Return the type of the lowest layer of a type representing a stack of stream layers. + + This type alias will return the type of lowest layer object for a type + which defines a stack of stream layers. + + @param T The type determine the lowest layer type of. + + @return The type of the lowest layer. +*/ +template +#if BOOST_BEAST_DOXYGEN +using lowest_layer_type = __see_below__; +#else +using lowest_layer_type = detail::lowest_layer_type; +#endif + +/** Return the lowest layer in a stack of stream layers. + + If `t.next_layer()` is well-defined, returns + `lowest_layer(t.next_layer())`. Otherwise, it returns `t`. + + A stream layer is an object of class type which wraps another object through + composition, and meets some or all of the named requirements of the wrapped + type while optionally changing behavior. Examples of stream layers include + `net::ssl::stream` or @ref beast::websocket::stream. The owner of a stream + layer can interact directly with the wrapper, by passing it to stream + algorithms. Or, the owner can obtain a reference to the wrapped object by + calling `next_layer()` and accessing its members. This is necessary when it is + desired to access functionality in the next layer which is not available + in the wrapper. For example, @ref websocket::stream permits reading and + writing, but in order to establish the underlying connection, members + of the wrapped stream (such as `connect`) must be invoked directly. + + Usually the last object in the chain of composition is the concrete socket + object (for example, a `net::basic_socket` or a class derived from it). + The function @ref get_lowest_layer exists to easily obtain the concrete + socket when it is desired to perform an action that is not prescribed by + a named requirement, such as changing a socket option, cancelling all + pending asynchronous I/O, or closing the socket (perhaps by using + @ref close_socket). + + @par Example + @code + // Set non-blocking mode on a stack of stream + // layers with a regular socket at the lowest layer. + template + void set_non_blocking (Stream& stream) + { + error_code ec; + // A compile error here means your lowest layer is not the right type! + get_lowest_layer(stream).non_blocking(true, ec); + if(ec) + throw system_error{ec}; + } + @endcode + + @param t The layer in a stack of layered objects for which the lowest layer is returned. +*/ +template +lowest_layer_type& +get_lowest_layer(T& t) noexcept +{ + return detail::get_lowest_layer_impl( + t, detail::has_next_layer{}); +} + +} // beast +} // boost + +#endif diff --git a/test/asio.cpp b/test/asio.cpp index bf00c8ff..24b52d2c 100644 --- a/test/asio.cpp +++ b/test/asio.cpp @@ -1 +1,15 @@ +// +// Copyright (c) 2019 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) +// +// Official repository: https://github.com/boostorg/beast +// + +// This file is used to build the asio static library, +// used with BOOST_ASIO_SEPARATE_COMPILATION which helps +// reduce compilation time + #include +#include diff --git a/test/beast/core/CMakeLists.txt b/test/beast/core/CMakeLists.txt index 2729b849..7b285631 100644 --- a/test/beast/core/CMakeLists.txt +++ b/test/beast/core/CMakeLists.txt @@ -40,6 +40,7 @@ add_executable (tests-beast-core buffers_range.cpp buffers_suffix.cpp buffers_to_string.cpp + close_socket.cpp error.cpp file.cpp file_posix.cpp @@ -47,6 +48,7 @@ add_executable (tests-beast-core file_win32.cpp flat_buffer.cpp flat_static_buffer.cpp + get_lowest_layer.cpp handler_ptr.cpp make_printable.cpp multi_buffer.cpp diff --git a/test/beast/core/Jamfile b/test/beast/core/Jamfile index 801f060f..51aa2a9b 100644 --- a/test/beast/core/Jamfile +++ b/test/beast/core/Jamfile @@ -28,6 +28,7 @@ local SOURCES = buffers_range.cpp buffers_suffix.cpp buffers_to_string.cpp + close_socket.cpp error.cpp file.cpp file_posix.cpp @@ -35,6 +36,7 @@ local SOURCES = file_win32.cpp flat_buffer.cpp flat_static_buffer.cpp + get_lowest_layer.cpp handler_ptr.cpp make_printable.cpp multi_buffer.cpp diff --git a/test/beast/core/close_socket.cpp b/test/beast/core/close_socket.cpp new file mode 100644 index 00000000..13e8f660 --- /dev/null +++ b/test/beast/core/close_socket.cpp @@ -0,0 +1,73 @@ +// +// Copyright (c) 2018 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) +// +// Official repository: https://github.com/boostorg/beast +// + +// Test that header file is self-contained. +#include + +#include +#include + +#include +#include + +namespace boost { +namespace beast { + +class close_socket_test : public beast::unit_test::suite +{ +public: + template + struct layer + { + T t; + + template + explicit + layer(U&& u) + : t(std::forward(u)) + { + } + + T& next_layer() + { + return t; + } + }; + + void + testClose() + { + net::io_context ioc; + { + net::ip::tcp::socket sock(ioc); + sock.open(net::ip::tcp::v4()); + BEAST_EXPECT(sock.is_open()); + close_socket(get_lowest_layer(sock)); + BEAST_EXPECT(! sock.is_open()); + } + { + layer layer(ioc); + layer.next_layer().open(net::ip::tcp::v4()); + BEAST_EXPECT(layer.next_layer().is_open()); + close_socket(get_lowest_layer(layer)); + BEAST_EXPECT(! layer.next_layer().is_open()); + } + } + + void + run() override + { + testClose(); + } +}; + +BEAST_DEFINE_TESTSUITE(beast,core,close_socket); + +} // beast +} // boost diff --git a/test/beast/core/get_lowest_layer.cpp b/test/beast/core/get_lowest_layer.cpp new file mode 100644 index 00000000..8e8af654 --- /dev/null +++ b/test/beast/core/get_lowest_layer.cpp @@ -0,0 +1,191 @@ +// +// Copyright (c) 2018 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) +// +// Official repository: https://github.com/boostorg/beast +// + +// Test that header file is self-contained. +#include + +#include +#include +#include + +namespace boost { +namespace beast { + +class get_lowest_layer_test + : public beast::unit_test::suite +{ +public: + struct without + { + int dummy = 0; + + without() = default; + + template + std::size_t write_some(T const&) + { + return 0; + } + + template + std::size_t write_some(T const&, error_code&) + { + return 0; + } + }; + + template + struct with + { + T t; + + with() = default; + + T& + next_layer() + { + return t; + } + + T const& + next_layer() const + { + return t; + } + }; + + BOOST_STATIC_ASSERT( + ! detail::has_next_layer::value); + + BOOST_STATIC_ASSERT( + detail::has_next_layer>::value); + + BOOST_STATIC_ASSERT( + detail::has_next_layer>>::value); + + void + testGetLowestLayer() + { + { + without w{}; + BEAST_EXPECT(&get_lowest_layer(w) == &w); + } + { + without const w{}; + BEAST_EXPECT(&get_lowest_layer(w) == &w); + } + { + with w{}; + BEAST_EXPECT(&get_lowest_layer(w) == &w.t); + } + { + with const w{}; + BEAST_EXPECT(&get_lowest_layer(w) == &w.t); + } + { + with> w{}; + BEAST_EXPECT(&get_lowest_layer(w) == &w.t.t); + } + { + with> const w{}; + BEAST_EXPECT(&get_lowest_layer(w) == &w.t.t); + } + { + with>> w{}; + BEAST_EXPECT(&get_lowest_layer(w) == &w.t.t.t); + } + { + with>> const w{}; + BEAST_EXPECT(&get_lowest_layer(w) == &w.t.t.t); + } + } + + //-------------------------------------------------------------------------- +/* + @par Example + This code implements a SyncWriteStream wrapper which calls + `std::terminate` upon any error. +*/ + template + class write_stream + { + NextLayer next_layer_; + + public: + static_assert(is_sync_write_stream::value, + "SyncWriteStream requirements not met"); + + template + explicit + write_stream(Args&&... args) + : next_layer_(std::forward(args)...) + { + } + + NextLayer& next_layer() noexcept + { + return next_layer_; + } + + NextLayer const& next_layer() const noexcept + { + return next_layer_; + } + + template + std::size_t + write_some(ConstBufferSequence const& buffers) + { + error_code ec; + auto const bytes_transferred = next_layer_.write_some(buffers, ec); + if(ec) + std::terminate(); + return bytes_transferred; + } + + template + std::size_t + write_some(ConstBufferSequence const& buffers, error_code& ec) + { + auto const bytes_transferred = next_layer_.write_some(buffers, ec); + if(ec) + std::terminate(); + return bytes_transferred; + } + }; + + void + testJavadoc() + { + using type = write_stream; + type s; + BOOST_STATIC_ASSERT(std::is_same< + decltype(get_lowest_layer(s)), without&>::value); + +#if 0 + BEAST_EXPECT(static_cast< + std::size_t(type::*)(net::const_buffer)>( + &type::write_some)); +#endif + } + + //-------------------------------------------------------------------------- + + void + run() override + { + testGetLowestLayer(); + testJavadoc(); + } +}; + +BEAST_DEFINE_TESTSUITE(beast,core,get_lowest_layer); + +} // beast +} // boost diff --git a/test/doc/CMakeLists.txt b/test/doc/CMakeLists.txt index d5283cbe..4c253993 100644 --- a/test/doc/CMakeLists.txt +++ b/test/doc/CMakeLists.txt @@ -17,8 +17,10 @@ add_executable (tests-doc ${EXTRAS_FILES} ${TEST_MAIN} Jamfile + snippets.ipp core_examples.cpp core_snippets.cpp + core_3_layers.cpp http_examples.cpp http_snippets.cpp websocket_snippets.cpp diff --git a/test/doc/Jamfile b/test/doc/Jamfile index 3061c8bb..9d6d139b 100644 --- a/test/doc/Jamfile +++ b/test/doc/Jamfile @@ -7,17 +7,27 @@ # Official repository: https://github.com/boostorg/beast # +import ac ; + +project + : requirements + [ ac.check-library /boost/beast//ssl : /boost/beast//ssl : no ] + /boost/beast//crypto + ; + alias run-tests : [ compile core_snippets.cpp ] [ compile http_snippets.cpp ] [ compile websocket_snippets.cpp ] [ run core_examples.cpp $(TEST_MAIN) ] + [ run core_3_layers.cpp $(TEST_MAIN) ] [ run http_examples.cpp $(TEST_MAIN) ] ; exe fat-tests : $(TEST_MAIN) core_examples.cpp + core_3_layers.cpp http_examples.cpp ; diff --git a/test/doc/core_3_layers.cpp b/test/doc/core_3_layers.cpp new file mode 100644 index 00000000..b63403cc --- /dev/null +++ b/test/doc/core_3_layers.cpp @@ -0,0 +1,281 @@ +// +// Copyright (c) 2016-2017 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) +// +// Official repository: https://github.com/boostorg/beast +// + +#include "snippets.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace beast { + +namespace { + +void +snippets() +{ + #include "snippets.ipp" + { + //[code_core_3_layers_1 + + net::ssl::stream ss(ioc, ctx); + + //] + } + { + //[code_core_3_layers_2 + + websocket::stream ws(ioc); + + //] + } + //[code_core_3_layers_3 + + websocket::stream> ws(ioc, ctx); + + //] +} + +//[code_core_3_layers_4 + +// Set non-blocking mode on a stack of stream +// layers with a regular socket at the lowest layer. +template +void set_non_blocking (Stream& stream) +{ + error_code ec; + // A compile error here means your lowest layer is not the right type! + get_lowest_layer(stream).non_blocking(true, ec); + if(ec) + throw system_error{ec}; +} + +//] + +//[code_core_3_layers_5 + +// A layered stream which counts the bytes read and bytes written on the next layer +template +class counted_stream +{ + NextLayer next_layer_; + std::size_t bytes_read_ = 0; + std::size_t bytes_written_ = 0; + +public: + /// The type of executor used by this stream + using executor_type = detail::get_executor_type; + + /// Constructor + template + explicit + counted_stream(Args&&... args) + : next_layer_(std::forward(args)...) + { + } + + /// Returns an instance of the executor used to submit completion handlers + executor_type get_executor() noexcept + { + return next_layer_.get_executor(); + } + + /// Returns a reference to the next layer + NextLayer& next_layer() noexcept + { + return next_layer_; + } + + /// Returns a reference to the next layer + NextLayer const& next_layer() const noexcept + { + return next_layer_; + } + + /// Returns the total number of bytes read since the stream was constructed + std::size_t bytes_read() const noexcept + { + return bytes_read_; + } + + /// Returns the total number of bytes written since the stream was constructed + std::size_t bytes_written() const noexcept + { + return bytes_written_; + } + + /// Read some data from the stream + template + std::size_t read_some(MutableBufferSequence const& buffers) + { + auto const bytes_transferred = next_layer_.read_some(buffers); + bytes_read_ += bytes_transferred; + return bytes_transferred; + } + + /// Read some data from the stream + template + std::size_t read_some(MutableBufferSequence const& buffers, error_code& ec) + { + auto const bytes_transferred = next_layer_.read_some(buffers, ec); + bytes_read_ += bytes_transferred; + return bytes_transferred; + } + + /// Write some data to the stream + template + std::size_t write_some(ConstBufferSequence const& buffers) + { + auto const bytes_transferred = next_layer_.write_some(buffers); + bytes_written_ += bytes_transferred; + return bytes_transferred; + } + + /// Write some data to the stream + template + std::size_t write_some(ConstBufferSequence const& buffers, error_code& ec) + { + auto const bytes_transferred = next_layer_.write_some(buffers, ec); + bytes_written_ += bytes_transferred; + return bytes_transferred; + } + + /// Read some data from the stream asynchronously + template + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void(error_code, std::size_t)) + async_read_some( + MutableBufferSequence const& buffers, + ReadHandler&& handler) + { + using handler_type = BOOST_ASIO_HANDLER_TYPE( + ReadHandler, void(error_code, std::size_t)); + struct op : async_op_base + { + counted_stream& stream_; + + op( + counted_stream& stream, + handler_type&& handler, + MutableBufferSequence const& buffers) + : async_op_base( + std::move(handler), stream.get_executor()) + , stream_(stream) + { + stream_.next_layer().async_read_some(buffers, std::move(*this)); + } + + void operator()(error_code ec, std::size_t bytes_transferred) + { + stream_.bytes_read_ += bytes_transferred; + this->invoke(ec, bytes_transferred); + } + }; + net::async_completion init{handler}; + op(*this, std::move(init.completion_handler), buffers); + return init.result.get(); + } + + /// Write some data to the stream asynchronously + template + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void(error_code, std::size_t)) + async_write_some( + ConstBufferSequence const& buffers, + WriteHandler&& handler) + { + using handler_type = BOOST_ASIO_HANDLER_TYPE( + WriteHandler, void(error_code, std::size_t)); + struct op : async_op_base + { + counted_stream& stream_; + + op( counted_stream& stream, + handler_type&& handler, + ConstBufferSequence const& buffers) + : async_op_base( + std::move(handler), stream.get_executor()) + , stream_(stream) + { + stream_.next_layer().async_write_some(buffers, std::move(*this)); + } + + void operator()(error_code ec, std::size_t bytes_transferred) + { + stream_.bytes_written_ += bytes_transferred; + this->invoke(ec, bytes_transferred); + } + }; + net::async_completion init{handler}; + op(*this, std::move(init.completion_handler), buffers); + return init.result.get(); + } +}; +//] + +BOOST_STATIC_ASSERT(is_sync_read_stream>::value); +BOOST_STATIC_ASSERT(is_sync_write_stream>::value); +BOOST_STATIC_ASSERT(is_async_read_stream>::value); +BOOST_STATIC_ASSERT(is_async_write_stream>::value); + +} // (anon) + +struct core_3_layers_test + : public beast::unit_test::suite +{ + struct handler + { + void operator()(error_code, std::size_t) + { + } + }; + + void + run() override + { + BEAST_EXPECT(&snippets); + BEAST_EXPECT(&set_non_blocking); + + BEAST_EXPECT(&counted_stream::get_executor); + BEAST_EXPECT(static_cast< + test::stream&(counted_stream::*)()>( + &counted_stream::next_layer)); + BEAST_EXPECT(static_cast< + test::stream const&(counted_stream::*)() const>( + &counted_stream::next_layer)); + BEAST_EXPECT(&counted_stream::bytes_read); + BEAST_EXPECT(&counted_stream::bytes_written); + BEAST_EXPECT(static_cast< + std::size_t(counted_stream::*)(net::mutable_buffer const&)>( + &counted_stream::read_some)); + BEAST_EXPECT(static_cast< + std::size_t(counted_stream::*)(net::mutable_buffer const&, error_code&)>( + &counted_stream::read_some)); + BEAST_EXPECT(static_cast< + std::size_t(counted_stream::*)(net::const_buffer const&)>( + &counted_stream::write_some)); + BEAST_EXPECT(static_cast< + std::size_t(counted_stream::*)(net::const_buffer const&, error_code&)>( + &counted_stream::write_some)); + BEAST_EXPECT((&counted_stream::async_read_some)); + BEAST_EXPECT((&counted_stream::async_write_some)); + } +}; + +BEAST_DEFINE_TESTSUITE(beast,doc,core_3_layers); + +} // beast +} // boost diff --git a/test/doc/snippets.hpp b/test/doc/snippets.hpp new file mode 100644 index 00000000..90989d60 --- /dev/null +++ b/test/doc/snippets.hpp @@ -0,0 +1,21 @@ +// +// Copyright (c) 2019 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) +// +// Official repository: https://github.com/boostorg/beast +// + +#ifndef SNIPPETS_HPP +#define SNIPPETS_HPP + +// This file must be included before including snippets.ipp + +#include +#include +#include +#include +#include + +#endif diff --git a/test/doc/snippets.ipp b/test/doc/snippets.ipp new file mode 100644 index 00000000..66cf8777 --- /dev/null +++ b/test/doc/snippets.ipp @@ -0,0 +1,26 @@ +// +// Copyright (c) 2019 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) +// +// Official repository: https://github.com/boostorg/beast +// + +// This header file is designed to be included multiple times +// inside of function bodies holding documentation snippets. + +using namespace boost::beast; +namespace net = boost::asio; +namespace ssl = boost::asio::ssl; +using tcp = net::ip::tcp; + +error_code ec; +net::io_context ioc; +auto work = net::make_work_guard(ioc); +std::thread t{[&](){ ioc.run(); }}; + +tcp::socket sock(ioc); + +ssl::context ctx(ssl::context::sslv23); + diff --git a/tools/user-config.jam b/tools/user-config.jam new file mode 100644 index 00000000..574d1374 --- /dev/null +++ b/tools/user-config.jam @@ -0,0 +1,12 @@ +# Used on CI + +import os ; + +local OPENSSL_ROOT = [ os.environ OPENSSL_ROOT ] ; + +project + : requirements + $(OPENSSL_ROOT)/include + debug:$(OPENSSL_ROOT)/debug/lib + release:$(OPENSSL_ROOT)/lib + ;