summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/beast/example
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/beast/example')
-rw-r--r--src/boost/libs/beast/example/CMakeLists.txt14
-rw-r--r--src/boost/libs/beast/example/Jamfile32
-rw-r--r--src/boost/libs/beast/example/advanced/CMakeLists.txt11
-rw-r--r--src/boost/libs/beast/example/advanced/Jamfile13
-rw-r--r--src/boost/libs/beast/example/advanced/server-flex/CMakeLists.txt31
-rw-r--r--src/boost/libs/beast/example/advanced/server-flex/Jamfile22
-rw-r--r--src/boost/libs/beast/example/advanced/server-flex/advanced_server_flex.cpp1030
-rw-r--r--src/boost/libs/beast/example/advanced/server/CMakeLists.txt23
-rw-r--r--src/boost/libs/beast/example/advanced/server/Jamfile15
-rw-r--r--src/boost/libs/beast/example/advanced/server/advanced_server.cpp700
-rw-r--r--src/boost/libs/beast/example/common/root_certificates.hpp151
-rw-r--r--src/boost/libs/beast/example/common/server_certificate.hpp124
-rw-r--r--src/boost/libs/beast/example/echo-op/CMakeLists.txt23
-rw-r--r--src/boost/libs/beast/example/echo-op/Jamfile15
-rw-r--r--src/boost/libs/beast/example/echo-op/echo_op.cpp377
-rw-r--r--src/boost/libs/beast/example/http/CMakeLists.txt11
-rw-r--r--src/boost/libs/beast/example/http/Jamfile11
-rw-r--r--src/boost/libs/beast/example/http/client/CMakeLists.txt20
-rw-r--r--src/boost/libs/beast/example/http/client/Jamfile18
-rw-r--r--src/boost/libs/beast/example/http/client/async-ssl-system-executor/CMakeLists.txt31
-rw-r--r--src/boost/libs/beast/example/http/client/async-ssl-system-executor/Jamfile22
-rw-r--r--src/boost/libs/beast/example/http/client/async-ssl-system-executor/http_client_async_ssl_system_executor.cpp246
-rw-r--r--src/boost/libs/beast/example/http/client/async-ssl/CMakeLists.txt31
-rw-r--r--src/boost/libs/beast/example/http/client/async-ssl/Jamfile22
-rw-r--r--src/boost/libs/beast/example/http/client/async-ssl/http_client_async_ssl.cpp244
-rw-r--r--src/boost/libs/beast/example/http/client/async/CMakeLists.txt23
-rw-r--r--src/boost/libs/beast/example/http/client/async/Jamfile15
-rw-r--r--src/boost/libs/beast/example/http/client/async/http_client_async.cpp189
-rw-r--r--src/boost/libs/beast/example/http/client/coro-ssl/CMakeLists.txt31
-rw-r--r--src/boost/libs/beast/example/http/client/coro-ssl/Jamfile23
-rw-r--r--src/boost/libs/beast/example/http/client/coro-ssl/http_client_coro_ssl.cpp180
-rw-r--r--src/boost/libs/beast/example/http/client/coro/CMakeLists.txt23
-rw-r--r--src/boost/libs/beast/example/http/client/coro/Jamfile16
-rw-r--r--src/boost/libs/beast/example/http/client/coro/http_client_coro.cpp144
-rw-r--r--src/boost/libs/beast/example/http/client/crawl/CMakeLists.txt26
-rw-r--r--src/boost/libs/beast/example/http/client/crawl/Jamfile16
-rw-r--r--src/boost/libs/beast/example/http/client/crawl/http_crawl.cpp409
-rw-r--r--src/boost/libs/beast/example/http/client/crawl/urls_large_data.cpp10021
-rw-r--r--src/boost/libs/beast/example/http/client/crawl/urls_large_data.hpp18
-rw-r--r--src/boost/libs/beast/example/http/client/sync-ssl/CMakeLists.txt31
-rw-r--r--src/boost/libs/beast/example/http/client/sync-ssl/Jamfile22
-rw-r--r--src/boost/libs/beast/example/http/client/sync-ssl/http_client_sync_ssl.cpp128
-rw-r--r--src/boost/libs/beast/example/http/client/sync/CMakeLists.txt23
-rw-r--r--src/boost/libs/beast/example/http/client/sync/Jamfile15
-rw-r--r--src/boost/libs/beast/example/http/client/sync/http_client_sync.cpp105
-rw-r--r--src/boost/libs/beast/example/http/server/CMakeLists.txt23
-rw-r--r--src/boost/libs/beast/example/http/server/Jamfile22
-rw-r--r--src/boost/libs/beast/example/http/server/async-ssl/CMakeLists.txt31
-rw-r--r--src/boost/libs/beast/example/http/server/async-ssl/Jamfile22
-rw-r--r--src/boost/libs/beast/example/http/server/async-ssl/http_server_async_ssl.cpp564
-rw-r--r--src/boost/libs/beast/example/http/server/async/CMakeLists.txt24
-rw-r--r--src/boost/libs/beast/example/http/server/async/Jamfile15
-rw-r--r--src/boost/libs/beast/example/http/server/async/http_server_async.cpp490
-rw-r--r--src/boost/libs/beast/example/http/server/coro-ssl/CMakeLists.txt31
-rw-r--r--src/boost/libs/beast/example/http/server/coro-ssl/Jamfile23
-rw-r--r--src/boost/libs/beast/example/http/server/coro-ssl/http_server_coro_ssl.cpp432
-rw-r--r--src/boost/libs/beast/example/http/server/coro/CMakeLists.txt23
-rw-r--r--src/boost/libs/beast/example/http/server/coro/Jamfile16
-rw-r--r--src/boost/libs/beast/example/http/server/coro/http_server_coro.cpp387
-rw-r--r--src/boost/libs/beast/example/http/server/fast/CMakeLists.txt26
-rw-r--r--src/boost/libs/beast/example/http/server/fast/Jamfile15
-rw-r--r--src/boost/libs/beast/example/http/server/fast/fields_alloc.hpp205
-rw-r--r--src/boost/libs/beast/example/http/server/fast/http_server_fast.cpp352
-rw-r--r--src/boost/libs/beast/example/http/server/flex/CMakeLists.txt31
-rw-r--r--src/boost/libs/beast/example/http/server/flex/Jamfile22
-rw-r--r--src/boost/libs/beast/example/http/server/flex/http_server_flex.cpp712
-rw-r--r--src/boost/libs/beast/example/http/server/small/CMakeLists.txt23
-rw-r--r--src/boost/libs/beast/example/http/server/small/Jamfile15
-rw-r--r--src/boost/libs/beast/example/http/server/small/http_server_small.cpp251
-rw-r--r--src/boost/libs/beast/example/http/server/stackless-ssl/CMakeLists.txt31
-rw-r--r--src/boost/libs/beast/example/http/server/stackless-ssl/Jamfile22
-rw-r--r--src/boost/libs/beast/example/http/server/stackless-ssl/http_server_stackless_ssl.cpp560
-rw-r--r--src/boost/libs/beast/example/http/server/stackless/CMakeLists.txt23
-rw-r--r--src/boost/libs/beast/example/http/server/stackless/Jamfile15
-rw-r--r--src/boost/libs/beast/example/http/server/stackless/http_server_stackless.cpp493
-rw-r--r--src/boost/libs/beast/example/http/server/sync-ssl/CMakeLists.txt31
-rw-r--r--src/boost/libs/beast/example/http/server/sync-ssl/Jamfile22
-rw-r--r--src/boost/libs/beast/example/http/server/sync-ssl/http_server_sync_ssl.cpp356
-rw-r--r--src/boost/libs/beast/example/http/server/sync/CMakeLists.txt24
-rw-r--r--src/boost/libs/beast/example/http/server/sync/Jamfile15
-rw-r--r--src/boost/libs/beast/example/http/server/sync/http_server_sync.cpp335
-rw-r--r--src/boost/libs/beast/example/websocket/CMakeLists.txt11
-rw-r--r--src/boost/libs/beast/example/websocket/Jamfile11
-rw-r--r--src/boost/libs/beast/example/websocket/client/CMakeLists.txt19
-rw-r--r--src/boost/libs/beast/example/websocket/client/Jamfile18
-rw-r--r--src/boost/libs/beast/example/websocket/client/async-ssl-system-executor/CMakeLists.txt31
-rw-r--r--src/boost/libs/beast/example/websocket/client/async-ssl-system-executor/Jamfile22
-rw-r--r--src/boost/libs/beast/example/websocket/client/async-ssl-system-executor/websocket_client_async_ssl_system_executor.cpp259
-rw-r--r--src/boost/libs/beast/example/websocket/client/async-ssl/CMakeLists.txt31
-rw-r--r--src/boost/libs/beast/example/websocket/client/async-ssl/Jamfile22
-rw-r--r--src/boost/libs/beast/example/websocket/client/async-ssl/websocket_client_async_ssl.cpp252
-rw-r--r--src/boost/libs/beast/example/websocket/client/async/CMakeLists.txt23
-rw-r--r--src/boost/libs/beast/example/websocket/client/async/Jamfile15
-rw-r--r--src/boost/libs/beast/example/websocket/client/async/websocket_client_async.cpp223
-rw-r--r--src/boost/libs/beast/example/websocket/client/coro-ssl/CMakeLists.txt31
-rw-r--r--src/boost/libs/beast/example/websocket/client/coro-ssl/Jamfile23
-rw-r--r--src/boost/libs/beast/example/websocket/client/coro-ssl/websocket_client_coro_ssl.cpp175
-rw-r--r--src/boost/libs/beast/example/websocket/client/coro/CMakeLists.txt23
-rw-r--r--src/boost/libs/beast/example/websocket/client/coro/Jamfile16
-rw-r--r--src/boost/libs/beast/example/websocket/client/coro/websocket_client_coro.cpp153
-rw-r--r--src/boost/libs/beast/example/websocket/client/sync-ssl/CMakeLists.txt31
-rw-r--r--src/boost/libs/beast/example/websocket/client/sync-ssl/Jamfile22
-rw-r--r--src/boost/libs/beast/example/websocket/client/sync-ssl/websocket_client_sync_ssl.cpp116
-rw-r--r--src/boost/libs/beast/example/websocket/client/sync/CMakeLists.txt23
-rw-r--r--src/boost/libs/beast/example/websocket/client/sync/Jamfile15
-rw-r--r--src/boost/libs/beast/example/websocket/client/sync/websocket_client_sync.cpp105
-rw-r--r--src/boost/libs/beast/example/websocket/server/CMakeLists.txt22
-rw-r--r--src/boost/libs/beast/example/websocket/server/Jamfile21
-rw-r--r--src/boost/libs/beast/example/websocket/server/async-ssl/CMakeLists.txt31
-rw-r--r--src/boost/libs/beast/example/websocket/server/async-ssl/Jamfile22
-rw-r--r--src/boost/libs/beast/example/websocket/server/async-ssl/websocket_server_async_ssl.cpp317
-rw-r--r--src/boost/libs/beast/example/websocket/server/async/CMakeLists.txt23
-rw-r--r--src/boost/libs/beast/example/websocket/server/async/Jamfile15
-rw-r--r--src/boost/libs/beast/example/websocket/server/async/websocket_server_async.cpp281
-rw-r--r--src/boost/libs/beast/example/websocket/server/chat-multi/CMakeLists.txt41
-rw-r--r--src/boost/libs/beast/example/websocket/server/chat-multi/Jamfile19
-rw-r--r--src/boost/libs/beast/example/websocket/server/chat-multi/beast.hpp19
-rw-r--r--src/boost/libs/beast/example/websocket/server/chat-multi/chat_client.html60
-rw-r--r--src/boost/libs/beast/example/websocket/server/chat-multi/http_session.cpp371
-rw-r--r--src/boost/libs/beast/example/websocket/server/chat-multi/http_session.hpp48
-rw-r--r--src/boost/libs/beast/example/websocket/server/chat-multi/listener.cpp101
-rw-r--r--src/boost/libs/beast/example/websocket/server/chat-multi/listener.hpp42
-rw-r--r--src/boost/libs/beast/example/websocket/server/chat-multi/main.cpp84
-rw-r--r--src/boost/libs/beast/example/websocket/server/chat-multi/net.hpp18
-rw-r--r--src/boost/libs/beast/example/websocket/server/chat-multi/shared_state.cpp59
-rw-r--r--src/boost/libs/beast/example/websocket/server/chat-multi/shared_state.hpp48
-rw-r--r--src/boost/libs/beast/example/websocket/server/chat-multi/websocket_session.cpp135
-rw-r--r--src/boost/libs/beast/example/websocket/server/chat-multi/websocket_session.hpp86
-rw-r--r--src/boost/libs/beast/example/websocket/server/coro-ssl/CMakeLists.txt31
-rw-r--r--src/boost/libs/beast/example/websocket/server/coro-ssl/Jamfile23
-rw-r--r--src/boost/libs/beast/example/websocket/server/coro-ssl/websocket_server_coro_ssl.cpp206
-rw-r--r--src/boost/libs/beast/example/websocket/server/coro/CMakeLists.txt23
-rw-r--r--src/boost/libs/beast/example/websocket/server/coro/Jamfile16
-rw-r--r--src/boost/libs/beast/example/websocket/server/coro/websocket_server_coro.cpp180
-rw-r--r--src/boost/libs/beast/example/websocket/server/fast/CMakeLists.txt23
-rw-r--r--src/boost/libs/beast/example/websocket/server/fast/Jamfile16
-rw-r--r--src/boost/libs/beast/example/websocket/server/fast/websocket_server_fast.cpp480
-rw-r--r--src/boost/libs/beast/example/websocket/server/stackless-ssl/CMakeLists.txt31
-rw-r--r--src/boost/libs/beast/example/websocket/server/stackless-ssl/Jamfile22
-rw-r--r--src/boost/libs/beast/example/websocket/server/stackless-ssl/websocket_server_stackless_ssl.cpp314
-rw-r--r--src/boost/libs/beast/example/websocket/server/stackless/CMakeLists.txt23
-rw-r--r--src/boost/libs/beast/example/websocket/server/stackless/Jamfile15
-rw-r--r--src/boost/libs/beast/example/websocket/server/stackless/websocket_server_stackless.cpp282
-rw-r--r--src/boost/libs/beast/example/websocket/server/sync-ssl/CMakeLists.txt31
-rw-r--r--src/boost/libs/beast/example/websocket/server/sync-ssl/Jamfile22
-rw-r--r--src/boost/libs/beast/example/websocket/server/sync-ssl/websocket_server_sync_ssl.cpp137
-rw-r--r--src/boost/libs/beast/example/websocket/server/sync/CMakeLists.txt23
-rw-r--r--src/boost/libs/beast/example/websocket/server/sync/Jamfile15
-rw-r--r--src/boost/libs/beast/example/websocket/server/sync/websocket_server_sync.cpp121
149 files changed, 25944 insertions, 0 deletions
diff --git a/src/boost/libs/beast/example/CMakeLists.txt b/src/boost/libs/beast/example/CMakeLists.txt
new file mode 100644
index 000000000..950c29db9
--- /dev/null
+++ b/src/boost/libs/beast/example/CMakeLists.txt
@@ -0,0 +1,14 @@
+#
+# Copyright (c) 2013-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
+#
+
+add_subdirectory (advanced)
+add_subdirectory (http)
+add_subdirectory (websocket)
+
+add_subdirectory (echo-op)
diff --git a/src/boost/libs/beast/example/Jamfile b/src/boost/libs/beast/example/Jamfile
new file mode 100644
index 000000000..8b49d5fd4
--- /dev/null
+++ b/src/boost/libs/beast/example/Jamfile
@@ -0,0 +1,32 @@
+#
+# Copyright (c) 2013-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
+#
+
+import testing ;
+import ../../config/checks/config : requires ;
+
+project /boost/beast/example
+ : requirements
+ [ requires
+ cxx11_constexpr
+ cxx11_decltype
+ cxx11_hdr_tuple
+ #cxx11_sfinae_expr # Every MSVC fails this
+ cxx11_template_aliases
+ cxx11_variadic_templates
+ ]
+ <library>/boost/beast//lib-asio/<link>static
+ <boost.beast.separate-compilation>on:<library>/boost/beast//lib-beast/<link>static
+ ;
+
+build-project advanced ;
+build-project http ;
+build-project websocket ;
+
+# legacy
+build-project echo-op ;
diff --git a/src/boost/libs/beast/example/advanced/CMakeLists.txt b/src/boost/libs/beast/example/advanced/CMakeLists.txt
new file mode 100644
index 000000000..af83e043b
--- /dev/null
+++ b/src/boost/libs/beast/example/advanced/CMakeLists.txt
@@ -0,0 +1,11 @@
+#
+# Copyright (c) 2013-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
+#
+
+add_subdirectory (server)
+add_subdirectory (server-flex)
diff --git a/src/boost/libs/beast/example/advanced/Jamfile b/src/boost/libs/beast/example/advanced/Jamfile
new file mode 100644
index 000000000..d1053a900
--- /dev/null
+++ b/src/boost/libs/beast/example/advanced/Jamfile
@@ -0,0 +1,13 @@
+#
+# Copyright (c) 2013-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
+#
+
+build-project server ;
+
+# SSL
+build-project server-flex ;
diff --git a/src/boost/libs/beast/example/advanced/server-flex/CMakeLists.txt b/src/boost/libs/beast/example/advanced/server-flex/CMakeLists.txt
new file mode 100644
index 000000000..d6075b277
--- /dev/null
+++ b/src/boost/libs/beast/example/advanced/server-flex/CMakeLists.txt
@@ -0,0 +1,31 @@
+#
+# 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
+#
+
+if (OPENSSL_FOUND)
+ GroupSources(include/boost/beast beast)
+ GroupSources(example/common common)
+ GroupSources(example/advanced/server-flex "/")
+
+ add_executable (advanced-server-flex
+ ${BOOST_BEAST_FILES}
+ ${PROJECT_SOURCE_DIR}/example/common/server_certificate.hpp
+ Jamfile
+ advanced_server_flex.cpp
+ )
+
+ set_property(TARGET advanced-server-flex PROPERTY FOLDER "example-advanced-server")
+
+ target_link_libraries (advanced-server-flex
+ OpenSSL::SSL OpenSSL::Crypto
+ lib-asio
+ lib-asio-ssl
+ lib-beast
+ )
+
+endif()
diff --git a/src/boost/libs/beast/example/advanced/server-flex/Jamfile b/src/boost/libs/beast/example/advanced/server-flex/Jamfile
new file mode 100644
index 000000000..e7bd844aa
--- /dev/null
+++ b/src/boost/libs/beast/example/advanced/server-flex/Jamfile
@@ -0,0 +1,22 @@
+#
+# 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
+#
+
+import ac ;
+
+project
+ : requirements
+ [ ac.check-library /boost/beast//lib-asio-ssl : <library>/boost/beast//lib-asio-ssl/<link>static : <build>no ]
+ ;
+
+exe advanced-server-flex :
+ advanced_server_flex.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ ;
diff --git a/src/boost/libs/beast/example/advanced/server-flex/advanced_server_flex.cpp b/src/boost/libs/beast/example/advanced/server-flex/advanced_server_flex.cpp
new file mode 100644
index 000000000..b0c889bf9
--- /dev/null
+++ b/src/boost/libs/beast/example/advanced/server-flex/advanced_server_flex.cpp
@@ -0,0 +1,1030 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: Advanced server, flex (plain + SSL)
+//
+//------------------------------------------------------------------------------
+
+#include "example/common/server_certificate.hpp"
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/http.hpp>
+#include <boost/beast/ssl.hpp>
+#include <boost/beast/websocket.hpp>
+#include <boost/beast/version.hpp>
+#include <boost/asio/bind_executor.hpp>
+#include <boost/asio/dispatch.hpp>
+#include <boost/asio/signal_set.hpp>
+#include <boost/asio/steady_timer.hpp>
+#include <boost/asio/strand.hpp>
+#include <boost/make_unique.hpp>
+#include <boost/optional.hpp>
+#include <algorithm>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <thread>
+#include <vector>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+// Return a reasonable mime type based on the extension of a file.
+beast::string_view
+mime_type(beast::string_view path)
+{
+ using beast::iequals;
+ auto const ext = [&path]
+ {
+ auto const pos = path.rfind(".");
+ if(pos == beast::string_view::npos)
+ return beast::string_view{};
+ return path.substr(pos);
+ }();
+ if(iequals(ext, ".htm")) return "text/html";
+ if(iequals(ext, ".html")) return "text/html";
+ if(iequals(ext, ".php")) return "text/html";
+ if(iequals(ext, ".css")) return "text/css";
+ if(iequals(ext, ".txt")) return "text/plain";
+ if(iequals(ext, ".js")) return "application/javascript";
+ if(iequals(ext, ".json")) return "application/json";
+ if(iequals(ext, ".xml")) return "application/xml";
+ if(iequals(ext, ".swf")) return "application/x-shockwave-flash";
+ if(iequals(ext, ".flv")) return "video/x-flv";
+ if(iequals(ext, ".png")) return "image/png";
+ if(iequals(ext, ".jpe")) return "image/jpeg";
+ if(iequals(ext, ".jpeg")) return "image/jpeg";
+ if(iequals(ext, ".jpg")) return "image/jpeg";
+ if(iequals(ext, ".gif")) return "image/gif";
+ if(iequals(ext, ".bmp")) return "image/bmp";
+ if(iequals(ext, ".ico")) return "image/vnd.microsoft.icon";
+ if(iequals(ext, ".tiff")) return "image/tiff";
+ if(iequals(ext, ".tif")) return "image/tiff";
+ if(iequals(ext, ".svg")) return "image/svg+xml";
+ if(iequals(ext, ".svgz")) return "image/svg+xml";
+ return "application/text";
+}
+
+// Append an HTTP rel-path to a local filesystem path.
+// The returned path is normalized for the platform.
+std::string
+path_cat(
+ beast::string_view base,
+ beast::string_view path)
+{
+ if(base.empty())
+ return std::string(path);
+ std::string result(base);
+#ifdef BOOST_MSVC
+ char constexpr path_separator = '\\';
+ if(result.back() == path_separator)
+ result.resize(result.size() - 1);
+ result.append(path.data(), path.size());
+ for(auto& c : result)
+ if(c == '/')
+ c = path_separator;
+#else
+ char constexpr path_separator = '/';
+ if(result.back() == path_separator)
+ result.resize(result.size() - 1);
+ result.append(path.data(), path.size());
+#endif
+ return result;
+}
+
+// This function produces an HTTP response for the given
+// request. The type of the response object depends on the
+// contents of the request, so the interface requires the
+// caller to pass a generic lambda for receiving the response.
+template<
+ class Body, class Allocator,
+ class Send>
+void
+handle_request(
+ beast::string_view doc_root,
+ http::request<Body, http::basic_fields<Allocator>>&& req,
+ Send&& send)
+{
+ // Returns a bad request response
+ auto const bad_request =
+ [&req](beast::string_view why)
+ {
+ http::response<http::string_body> res{http::status::bad_request, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = std::string(why);
+ res.prepare_payload();
+ return res;
+ };
+
+ // Returns a not found response
+ auto const not_found =
+ [&req](beast::string_view target)
+ {
+ http::response<http::string_body> res{http::status::not_found, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = "The resource '" + std::string(target) + "' was not found.";
+ res.prepare_payload();
+ return res;
+ };
+
+ // Returns a server error response
+ auto const server_error =
+ [&req](beast::string_view what)
+ {
+ http::response<http::string_body> res{http::status::internal_server_error, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = "An error occurred: '" + std::string(what) + "'";
+ res.prepare_payload();
+ return res;
+ };
+
+ // Make sure we can handle the method
+ if( req.method() != http::verb::get &&
+ req.method() != http::verb::head)
+ return send(bad_request("Unknown HTTP-method"));
+
+ // Request path must be absolute and not contain "..".
+ if( req.target().empty() ||
+ req.target()[0] != '/' ||
+ req.target().find("..") != beast::string_view::npos)
+ return send(bad_request("Illegal request-target"));
+
+ // Build the path to the requested file
+ std::string path = path_cat(doc_root, req.target());
+ if(req.target().back() == '/')
+ path.append("index.html");
+
+ // Attempt to open the file
+ beast::error_code ec;
+ http::file_body::value_type body;
+ body.open(path.c_str(), beast::file_mode::scan, ec);
+
+ // Handle the case where the file doesn't exist
+ if(ec == beast::errc::no_such_file_or_directory)
+ return send(not_found(req.target()));
+
+ // Handle an unknown error
+ if(ec)
+ return send(server_error(ec.message()));
+
+ // Cache the size since we need it after the move
+ auto const size = body.size();
+
+ // Respond to HEAD request
+ if(req.method() == http::verb::head)
+ {
+ http::response<http::empty_body> res{http::status::ok, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, mime_type(path));
+ res.content_length(size);
+ res.keep_alive(req.keep_alive());
+ return send(std::move(res));
+ }
+
+ // Respond to GET request
+ http::response<http::file_body> res{
+ std::piecewise_construct,
+ std::make_tuple(std::move(body)),
+ std::make_tuple(http::status::ok, req.version())};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, mime_type(path));
+ res.content_length(size);
+ res.keep_alive(req.keep_alive());
+ return send(std::move(res));
+}
+
+//------------------------------------------------------------------------------
+
+// Report a failure
+void
+fail(beast::error_code ec, char const* what)
+{
+ // ssl::error::stream_truncated, also known as an SSL "short read",
+ // indicates the peer closed the connection without performing the
+ // required closing handshake (for example, Google does this to
+ // improve performance). Generally this can be a security issue,
+ // but if your communication protocol is self-terminated (as
+ // it is with both HTTP and WebSocket) then you may simply
+ // ignore the lack of close_notify.
+ //
+ // https://github.com/boostorg/beast/issues/38
+ //
+ // https://security.stackexchange.com/questions/91435/how-to-handle-a-malicious-ssl-tls-shutdown
+ //
+ // When a short read would cut off the end of an HTTP message,
+ // Beast returns the error beast::http::error::partial_message.
+ // Therefore, if we see a short read here, it has occurred
+ // after the message has been completed, so it is safe to ignore it.
+
+ if(ec == net::ssl::error::stream_truncated)
+ return;
+
+ std::cerr << what << ": " << ec.message() << "\n";
+}
+
+//------------------------------------------------------------------------------
+
+// Echoes back all received WebSocket messages.
+// This uses the Curiously Recurring Template Pattern so that
+// the same code works with both SSL streams and regular sockets.
+template<class Derived>
+class websocket_session
+{
+ // Access the derived class, this is part of
+ // the Curiously Recurring Template Pattern idiom.
+ Derived&
+ derived()
+ {
+ return static_cast<Derived&>(*this);
+ }
+
+ beast::flat_buffer buffer_;
+
+ // Start the asynchronous operation
+ template<class Body, class Allocator>
+ void
+ do_accept(http::request<Body, http::basic_fields<Allocator>> req)
+ {
+ // Set suggested timeout settings for the websocket
+ derived().ws().set_option(
+ websocket::stream_base::timeout::suggested(
+ beast::role_type::server));
+
+ // Set a decorator to change the Server of the handshake
+ derived().ws().set_option(
+ websocket::stream_base::decorator(
+ [](websocket::response_type& res)
+ {
+ res.set(http::field::server,
+ std::string(BOOST_BEAST_VERSION_STRING) +
+ " advanced-server-flex");
+ }));
+
+ // Accept the websocket handshake
+ derived().ws().async_accept(
+ req,
+ beast::bind_front_handler(
+ &websocket_session::on_accept,
+ derived().shared_from_this()));
+ }
+
+ void
+ on_accept(beast::error_code ec)
+ {
+ if(ec)
+ return fail(ec, "accept");
+
+ // Read a message
+ do_read();
+ }
+
+ void
+ do_read()
+ {
+ // Read a message into our buffer
+ derived().ws().async_read(
+ buffer_,
+ beast::bind_front_handler(
+ &websocket_session::on_read,
+ derived().shared_from_this()));
+ }
+
+ void
+ on_read(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ // This indicates that the websocket_session was closed
+ if(ec == websocket::error::closed)
+ return;
+
+ if(ec)
+ fail(ec, "read");
+
+ // Echo the message
+ derived().ws().text(derived().ws().got_text());
+ derived().ws().async_write(
+ buffer_.data(),
+ beast::bind_front_handler(
+ &websocket_session::on_write,
+ derived().shared_from_this()));
+ }
+
+ void
+ on_write(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ if(ec)
+ return fail(ec, "write");
+
+ // Clear the buffer
+ buffer_.consume(buffer_.size());
+
+ // Do another read
+ do_read();
+ }
+
+public:
+ // Start the asynchronous operation
+ template<class Body, class Allocator>
+ void
+ run(http::request<Body, http::basic_fields<Allocator>> req)
+ {
+ // Accept the WebSocket upgrade request
+ do_accept(std::move(req));
+ }
+};
+
+//------------------------------------------------------------------------------
+
+// Handles a plain WebSocket connection
+class plain_websocket_session
+ : public websocket_session<plain_websocket_session>
+ , public std::enable_shared_from_this<plain_websocket_session>
+{
+ websocket::stream<beast::tcp_stream> ws_;
+
+public:
+ // Create the session
+ explicit
+ plain_websocket_session(
+ beast::tcp_stream&& stream)
+ : ws_(std::move(stream))
+ {
+ }
+
+ // Called by the base class
+ websocket::stream<beast::tcp_stream>&
+ ws()
+ {
+ return ws_;
+ }
+};
+
+//------------------------------------------------------------------------------
+
+// Handles an SSL WebSocket connection
+class ssl_websocket_session
+ : public websocket_session<ssl_websocket_session>
+ , public std::enable_shared_from_this<ssl_websocket_session>
+{
+ websocket::stream<
+ beast::ssl_stream<beast::tcp_stream>> ws_;
+
+public:
+ // Create the ssl_websocket_session
+ explicit
+ ssl_websocket_session(
+ beast::ssl_stream<beast::tcp_stream>&& stream)
+ : ws_(std::move(stream))
+ {
+ }
+
+ // Called by the base class
+ websocket::stream<
+ beast::ssl_stream<beast::tcp_stream>>&
+ ws()
+ {
+ return ws_;
+ }
+};
+
+//------------------------------------------------------------------------------
+
+template<class Body, class Allocator>
+void
+make_websocket_session(
+ beast::tcp_stream stream,
+ http::request<Body, http::basic_fields<Allocator>> req)
+{
+ std::make_shared<plain_websocket_session>(
+ std::move(stream))->run(std::move(req));
+}
+
+template<class Body, class Allocator>
+void
+make_websocket_session(
+ beast::ssl_stream<beast::tcp_stream> stream,
+ http::request<Body, http::basic_fields<Allocator>> req)
+{
+ std::make_shared<ssl_websocket_session>(
+ std::move(stream))->run(std::move(req));
+}
+
+//------------------------------------------------------------------------------
+
+// Handles an HTTP server connection.
+// This uses the Curiously Recurring Template Pattern so that
+// the same code works with both SSL streams and regular sockets.
+template<class Derived>
+class http_session
+{
+ // Access the derived class, this is part of
+ // the Curiously Recurring Template Pattern idiom.
+ Derived&
+ derived()
+ {
+ return static_cast<Derived&>(*this);
+ }
+
+ // This queue is used for HTTP pipelining.
+ class queue
+ {
+ enum
+ {
+ // Maximum number of responses we will queue
+ limit = 8
+ };
+
+ // The type-erased, saved work item
+ struct work
+ {
+ virtual ~work() = default;
+ virtual void operator()() = 0;
+ };
+
+ http_session& self_;
+ std::vector<std::unique_ptr<work>> items_;
+
+ public:
+ explicit
+ queue(http_session& self)
+ : self_(self)
+ {
+ static_assert(limit > 0, "queue limit must be positive");
+ items_.reserve(limit);
+ }
+
+ // Returns `true` if we have reached the queue limit
+ bool
+ is_full() const
+ {
+ return items_.size() >= limit;
+ }
+
+ // Called when a message finishes sending
+ // Returns `true` if the caller should initiate a read
+ bool
+ on_write()
+ {
+ BOOST_ASSERT(! items_.empty());
+ auto const was_full = is_full();
+ items_.erase(items_.begin());
+ if(! items_.empty())
+ (*items_.front())();
+ return was_full;
+ }
+
+ // Called by the HTTP handler to send a response.
+ template<bool isRequest, class Body, class Fields>
+ void
+ operator()(http::message<isRequest, Body, Fields>&& msg)
+ {
+ // This holds a work item
+ struct work_impl : work
+ {
+ http_session& self_;
+ http::message<isRequest, Body, Fields> msg_;
+
+ work_impl(
+ http_session& self,
+ http::message<isRequest, Body, Fields>&& msg)
+ : self_(self)
+ , msg_(std::move(msg))
+ {
+ }
+
+ void
+ operator()()
+ {
+ http::async_write(
+ self_.derived().stream(),
+ msg_,
+ beast::bind_front_handler(
+ &http_session::on_write,
+ self_.derived().shared_from_this(),
+ msg_.need_eof()));
+ }
+ };
+
+ // Allocate and store the work
+ items_.push_back(
+ boost::make_unique<work_impl>(self_, std::move(msg)));
+
+ // If there was no previous work, start this one
+ if(items_.size() == 1)
+ (*items_.front())();
+ }
+ };
+
+ std::shared_ptr<std::string const> doc_root_;
+ queue queue_;
+
+ // The parser is stored in an optional container so we can
+ // construct it from scratch it at the beginning of each new message.
+ boost::optional<http::request_parser<http::string_body>> parser_;
+
+protected:
+ beast::flat_buffer buffer_;
+
+public:
+ // Construct the session
+ http_session(
+ beast::flat_buffer buffer,
+ std::shared_ptr<std::string const> const& doc_root)
+ : doc_root_(doc_root)
+ , queue_(*this)
+ , buffer_(std::move(buffer))
+ {
+ }
+
+ void
+ do_read()
+ {
+ // Construct a new parser for each message
+ parser_.emplace();
+
+ // Apply a reasonable limit to the allowed size
+ // of the body in bytes to prevent abuse.
+ parser_->body_limit(10000);
+
+ // Set the timeout.
+ beast::get_lowest_layer(
+ derived().stream()).expires_after(std::chrono::seconds(30));
+
+ // Read a request using the parser-oriented interface
+ http::async_read(
+ derived().stream(),
+ buffer_,
+ *parser_,
+ beast::bind_front_handler(
+ &http_session::on_read,
+ derived().shared_from_this()));
+ }
+
+ void
+ on_read(beast::error_code ec, std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ // This means they closed the connection
+ if(ec == http::error::end_of_stream)
+ return derived().do_eof();
+
+ if(ec)
+ return fail(ec, "read");
+
+ // See if it is a WebSocket Upgrade
+ if(websocket::is_upgrade(parser_->get()))
+ {
+ // Disable the timeout.
+ // The websocket::stream uses its own timeout settings.
+ beast::get_lowest_layer(derived().stream()).expires_never();
+
+ // Create a websocket session, transferring ownership
+ // of both the socket and the HTTP request.
+ return make_websocket_session(
+ derived().release_stream(),
+ parser_->release());
+ }
+
+ // Send the response
+ handle_request(*doc_root_, parser_->release(), queue_);
+
+ // If we aren't at the queue limit, try to pipeline another request
+ if(! queue_.is_full())
+ do_read();
+ }
+
+ void
+ on_write(bool close, beast::error_code ec, std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ if(ec)
+ return fail(ec, "write");
+
+ if(close)
+ {
+ // This means we should close the connection, usually because
+ // the response indicated the "Connection: close" semantic.
+ return derived().do_eof();
+ }
+
+ // Inform the queue that a write completed
+ if(queue_.on_write())
+ {
+ // Read another request
+ do_read();
+ }
+ }
+};
+
+//------------------------------------------------------------------------------
+
+// Handles a plain HTTP connection
+class plain_http_session
+ : public http_session<plain_http_session>
+ , public std::enable_shared_from_this<plain_http_session>
+{
+ beast::tcp_stream stream_;
+
+public:
+ // Create the session
+ plain_http_session(
+ beast::tcp_stream&& stream,
+ beast::flat_buffer&& buffer,
+ std::shared_ptr<std::string const> const& doc_root)
+ : http_session<plain_http_session>(
+ std::move(buffer),
+ doc_root)
+ , stream_(std::move(stream))
+ {
+ }
+
+ // Start the session
+ void
+ run()
+ {
+ this->do_read();
+ }
+
+ // Called by the base class
+ beast::tcp_stream&
+ stream()
+ {
+ return stream_;
+ }
+
+ // Called by the base class
+ beast::tcp_stream
+ release_stream()
+ {
+ return std::move(stream_);
+ }
+
+ // Called by the base class
+ void
+ do_eof()
+ {
+ // Send a TCP shutdown
+ beast::error_code ec;
+ stream_.socket().shutdown(tcp::socket::shutdown_send, ec);
+
+ // At this point the connection is closed gracefully
+ }
+};
+
+//------------------------------------------------------------------------------
+
+// Handles an SSL HTTP connection
+class ssl_http_session
+ : public http_session<ssl_http_session>
+ , public std::enable_shared_from_this<ssl_http_session>
+{
+ beast::ssl_stream<beast::tcp_stream> stream_;
+
+public:
+ // Create the http_session
+ ssl_http_session(
+ beast::tcp_stream&& stream,
+ ssl::context& ctx,
+ beast::flat_buffer&& buffer,
+ std::shared_ptr<std::string const> const& doc_root)
+ : http_session<ssl_http_session>(
+ std::move(buffer),
+ doc_root)
+ , stream_(std::move(stream), ctx)
+ {
+ }
+
+ // Start the session
+ void
+ run()
+ {
+ // Set the timeout.
+ beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30));
+
+ // Perform the SSL handshake
+ // Note, this is the buffered version of the handshake.
+ stream_.async_handshake(
+ ssl::stream_base::server,
+ buffer_.data(),
+ beast::bind_front_handler(
+ &ssl_http_session::on_handshake,
+ shared_from_this()));
+ }
+
+ // Called by the base class
+ beast::ssl_stream<beast::tcp_stream>&
+ stream()
+ {
+ return stream_;
+ }
+
+ // Called by the base class
+ beast::ssl_stream<beast::tcp_stream>
+ release_stream()
+ {
+ return std::move(stream_);
+ }
+
+ // Called by the base class
+ void
+ do_eof()
+ {
+ // Set the timeout.
+ beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30));
+
+ // Perform the SSL shutdown
+ stream_.async_shutdown(
+ beast::bind_front_handler(
+ &ssl_http_session::on_shutdown,
+ shared_from_this()));
+ }
+
+private:
+ void
+ on_handshake(
+ beast::error_code ec,
+ std::size_t bytes_used)
+ {
+ if(ec)
+ return fail(ec, "handshake");
+
+ // Consume the portion of the buffer used by the handshake
+ buffer_.consume(bytes_used);
+
+ do_read();
+ }
+
+ void
+ on_shutdown(beast::error_code ec)
+ {
+ if(ec)
+ return fail(ec, "shutdown");
+
+ // At this point the connection is closed gracefully
+ }
+};
+
+//------------------------------------------------------------------------------
+
+// Detects SSL handshakes
+class detect_session : public std::enable_shared_from_this<detect_session>
+{
+ beast::tcp_stream stream_;
+ ssl::context& ctx_;
+ std::shared_ptr<std::string const> doc_root_;
+ beast::flat_buffer buffer_;
+
+public:
+ explicit
+ detect_session(
+ tcp::socket&& socket,
+ ssl::context& ctx,
+ std::shared_ptr<std::string const> const& doc_root)
+ : stream_(std::move(socket))
+ , ctx_(ctx)
+ , doc_root_(doc_root)
+ {
+ }
+
+ // Launch the detector
+ void
+ run()
+ {
+ // We need to be executing within a strand to perform async operations
+ // on the I/O objects in this session. Although not strictly necessary
+ // for single-threaded contexts, this example code is written to be
+ // thread-safe by default.
+ net::dispatch(
+ stream_.get_executor(),
+ beast::bind_front_handler(
+ &detect_session::on_run,
+ this->shared_from_this()));
+ }
+
+ void
+ on_run()
+ {
+ // Set the timeout.
+ stream_.expires_after(std::chrono::seconds(30));
+
+ beast::async_detect_ssl(
+ stream_,
+ buffer_,
+ beast::bind_front_handler(
+ &detect_session::on_detect,
+ this->shared_from_this()));
+ }
+
+ void
+ on_detect(beast::error_code ec, bool result)
+ {
+ if(ec)
+ return fail(ec, "detect");
+
+ if(result)
+ {
+ // Launch SSL session
+ std::make_shared<ssl_http_session>(
+ std::move(stream_),
+ ctx_,
+ std::move(buffer_),
+ doc_root_)->run();
+ return;
+ }
+
+ // Launch plain session
+ std::make_shared<plain_http_session>(
+ std::move(stream_),
+ std::move(buffer_),
+ doc_root_)->run();
+ }
+};
+
+// Accepts incoming connections and launches the sessions
+class listener : public std::enable_shared_from_this<listener>
+{
+ net::io_context& ioc_;
+ ssl::context& ctx_;
+ tcp::acceptor acceptor_;
+ std::shared_ptr<std::string const> doc_root_;
+
+public:
+ listener(
+ net::io_context& ioc,
+ ssl::context& ctx,
+ tcp::endpoint endpoint,
+ std::shared_ptr<std::string const> const& doc_root)
+ : ioc_(ioc)
+ , ctx_(ctx)
+ , acceptor_(net::make_strand(ioc))
+ , doc_root_(doc_root)
+ {
+ beast::error_code ec;
+
+ // Open the acceptor
+ acceptor_.open(endpoint.protocol(), ec);
+ if(ec)
+ {
+ fail(ec, "open");
+ return;
+ }
+
+ // Allow address reuse
+ acceptor_.set_option(net::socket_base::reuse_address(true), ec);
+ if(ec)
+ {
+ fail(ec, "set_option");
+ return;
+ }
+
+ // Bind to the server address
+ acceptor_.bind(endpoint, ec);
+ if(ec)
+ {
+ fail(ec, "bind");
+ return;
+ }
+
+ // Start listening for connections
+ acceptor_.listen(
+ net::socket_base::max_listen_connections, ec);
+ if(ec)
+ {
+ fail(ec, "listen");
+ return;
+ }
+ }
+
+ // Start accepting incoming connections
+ void
+ run()
+ {
+ do_accept();
+ }
+
+private:
+ void
+ do_accept()
+ {
+ // The new connection gets its own strand
+ acceptor_.async_accept(
+ net::make_strand(ioc_),
+ beast::bind_front_handler(
+ &listener::on_accept,
+ shared_from_this()));
+ }
+
+ void
+ on_accept(beast::error_code ec, tcp::socket socket)
+ {
+ if(ec)
+ {
+ fail(ec, "accept");
+ }
+ else
+ {
+ // Create the detector http_session and run it
+ std::make_shared<detect_session>(
+ std::move(socket),
+ ctx_,
+ doc_root_)->run();
+ }
+
+ // Accept another connection
+ do_accept();
+ }
+};
+
+//------------------------------------------------------------------------------
+
+int main(int argc, char* argv[])
+{
+ // Check command line arguments.
+ if (argc != 5)
+ {
+ std::cerr <<
+ "Usage: advanced-server-flex <address> <port> <doc_root> <threads>\n" <<
+ "Example:\n" <<
+ " advanced-server-flex 0.0.0.0 8080 . 1\n";
+ return EXIT_FAILURE;
+ }
+ auto const address = net::ip::make_address(argv[1]);
+ auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
+ auto const doc_root = std::make_shared<std::string>(argv[3]);
+ auto const threads = std::max<int>(1, std::atoi(argv[4]));
+
+ // The io_context is required for all I/O
+ net::io_context ioc{threads};
+
+ // The SSL context is required, and holds certificates
+ ssl::context ctx{ssl::context::tlsv12};
+
+ // This holds the self-signed certificate used by the server
+ load_server_certificate(ctx);
+
+ // Create and launch a listening port
+ std::make_shared<listener>(
+ ioc,
+ ctx,
+ tcp::endpoint{address, port},
+ doc_root)->run();
+
+ // Capture SIGINT and SIGTERM to perform a clean shutdown
+ net::signal_set signals(ioc, SIGINT, SIGTERM);
+ signals.async_wait(
+ [&](beast::error_code const&, int)
+ {
+ // Stop the `io_context`. This will cause `run()`
+ // to return immediately, eventually destroying the
+ // `io_context` and all of the sockets in it.
+ ioc.stop();
+ });
+
+ // Run the I/O service on the requested number of threads
+ std::vector<std::thread> v;
+ v.reserve(threads - 1);
+ for(auto i = threads - 1; i > 0; --i)
+ v.emplace_back(
+ [&ioc]
+ {
+ ioc.run();
+ });
+ ioc.run();
+
+ // (If we get here, it means we got a SIGINT or SIGTERM)
+
+ // Block until all the threads exit
+ for(auto& t : v)
+ t.join();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/advanced/server/CMakeLists.txt b/src/boost/libs/beast/example/advanced/server/CMakeLists.txt
new file mode 100644
index 000000000..08014afee
--- /dev/null
+++ b/src/boost/libs/beast/example/advanced/server/CMakeLists.txt
@@ -0,0 +1,23 @@
+#
+# 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
+#
+
+GroupSources(include/boost/beast beast)
+GroupSources(example/advanced/server "/")
+
+add_executable (advanced-server
+ ${BOOST_BEAST_FILES}
+ Jamfile
+ advanced_server.cpp
+)
+
+target_link_libraries(advanced-server
+ lib-asio
+ lib-beast)
+
+set_property(TARGET advanced-server PROPERTY FOLDER "example-advanced-server")
diff --git a/src/boost/libs/beast/example/advanced/server/Jamfile b/src/boost/libs/beast/example/advanced/server/Jamfile
new file mode 100644
index 000000000..5f9ceecd8
--- /dev/null
+++ b/src/boost/libs/beast/example/advanced/server/Jamfile
@@ -0,0 +1,15 @@
+#
+# 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
+#
+
+exe advanced-server :
+ advanced_server.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ ;
diff --git a/src/boost/libs/beast/example/advanced/server/advanced_server.cpp b/src/boost/libs/beast/example/advanced/server/advanced_server.cpp
new file mode 100644
index 000000000..715f8b8ca
--- /dev/null
+++ b/src/boost/libs/beast/example/advanced/server/advanced_server.cpp
@@ -0,0 +1,700 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: Advanced server
+//
+//------------------------------------------------------------------------------
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/http.hpp>
+#include <boost/beast/websocket.hpp>
+#include <boost/beast/version.hpp>
+#include <boost/asio/bind_executor.hpp>
+#include <boost/asio/dispatch.hpp>
+#include <boost/asio/signal_set.hpp>
+#include <boost/asio/strand.hpp>
+#include <boost/make_unique.hpp>
+#include <boost/optional.hpp>
+#include <algorithm>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <thread>
+#include <vector>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+// Return a reasonable mime type based on the extension of a file.
+beast::string_view
+mime_type(beast::string_view path)
+{
+ using beast::iequals;
+ auto const ext = [&path]
+ {
+ auto const pos = path.rfind(".");
+ if(pos == beast::string_view::npos)
+ return beast::string_view{};
+ return path.substr(pos);
+ }();
+ if(iequals(ext, ".htm")) return "text/html";
+ if(iequals(ext, ".html")) return "text/html";
+ if(iequals(ext, ".php")) return "text/html";
+ if(iequals(ext, ".css")) return "text/css";
+ if(iequals(ext, ".txt")) return "text/plain";
+ if(iequals(ext, ".js")) return "application/javascript";
+ if(iequals(ext, ".json")) return "application/json";
+ if(iequals(ext, ".xml")) return "application/xml";
+ if(iequals(ext, ".swf")) return "application/x-shockwave-flash";
+ if(iequals(ext, ".flv")) return "video/x-flv";
+ if(iequals(ext, ".png")) return "image/png";
+ if(iequals(ext, ".jpe")) return "image/jpeg";
+ if(iequals(ext, ".jpeg")) return "image/jpeg";
+ if(iequals(ext, ".jpg")) return "image/jpeg";
+ if(iequals(ext, ".gif")) return "image/gif";
+ if(iequals(ext, ".bmp")) return "image/bmp";
+ if(iequals(ext, ".ico")) return "image/vnd.microsoft.icon";
+ if(iequals(ext, ".tiff")) return "image/tiff";
+ if(iequals(ext, ".tif")) return "image/tiff";
+ if(iequals(ext, ".svg")) return "image/svg+xml";
+ if(iequals(ext, ".svgz")) return "image/svg+xml";
+ return "application/text";
+}
+
+// Append an HTTP rel-path to a local filesystem path.
+// The returned path is normalized for the platform.
+std::string
+path_cat(
+ beast::string_view base,
+ beast::string_view path)
+{
+ if(base.empty())
+ return std::string(path);
+ std::string result(base);
+#ifdef BOOST_MSVC
+ char constexpr path_separator = '\\';
+ if(result.back() == path_separator)
+ result.resize(result.size() - 1);
+ result.append(path.data(), path.size());
+ for(auto& c : result)
+ if(c == '/')
+ c = path_separator;
+#else
+ char constexpr path_separator = '/';
+ if(result.back() == path_separator)
+ result.resize(result.size() - 1);
+ result.append(path.data(), path.size());
+#endif
+ return result;
+}
+
+// This function produces an HTTP response for the given
+// request. The type of the response object depends on the
+// contents of the request, so the interface requires the
+// caller to pass a generic lambda for receiving the response.
+template<
+ class Body, class Allocator,
+ class Send>
+void
+handle_request(
+ beast::string_view doc_root,
+ http::request<Body, http::basic_fields<Allocator>>&& req,
+ Send&& send)
+{
+ // Returns a bad request response
+ auto const bad_request =
+ [&req](beast::string_view why)
+ {
+ http::response<http::string_body> res{http::status::bad_request, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = std::string(why);
+ res.prepare_payload();
+ return res;
+ };
+
+ // Returns a not found response
+ auto const not_found =
+ [&req](beast::string_view target)
+ {
+ http::response<http::string_body> res{http::status::not_found, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = "The resource '" + std::string(target) + "' was not found.";
+ res.prepare_payload();
+ return res;
+ };
+
+ // Returns a server error response
+ auto const server_error =
+ [&req](beast::string_view what)
+ {
+ http::response<http::string_body> res{http::status::internal_server_error, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = "An error occurred: '" + std::string(what) + "'";
+ res.prepare_payload();
+ return res;
+ };
+
+ // Make sure we can handle the method
+ if( req.method() != http::verb::get &&
+ req.method() != http::verb::head)
+ return send(bad_request("Unknown HTTP-method"));
+
+ // Request path must be absolute and not contain "..".
+ if( req.target().empty() ||
+ req.target()[0] != '/' ||
+ req.target().find("..") != beast::string_view::npos)
+ return send(bad_request("Illegal request-target"));
+
+ // Build the path to the requested file
+ std::string path = path_cat(doc_root, req.target());
+ if(req.target().back() == '/')
+ path.append("index.html");
+
+ // Attempt to open the file
+ beast::error_code ec;
+ http::file_body::value_type body;
+ body.open(path.c_str(), beast::file_mode::scan, ec);
+
+ // Handle the case where the file doesn't exist
+ if(ec == beast::errc::no_such_file_or_directory)
+ return send(not_found(req.target()));
+
+ // Handle an unknown error
+ if(ec)
+ return send(server_error(ec.message()));
+
+ // Cache the size since we need it after the move
+ auto const size = body.size();
+
+ // Respond to HEAD request
+ if(req.method() == http::verb::head)
+ {
+ http::response<http::empty_body> res{http::status::ok, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, mime_type(path));
+ res.content_length(size);
+ res.keep_alive(req.keep_alive());
+ return send(std::move(res));
+ }
+
+ // Respond to GET request
+ http::response<http::file_body> res{
+ std::piecewise_construct,
+ std::make_tuple(std::move(body)),
+ std::make_tuple(http::status::ok, req.version())};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, mime_type(path));
+ res.content_length(size);
+ res.keep_alive(req.keep_alive());
+ return send(std::move(res));
+}
+
+//------------------------------------------------------------------------------
+
+// Report a failure
+void
+fail(beast::error_code ec, char const* what)
+{
+ std::cerr << what << ": " << ec.message() << "\n";
+}
+
+// Echoes back all received WebSocket messages
+class websocket_session : public std::enable_shared_from_this<websocket_session>
+{
+ websocket::stream<beast::tcp_stream> ws_;
+ beast::flat_buffer buffer_;
+
+public:
+ // Take ownership of the socket
+ explicit
+ websocket_session(tcp::socket&& socket)
+ : ws_(std::move(socket))
+ {
+ }
+
+ // Start the asynchronous accept operation
+ template<class Body, class Allocator>
+ void
+ do_accept(http::request<Body, http::basic_fields<Allocator>> req)
+ {
+ // Set suggested timeout settings for the websocket
+ ws_.set_option(
+ websocket::stream_base::timeout::suggested(
+ beast::role_type::server));
+
+ // Set a decorator to change the Server of the handshake
+ ws_.set_option(websocket::stream_base::decorator(
+ [](websocket::response_type& res)
+ {
+ res.set(http::field::server,
+ std::string(BOOST_BEAST_VERSION_STRING) +
+ " advanced-server");
+ }));
+
+ // Accept the websocket handshake
+ ws_.async_accept(
+ req,
+ beast::bind_front_handler(
+ &websocket_session::on_accept,
+ shared_from_this()));
+ }
+
+private:
+ void
+ on_accept(beast::error_code ec)
+ {
+ if(ec)
+ return fail(ec, "accept");
+
+ // Read a message
+ do_read();
+ }
+
+ void
+ do_read()
+ {
+ // Read a message into our buffer
+ ws_.async_read(
+ buffer_,
+ beast::bind_front_handler(
+ &websocket_session::on_read,
+ shared_from_this()));
+ }
+
+ void
+ on_read(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ // This indicates that the websocket_session was closed
+ if(ec == websocket::error::closed)
+ return;
+
+ if(ec)
+ fail(ec, "read");
+
+ // Echo the message
+ ws_.text(ws_.got_text());
+ ws_.async_write(
+ buffer_.data(),
+ beast::bind_front_handler(
+ &websocket_session::on_write,
+ shared_from_this()));
+ }
+
+ void
+ on_write(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ if(ec)
+ return fail(ec, "write");
+
+ // Clear the buffer
+ buffer_.consume(buffer_.size());
+
+ // Do another read
+ do_read();
+ }
+};
+
+//------------------------------------------------------------------------------
+
+// Handles an HTTP server connection
+class http_session : public std::enable_shared_from_this<http_session>
+{
+ // This queue is used for HTTP pipelining.
+ class queue
+ {
+ enum
+ {
+ // Maximum number of responses we will queue
+ limit = 8
+ };
+
+ // The type-erased, saved work item
+ struct work
+ {
+ virtual ~work() = default;
+ virtual void operator()() = 0;
+ };
+
+ http_session& self_;
+ std::vector<std::unique_ptr<work>> items_;
+
+ public:
+ explicit
+ queue(http_session& self)
+ : self_(self)
+ {
+ static_assert(limit > 0, "queue limit must be positive");
+ items_.reserve(limit);
+ }
+
+ // Returns `true` if we have reached the queue limit
+ bool
+ is_full() const
+ {
+ return items_.size() >= limit;
+ }
+
+ // Called when a message finishes sending
+ // Returns `true` if the caller should initiate a read
+ bool
+ on_write()
+ {
+ BOOST_ASSERT(! items_.empty());
+ auto const was_full = is_full();
+ items_.erase(items_.begin());
+ if(! items_.empty())
+ (*items_.front())();
+ return was_full;
+ }
+
+ // Called by the HTTP handler to send a response.
+ template<bool isRequest, class Body, class Fields>
+ void
+ operator()(http::message<isRequest, Body, Fields>&& msg)
+ {
+ // This holds a work item
+ struct work_impl : work
+ {
+ http_session& self_;
+ http::message<isRequest, Body, Fields> msg_;
+
+ work_impl(
+ http_session& self,
+ http::message<isRequest, Body, Fields>&& msg)
+ : self_(self)
+ , msg_(std::move(msg))
+ {
+ }
+
+ void
+ operator()()
+ {
+ http::async_write(
+ self_.stream_,
+ msg_,
+ beast::bind_front_handler(
+ &http_session::on_write,
+ self_.shared_from_this(),
+ msg_.need_eof()));
+ }
+ };
+
+ // Allocate and store the work
+ items_.push_back(
+ boost::make_unique<work_impl>(self_, std::move(msg)));
+
+ // If there was no previous work, start this one
+ if(items_.size() == 1)
+ (*items_.front())();
+ }
+ };
+
+ beast::tcp_stream stream_;
+ beast::flat_buffer buffer_;
+ std::shared_ptr<std::string const> doc_root_;
+ queue queue_;
+
+ // The parser is stored in an optional container so we can
+ // construct it from scratch it at the beginning of each new message.
+ boost::optional<http::request_parser<http::string_body>> parser_;
+
+public:
+ // Take ownership of the socket
+ http_session(
+ tcp::socket&& socket,
+ std::shared_ptr<std::string const> const& doc_root)
+ : stream_(std::move(socket))
+ , doc_root_(doc_root)
+ , queue_(*this)
+ {
+ }
+
+ // Start the session
+ void
+ run()
+ {
+ // We need to be executing within a strand to perform async operations
+ // on the I/O objects in this session. Although not strictly necessary
+ // for single-threaded contexts, this example code is written to be
+ // thread-safe by default.
+ net::dispatch(
+ stream_.get_executor(),
+ beast::bind_front_handler(
+ &http_session::do_read,
+ this->shared_from_this()));
+ }
+
+
+private:
+ void
+ do_read()
+ {
+ // Construct a new parser for each message
+ parser_.emplace();
+
+ // Apply a reasonable limit to the allowed size
+ // of the body in bytes to prevent abuse.
+ parser_->body_limit(10000);
+
+ // Set the timeout.
+ stream_.expires_after(std::chrono::seconds(30));
+
+ // Read a request using the parser-oriented interface
+ http::async_read(
+ stream_,
+ buffer_,
+ *parser_,
+ beast::bind_front_handler(
+ &http_session::on_read,
+ shared_from_this()));
+ }
+
+ void
+ on_read(beast::error_code ec, std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ // This means they closed the connection
+ if(ec == http::error::end_of_stream)
+ return do_close();
+
+ if(ec)
+ return fail(ec, "read");
+
+ // See if it is a WebSocket Upgrade
+ if(websocket::is_upgrade(parser_->get()))
+ {
+ // Create a websocket session, transferring ownership
+ // of both the socket and the HTTP request.
+ std::make_shared<websocket_session>(
+ stream_.release_socket())->do_accept(parser_->release());
+ return;
+ }
+
+ // Send the response
+ handle_request(*doc_root_, parser_->release(), queue_);
+
+ // If we aren't at the queue limit, try to pipeline another request
+ if(! queue_.is_full())
+ do_read();
+ }
+
+ void
+ on_write(bool close, beast::error_code ec, std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ if(ec)
+ return fail(ec, "write");
+
+ if(close)
+ {
+ // This means we should close the connection, usually because
+ // the response indicated the "Connection: close" semantic.
+ return do_close();
+ }
+
+ // Inform the queue that a write completed
+ if(queue_.on_write())
+ {
+ // Read another request
+ do_read();
+ }
+ }
+
+ void
+ do_close()
+ {
+ // Send a TCP shutdown
+ beast::error_code ec;
+ stream_.socket().shutdown(tcp::socket::shutdown_send, ec);
+
+ // At this point the connection is closed gracefully
+ }
+};
+
+//------------------------------------------------------------------------------
+
+// Accepts incoming connections and launches the sessions
+class listener : public std::enable_shared_from_this<listener>
+{
+ net::io_context& ioc_;
+ tcp::acceptor acceptor_;
+ std::shared_ptr<std::string const> doc_root_;
+
+public:
+ listener(
+ net::io_context& ioc,
+ tcp::endpoint endpoint,
+ std::shared_ptr<std::string const> const& doc_root)
+ : ioc_(ioc)
+ , acceptor_(net::make_strand(ioc))
+ , doc_root_(doc_root)
+ {
+ beast::error_code ec;
+
+ // Open the acceptor
+ acceptor_.open(endpoint.protocol(), ec);
+ if(ec)
+ {
+ fail(ec, "open");
+ return;
+ }
+
+ // Allow address reuse
+ acceptor_.set_option(net::socket_base::reuse_address(true), ec);
+ if(ec)
+ {
+ fail(ec, "set_option");
+ return;
+ }
+
+ // Bind to the server address
+ acceptor_.bind(endpoint, ec);
+ if(ec)
+ {
+ fail(ec, "bind");
+ return;
+ }
+
+ // Start listening for connections
+ acceptor_.listen(
+ net::socket_base::max_listen_connections, ec);
+ if(ec)
+ {
+ fail(ec, "listen");
+ return;
+ }
+ }
+
+ // Start accepting incoming connections
+ void
+ run()
+ {
+ // We need to be executing within a strand to perform async operations
+ // on the I/O objects in this session. Although not strictly necessary
+ // for single-threaded contexts, this example code is written to be
+ // thread-safe by default.
+ net::dispatch(
+ acceptor_.get_executor(),
+ beast::bind_front_handler(
+ &listener::do_accept,
+ this->shared_from_this()));
+ }
+
+private:
+ void
+ do_accept()
+ {
+ // The new connection gets its own strand
+ acceptor_.async_accept(
+ net::make_strand(ioc_),
+ beast::bind_front_handler(
+ &listener::on_accept,
+ shared_from_this()));
+ }
+
+ void
+ on_accept(beast::error_code ec, tcp::socket socket)
+ {
+ if(ec)
+ {
+ fail(ec, "accept");
+ }
+ else
+ {
+ // Create the http session and run it
+ std::make_shared<http_session>(
+ std::move(socket),
+ doc_root_)->run();
+ }
+
+ // Accept another connection
+ do_accept();
+ }
+};
+
+//------------------------------------------------------------------------------
+
+int main(int argc, char* argv[])
+{
+ // Check command line arguments.
+ if (argc != 5)
+ {
+ std::cerr <<
+ "Usage: advanced-server <address> <port> <doc_root> <threads>\n" <<
+ "Example:\n" <<
+ " advanced-server 0.0.0.0 8080 . 1\n";
+ return EXIT_FAILURE;
+ }
+ auto const address = net::ip::make_address(argv[1]);
+ auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
+ auto const doc_root = std::make_shared<std::string>(argv[3]);
+ auto const threads = std::max<int>(1, std::atoi(argv[4]));
+
+ // The io_context is required for all I/O
+ net::io_context ioc{threads};
+
+ // Create and launch a listening port
+ std::make_shared<listener>(
+ ioc,
+ tcp::endpoint{address, port},
+ doc_root)->run();
+
+ // Capture SIGINT and SIGTERM to perform a clean shutdown
+ net::signal_set signals(ioc, SIGINT, SIGTERM);
+ signals.async_wait(
+ [&](beast::error_code const&, int)
+ {
+ // Stop the `io_context`. This will cause `run()`
+ // to return immediately, eventually destroying the
+ // `io_context` and all of the sockets in it.
+ ioc.stop();
+ });
+
+ // Run the I/O service on the requested number of threads
+ std::vector<std::thread> v;
+ v.reserve(threads - 1);
+ for(auto i = threads - 1; i > 0; --i)
+ v.emplace_back(
+ [&ioc]
+ {
+ ioc.run();
+ });
+ ioc.run();
+
+ // (If we get here, it means we got a SIGINT or SIGTERM)
+
+ // Block until all the threads exit
+ for(auto& t : v)
+ t.join();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/common/root_certificates.hpp b/src/boost/libs/beast/example/common/root_certificates.hpp
new file mode 100644
index 000000000..aa65bdeb8
--- /dev/null
+++ b/src/boost/libs/beast/example/common/root_certificates.hpp
@@ -0,0 +1,151 @@
+//
+// Copyright (c) 2016-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 BOOST_BEAST_EXAMPLE_COMMON_ROOT_CERTIFICATES_HPP
+#define BOOST_BEAST_EXAMPLE_COMMON_ROOT_CERTIFICATES_HPP
+
+#include <boost/asio/ssl.hpp>
+#include <string>
+
+/*
+ PLEASE READ
+
+ These root certificates here are included just to make the
+ SSL client examples work. They are NOT intended to be
+ illustrative of best-practices for performing TLS certificate
+ verification.
+
+ A REAL program which needs to verify the authenticity of a
+ server IP address resolved from a given DNS name needs to
+ consult the operating system specific certificate store
+ to validate the chain of signatures, compare the domain name
+ properly against the domain name in the certificate, check
+ the certificate revocation list, and probably do some other
+ things.
+
+ ALL of these operations are entirely outside the scope of
+ both Boost.Beast and Boost.Asio.
+
+ See (work in progress):
+ https://github.com/djarek/certify
+
+ tl;dr: root_certificates.hpp should not be used in production code
+*/
+
+namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp>
+
+namespace detail {
+
+inline
+void
+load_root_certificates(ssl::context& ctx, boost::system::error_code& ec)
+{
+ std::string const cert =
+ /* This is the DigiCert Global Root CA
+
+ CN = DigiCert High Assurance EV Root CA
+ OU = www.digicert.com
+ O = DigiCert Inc
+ C = US
+
+ Valid to: 10 November 2031
+
+ Serial #:
+ 08:3B:E0:56:90:42:46:B1:A1:75:6A:C9:59:91:C7:4A
+
+ SHA1 Fingerprint:
+ A8:98:5D:3A:65:E5:E5:C4:B2:D7:D6:6D:40:C6:DD:2F:B1:9C:54:36
+
+ SHA256 Fingerprint:
+ 43:48:A0:E9:44:4C:78:CB:26:5E:05:8D:5E:89:44:B4:D8:4F:96:62:BD:26:DB:25:7F:89:34:A4:43:C7:01:61
+ */
+ "-----BEGIN CERTIFICATE-----\n"
+ "MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh\n"
+ "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n"
+ "d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\n"
+ "QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT\n"
+ "MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n"
+ "b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG\n"
+ "9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB\n"
+ "CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97\n"
+ "nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt\n"
+ "43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P\n"
+ "T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4\n"
+ "gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO\n"
+ "BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR\n"
+ "TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw\n"
+ "DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr\n"
+ "hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg\n"
+ "06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF\n"
+ "PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls\n"
+ "YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk\n"
+ "CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=\n"
+ "-----END CERTIFICATE-----\n"
+
+ /* This is the GeoTrust root certificate.
+
+ CN = GeoTrust Global CA
+ O = GeoTrust Inc.
+ C = US
+ Valid to: Friday, ‎May ‎20, ‎2022 9:00:00 PM
+
+ Thumbprint(sha1):
+ ‎de 28 f4 a4 ff e5 b9 2f a3 c5 03 d1 a3 49 a7 f9 96 2a 82 12
+ */
+ "-----BEGIN CERTIFICATE-----\n"
+ "MIIDaDCCAlCgAwIBAgIJAO8vBu8i8exWMA0GCSqGSIb3DQEBCwUAMEkxCzAJBgNV\n"
+ "BAYTAlVTMQswCQYDVQQIDAJDQTEtMCsGA1UEBwwkTG9zIEFuZ2VsZXNPPUJlYXN0\n"
+ "Q049d3d3LmV4YW1wbGUuY29tMB4XDTE3MDUwMzE4MzkxMloXDTQ0MDkxODE4Mzkx\n"
+ "MlowSTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMS0wKwYDVQQHDCRMb3MgQW5n\n"
+ "ZWxlc089QmVhc3RDTj13d3cuZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUA\n"
+ "A4IBDwAwggEKAoIBAQDJ7BRKFO8fqmsEXw8v9YOVXyrQVsVbjSSGEs4Vzs4cJgcF\n"
+ "xqGitbnLIrOgiJpRAPLy5MNcAXE1strVGfdEf7xMYSZ/4wOrxUyVw/Ltgsft8m7b\n"
+ "Fu8TsCzO6XrxpnVtWk506YZ7ToTa5UjHfBi2+pWTxbpN12UhiZNUcrRsqTFW+6fO\n"
+ "9d7xm5wlaZG8cMdg0cO1bhkz45JSl3wWKIES7t3EfKePZbNlQ5hPy7Pd5JTmdGBp\n"
+ "yY8anC8u4LPbmgW0/U31PH0rRVfGcBbZsAoQw5Tc5dnb6N2GEIbq3ehSfdDHGnrv\n"
+ "enu2tOK9Qx6GEzXh3sekZkxcgh+NlIxCNxu//Dk9AgMBAAGjUzBRMB0GA1UdDgQW\n"
+ "BBTZh0N9Ne1OD7GBGJYz4PNESHuXezAfBgNVHSMEGDAWgBTZh0N9Ne1OD7GBGJYz\n"
+ "4PNESHuXezAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCmTJVT\n"
+ "LH5Cru1vXtzb3N9dyolcVH82xFVwPewArchgq+CEkajOU9bnzCqvhM4CryBb4cUs\n"
+ "gqXWp85hAh55uBOqXb2yyESEleMCJEiVTwm/m26FdONvEGptsiCmF5Gxi0YRtn8N\n"
+ "V+KhrQaAyLrLdPYI7TrwAOisq2I1cD0mt+xgwuv/654Rl3IhOMx+fKWKJ9qLAiaE\n"
+ "fQyshjlPP9mYVxWOxqctUdQ8UnsUKKGEUcVrA08i1OAnVKlPFjKBvk+r7jpsTPcr\n"
+ "9pWXTO9JrYMML7d+XRSZA1n3856OqZDX4403+9FnXCvfcLZLLKTBvwwFgEFGpzjK\n"
+ "UEVbkhd5qstF6qWK\n"
+ "-----END CERTIFICATE-----\n";
+ ;
+
+ ctx.add_certificate_authority(
+ boost::asio::buffer(cert.data(), cert.size()), ec);
+ if(ec)
+ return;
+}
+
+} // detail
+
+// Load the root certificates into an ssl::context
+
+inline
+void
+load_root_certificates(ssl::context& ctx, boost::system::error_code& ec)
+{
+ detail::load_root_certificates(ctx, ec);
+}
+
+inline
+void
+load_root_certificates(ssl::context& ctx)
+{
+ boost::system::error_code ec;
+ detail::load_root_certificates(ctx, ec);
+ if(ec)
+ throw boost::system::system_error{ec};
+}
+
+#endif
diff --git a/src/boost/libs/beast/example/common/server_certificate.hpp b/src/boost/libs/beast/example/common/server_certificate.hpp
new file mode 100644
index 000000000..a20110e40
--- /dev/null
+++ b/src/boost/libs/beast/example/common/server_certificate.hpp
@@ -0,0 +1,124 @@
+//
+// Copyright (c) 2016-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 BOOST_BEAST_EXAMPLE_COMMON_SERVER_CERTIFICATE_HPP
+#define BOOST_BEAST_EXAMPLE_COMMON_SERVER_CERTIFICATE_HPP
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/ssl/context.hpp>
+#include <cstddef>
+#include <memory>
+
+/* Load a signed certificate into the ssl context, and configure
+ the context for use with a server.
+
+ For this to work with the browser or operating system, it is
+ necessary to import the "Beast Test CA" certificate into
+ the local certificate store, browser, or operating system
+ depending on your environment Please see the documentation
+ accompanying the Beast certificate for more details.
+*/
+inline
+void
+load_server_certificate(boost::asio::ssl::context& ctx)
+{
+ /*
+ The certificate was generated from CMD.EXE on Windows 10 using:
+
+ winpty openssl dhparam -out dh.pem 2048
+ winpty openssl req -newkey rsa:2048 -nodes -keyout key.pem -x509 -days 10000 -out cert.pem -subj "//C=US\ST=CA\L=Los Angeles\O=Beast\CN=www.example.com"
+ */
+
+ std::string const cert =
+ "-----BEGIN CERTIFICATE-----\n"
+ "MIIDaDCCAlCgAwIBAgIJAO8vBu8i8exWMA0GCSqGSIb3DQEBCwUAMEkxCzAJBgNV\n"
+ "BAYTAlVTMQswCQYDVQQIDAJDQTEtMCsGA1UEBwwkTG9zIEFuZ2VsZXNPPUJlYXN0\n"
+ "Q049d3d3LmV4YW1wbGUuY29tMB4XDTE3MDUwMzE4MzkxMloXDTQ0MDkxODE4Mzkx\n"
+ "MlowSTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMS0wKwYDVQQHDCRMb3MgQW5n\n"
+ "ZWxlc089QmVhc3RDTj13d3cuZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUA\n"
+ "A4IBDwAwggEKAoIBAQDJ7BRKFO8fqmsEXw8v9YOVXyrQVsVbjSSGEs4Vzs4cJgcF\n"
+ "xqGitbnLIrOgiJpRAPLy5MNcAXE1strVGfdEf7xMYSZ/4wOrxUyVw/Ltgsft8m7b\n"
+ "Fu8TsCzO6XrxpnVtWk506YZ7ToTa5UjHfBi2+pWTxbpN12UhiZNUcrRsqTFW+6fO\n"
+ "9d7xm5wlaZG8cMdg0cO1bhkz45JSl3wWKIES7t3EfKePZbNlQ5hPy7Pd5JTmdGBp\n"
+ "yY8anC8u4LPbmgW0/U31PH0rRVfGcBbZsAoQw5Tc5dnb6N2GEIbq3ehSfdDHGnrv\n"
+ "enu2tOK9Qx6GEzXh3sekZkxcgh+NlIxCNxu//Dk9AgMBAAGjUzBRMB0GA1UdDgQW\n"
+ "BBTZh0N9Ne1OD7GBGJYz4PNESHuXezAfBgNVHSMEGDAWgBTZh0N9Ne1OD7GBGJYz\n"
+ "4PNESHuXezAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCmTJVT\n"
+ "LH5Cru1vXtzb3N9dyolcVH82xFVwPewArchgq+CEkajOU9bnzCqvhM4CryBb4cUs\n"
+ "gqXWp85hAh55uBOqXb2yyESEleMCJEiVTwm/m26FdONvEGptsiCmF5Gxi0YRtn8N\n"
+ "V+KhrQaAyLrLdPYI7TrwAOisq2I1cD0mt+xgwuv/654Rl3IhOMx+fKWKJ9qLAiaE\n"
+ "fQyshjlPP9mYVxWOxqctUdQ8UnsUKKGEUcVrA08i1OAnVKlPFjKBvk+r7jpsTPcr\n"
+ "9pWXTO9JrYMML7d+XRSZA1n3856OqZDX4403+9FnXCvfcLZLLKTBvwwFgEFGpzjK\n"
+ "UEVbkhd5qstF6qWK\n"
+ "-----END CERTIFICATE-----\n";
+
+ std::string const key =
+ "-----BEGIN PRIVATE KEY-----\n"
+ "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDJ7BRKFO8fqmsE\n"
+ "Xw8v9YOVXyrQVsVbjSSGEs4Vzs4cJgcFxqGitbnLIrOgiJpRAPLy5MNcAXE1strV\n"
+ "GfdEf7xMYSZ/4wOrxUyVw/Ltgsft8m7bFu8TsCzO6XrxpnVtWk506YZ7ToTa5UjH\n"
+ "fBi2+pWTxbpN12UhiZNUcrRsqTFW+6fO9d7xm5wlaZG8cMdg0cO1bhkz45JSl3wW\n"
+ "KIES7t3EfKePZbNlQ5hPy7Pd5JTmdGBpyY8anC8u4LPbmgW0/U31PH0rRVfGcBbZ\n"
+ "sAoQw5Tc5dnb6N2GEIbq3ehSfdDHGnrvenu2tOK9Qx6GEzXh3sekZkxcgh+NlIxC\n"
+ "Nxu//Dk9AgMBAAECggEBAK1gV8uETg4SdfE67f9v/5uyK0DYQH1ro4C7hNiUycTB\n"
+ "oiYDd6YOA4m4MiQVJuuGtRR5+IR3eI1zFRMFSJs4UqYChNwqQGys7CVsKpplQOW+\n"
+ "1BCqkH2HN/Ix5662Dv3mHJemLCKUON77IJKoq0/xuZ04mc9csykox6grFWB3pjXY\n"
+ "OEn9U8pt5KNldWfpfAZ7xu9WfyvthGXlhfwKEetOuHfAQv7FF6s25UIEU6Hmnwp9\n"
+ "VmYp2twfMGdztz/gfFjKOGxf92RG+FMSkyAPq/vhyB7oQWxa+vdBn6BSdsfn27Qs\n"
+ "bTvXrGe4FYcbuw4WkAKTljZX7TUegkXiwFoSps0jegECgYEA7o5AcRTZVUmmSs8W\n"
+ "PUHn89UEuDAMFVk7grG1bg8exLQSpugCykcqXt1WNrqB7x6nB+dbVANWNhSmhgCg\n"
+ "VrV941vbx8ketqZ9YInSbGPWIU/tss3r8Yx2Ct3mQpvpGC6iGHzEc/NHJP8Efvh/\n"
+ "CcUWmLjLGJYYeP5oNu5cncC3fXUCgYEA2LANATm0A6sFVGe3sSLO9un1brA4zlZE\n"
+ "Hjd3KOZnMPt73B426qUOcw5B2wIS8GJsUES0P94pKg83oyzmoUV9vJpJLjHA4qmL\n"
+ "CDAd6CjAmE5ea4dFdZwDDS8F9FntJMdPQJA9vq+JaeS+k7ds3+7oiNe+RUIHR1Sz\n"
+ "VEAKh3Xw66kCgYB7KO/2Mchesu5qku2tZJhHF4QfP5cNcos511uO3bmJ3ln+16uR\n"
+ "GRqz7Vu0V6f7dvzPJM/O2QYqV5D9f9dHzN2YgvU9+QSlUeFK9PyxPv3vJt/WP1//\n"
+ "zf+nbpaRbwLxnCnNsKSQJFpnrE166/pSZfFbmZQpNlyeIuJU8czZGQTifQKBgHXe\n"
+ "/pQGEZhVNab+bHwdFTxXdDzr+1qyrodJYLaM7uFES9InVXQ6qSuJO+WosSi2QXlA\n"
+ "hlSfwwCwGnHXAPYFWSp5Owm34tbpp0mi8wHQ+UNgjhgsE2qwnTBUvgZ3zHpPORtD\n"
+ "23KZBkTmO40bIEyIJ1IZGdWO32q79nkEBTY+v/lRAoGBAI1rbouFYPBrTYQ9kcjt\n"
+ "1yfu4JF5MvO9JrHQ9tOwkqDmNCWx9xWXbgydsn/eFtuUMULWsG3lNjfst/Esb8ch\n"
+ "k5cZd6pdJZa4/vhEwrYYSuEjMCnRb0lUsm7TsHxQrUd6Fi/mUuFU/haC0o0chLq7\n"
+ "pVOUFq5mW8p0zbtfHbjkgxyF\n"
+ "-----END PRIVATE KEY-----\n";
+
+ std::string const dh =
+ "-----BEGIN DH PARAMETERS-----\n"
+ "MIIBCAKCAQEArzQc5mpm0Fs8yahDeySj31JZlwEphUdZ9StM2D8+Fo7TMduGtSi+\n"
+ "/HRWVwHcTFAgrxVdm+dl474mOUqqaz4MpzIb6+6OVfWHbQJmXPepZKyu4LgUPvY/\n"
+ "4q3/iDMjIS0fLOu/bLuObwU5ccZmDgfhmz1GanRlTQOiYRty3FiOATWZBRh6uv4u\n"
+ "tff4A9Bm3V9tLx9S6djq31w31Gl7OQhryodW28kc16t9TvO1BzcV3HjRPwpe701X\n"
+ "oEEZdnZWANkkpR/m/pfgdmGPU66S2sXMHgsliViQWpDCYeehrvFRHEdR9NV+XJfC\n"
+ "QMUk26jPTIVTLfXmmwU0u8vUkpR7LQKkwwIBAg==\n"
+ "-----END DH PARAMETERS-----\n";
+
+ ctx.set_password_callback(
+ [](std::size_t,
+ boost::asio::ssl::context_base::password_purpose)
+ {
+ return "test";
+ });
+
+ ctx.set_options(
+ boost::asio::ssl::context::default_workarounds |
+ boost::asio::ssl::context::no_sslv2 |
+ boost::asio::ssl::context::single_dh_use);
+
+ ctx.use_certificate_chain(
+ boost::asio::buffer(cert.data(), cert.size()));
+
+ ctx.use_private_key(
+ boost::asio::buffer(key.data(), key.size()),
+ boost::asio::ssl::context::file_format::pem);
+
+ ctx.use_tmp_dh(
+ boost::asio::buffer(dh.data(), dh.size()));
+}
+
+#endif
diff --git a/src/boost/libs/beast/example/echo-op/CMakeLists.txt b/src/boost/libs/beast/example/echo-op/CMakeLists.txt
new file mode 100644
index 000000000..d0e086b6e
--- /dev/null
+++ b/src/boost/libs/beast/example/echo-op/CMakeLists.txt
@@ -0,0 +1,23 @@
+#
+# 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
+#
+
+GroupSources(include/boost/beast beast)
+GroupSources(example/echo-op "/")
+
+add_executable (echo-op
+ ${BOOST_BEAST_FILES}
+ Jamfile
+ echo_op.cpp
+)
+
+target_link_libraries(echo-op
+ lib-asio
+ lib-beast)
+
+set_property(TARGET echo-op PROPERTY FOLDER "example")
diff --git a/src/boost/libs/beast/example/echo-op/Jamfile b/src/boost/libs/beast/example/echo-op/Jamfile
new file mode 100644
index 000000000..caeb767e2
--- /dev/null
+++ b/src/boost/libs/beast/example/echo-op/Jamfile
@@ -0,0 +1,15 @@
+#
+# 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
+#
+
+exe echo-op :
+ echo_op.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ ;
diff --git a/src/boost/libs/beast/example/echo-op/echo_op.cpp b/src/boost/libs/beast/example/echo-op/echo_op.cpp
new file mode 100644
index 000000000..475940beb
--- /dev/null
+++ b/src/boost/libs/beast/example/echo-op/echo_op.cpp
@@ -0,0 +1,377 @@
+//
+// Copyright (c) 2016-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
+//
+
+#include <boost/beast/core.hpp>
+#include <boost/asio.hpp>
+#include <cstddef>
+#include <iostream>
+#include <memory>
+#include <utility>
+
+namespace net = boost::asio;
+namespace beast = boost::beast;
+
+//[example_core_echo_op_1
+
+template<
+ class AsyncStream,
+ class DynamicBuffer,
+ class CompletionToken>
+auto
+async_echo (AsyncStream& stream, DynamicBuffer& buffer, CompletionToken&& token)
+
+//]
+ ->
+ typename net::async_result<
+ typename std::decay<CompletionToken>::type,
+ void(beast::error_code)>::return_type;
+
+//------------------------------------------------------------------------------
+
+//[example_core_echo_op_2
+
+/** Asynchronously read a line and echo it back.
+
+ This function is used to asynchronously read a line ending
+ in a newline (`"\n"`) from the stream, and then write
+ it back.
+
+ This call always returns immediately. The asynchronous operation
+ will continue until one of the following conditions is true:
+
+ @li A line was read in and written back on the stream
+
+ @li An error occurs.
+
+ The algorithm, known as a <em>composed asynchronous operation</em>,
+ is implemented in terms of calls to the stream's `async_read_some`
+ and `async_write_some` function. The program must ensure that no
+ other reads or writes are performed until this operation completes.
+
+ Since the length of the line is not known ahead of time, the
+ implementation may read additional characters that lie past the
+ first line. These characters are stored in the dynamic buffer_.
+ The same dynamic buffer must be presented again in each call,
+ to provide the implementation with any leftover bytes.
+
+ @param stream The stream to operate on. The type must meet the
+ requirements of <em>AsyncReadStream</em> and @AsyncWriteStream
+
+ @param buffer A dynamic buffer to hold implementation-defined
+ temporary data. Ownership is not transferred; the caller is
+ responsible for ensuring that the lifetime of this object is
+ extended least until the completion handler is invoked.
+
+ @param token The handler to be called when the operation completes.
+ The implementation takes ownership of the handler by performing a decay-copy.
+ The handler must be invocable with this signature:
+ @code
+ void handler(
+ beast::error_code error // Result of operation.
+ );
+ @endcode
+
+ Regardless of whether the asynchronous operation completes immediately or
+ not, the handler will not be invoked from within this function. Invocation
+ of the handler will be performed in a manner equivalent to using
+ `net::post`.
+*/
+template<
+ class AsyncStream,
+ class DynamicBuffer,
+ class CompletionToken>
+auto
+async_echo (
+ AsyncStream& stream,
+ DynamicBuffer& buffer, /*< Unlike Asio, we pass by non-const reference instead of rvalue-ref >*/
+ CompletionToken&& token) ->
+ typename net::async_result< /*< `async_result` deduces the return type from the completion handler >*/
+ typename std::decay<CompletionToken>::type,
+ void(beast::error_code) /*< The completion handler signature goes here >*/
+ >::return_type;
+//]
+
+//[example_core_echo_op_3
+
+template<class AsyncStream, class Handler>
+class echo_op;
+
+// This example uses the Asio's stackless "fauxroutines", implemented
+// using a macro-based solution. It makes the code easier to write and
+// easier to read. This include file defines the necessary macros and types.
+#include <boost/asio/yield.hpp>
+
+// Read a line and echo it back
+//
+template<
+ class AsyncStream,
+ class DynamicBuffer,
+ class CompletionToken>
+auto
+async_echo(
+ AsyncStream& stream,
+ DynamicBuffer& buffer,
+ CompletionToken&& token) ->
+ typename net::async_result<
+ typename std::decay<CompletionToken>::type,
+ void(beast::error_code)>::return_type /*< The completion handler signature goes here >*/
+{
+ // Perform some type checks using static assert, this helps
+ // with more friendly error messages when passing the wrong types.
+ static_assert(
+ beast::is_async_stream<AsyncStream>::value,
+ "AsyncStream type requirements not met");
+ static_assert(
+ net::is_dynamic_buffer<DynamicBuffer>::value,
+ "DynamicBuffer type requirements not met");
+
+ // This class template deduces the actual handler type from a
+ // CompletionToken, captures a local reference to the handler,
+ // and creates the `async_result` object which becomes the
+ // return value of this initiating function.
+
+ net::async_completion<CompletionToken, void(beast::error_code)> init(token);
+
+ // The helper macro BOOST_ASIO_HANDLER_TYPE converts the completion
+ // token type into a concrete handler type of the correct signature.
+
+ using handler_type = BOOST_ASIO_HANDLER_TYPE(CompletionToken, void(beast::error_code));
+
+ // The class template `async_base` holds the caller's completion
+ // handler for us, and provides all of the boilerplate for forwarding
+ // the associated allocator and associated executor from the caller's
+ // handler to our operation. It also maintains a `net::executor_work_guard`
+ // for the executor associated with the stream. This work guard is
+ // inexpensive, and prevents the execution context from running out
+ // of work. It is usually necessary although rarely it can be skipped
+ // depending on the operation (this echo example needs it because it
+ // performs more than one asynchronous operation in a row).
+ // We declare this type alias to make the code easier to read.
+
+ using base_type = beast::async_base<
+ handler_type, /*< The type of the completion handler obtained from the token >*/
+ beast::executor_type<AsyncStream> /*< The type of executor used by the stream to dispatch asynchronous operations >*/
+ >;
+
+ // This nested class implements the echo composed operation as a
+ // stateful completion handler. We derive from `async_base` to
+ // take care of boilerplate and we derived from asio::coroutine to
+ // allow the reenter and yield keywords to work.
+
+ struct echo_op : base_type, boost::asio::coroutine
+ {
+ AsyncStream& stream_;
+ DynamicBuffer& buffer_;
+
+ echo_op(
+ AsyncStream& stream,
+ DynamicBuffer& buffer,
+ handler_type&& handler)
+ : base_type(
+ std::move(handler), /*< The `async_base` helper takes ownership of the handler, >*/
+ stream.get_executor()) /*< and also needs to know which executor to use. >*/
+ , stream_(stream)
+ , buffer_(buffer)
+ {
+ // Launch the operation directly from the constructor. We
+ // pass `false` for `cont` to indicate that the calling
+ // thread does not represent a continuation of our
+ // asynchronous control flow.
+ (*this)({}, 0, false);
+ }
+
+ // If a newline is present in the buffer sequence, this function returns
+ // the number of characters from the beginning of the buffer up to the
+ // newline, including the newline character. Otherwise it returns zero.
+
+ std::size_t
+ find_newline(typename DynamicBuffer::const_buffers_type const& buffers)
+ {
+ // The `buffers_iterator` class template provides random-access
+ // iterators into a buffer sequence. Use the standard algorithm
+ // to look for the new line if it exists.
+
+ auto begin = net::buffers_iterator<
+ typename DynamicBuffer::const_buffers_type>::begin(buffers);
+ auto end = net::buffers_iterator<
+ typename DynamicBuffer::const_buffers_type>::end(buffers);
+ auto result = std::find(begin, end, '\n');
+
+ if(result == end)
+ return 0; // not found
+
+ return result + 1 - begin;
+ }
+
+ // This is the entry point of our completion handler. Every time an
+ // asynchronous operation completes, this function will be invoked.
+
+ void
+ operator()(
+ beast::error_code ec,
+ std::size_t bytes_transferred = 0,
+ bool cont = true) /*< Second and subsequent invocations will seee `cont=true`. */
+ {
+ // The `reenter` keyword transfers control to the last
+ // yield point, or to the beginning of the scope if
+ // this is the first time.
+
+ reenter(*this)
+ {
+ for(;;)
+ {
+ std::size_t pos;
+
+ // Search for a newline in the readable bytes of the buffer
+ pos = find_newline(buffer_.data());
+
+ // If we don't have the newline, then read more
+ if(pos == 0)
+ {
+ std::size_t bytes_to_read;
+
+ // Determine the number of bytes to read,
+ // using available capacity in the buffer first.
+
+ bytes_to_read = std::min<std::size_t>(
+ std::max<std::size_t>(512, // under 512 is too little,
+ buffer_.capacity() - buffer_.size()),
+ std::min<std::size_t>(65536, // and over 65536 is too much.
+ buffer_.max_size() - buffer_.size()));
+
+ // Read some data into our dynamic buffer_. We transfer
+ // ownership of the composed operation by using the
+ // `std::move(*this)` idiom. The `yield` keyword causes
+ // the function to return immediately after the initiating
+ // function returns.
+
+ yield stream_.async_read_some(
+ buffer_.prepare(bytes_to_read), std::move(*this));
+
+ // After the `async_read_some` completes, control is
+ // transferred to this line by the `reenter` keyword.
+
+ // Move the bytes read from the writable area to the
+ // readable area.
+
+ buffer_.commit(bytes_transferred);
+
+ // If an error occurs, deliver it to the caller's completion handler.
+ if(ec)
+ break;
+
+ // Keep looping until we get the newline
+ continue;
+ }
+
+ // We have our newline, so send the first `pos` bytes of the
+ // buffers. The function `buffers_prefix` returns the front part
+ // of the buffers we want.
+
+ yield net::async_write(stream_,
+ beast::buffers_prefix(pos, buffer_.data()), std::move(*this));
+
+ // After the `async_write` completes, our completion handler will
+ // be invoked with the error and the number of bytes transferred,
+ // and the `reenter` statement above will cause control to jump
+ // to the following line. The variable `pos` is no longer valid
+ // (remember that we returned from the function using `yield` above)
+ // but we can use `bytes_transferred` to know how much of the buffer
+ // to consume. With "real" coroutines this will be easier and more
+ // natural.
+
+ buffer_.consume(bytes_transferred);
+
+ // The loop terminates here, and we will either deliver a
+ // successful result or an error to the caller's completion handler.
+
+ break;
+ }
+
+ // When a composed operation completes immediately, it must not
+ // directly invoke the completion handler otherwise it could
+ // lead to unfairness, starvation, or stack overflow. Therefore,
+ // if cont == false (meaning, that the call stack still includes
+ // the frame of the initiating function) then we need to use
+ // `net::post` to cause us to be called again after the initiating
+ // function. The function `async_base::invoke` takes care of
+ // calling the final completion handler, using post if the
+ // first argument is false, otherwise invoking it directly.
+
+ this->complete(cont, ec);
+ }
+ }
+ };
+
+ // Create the composed operation and launch it. This is a constructor
+ // call followed by invocation of operator(). We use BOOST_ASIO_HANDLER_TYPE
+ // to convert the completion token into the correct handler type,
+ // allowing user-defined specializations of the async_result template
+ // to be used.
+
+ echo_op(stream, buffer, std::move(init.completion_handler));
+
+ // This hook lets the caller see a return value when appropriate.
+ // For example this might return std::future<error_code> if
+ // CompletionToken is net::use_future, or this might
+ // return an error code if CompletionToken specifies a coroutine.
+
+ return init.result.get();
+}
+
+// Including this file undefines the macros used by the stackless fauxroutines.
+#include <boost/asio/unyield.hpp>
+
+//]
+
+struct move_only_handler
+{
+ move_only_handler() = default;
+ move_only_handler(move_only_handler&&) = default;
+ move_only_handler(move_only_handler const&) = delete;
+
+ void operator()(beast::error_code ec)
+ {
+ if(ec)
+ std::cerr << ": " << ec.message() << std::endl;
+ }
+};
+
+int main(int argc, char** argv)
+{
+ if(argc != 3)
+ {
+ std::cerr
+ << "Usage: echo-op <address> <port>\n"
+ << "Example:\n"
+ << " echo-op 0.0.0.0 8080\n";
+ return EXIT_FAILURE;
+ }
+
+ namespace net = boost::asio;
+ auto const address{net::ip::make_address(argv[1])};
+ auto const port{static_cast<unsigned short>(std::atoi(argv[2]))};
+
+ using endpoint_type = net::ip::tcp::endpoint;
+
+ // Create a listening socket, accept a connection, perform
+ // the echo, and then shut everything down and exit.
+ net::io_context ioc;
+ net::ip::tcp::acceptor acceptor{ioc};
+ endpoint_type ep{address, port};
+ acceptor.open(ep.protocol());
+ acceptor.set_option(net::socket_base::reuse_address(true));
+ acceptor.bind(ep);
+ acceptor.listen();
+ auto sock = acceptor.accept();
+ beast::flat_buffer buffer;
+ async_echo(sock, buffer, move_only_handler{});
+ ioc.run();
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/http/CMakeLists.txt b/src/boost/libs/beast/example/http/CMakeLists.txt
new file mode 100644
index 000000000..d38604dd0
--- /dev/null
+++ b/src/boost/libs/beast/example/http/CMakeLists.txt
@@ -0,0 +1,11 @@
+#
+# Copyright (c) 2013-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
+#
+
+add_subdirectory (client)
+add_subdirectory (server)
diff --git a/src/boost/libs/beast/example/http/Jamfile b/src/boost/libs/beast/example/http/Jamfile
new file mode 100644
index 000000000..32f2c5144
--- /dev/null
+++ b/src/boost/libs/beast/example/http/Jamfile
@@ -0,0 +1,11 @@
+#
+# Copyright (c) 2013-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
+#
+
+build-project client ;
+build-project server ;
diff --git a/src/boost/libs/beast/example/http/client/CMakeLists.txt b/src/boost/libs/beast/example/http/client/CMakeLists.txt
new file mode 100644
index 000000000..0c9d18156
--- /dev/null
+++ b/src/boost/libs/beast/example/http/client/CMakeLists.txt
@@ -0,0 +1,20 @@
+#
+# Copyright (c) 2013-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
+#
+
+add_subdirectory (async)
+add_subdirectory (coro)
+add_subdirectory (crawl)
+add_subdirectory (sync)
+
+if (OPENSSL_FOUND)
+ add_subdirectory (async-ssl)
+ add_subdirectory (async-ssl-system-executor)
+ add_subdirectory (coro-ssl)
+ add_subdirectory (sync-ssl)
+endif()
diff --git a/src/boost/libs/beast/example/http/client/Jamfile b/src/boost/libs/beast/example/http/client/Jamfile
new file mode 100644
index 000000000..11dd77ee5
--- /dev/null
+++ b/src/boost/libs/beast/example/http/client/Jamfile
@@ -0,0 +1,18 @@
+#
+# Copyright (c) 2013-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
+#
+
+build-project async ;
+build-project coro ;
+build-project crawl ;
+build-project sync ;
+
+# SSL
+build-project async-ssl ;
+build-project coro-ssl ;
+build-project sync-ssl ;
diff --git a/src/boost/libs/beast/example/http/client/async-ssl-system-executor/CMakeLists.txt b/src/boost/libs/beast/example/http/client/async-ssl-system-executor/CMakeLists.txt
new file mode 100644
index 000000000..049a2fea9
--- /dev/null
+++ b/src/boost/libs/beast/example/http/client/async-ssl-system-executor/CMakeLists.txt
@@ -0,0 +1,31 @@
+#
+# 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
+#
+
+if (OPENSSL_FOUND)
+ GroupSources(include/boost/beast beast)
+ GroupSources(example/common common)
+ GroupSources(example/http/client/async-ssl-system-executor "/")
+
+ add_executable (http-client-async-ssl-system-executor
+ ${BOOST_BEAST_FILES}
+ ${PROJECT_SOURCE_DIR}/example/common/root_certificates.hpp
+ Jamfile
+ http_client_async_ssl_system_executor.cpp
+ )
+
+ set_property(TARGET http-client-async-ssl-system-executor PROPERTY FOLDER "example-http-client")
+
+ target_link_libraries (http-client-async-ssl-system-executor
+ OpenSSL::SSL OpenSSL::Crypto
+ lib-asio
+ lib-asio-ssl
+ lib-beast
+ )
+
+endif()
diff --git a/src/boost/libs/beast/example/http/client/async-ssl-system-executor/Jamfile b/src/boost/libs/beast/example/http/client/async-ssl-system-executor/Jamfile
new file mode 100644
index 000000000..732da8631
--- /dev/null
+++ b/src/boost/libs/beast/example/http/client/async-ssl-system-executor/Jamfile
@@ -0,0 +1,22 @@
+#
+# 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
+#
+
+import ac ;
+
+project
+ : requirements
+ [ ac.check-library /boost/beast//lib-asio-ssl : <library>/boost/beast//lib-asio-ssl/<link>static : <build>no ]
+ ;
+
+exe http-client-async-ssl-system-executor :
+ http_client_async_ssl_system_executor.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ ;
diff --git a/src/boost/libs/beast/example/http/client/async-ssl-system-executor/http_client_async_ssl_system_executor.cpp b/src/boost/libs/beast/example/http/client/async-ssl-system-executor/http_client_async_ssl_system_executor.cpp
new file mode 100644
index 000000000..19ca0be69
--- /dev/null
+++ b/src/boost/libs/beast/example/http/client/async-ssl-system-executor/http_client_async_ssl_system_executor.cpp
@@ -0,0 +1,246 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: HTTP SSL client, asynchronous, using system_executor
+//
+//------------------------------------------------------------------------------
+
+#include "example/common/root_certificates.hpp"
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/http.hpp>
+#include <boost/beast/ssl.hpp>
+#include <boost/beast/version.hpp>
+#include <boost/asio/strand.hpp>
+#include <boost/asio/system_executor.hpp>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <string>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+//------------------------------------------------------------------------------
+
+// Report a failure
+void
+fail(beast::error_code ec, char const* what)
+{
+ std::cerr << what << ": " << ec.message() << "\n";
+}
+
+// Performs an HTTP GET and prints the response
+class session : public std::enable_shared_from_this<session>
+{
+ tcp::resolver resolver_;
+ beast::ssl_stream<beast::tcp_stream> stream_;
+ beast::flat_buffer buffer_; // (Must persist between reads)
+ http::request<http::empty_body> req_;
+ http::response<http::string_body> res_;
+
+ // Objects are constructed with a strand to
+ // ensure that handlers do not execute concurrently.
+ session(net::strand<net::system_executor> strand, ssl::context& ctx)
+ : resolver_(strand)
+ , stream_(strand, ctx)
+ {
+ }
+
+public:
+ // Delegate construction to a prive constructor to be able to use
+ // the same strand for both I/O object.
+ explicit
+ session(ssl::context& ctx)
+ : session(net::make_strand(net::system_executor()), ctx)
+ {
+ }
+
+ // Start the asynchronous operation
+ void
+ run(
+ char const* host,
+ char const* port,
+ char const* target,
+ int version)
+ {
+ // Set SNI Hostname (many hosts need this to handshake successfully)
+ if(! SSL_set_tlsext_host_name(stream_.native_handle(), host))
+ {
+ beast::error_code ec{static_cast<int>(::ERR_get_error()), net::error::get_ssl_category()};
+ std::cerr << ec.message() << "\n";
+ return;
+ }
+
+ // Set up an HTTP GET request message
+ req_.version(version);
+ req_.method(http::verb::get);
+ req_.target(target);
+ req_.set(http::field::host, host);
+ req_.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
+
+ // Look up the domain name
+ resolver_.async_resolve(
+ host,
+ port,
+ beast::bind_front_handler(
+ &session::on_resolve,
+ shared_from_this()));
+ }
+
+ void
+ on_resolve(
+ beast::error_code ec,
+ tcp::resolver::results_type results)
+ {
+ if(ec)
+ return fail(ec, "resolve");
+
+ // Set a timeout on the operation
+ beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30));
+
+ // Make the connection on the IP address we get from a lookup
+ beast::get_lowest_layer(stream_).async_connect(
+ results,
+ beast::bind_front_handler(
+ &session::on_connect,
+ shared_from_this()));
+ }
+
+ void
+ on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type)
+ {
+ if(ec)
+ return fail(ec, "connect");
+
+ // Perform the SSL handshake
+ stream_.async_handshake(
+ ssl::stream_base::client,
+ beast::bind_front_handler(
+ &session::on_handshake,
+ shared_from_this()));
+ }
+
+ void
+ on_handshake(beast::error_code ec)
+ {
+ if(ec)
+ return fail(ec, "handshake");
+
+ // Set a timeout on the operation
+ beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30));
+
+ // Send the HTTP request to the remote host
+ http::async_write(stream_, req_,
+ beast::bind_front_handler(
+ &session::on_write,
+ shared_from_this()));
+ }
+
+ void
+ on_write(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ if(ec)
+ return fail(ec, "write");
+
+ // Receive the HTTP response
+ http::async_read(stream_, buffer_, res_,
+ beast::bind_front_handler(
+ &session::on_read,
+ shared_from_this()));
+ }
+
+ void
+ on_read(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ if(ec)
+ return fail(ec, "read");
+
+ // Write the message to standard out
+ std::cout << res_ << std::endl;
+
+ // Set a timeout on the operation
+ beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30));
+
+ // Gracefully close the stream
+ stream_.async_shutdown(
+ beast::bind_front_handler(
+ &session::on_shutdown,
+ shared_from_this()));
+ }
+
+ void
+ on_shutdown(beast::error_code ec)
+ {
+ if(ec == net::error::eof)
+ {
+ // Rationale:
+ // http://stackoverflow.com/questions/25587403/boost-asio-ssl-async-shutdown-always-finishes-with-an-error
+ ec = {};
+ }
+ if(ec)
+ return fail(ec, "shutdown");
+
+ // If we get here then the connection is closed gracefully
+ }
+};
+
+//------------------------------------------------------------------------------
+
+int main(int argc, char** argv)
+{
+ // Check command line arguments.
+ if(argc != 4 && argc != 5)
+ {
+ std::cerr <<
+ "Usage: http-client-async-ssl-system-executor <host> <port> <target> [<HTTP version: 1.0 or 1.1(default)>]\n" <<
+ "Example:\n" <<
+ " http-client-async-ssl-system-executor www.example.com 443 /\n" <<
+ " http-client-async-ssl-system-executor www.example.com 443 / 1.0\n";
+ return EXIT_FAILURE;
+ }
+ auto const host = argv[1];
+ auto const port = argv[2];
+ auto const target = argv[3];
+ int version = argc == 5 && !std::strcmp("1.0", argv[4]) ? 10 : 11;
+
+ // The SSL context is required, and holds certificates
+ ssl::context ctx{ssl::context::tlsv12_client};
+
+ // This holds the root certificate used for verification
+ load_root_certificates(ctx);
+
+ // Verify the remote server's certificate
+ ctx.set_verify_mode(ssl::verify_peer);
+
+ // Launch the asynchronous operation
+ std::make_shared<session>(ctx)->run(host, port, target, version);
+
+
+ // The async operations will run on the system_executor.
+ // Because the main thread has nothing to do in this example, we just wait
+ // for the system_executor to run out of work.
+ net::system_executor().context().join();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/http/client/async-ssl/CMakeLists.txt b/src/boost/libs/beast/example/http/client/async-ssl/CMakeLists.txt
new file mode 100644
index 000000000..a64fbf618
--- /dev/null
+++ b/src/boost/libs/beast/example/http/client/async-ssl/CMakeLists.txt
@@ -0,0 +1,31 @@
+#
+# 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
+#
+
+if (OPENSSL_FOUND)
+ GroupSources(include/boost/beast beast)
+ GroupSources(example/common common)
+ GroupSources(example/http/client/async-ssl "/")
+
+ add_executable (http-client-async-ssl
+ ${BOOST_BEAST_FILES}
+ ${PROJECT_SOURCE_DIR}/example/common/root_certificates.hpp
+ Jamfile
+ http_client_async_ssl.cpp
+ )
+
+ set_property(TARGET http-client-async-ssl PROPERTY FOLDER "example-http-client")
+
+ target_link_libraries (http-client-async-ssl
+ OpenSSL::SSL OpenSSL::Crypto
+ lib-asio
+ lib-asio-ssl
+ lib-beast
+ )
+
+endif()
diff --git a/src/boost/libs/beast/example/http/client/async-ssl/Jamfile b/src/boost/libs/beast/example/http/client/async-ssl/Jamfile
new file mode 100644
index 000000000..c11bcb072
--- /dev/null
+++ b/src/boost/libs/beast/example/http/client/async-ssl/Jamfile
@@ -0,0 +1,22 @@
+#
+# 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
+#
+
+import ac ;
+
+project
+ : requirements
+ [ ac.check-library /boost/beast//lib-asio-ssl : <library>/boost/beast//lib-asio-ssl/<link>static : <build>no ]
+ ;
+
+exe http-client-async-ssl :
+ http_client_async_ssl.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ ;
diff --git a/src/boost/libs/beast/example/http/client/async-ssl/http_client_async_ssl.cpp b/src/boost/libs/beast/example/http/client/async-ssl/http_client_async_ssl.cpp
new file mode 100644
index 000000000..2a5f95bd9
--- /dev/null
+++ b/src/boost/libs/beast/example/http/client/async-ssl/http_client_async_ssl.cpp
@@ -0,0 +1,244 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: HTTP SSL client, asynchronous
+//
+//------------------------------------------------------------------------------
+
+#include "example/common/root_certificates.hpp"
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/http.hpp>
+#include <boost/beast/ssl.hpp>
+#include <boost/beast/version.hpp>
+#include <boost/asio/strand.hpp>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <string>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+//------------------------------------------------------------------------------
+
+// Report a failure
+void
+fail(beast::error_code ec, char const* what)
+{
+ std::cerr << what << ": " << ec.message() << "\n";
+}
+
+// Performs an HTTP GET and prints the response
+class session : public std::enable_shared_from_this<session>
+{
+ tcp::resolver resolver_;
+ beast::ssl_stream<beast::tcp_stream> stream_;
+ beast::flat_buffer buffer_; // (Must persist between reads)
+ http::request<http::empty_body> req_;
+ http::response<http::string_body> res_;
+
+public:
+ explicit
+ session(
+ net::executor ex,
+ ssl::context& ctx)
+ : resolver_(ex)
+ , stream_(ex, ctx)
+ {
+ }
+
+ // Start the asynchronous operation
+ void
+ run(
+ char const* host,
+ char const* port,
+ char const* target,
+ int version)
+ {
+ // Set SNI Hostname (many hosts need this to handshake successfully)
+ if(! SSL_set_tlsext_host_name(stream_.native_handle(), host))
+ {
+ beast::error_code ec{static_cast<int>(::ERR_get_error()), net::error::get_ssl_category()};
+ std::cerr << ec.message() << "\n";
+ return;
+ }
+
+ // Set up an HTTP GET request message
+ req_.version(version);
+ req_.method(http::verb::get);
+ req_.target(target);
+ req_.set(http::field::host, host);
+ req_.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
+
+ // Look up the domain name
+ resolver_.async_resolve(
+ host,
+ port,
+ beast::bind_front_handler(
+ &session::on_resolve,
+ shared_from_this()));
+ }
+
+ void
+ on_resolve(
+ beast::error_code ec,
+ tcp::resolver::results_type results)
+ {
+ if(ec)
+ return fail(ec, "resolve");
+
+ // Set a timeout on the operation
+ beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30));
+
+ // Make the connection on the IP address we get from a lookup
+ beast::get_lowest_layer(stream_).async_connect(
+ results,
+ beast::bind_front_handler(
+ &session::on_connect,
+ shared_from_this()));
+ }
+
+ void
+ on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type)
+ {
+ if(ec)
+ return fail(ec, "connect");
+
+ // Perform the SSL handshake
+ stream_.async_handshake(
+ ssl::stream_base::client,
+ beast::bind_front_handler(
+ &session::on_handshake,
+ shared_from_this()));
+ }
+
+ void
+ on_handshake(beast::error_code ec)
+ {
+ if(ec)
+ return fail(ec, "handshake");
+
+ // Set a timeout on the operation
+ beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30));
+
+ // Send the HTTP request to the remote host
+ http::async_write(stream_, req_,
+ beast::bind_front_handler(
+ &session::on_write,
+ shared_from_this()));
+ }
+
+ void
+ on_write(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ if(ec)
+ return fail(ec, "write");
+
+ // Receive the HTTP response
+ http::async_read(stream_, buffer_, res_,
+ beast::bind_front_handler(
+ &session::on_read,
+ shared_from_this()));
+ }
+
+ void
+ on_read(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ if(ec)
+ return fail(ec, "read");
+
+ // Write the message to standard out
+ std::cout << res_ << std::endl;
+
+ // Set a timeout on the operation
+ beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30));
+
+ // Gracefully close the stream
+ stream_.async_shutdown(
+ beast::bind_front_handler(
+ &session::on_shutdown,
+ shared_from_this()));
+ }
+
+ void
+ on_shutdown(beast::error_code ec)
+ {
+ if(ec == net::error::eof)
+ {
+ // Rationale:
+ // http://stackoverflow.com/questions/25587403/boost-asio-ssl-async-shutdown-always-finishes-with-an-error
+ ec = {};
+ }
+ if(ec)
+ return fail(ec, "shutdown");
+
+ // If we get here then the connection is closed gracefully
+ }
+};
+
+//------------------------------------------------------------------------------
+
+int main(int argc, char** argv)
+{
+ // Check command line arguments.
+ if(argc != 4 && argc != 5)
+ {
+ std::cerr <<
+ "Usage: http-client-async-ssl <host> <port> <target> [<HTTP version: 1.0 or 1.1(default)>]\n" <<
+ "Example:\n" <<
+ " http-client-async-ssl www.example.com 443 /\n" <<
+ " http-client-async-ssl www.example.com 443 / 1.0\n";
+ return EXIT_FAILURE;
+ }
+ auto const host = argv[1];
+ auto const port = argv[2];
+ auto const target = argv[3];
+ int version = argc == 5 && !std::strcmp("1.0", argv[4]) ? 10 : 11;
+
+ // The io_context is required for all I/O
+ net::io_context ioc;
+
+ // The SSL context is required, and holds certificates
+ ssl::context ctx{ssl::context::tlsv12_client};
+
+ // This holds the root certificate used for verification
+ load_root_certificates(ctx);
+
+ // Verify the remote server's certificate
+ ctx.set_verify_mode(ssl::verify_peer);
+
+ // Launch the asynchronous operation
+ // The session is constructed with a strand to
+ // ensure that handlers do not execute concurrently.
+ std::make_shared<session>(
+ net::make_strand(ioc),
+ ctx
+ )->run(host, port, target, version);
+
+ // Run the I/O service. The call will return when
+ // the get operation is complete.
+ ioc.run();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/http/client/async/CMakeLists.txt b/src/boost/libs/beast/example/http/client/async/CMakeLists.txt
new file mode 100644
index 000000000..3847ce610
--- /dev/null
+++ b/src/boost/libs/beast/example/http/client/async/CMakeLists.txt
@@ -0,0 +1,23 @@
+#
+# 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
+#
+
+GroupSources(include/boost/beast beast)
+GroupSources(example/http/client/async "/")
+
+add_executable (http-client-async
+ ${BOOST_BEAST_FILES}
+ Jamfile
+ http_client_async.cpp
+)
+
+target_link_libraries(http-client-async
+ lib-asio
+ lib-beast)
+
+set_property(TARGET http-client-async PROPERTY FOLDER "example-http-client")
diff --git a/src/boost/libs/beast/example/http/client/async/Jamfile b/src/boost/libs/beast/example/http/client/async/Jamfile
new file mode 100644
index 000000000..abc9d4d61
--- /dev/null
+++ b/src/boost/libs/beast/example/http/client/async/Jamfile
@@ -0,0 +1,15 @@
+#
+# 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
+#
+
+exe http-client-async :
+ http_client_async.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ ;
diff --git a/src/boost/libs/beast/example/http/client/async/http_client_async.cpp b/src/boost/libs/beast/example/http/client/async/http_client_async.cpp
new file mode 100644
index 000000000..f451df51c
--- /dev/null
+++ b/src/boost/libs/beast/example/http/client/async/http_client_async.cpp
@@ -0,0 +1,189 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: HTTP client, asynchronous
+//
+//------------------------------------------------------------------------------
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/http.hpp>
+#include <boost/beast/version.hpp>
+#include <boost/asio/strand.hpp>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <string>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+//------------------------------------------------------------------------------
+
+// Report a failure
+void
+fail(beast::error_code ec, char const* what)
+{
+ std::cerr << what << ": " << ec.message() << "\n";
+}
+
+// Performs an HTTP GET and prints the response
+class session : public std::enable_shared_from_this<session>
+{
+ tcp::resolver resolver_;
+ beast::tcp_stream stream_;
+ beast::flat_buffer buffer_; // (Must persist between reads)
+ http::request<http::empty_body> req_;
+ http::response<http::string_body> res_;
+
+public:
+ // Objects are constructed with a strand to
+ // ensure that handlers do not execute concurrently.
+ explicit
+ session(net::io_context& ioc)
+ : resolver_(net::make_strand(ioc))
+ , stream_(net::make_strand(ioc))
+ {
+ }
+
+ // Start the asynchronous operation
+ void
+ run(
+ char const* host,
+ char const* port,
+ char const* target,
+ int version)
+ {
+ // Set up an HTTP GET request message
+ req_.version(version);
+ req_.method(http::verb::get);
+ req_.target(target);
+ req_.set(http::field::host, host);
+ req_.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
+
+ // Look up the domain name
+ resolver_.async_resolve(
+ host,
+ port,
+ beast::bind_front_handler(
+ &session::on_resolve,
+ shared_from_this()));
+ }
+
+ void
+ on_resolve(
+ beast::error_code ec,
+ tcp::resolver::results_type results)
+ {
+ if(ec)
+ return fail(ec, "resolve");
+
+ // Set a timeout on the operation
+ stream_.expires_after(std::chrono::seconds(30));
+
+ // Make the connection on the IP address we get from a lookup
+ stream_.async_connect(
+ results,
+ beast::bind_front_handler(
+ &session::on_connect,
+ shared_from_this()));
+ }
+
+ void
+ on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type)
+ {
+ if(ec)
+ return fail(ec, "connect");
+
+ // Set a timeout on the operation
+ stream_.expires_after(std::chrono::seconds(30));
+
+ // Send the HTTP request to the remote host
+ http::async_write(stream_, req_,
+ beast::bind_front_handler(
+ &session::on_write,
+ shared_from_this()));
+ }
+
+ void
+ on_write(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ if(ec)
+ return fail(ec, "write");
+
+ // Receive the HTTP response
+ http::async_read(stream_, buffer_, res_,
+ beast::bind_front_handler(
+ &session::on_read,
+ shared_from_this()));
+ }
+
+ void
+ on_read(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ if(ec)
+ return fail(ec, "read");
+
+ // Write the message to standard out
+ std::cout << res_ << std::endl;
+
+ // Gracefully close the socket
+ stream_.socket().shutdown(tcp::socket::shutdown_both, ec);
+
+ // not_connected happens sometimes so don't bother reporting it.
+ if(ec && ec != beast::errc::not_connected)
+ return fail(ec, "shutdown");
+
+ // If we get here then the connection is closed gracefully
+ }
+};
+
+//------------------------------------------------------------------------------
+
+int main(int argc, char** argv)
+{
+ // Check command line arguments.
+ if(argc != 4 && argc != 5)
+ {
+ std::cerr <<
+ "Usage: http-client-async <host> <port> <target> [<HTTP version: 1.0 or 1.1(default)>]\n" <<
+ "Example:\n" <<
+ " http-client-async www.example.com 80 /\n" <<
+ " http-client-async www.example.com 80 / 1.0\n";
+ return EXIT_FAILURE;
+ }
+ auto const host = argv[1];
+ auto const port = argv[2];
+ auto const target = argv[3];
+ int version = argc == 5 && !std::strcmp("1.0", argv[4]) ? 10 : 11;
+
+ // The io_context is required for all I/O
+ net::io_context ioc;
+
+ // Launch the asynchronous operation
+ std::make_shared<session>(ioc)->run(host, port, target, version);
+
+ // Run the I/O service. The call will return when
+ // the get operation is complete.
+ ioc.run();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/http/client/coro-ssl/CMakeLists.txt b/src/boost/libs/beast/example/http/client/coro-ssl/CMakeLists.txt
new file mode 100644
index 000000000..54fe3ae25
--- /dev/null
+++ b/src/boost/libs/beast/example/http/client/coro-ssl/CMakeLists.txt
@@ -0,0 +1,31 @@
+#
+# 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
+#
+
+if (OPENSSL_FOUND)
+ GroupSources(include/boost/beast beast)
+ GroupSources(example/common common)
+ GroupSources(example/http/client/coro-ssl "/")
+
+ add_executable (http-client-coro-ssl
+ ${BOOST_BEAST_FILES}
+ ${PROJECT_SOURCE_DIR}/example/common/root_certificates.hpp
+ Jamfile
+ http_client_coro_ssl.cpp
+ )
+
+ set_property(TARGET http-client-coro-ssl PROPERTY FOLDER "example-http-client")
+
+ target_link_libraries (http-client-coro-ssl
+ OpenSSL::SSL OpenSSL::Crypto
+ lib-asio
+ lib-asio-ssl
+ lib-beast
+ )
+
+endif()
diff --git a/src/boost/libs/beast/example/http/client/coro-ssl/Jamfile b/src/boost/libs/beast/example/http/client/coro-ssl/Jamfile
new file mode 100644
index 000000000..f2c126c59
--- /dev/null
+++ b/src/boost/libs/beast/example/http/client/coro-ssl/Jamfile
@@ -0,0 +1,23 @@
+#
+# 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
+#
+
+import ac ;
+
+project
+ : requirements
+ [ ac.check-library /boost/beast//lib-asio-ssl : <library>/boost/beast//lib-asio-ssl/<link>static : <build>no ]
+ ;
+
+exe http-client-coro-ssl :
+ http_client_coro_ssl.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ <library>/boost/coroutine//boost_coroutine
+ ;
diff --git a/src/boost/libs/beast/example/http/client/coro-ssl/http_client_coro_ssl.cpp b/src/boost/libs/beast/example/http/client/coro-ssl/http_client_coro_ssl.cpp
new file mode 100644
index 000000000..8454db908
--- /dev/null
+++ b/src/boost/libs/beast/example/http/client/coro-ssl/http_client_coro_ssl.cpp
@@ -0,0 +1,180 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: HTTP SSL client, coroutine
+//
+//------------------------------------------------------------------------------
+
+#include "example/common/root_certificates.hpp"
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/http.hpp>
+#include <boost/beast/ssl.hpp>
+#include <boost/beast/version.hpp>
+#include <boost/asio/spawn.hpp>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <string>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+//------------------------------------------------------------------------------
+
+// Report a failure
+void
+fail(beast::error_code ec, char const* what)
+{
+ std::cerr << what << ": " << ec.message() << "\n";
+}
+
+// Performs an HTTP GET and prints the response
+void
+do_session(
+ std::string const& host,
+ std::string const& port,
+ std::string const& target,
+ int version,
+ net::io_context& ioc,
+ ssl::context& ctx,
+ net::yield_context yield)
+{
+ beast::error_code ec;
+
+ // These objects perform our I/O
+ tcp::resolver resolver(ioc);
+ beast::ssl_stream<beast::tcp_stream> stream(ioc, ctx);
+
+ // Set SNI Hostname (many hosts need this to handshake successfully)
+ if(! SSL_set_tlsext_host_name(stream.native_handle(), host.c_str()))
+ {
+ ec.assign(static_cast<int>(::ERR_get_error()), net::error::get_ssl_category());
+ std::cerr << ec.message() << "\n";
+ return;
+ }
+
+ // Look up the domain name
+ auto const results = resolver.async_resolve(host, port, yield[ec]);
+ if(ec)
+ return fail(ec, "resolve");
+
+ // Set the timeout.
+ beast::get_lowest_layer(stream).expires_after(std::chrono::seconds(30));
+
+ // Make the connection on the IP address we get from a lookup
+ get_lowest_layer(stream).async_connect(results, yield[ec]);
+ if(ec)
+ return fail(ec, "connect");
+
+ // Set the timeout.
+ beast::get_lowest_layer(stream).expires_after(std::chrono::seconds(30));
+
+ // Perform the SSL handshake
+ stream.async_handshake(ssl::stream_base::client, yield[ec]);
+ if(ec)
+ return fail(ec, "handshake");
+
+ // Set up an HTTP GET request message
+ http::request<http::string_body> req{http::verb::get, target, version};
+ req.set(http::field::host, host);
+ req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
+
+ // Set the timeout.
+ beast::get_lowest_layer(stream).expires_after(std::chrono::seconds(30));
+
+ // Send the HTTP request to the remote host
+ http::async_write(stream, req, yield[ec]);
+ if(ec)
+ return fail(ec, "write");
+
+ // This buffer is used for reading and must be persisted
+ beast::flat_buffer b;
+
+ // Declare a container to hold the response
+ http::response<http::dynamic_body> res;
+
+ // Receive the HTTP response
+ http::async_read(stream, b, res, yield[ec]);
+ if(ec)
+ return fail(ec, "read");
+
+ // Write the message to standard out
+ std::cout << res << std::endl;
+
+ // Set the timeout.
+ beast::get_lowest_layer(stream).expires_after(std::chrono::seconds(30));
+
+ // Gracefully close the stream
+ stream.async_shutdown(yield[ec]);
+ if(ec == net::error::eof)
+ {
+ // Rationale:
+ // http://stackoverflow.com/questions/25587403/boost-asio-ssl-async-shutdown-always-finishes-with-an-error
+ ec = {};
+ }
+ if(ec)
+ return fail(ec, "shutdown");
+
+ // If we get here then the connection is closed gracefully
+}
+
+//------------------------------------------------------------------------------
+
+int main(int argc, char** argv)
+{
+ // Check command line arguments.
+ if(argc != 4 && argc != 5)
+ {
+ std::cerr <<
+ "Usage: http-client-coro-ssl <host> <port> <target> [<HTTP version: 1.0 or 1.1(default)>]\n" <<
+ "Example:\n" <<
+ " http-client-coro-ssl www.example.com 443 /\n" <<
+ " http-client-coro-ssl www.example.com 443 / 1.0\n";
+ return EXIT_FAILURE;
+ }
+ auto const host = argv[1];
+ auto const port = argv[2];
+ auto const target = argv[3];
+ int version = argc == 5 && !std::strcmp("1.0", argv[4]) ? 10 : 11;
+
+ // The io_context is required for all I/O
+ net::io_context ioc;
+
+ // The SSL context is required, and holds certificates
+ ssl::context ctx{ssl::context::tlsv12_client};
+
+ // This holds the root certificate used for verification
+ load_root_certificates(ctx);
+
+ // Verify the remote server's certificate
+ ctx.set_verify_mode(ssl::verify_peer);
+
+ // Launch the asynchronous operation
+ boost::asio::spawn(ioc, std::bind(
+ &do_session,
+ std::string(host),
+ std::string(port),
+ std::string(target),
+ version,
+ std::ref(ioc),
+ std::ref(ctx),
+ std::placeholders::_1));
+
+ // Run the I/O service. The call will return when
+ // the get operation is complete.
+ ioc.run();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/http/client/coro/CMakeLists.txt b/src/boost/libs/beast/example/http/client/coro/CMakeLists.txt
new file mode 100644
index 000000000..1a791ab1b
--- /dev/null
+++ b/src/boost/libs/beast/example/http/client/coro/CMakeLists.txt
@@ -0,0 +1,23 @@
+#
+# 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
+#
+
+GroupSources(include/boost/beast beast)
+GroupSources(example/http/client/coro "/")
+
+add_executable (http-client-coro
+ ${BOOST_BEAST_FILES}
+ Jamfile
+ http_client_coro.cpp
+ )
+
+target_link_libraries(http-client-coro
+ lib-asio
+ lib-beast)
+
+set_property(TARGET http-client-coro PROPERTY FOLDER "example-http-client")
diff --git a/src/boost/libs/beast/example/http/client/coro/Jamfile b/src/boost/libs/beast/example/http/client/coro/Jamfile
new file mode 100644
index 000000000..25ebe2fda
--- /dev/null
+++ b/src/boost/libs/beast/example/http/client/coro/Jamfile
@@ -0,0 +1,16 @@
+#
+# 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
+#
+
+exe http-client-coro :
+ http_client_coro.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ <library>/boost/coroutine//boost_coroutine
+ ;
diff --git a/src/boost/libs/beast/example/http/client/coro/http_client_coro.cpp b/src/boost/libs/beast/example/http/client/coro/http_client_coro.cpp
new file mode 100644
index 000000000..274ec05e0
--- /dev/null
+++ b/src/boost/libs/beast/example/http/client/coro/http_client_coro.cpp
@@ -0,0 +1,144 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: HTTP client, coroutine
+//
+//------------------------------------------------------------------------------
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/http.hpp>
+#include <boost/beast/version.hpp>
+#include <boost/asio/spawn.hpp>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <string>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+//------------------------------------------------------------------------------
+
+// Report a failure
+void
+fail(beast::error_code ec, char const* what)
+{
+ std::cerr << what << ": " << ec.message() << "\n";
+}
+
+// Performs an HTTP GET and prints the response
+void
+do_session(
+ std::string const& host,
+ std::string const& port,
+ std::string const& target,
+ int version,
+ net::io_context& ioc,
+ net::yield_context yield)
+{
+ beast::error_code ec;
+
+ // These objects perform our I/O
+ tcp::resolver resolver(ioc);
+ beast::tcp_stream stream(ioc);
+
+ // Look up the domain name
+ auto const results = resolver.async_resolve(host, port, yield[ec]);
+ if(ec)
+ return fail(ec, "resolve");
+
+ // Set the timeout.
+ stream.expires_after(std::chrono::seconds(30));
+
+ // Make the connection on the IP address we get from a lookup
+ stream.async_connect(results, yield[ec]);
+ if(ec)
+ return fail(ec, "connect");
+
+ // Set up an HTTP GET request message
+ http::request<http::string_body> req{http::verb::get, target, version};
+ req.set(http::field::host, host);
+ req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
+
+ // Set the timeout.
+ stream.expires_after(std::chrono::seconds(30));
+
+ // Send the HTTP request to the remote host
+ http::async_write(stream, req, yield[ec]);
+ if(ec)
+ return fail(ec, "write");
+
+ // This buffer is used for reading and must be persisted
+ beast::flat_buffer b;
+
+ // Declare a container to hold the response
+ http::response<http::dynamic_body> res;
+
+ // Receive the HTTP response
+ http::async_read(stream, b, res, yield[ec]);
+ if(ec)
+ return fail(ec, "read");
+
+ // Write the message to standard out
+ std::cout << res << std::endl;
+
+ // Gracefully close the socket
+ stream.socket().shutdown(tcp::socket::shutdown_both, ec);
+
+ // not_connected happens sometimes
+ // so don't bother reporting it.
+ //
+ if(ec && ec != beast::errc::not_connected)
+ return fail(ec, "shutdown");
+
+ // If we get here then the connection is closed gracefully
+}
+
+//------------------------------------------------------------------------------
+
+int main(int argc, char** argv)
+{
+ // Check command line arguments.
+ if(argc != 4 && argc != 5)
+ {
+ std::cerr <<
+ "Usage: http-client-coro <host> <port> <target> [<HTTP version: 1.0 or 1.1(default)>]\n" <<
+ "Example:\n" <<
+ " http-client-coro www.example.com 80 /\n" <<
+ " http-client-coro www.example.com 80 / 1.0\n";
+ return EXIT_FAILURE;
+ }
+ auto const host = argv[1];
+ auto const port = argv[2];
+ auto const target = argv[3];
+ int version = argc == 5 && !std::strcmp("1.0", argv[4]) ? 10 : 11;
+
+ // The io_context is required for all I/O
+ net::io_context ioc;
+
+ // Launch the asynchronous operation
+ boost::asio::spawn(ioc, std::bind(
+ &do_session,
+ std::string(host),
+ std::string(port),
+ std::string(target),
+ version,
+ std::ref(ioc),
+ std::placeholders::_1));
+
+ // Run the I/O service. The call will return when
+ // the get operation is complete.
+ ioc.run();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/http/client/crawl/CMakeLists.txt b/src/boost/libs/beast/example/http/client/crawl/CMakeLists.txt
new file mode 100644
index 000000000..b502c7d70
--- /dev/null
+++ b/src/boost/libs/beast/example/http/client/crawl/CMakeLists.txt
@@ -0,0 +1,26 @@
+#
+# 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
+#
+
+GroupSources(include/boost/beast beast)
+GroupSources(example/http/client/crawl "/")
+
+add_executable (http-crawl
+ ${BOOST_BEAST_FILES}
+ Jamfile
+ urls_large_data.hpp
+ urls_large_data.cpp
+ http_crawl.cpp
+)
+
+target_link_libraries(http-crawl
+ lib-asio
+ lib-beast)
+
+set_property(TARGET http-crawl PROPERTY FOLDER "example-http-client")
+
diff --git a/src/boost/libs/beast/example/http/client/crawl/Jamfile b/src/boost/libs/beast/example/http/client/crawl/Jamfile
new file mode 100644
index 000000000..8f94c9675
--- /dev/null
+++ b/src/boost/libs/beast/example/http/client/crawl/Jamfile
@@ -0,0 +1,16 @@
+#
+# 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
+#
+
+exe http-crawl :
+ http_crawl.cpp
+ urls_large_data.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ ;
diff --git a/src/boost/libs/beast/example/http/client/crawl/http_crawl.cpp b/src/boost/libs/beast/example/http/client/crawl/http_crawl.cpp
new file mode 100644
index 000000000..c303518d0
--- /dev/null
+++ b/src/boost/libs/beast/example/http/client/crawl/http_crawl.cpp
@@ -0,0 +1,409 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: HTTP crawl (asynchronous)
+//
+//------------------------------------------------------------------------------
+
+#include "urls_large_data.hpp"
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/http.hpp>
+#include <boost/beast/version.hpp>
+#include <boost/asio/bind_executor.hpp>
+#include <boost/asio/connect.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/post.hpp>
+#include <boost/asio/strand.hpp>
+#include <atomic>
+#include <chrono>
+#include <cstdlib>
+#include <functional>
+#include <iomanip>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <thread>
+#include <vector>
+#include <map>
+
+namespace chrono = std::chrono; // from <chrono>
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+using tcp = net::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+//------------------------------------------------------------------------------
+
+// This structure aggregates statistics on all the sites
+class crawl_report
+{
+ net::io_context& ioc_;
+ net::strand<
+ net::io_context::executor_type> strand_;
+ std::atomic<std::size_t> index_;
+ std::vector<char const*> const& hosts_;
+ std::size_t count_ = 0;
+
+public:
+ crawl_report(net::io_context& ioc)
+ : ioc_(ioc)
+ , strand_(ioc_.get_executor())
+ , index_(0)
+ , hosts_(urls_large_data())
+ {
+ }
+
+ // Run an aggregation function on the strand.
+ // This allows synchronization without a mutex.
+ template<class F>
+ void
+ aggregate(F const& f)
+ {
+ net::post(
+ strand_,
+ [&, f]
+ {
+ f(*this);
+ if(count_ % 100 == 0)
+ {
+ std::cerr <<
+ "Progress: " << count_ << " of " << hosts_.size() << "\n";
+ //std::cerr << *this;
+ }
+ ++count_;
+ });
+ }
+
+ // Returns the next host to check
+ char const*
+ get_host()
+ {
+ auto const n = index_++;
+ if(n >= hosts_.size())
+ return nullptr;
+ return hosts_[n];
+ }
+
+ // Counts the number of timer failures
+ std::size_t timer_failures = 0;
+
+ // Counts the number of name resolution failures
+ std::size_t resolve_failures = 0;
+
+ // Counts the number of connection failures
+ std::size_t connect_failures = 0;
+
+ // Counts the number of write failures
+ std::size_t write_failures = 0;
+
+ // Counts the number of read failures
+ std::size_t read_failures = 0;
+
+ // Counts the number of success reads
+ std::size_t success = 0;
+
+ // Counts the number received of each status code
+ std::map<unsigned, std::size_t> status_codes;
+};
+
+std::ostream&
+operator<<(std::ostream& os, crawl_report const& report)
+{
+ // Print the report
+ os <<
+ "Crawl report\n" <<
+ " Failure counts\n" <<
+ " Timer : " << report.timer_failures << "\n" <<
+ " Resolve : " << report.resolve_failures << "\n" <<
+ " Connect : " << report.connect_failures << "\n" <<
+ " Write : " << report.write_failures << "\n" <<
+ " Read : " << report.read_failures << "\n" <<
+ " Success : " << report.success << "\n" <<
+ " Status codes\n"
+ ;
+ for(auto const& result : report.status_codes)
+ os <<
+ " " << std::setw(3) << result.first << ": " << result.second <<
+ " (" << http::obsolete_reason(static_cast<http::status>(result.first)) << ")\n";
+ os.flush();
+ return os;
+}
+
+//------------------------------------------------------------------------------
+
+// Performs HTTP GET requests and aggregates the results into a report
+class worker : public std::enable_shared_from_this<worker>
+{
+ enum
+ {
+ // Use a small timeout to keep things lively
+ timeout = 5
+ };
+
+ crawl_report& report_;
+ tcp::resolver resolver_;
+ beast::tcp_stream stream_;
+ beast::flat_buffer buffer_; // (Must persist between reads)
+ http::request<http::empty_body> req_;
+ http::response<http::string_body> res_;
+
+public:
+ worker(worker&&) = default;
+
+ // Resolver and socket require an io_context
+ worker(
+ crawl_report& report,
+ net::io_context& ioc)
+ : report_(report)
+ , resolver_(net::make_strand(ioc))
+ , stream_(net::make_strand(ioc))
+ {
+ // Set up the common fields of the request
+ req_.version(11);
+ req_.method(http::verb::get);
+ req_.target("/");
+ req_.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
+ }
+
+ // Start the asynchronous operation
+ void
+ run()
+ {
+ do_get_host();
+ }
+
+ void
+ do_get_host()
+ {
+ // Grab another host
+ auto const host = report_.get_host();
+
+ // nullptr means no more work
+ if(! host)
+ return;
+
+ // The Host HTTP field is required
+ req_.set(http::field::host, host);
+
+ // Set up an HTTP GET request message
+ // Look up the domain name
+ resolver_.async_resolve(
+ host,
+ "http",
+ beast::bind_front_handler(
+ &worker::on_resolve,
+ shared_from_this()));
+ }
+
+ void
+ on_resolve(
+ beast::error_code ec,
+ tcp::resolver::results_type results)
+ {
+ if(ec)
+ {
+ report_.aggregate(
+ [](crawl_report& rep)
+ {
+ ++rep.resolve_failures;
+ });
+ return do_get_host();
+ }
+
+ // Set a timeout on the operation
+ stream_.expires_after(std::chrono::seconds(10));
+
+ // Make the connection on the IP address we get from a lookup
+ stream_.async_connect(
+ results,
+ beast::bind_front_handler(
+ &worker::on_connect,
+ shared_from_this()));
+ }
+
+ void
+ on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type)
+ {
+ if(ec)
+ {
+ report_.aggregate(
+ [](crawl_report& rep)
+ {
+ ++rep.connect_failures;
+ });
+ return do_get_host();
+ }
+
+ // Set a timeout on the operation
+ stream_.expires_after(std::chrono::seconds(10));
+
+ // Send the HTTP request to the remote host
+ http::async_write(
+ stream_,
+ req_,
+ beast::bind_front_handler(
+ &worker::on_write,
+ shared_from_this()));
+ }
+
+ void
+ on_write(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ if(ec)
+ {
+ report_.aggregate(
+ [](crawl_report& rep)
+ {
+ ++rep.write_failures;
+ });
+ return do_get_host();
+ }
+
+ // Receive the HTTP response
+ res_ = {};
+ http::async_read(
+ stream_,
+ buffer_,
+ res_,
+ beast::bind_front_handler(
+ &worker::on_read,
+ shared_from_this()));
+ }
+
+ void
+ on_read(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ if(ec)
+ {
+ report_.aggregate(
+ [](crawl_report& rep)
+ {
+ ++rep.read_failures;
+ });
+ return do_get_host();
+ }
+
+ auto const code = res_.result_int();
+ report_.aggregate(
+ [code](crawl_report& rep)
+ {
+ ++rep.success;
+ ++rep.status_codes[code];
+ });
+
+ // Gracefully close the socket
+ stream_.socket().shutdown(tcp::socket::shutdown_both, ec);
+ stream_.close();
+
+ // If we get here then the connection is closed gracefully
+
+ do_get_host();
+ }
+};
+
+class timer
+{
+ using clock_type = chrono::system_clock;
+
+ clock_type::time_point when_;
+
+public:
+ using duration = clock_type::duration;
+
+ timer()
+ : when_(clock_type::now())
+ {
+ }
+
+ duration
+ elapsed() const
+ {
+ return clock_type::now() - when_;
+ }
+};
+
+int main(int argc, char* argv[])
+{
+ // Check command line arguments.
+ if (argc != 2)
+ {
+ std::cerr <<
+ "Usage: http-crawl <threads>\n" <<
+ "Example:\n" <<
+ " http-crawl 100 1\n";
+ return EXIT_FAILURE;
+ }
+ auto const threads = std::max<int>(1, std::atoi(argv[1]));
+
+ // The io_context is required for all I/O
+ net::io_context ioc;
+
+ // The work keeps io_context::run from returning
+ auto work = net::make_work_guard(ioc);
+
+ // The report holds the aggregated statistics
+ crawl_report report{ioc};
+
+ timer t;
+
+ // Create and launch the worker threads.
+ std::vector<std::thread> workers;
+ workers.reserve(threads + 1);
+ for(int i = 0; i < threads; ++i)
+ workers.emplace_back(
+ [&report]
+ {
+ // We use a separate io_context for each worker because
+ // the asio resolver simulates asynchronous operation using
+ // a dedicated worker thread per io_context, and we want to
+ // do a lot of name resolutions in parallel.
+ net::io_context ioc{1};
+ std::make_shared<worker>(report, ioc)->run();
+ ioc.run();
+ });
+
+ // Add another thread to run the main io_context which
+ // is used to aggregate the statistics
+ workers.emplace_back(
+ [&ioc]
+ {
+ ioc.run();
+ });
+
+ // Now block until all threads exit
+ for(std::size_t i = 0; i < workers.size(); ++i)
+ {
+ auto& thread = workers[i];
+
+ // If this is the last thread, reset the
+ // work object so that it can return from run.
+ if(i == workers.size() - 1)
+ work.reset();
+
+ // Wait for the thread to exit
+ thread.join();
+ }
+
+ std::cout <<
+ "Elapsed time: " << chrono::duration_cast<chrono::seconds>(t.elapsed()).count() << " seconds\n";
+ std::cout << report;
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/http/client/crawl/urls_large_data.cpp b/src/boost/libs/beast/example/http/client/crawl/urls_large_data.cpp
new file mode 100644
index 000000000..cee46ee26
--- /dev/null
+++ b/src/boost/libs/beast/example/http/client/crawl/urls_large_data.cpp
@@ -0,0 +1,10021 @@
+//
+// Copyright (c) 2016-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
+//
+
+#include "urls_large_data.hpp"
+
+// Data from Alexa top 1 million sites
+// http://s3.amazonaws.com/alexa-static/top-1m.csv.zip
+//
+std::vector<char const*> const&
+urls_large_data()
+{
+ static std::vector <char const*> const urls ({
+ "google.com",
+ "facebook.com",
+ "youtube.com",
+ "yahoo.com",
+ "baidu.com",
+ "wikipedia.org",
+ "qq.com",
+ "linkedin.com",
+ "taobao.com",
+ "twitter.com",
+ "live.com",
+ "amazon.com",
+ "sina.com.cn",
+ "google.co.in",
+ "hao123.com",
+ "blogspot.com",
+ "weibo.com",
+ "wordpress.com",
+ "yandex.ru",
+ "yahoo.co.jp",
+ "tmall.com",
+ "bing.com",
+ "vk.com",
+ "ebay.com",
+ "360.cn",
+ "google.de",
+ "sohu.com",
+ "pinterest.com",
+ "google.co.uk",
+ "ask.com",
+ "google.fr",
+ "msn.com",
+ "163.com",
+ "soso.com",
+ "tumblr.com",
+ "google.co.jp",
+ "instagram.com",
+ "mail.ru",
+ "google.com.br",
+ "microsoft.com",
+ "paypal.com",
+ "google.ru",
+ "xvideos.com",
+ "google.es",
+ "imdb.com",
+ "apple.com",
+ "google.it",
+ "adcash.com",
+ "craigslist.org",
+ "stackoverflow.com",
+ "amazon.co.jp",
+ "neobux.com",
+ "google.com.hk",
+ "imgur.com",
+ "ifeng.com",
+ "cnn.com",
+ "google.com.mx",
+ "xhamster.com",
+ "xinhuanet.com",
+ "gmw.cn",
+ "reddit.com",
+ "bbc.co.uk",
+ "blogger.com",
+ "google.ca",
+ "fc2.com",
+ "vube.com",
+ "go.com",
+ "akamaihd.net",
+ "alipay.com",
+ "about.com",
+ "people.com.cn",
+ "t.co",
+ "googleusercontent.com",
+ "wordpress.org",
+ "odnoklassniki.ru",
+ "alibaba.com",
+ "google.com.tr",
+ "aliexpress.com",
+ "youku.com",
+ "conduit.com",
+ "huffingtonpost.com",
+ "godaddy.com",
+ "flickr.com",
+ "pornhub.com",
+ "google.com.au",
+ "amazon.de",
+ "blogspot.in",
+ "kickass.to",
+ "ebay.de",
+ "netflix.com",
+ "google.pl",
+ "thepiratebay.se",
+ "bp.blogspot.com",
+ "adobe.com",
+ "dailymotion.com",
+ "china.com",
+ "vimeo.com",
+ "dailymail.co.uk",
+ "cnet.com",
+ "rakuten.co.jp",
+ "espn.go.com",
+ "ku6.com",
+ "ebay.co.uk",
+ "themeforest.net",
+ "xnxx.com",
+ "livejasmin.com",
+ "indiatimes.com",
+ "aol.com",
+ "redtube.com",
+ "dropbox.com",
+ "amazonaws.com",
+ "uol.com.br",
+ "weather.com",
+ "m2newmedia.com",
+ "amazon.co.uk",
+ "google.com.ar",
+ "google.com.sa",
+ "pixnet.net",
+ "nytimes.com",
+ "slideshare.net",
+ "youporn.com",
+ "google.com.eg",
+ "buzzfeed.com",
+ "wikimedia.org",
+ "booking.com",
+ "livejournal.com",
+ "globo.com",
+ "fiverr.com",
+ "adf.ly",
+ "secureserver.net",
+ "mozilla.org",
+ "google.com.pk",
+ "google.com.tw",
+ "google.nl",
+ "yelp.com",
+ "sogou.com",
+ "ameblo.jp",
+ "directrev.com",
+ "clkmon.com",
+ "hootsuite.com",
+ "deviantart.com",
+ "blogfa.com",
+ "wikia.com",
+ "outbrain.com",
+ "flipkart.com",
+ "wikihow.com",
+ "etsy.com",
+ "google.co.th",
+ "soundcloud.com",
+ "google.co.za",
+ "avg.com",
+ "w3schools.com",
+ "theguardian.com",
+ "stumbleupon.com",
+ "espncricinfo.com",
+ "livedoor.com",
+ "forbes.com",
+ "archive.org",
+ "4shared.com",
+ "foxnews.com",
+ "files.wordpress.com",
+ "answers.com",
+ "bankofamerica.com",
+ "chase.com",
+ "google.co.ve",
+ "mediafire.com",
+ "torrentz.eu",
+ "badoo.com",
+ "salesforce.com",
+ "aweber.com",
+ "sourceforge.net",
+ "bbc.com",
+ "addthis.com",
+ "liveinternet.ru",
+ "china.com.cn",
+ "indeed.com",
+ "reference.com",
+ "github.com",
+ "skype.com",
+ "hostgator.com",
+ "google.gr",
+ "bet365.com",
+ "spiegel.de",
+ "ask.fm",
+ "so.com",
+ "statcounter.com",
+ "gameforge.com",
+ "onet.pl",
+ "naver.com",
+ "google.com.co",
+ "developunit.info",
+ "google.com.vn",
+ "google.co.id",
+ "nicovideo.jp",
+ "shutterstock.com",
+ "walmart.com",
+ "google.be",
+ "mailchimp.com",
+ "softonic.com",
+ "stackexchange.com",
+ "google.com.ng",
+ "google.com.ua",
+ "popads.net",
+ "allegro.pl",
+ "gamer.com.tw",
+ "wordreference.com",
+ "wellsfargo.com",
+ "loading-delivery1.com",
+ "zillow.com",
+ "tripadvisor.com",
+ "quikr.com",
+ "pandora.com",
+ "wsj.com",
+ "goo.ne.jp",
+ "bild.de",
+ "tube8.com",
+ "wix.com",
+ "google.se",
+ "coccoc.com",
+ "google.ro",
+ "suning.com",
+ "photobucket.com",
+ "weebly.com",
+ "tianya.cn",
+ "warriorforum.com",
+ "telegraph.co.uk",
+ "google.dz",
+ "naver.jp",
+ "php.net",
+ "ups.com",
+ "rambler.ru",
+ "zedo.com",
+ "reuters.com",
+ "google.at",
+ "media.tumblr.com",
+ "taringa.net",
+ "google.com.ph",
+ "chinaz.com",
+ "mashable.com",
+ "blogspot.com.es",
+ "hurriyet.com.tr",
+ "google.com.pe",
+ "bleacherreport.com",
+ "gmx.net",
+ "wp.pl",
+ "goodreads.com",
+ "leboncoin.fr",
+ "rutracker.org",
+ "lenta.ru",
+ "babylon.com",
+ "domaintools.com",
+ "sharelive.net",
+ "rediff.com",
+ "google.ch",
+ "comcast.net",
+ "twitch.tv",
+ "avito.ru",
+ "kaskus.co.id",
+ "nbcnews.com",
+ "onclickads.net",
+ "businessinsider.com",
+ "ikea.com",
+ "codecanyon.net",
+ "ndtv.com",
+ "usps.com",
+ "google.cl",
+ "doublepimp.com",
+ "moz.com",
+ "google.com.sg",
+ "usatoday.com",
+ "dmm.co.jp",
+ "amazon.fr",
+ "google.pt",
+ "ucoz.ru",
+ "rt.com",
+ "milliyet.com.tr",
+ "xuite.net",
+ "samsung.com",
+ "fedex.com",
+ "uploaded.net",
+ "pcpop.com",
+ "google.com.bd",
+ "bitly.com",
+ "goodgamestudios.com",
+ "ettoday.net",
+ "baomihua.com",
+ "39.net",
+ "web.de",
+ "rbc.ru",
+ "9gag.com",
+ "disqus.com",
+ "snapdeal.com",
+ "xcar.com.cn",
+ "washingtonpost.com",
+ "bloomberg.com",
+ "scribd.com",
+ "hp.com",
+ "constantcontact.com",
+ "4dsply.com",
+ "gsmarena.com",
+ "intuit.com",
+ "meetup.com",
+ "nih.gov",
+ "americanexpress.com",
+ "ehow.com",
+ "infusionsoft.com",
+ "google.cz",
+ "mercadolivre.com.br",
+ "myntra.com",
+ "varzesh3.com",
+ "mobile01.com",
+ "hardsextube.com",
+ "goal.com",
+ "thefreecamsecret.com",
+ "thefreedictionary.com",
+ "douban.com",
+ "iqiyi.com",
+ "it168.com",
+ "mama.cn",
+ "tmz.com",
+ "time.com",
+ "olx.in",
+ "microsoftonline.com",
+ "hulu.com",
+ "enet.com.cn",
+ "speedtest.net",
+ "orange.fr",
+ "free.fr",
+ "detik.com",
+ "bluehost.com",
+ "libero.it",
+ "histats.com",
+ "webmd.com",
+ "eazel.com",
+ "hudong.com",
+ "extratorrent.cc",
+ "google.co.kr",
+ "chaturbate.com",
+ "huanqiu.com",
+ "cnzz.com",
+ "daum.net",
+ "xing.com",
+ "force.com",
+ "jrj.com.cn",
+ "pchome.net",
+ "cj.com",
+ "youjizz.com",
+ "delta-search.com",
+ "techcrunch.com",
+ "motherless.com",
+ "tinyurl.com",
+ "beeg.com",
+ "kooora.com",
+ "google.cn",
+ "clickbank.com",
+ "yandex.ua",
+ "ad6media.fr",
+ "google.no",
+ "amazon.cn",
+ "zippyshare.com",
+ "acesse.com",
+ "google.co.hu",
+ "google.ae",
+ "hdfcbank.com",
+ "nba.com",
+ "zendesk.com",
+ "blogspot.co.uk",
+ "bestbuy.com",
+ "accuweather.com",
+ "getresponse.com",
+ "repubblica.it",
+ "xywy.com",
+ "ci123.com",
+ "ebay.in",
+ "in.com",
+ "ign.com",
+ "groupon.com",
+ "yesky.com",
+ "elpais.com",
+ "marca.com",
+ "kwejk.pl",
+ "caijing.com.cn",
+ "google.ie",
+ "cloudfront.net",
+ "intoday.in",
+ "wideinfo.org",
+ "pof.com",
+ "kakaku.com",
+ "bitauto.com",
+ "life.com.tw",
+ "xe.com",
+ "goo.gl",
+ "google.az",
+ "feedly.com",
+ "tagged.com",
+ "amazon.in",
+ "list-manage.com",
+ "w3.org",
+ "quora.com",
+ "ixxx.com",
+ "mysearchdial.com",
+ "dell.com",
+ "seznam.cz",
+ "t-online.de",
+ "plugrush.com",
+ "nydailynews.com",
+ "okcupid.com",
+ "istockphoto.com",
+ "snapdo.com",
+ "abcnews.go.com",
+ "target.com",
+ "latimes.com",
+ "mywebsearch.com",
+ "joomla.org",
+ "odesk.com",
+ "surveymonkey.com",
+ "elmundo.es",
+ "siteadvisor.com",
+ "aili.com",
+ "uimserv.net",
+ "ebay.com.au",
+ "doubleclick.com",
+ "zeobit.com",
+ "google.co.il",
+ "fbcdn.net",
+ "ero-advertising.com",
+ "issuu.com",
+ "naukri.com",
+ "gazeta.pl",
+ "ck101.com",
+ "udn.com",
+ "google.dk",
+ "ce.cn",
+ "capitalone.com",
+ "att.com",
+ "drudgereport.com",
+ "blackhatworld.com",
+ "adrotator.se",
+ "retailmenot.com",
+ "justdial.com",
+ "icicibank.com",
+ "likes.com",
+ "elance.com",
+ "cntv.cn",
+ "ameba.jp",
+ "java.com",
+ "lifehacker.com",
+ "jabong.com",
+ "gizmodo.com",
+ "ebay.it",
+ "lenovo.com",
+ "hypergames.net",
+ "google.fi",
+ "doorblog.jp",
+ "blogspot.de",
+ "jimdo.com",
+ "probux.com",
+ "blogspot.it",
+ "habrahabr.ru",
+ "webmoney.ru",
+ "irctc.co.in",
+ "sahibinden.com",
+ "github.io",
+ "informer.com",
+ "mysearchresults.com",
+ "upworthy.com",
+ "pch.com",
+ "eyny.com",
+ "canadaalltax.com",
+ "b5m.com",
+ "freelancer.com",
+ "match.com",
+ "searchfun.in",
+ "adnxs.com",
+ "sberbank.ru",
+ "ig.com.br",
+ "trulia.com",
+ "subscene.com",
+ "corriere.it",
+ "livescore.com",
+ "irs.gov",
+ "twoo.com",
+ "clixsense.com",
+ "4399.com",
+ "xda-developers.com",
+ "iminent.com",
+ "google.com.my",
+ "onlinesbi.com",
+ "empowernetwork.com",
+ "zing.vn",
+ "youdao.com",
+ "systweak.com",
+ "flipora.com",
+ "ning.com",
+ "engadget.com",
+ "abril.com.br",
+ "exoclick.com",
+ "semrush.com",
+ "commentcamarche.net",
+ "shareasale.com",
+ "vnexpress.net",
+ "battle.net",
+ "youm7.com",
+ "digg.com",
+ "rapidgator.net",
+ "expedia.com",
+ "twimg.com",
+ "newegg.com",
+ "lady8844.com",
+ "xgo.com.cn",
+ "pcgames.com.cn",
+ "fotolia.com",
+ "rednet.cn",
+ "inspsearch.com",
+ "lemonde.fr",
+ "adultfriendfinder.com",
+ "typepad.com",
+ "mercadolibre.com.ar",
+ "homedepot.com",
+ "chip.de",
+ "lefigaro.fr",
+ "swagbucks.com",
+ "taleo.net",
+ "kinopoisk.ru",
+ "oracle.com",
+ "who.is",
+ "2ch.net",
+ "qtrax.com",
+ "eonline.com",
+ "sochi2014.com",
+ "myfreecams.com",
+ "pcbaby.com.cn",
+ "gome.com.cn",
+ "amazon.it",
+ "timeanddate.com",
+ "bestusefuldownloads.com",
+ "foursquare.com",
+ "telexfree.com",
+ "gc.ca",
+ "58.com",
+ "hubspot.com",
+ "backpage.com",
+ "examiner.com",
+ "ria.ru",
+ "google.sk",
+ "opensiteexplorer.org",
+ "awesomehp.com",
+ "sexlog.com",
+ "gutefrage.net",
+ "steampowered.com",
+ "slate.com",
+ "marketwatch.com",
+ "beva.com",
+ "shaadi.com",
+ "v1.cn",
+ "teensdigest.com",
+ "blogspot.ru",
+ "taboola.com",
+ "citrixonline.com",
+ "hatena.ne.jp",
+ "seesaa.net",
+ "houzz.com",
+ "bodybuilding.com",
+ "webs.com",
+ "chexun.com",
+ "ya.ru",
+ "citibank.com",
+ "viralnova.com",
+ "2345.com",
+ "ashleyrnadison.com",
+ "verizonwireless.com",
+ "55bbs.com",
+ "theblaze.com",
+ "123rf.com",
+ "gotomeeting.com",
+ "kijiji.ca",
+ "linkbucks.com",
+ "haber7.com",
+ "pravda.com.ua",
+ "altervista.org",
+ "mihanblog.com",
+ "terra.com.br",
+ "soku.com",
+ "urbandictionary.com",
+ "mercadolibre.com.mx",
+ "pixiv.net",
+ "oneindia.in",
+ "yellowpages.com",
+ "hotels.com",
+ "drtuber.com",
+ "scoop.it",
+ "blogspot.jp",
+ "cbslocal.com",
+ "movie4k.to",
+ "cpmterra.com",
+ "hubpages.com",
+ "mobile.de",
+ "yaolan.com",
+ "etao.com",
+ "hidemyass.com",
+ "ca.gov",
+ "dreamstime.com",
+ "firedrive.com",
+ "searchengines.ru",
+ "m-w.com",
+ "ebay.fr",
+ "templatemonster.com",
+ "evernote.com",
+ "fastdailyfind.com",
+ "amazon.es",
+ "gateable.com",
+ "hupu.com",
+ "y8.com",
+ "blogspot.com.tr",
+ "tokobagus.com",
+ "azlyrics.com",
+ "website-unavailable.com",
+ "r10.net",
+ "wiktionary.org",
+ "bongacams.com",
+ "focus.de",
+ "linksynergy.com",
+ "steamcommunity.com",
+ "vk.me",
+ "sakura.ne.jp",
+ "foxsports.com",
+ "optmd.com",
+ "tabelog.com",
+ "narod.ru",
+ "glassdoor.com",
+ "outlook.com",
+ "europa.eu",
+ "viadeo.com",
+ "leadpages.net",
+ "ouedkniss.com",
+ "facenama.com",
+ "lpcloudsvr302.com",
+ "agoda.com",
+ "qvo6.com",
+ "majesticseo.com",
+ "mirror.co.uk",
+ "google.com.kw",
+ "filehippo.com",
+ "moneycontrol.com",
+ "duckduckgo.com",
+ "npr.org",
+ "coupons.com",
+ "mynet.com",
+ "allrecipes.com",
+ "priceline.com",
+ "liveleak.com",
+ "jqw.com",
+ "slickdeals.net",
+ "webcrawler.com",
+ "babytree.com",
+ "amung.us",
+ "tomshardware.com",
+ "openadserving.com",
+ "independent.co.uk",
+ "kompas.com",
+ "turbobit.net",
+ "google.kz",
+ "leo.org",
+ "yandex.com.tr",
+ "mp3skull.com",
+ "nordstrom.com",
+ "news.com.au",
+ "traidnt.net",
+ "wunderground.com",
+ "cnbc.com",
+ "jquery.com",
+ "dict.cc",
+ "persianblog.ir",
+ "clarin.com",
+ "all-free-download.com",
+ "fhserve.com",
+ "sape.ru",
+ "asos.com",
+ "addmefast.com",
+ "lequipe.fr",
+ "lapatilla.com",
+ "ancestry.com",
+ "stockstar.com",
+ "monster.com",
+ "people.com",
+ "gawker.com",
+ "howstuffworks.com",
+ "tradedoubler.com",
+ "over-blog.com",
+ "cbc.ca",
+ "fishcod.com",
+ "yoka.com",
+ "macys.com",
+ "gazeta.ru",
+ "free-tv-video-online.me",
+ "google.bg",
+ "google.lk",
+ "southwest.com",
+ "realtor.com",
+ "custhelp.com",
+ "bhaskar.com",
+ "softpedia.com",
+ "farsnews.com",
+ "cy-pr.com",
+ "theverge.com",
+ "tudou.com",
+ "youboy.com",
+ "porn.com",
+ "wetransfer.com",
+ "virgilio.it",
+ "mega.co.nz",
+ "sfgate.com",
+ "delta-homes.com",
+ "squarespace.com",
+ "watchseries.lt",
+ "overstock.com",
+ "nifty.com",
+ "jvzoo.com",
+ "lanacion.com.ar",
+ "prntscr.com",
+ "vesti.ru",
+ "zimbio.com",
+ "adscale.de",
+ "google.co.nz",
+ "yac.mx",
+ "tickld.com",
+ "kayak.com",
+ "youth.cn",
+ "jd.com",
+ "shopclues.com",
+ "allocine.fr",
+ "cracked.com",
+ "eventbrite.com",
+ "behance.net",
+ "youtube-mp3.org",
+ "bankmellat.ir",
+ "echo.msk.ru",
+ "autohome.com.cn",
+ "yandex.kz",
+ "sex.com",
+ "smh.com.au",
+ "digikala.com",
+ "mackolik.com",
+ "rottentomatoes.com",
+ "renren.com",
+ "wired.com",
+ "imageshack.us",
+ "interia.pl",
+ "zanox.com",
+ "eastday.com",
+ "fool.com",
+ "chinabyte.com",
+ "haberturk.com",
+ "hespress.com",
+ "wow.com",
+ "jobrapido.com",
+ "idnes.cz",
+ "qinbei.com",
+ "pr-cy.ru",
+ "klikbca.com",
+ "17ok.com",
+ "gamefaqs.com",
+ "immobilienscout24.de",
+ "biblegateway.com",
+ "espnfc.com",
+ "ehowenespanol.com",
+ "tabnak.ir",
+ "avazutracking.net",
+ "sapo.pt",
+ "welt.de",
+ "google.com.ec",
+ "sears.com",
+ "pcmag.com",
+ "nownews.com",
+ "kickstarter.com",
+ "pixlr.com",
+ "hongkiat.com",
+ "chinatimes.com",
+ "zoho.com",
+ "reverso.net",
+ "indianrail.gov.in",
+ "privatehomeclips.com",
+ "cbssports.com",
+ "entrepreneur.com",
+ "sporx.com",
+ "bhphotovideo.com",
+ "fatakat.com",
+ "xunlei.com",
+ "nikkei.com",
+ "chron.com",
+ "24h.com.vn",
+ "basecamp.com",
+ "airtel.in",
+ "dealshark.com",
+ "shopify.com",
+ "babycenter.com",
+ "letitbit.net",
+ "nuvid.com",
+ "yts.re",
+ "aparat.com",
+ "r2games.com",
+ "prestashop.com",
+ "alarabiya.net",
+ "india.com",
+ "magentocommerce.com",
+ "heise.de",
+ "sulekha.com",
+ "mpnrs.com",
+ "ibm.com",
+ "cbsnews.com",
+ "searchengineland.com",
+ "mapquest.com",
+ "ccb.com",
+ "zappos.com",
+ "rightmove.co.uk",
+ "sahadan.com",
+ "milanuncios.com",
+ "wenku.baidu.com/user/reg",
+ "ovh.net",
+ "screencast.com",
+ "ahrefs.com",
+ "6.cn",
+ "businessweek.com",
+ "linternaute.com",
+ "dafont.com",
+ "bestblackhatforum.com",
+ "streamcloud.eu",
+ "as.com",
+ "gtmetrix.com",
+ "wmmail.ru",
+ "spankwire.com",
+ "google.com.do",
+ "jeuxvideo.com",
+ "digitalpoint.com",
+ "amazon.ca",
+ "mlb.com",
+ "weheartit.com",
+ "list.ru",
+ "leagueoflegends.com",
+ "56.com",
+ "bloglovin.com",
+ "payoneer.com",
+ "nokia.com",
+ "aizhan.com",
+ "novinky.cz",
+ "ustream.tv",
+ "getbootstrap.com",
+ "seekingalpha.com",
+ "codwide.com",
+ "vice.com",
+ "usmagazine.com",
+ "primewire.ag",
+ "cam4.com",
+ "thehindu.com",
+ "deezer.com",
+ "graphicriver.net",
+ "dmm.com",
+ "biglobe.ne.jp",
+ "google.rs",
+ "z5x.net",
+ "tutsplus.com",
+ "icicibank.co.in",
+ "indiamart.com",
+ "gap.com",
+ "ensonhaber.com",
+ "sitepoint.com",
+ "rutor.org",
+ "chinanews.com",
+ "brainyquote.com",
+ "keepvid.com",
+ "censor.net.ua",
+ "subito.it",
+ "tablica.pl",
+ "onlylady.com",
+ "zulily.com",
+ "squidoo.com",
+ "change.org",
+ "sh.st",
+ "webhostingtalk.com",
+ "9gag.tv",
+ "nairaland.com",
+ "gulfup.com",
+ "staples.com",
+ "gamespot.com",
+ "woorank.com",
+ "box.com",
+ "infobae.com",
+ "elegantthemes.com",
+ "104.com.tw",
+ "aftonbladet.se",
+ "google.hr",
+ "myegy.com",
+ "noticias24.com",
+ "eastmoney.com",
+ "lowes.com",
+ "xtube.com",
+ "worldstarhiphop.com",
+ "glispa.com",
+ "verizon.com",
+ "united.com",
+ "linkwithin.com",
+ "google.com.ly",
+ "whitepages.com",
+ "games.la",
+ "dmoz.org",
+ "imagebam.com",
+ "careerbuilder.com",
+ "sky.com",
+ "instructables.com",
+ "mercadolibre.com.ve",
+ "makemytrip.com",
+ "pinimg.com",
+ "pingdom.com",
+ "foodnetwork.com",
+ "orf.at",
+ "android.com",
+ "wiocha.pl",
+ "csdn.net",
+ "appledaily.com.tw",
+ "nike.com",
+ "eluniversal.com.mx",
+ "delta.com",
+ "ezinearticles.com",
+ "sueddeutsche.de",
+ "woothemes.com",
+ "comcast.com",
+ "gismeteo.ru",
+ "lotour.com",
+ "nfl.com",
+ "xbox.com",
+ "almanar.com.lb",
+ "disney.go.com",
+ "ctrip.com",
+ "forexfactory.com",
+ "clicksvenue.com",
+ "nhl.com",
+ "ted.com",
+ "gstatic.com",
+ "forobeta.com",
+ "ovh.com",
+ "mystart.com",
+ "maktoob.com",
+ "nouvelobs.com",
+ "hindustantimes.com",
+ "billdesk.com",
+ "1und1.de",
+ "zhaopin.com",
+ "weather.gov",
+ "kioskea.net",
+ "myspace.com",
+ "firstpost.com",
+ "picmonkey.com",
+ "grooveshark.com",
+ "exblog.jp",
+ "pantip.com",
+ "earthlink.net",
+ "styletv.com.cn",
+ "icloud.com",
+ "manta.com",
+ "google.by",
+ "mediaset.it",
+ "searchenginewatch.com",
+ "japanpost.jp",
+ "postimg.org",
+ "mbc.net",
+ "cheezburger.com",
+ "workercn.cn",
+ "directadvert.ru",
+ "nationzoom.com",
+ "caixa.gov.br",
+ "gumtree.com",
+ "51job.com",
+ "viooz.co",
+ "usbank.com",
+ "wmtransfer.com",
+ "fidelity.com",
+ "gogetlinks.net",
+ "office365.com",
+ "pchome.com.tw",
+ "feedburner.com",
+ "mp3truck.net",
+ "sfr.fr",
+ "junglee.com",
+ "keezmovies.com",
+ "binarysystem4u.com",
+ "way2sms.com",
+ "oyunskor.com",
+ "peyvandha.ir",
+ "ticketmaster.com",
+ "lacaixa.es",
+ "video-one.com",
+ "yomiuri.co.jp",
+ "popcash.net",
+ "nypost.com",
+ "dubizzle.com",
+ "wpmudev.org",
+ "mgid.com",
+ "google.lt",
+ "zazzle.com",
+ "nbcolympics.com",
+ "battlefield.com",
+ "avast.com",
+ "jsfiddle.net",
+ "namecheap.com",
+ "css-tricks.com",
+ "friv.com",
+ "6park.com",
+ "xhamstercams.com",
+ "mysql.com",
+ "dx.com",
+ "thechive.com",
+ "vsuch.com",
+ "souq.com",
+ "anyoption.com",
+ "dantri.com.vn",
+ "ebay.es",
+ "abc.es",
+ "whatsapp.com",
+ "bitshare.com",
+ "savefrom.net",
+ "beytoote.com",
+ "xiaomi.com",
+ "prweb.com",
+ "prothom-alo.com",
+ "pagesjaunes.fr",
+ "bbb.org",
+ "eenadu.net",
+ "tinypic.com",
+ "whois.com",
+ "sourtimes.org",
+ "adk2.com",
+ "criteo.com",
+ "tistory.com",
+ "ilyke.net",
+ "ruten.com.tw",
+ "skysports.com",
+ "makeuseof.com",
+ "p5w.net",
+ "hh.ru",
+ "nationalgeographic.com",
+ "pornmd.com",
+ "rakuten.ne.jp",
+ "idealo.de",
+ "telegraaf.nl",
+ "barnesandnoble.com",
+ "mynavi.jp",
+ "4chan.org",
+ "media-fire.org",
+ "crunchbase.com",
+ "bravotube.net",
+ "myfitnesspal.com",
+ "today.com",
+ "mit.edu",
+ "cnmo.com",
+ "nu.nl",
+ "tripadvisor.co.uk",
+ "spotify.com",
+ "homeway.com.cn",
+ "dianping.com",
+ "costco.com",
+ "pastebin.com",
+ "dhgate.com",
+ "windowsphone.com",
+ "stagram.com",
+ "investopedia.com",
+ "ninemsn.com.au",
+ "excite.co.jp",
+ "22find.com",
+ "google.iq",
+ "hi5.com",
+ "ad4game.com",
+ "kohls.com",
+ "online.sh.cn",
+ "geocities.jp",
+ "investing.com",
+ "haberler.com",
+ "ft.com",
+ "weblio.jp",
+ "google.tn",
+ "list-manage1.com",
+ "hsbc.co.uk",
+ "ppstream.com",
+ "cloob.com",
+ "korrespondent.net",
+ "ucoz.com",
+ "1and1.com",
+ "mail.com",
+ "fotostrana.ru",
+ "accountonline.com",
+ "forgeofempires.com",
+ "dribbble.com",
+ "city-data.com",
+ "drupal.org",
+ "tunein.com",
+ "51fanli.com",
+ "ibtimes.com",
+ "intel.com",
+ "polyvore.com",
+ "cbs.com",
+ "bab.la",
+ "imobile.com.cn",
+ "bestadbid.com",
+ "eztv.it",
+ "smashingmagazine.com",
+ "skyrock.com",
+ "copyscape.com",
+ "cookpad.com",
+ "smallseotools.com",
+ "asus.com",
+ "anysex.com",
+ "nbcsports.com",
+ "kinox.to",
+ "mbank.com.pl",
+ "500px.com",
+ "sofanti.com",
+ "marktplaats.nl",
+ "cpanel.net",
+ "hm.com",
+ "chicagotribune.com",
+ "ultimate-guitar.com",
+ "infolinks.com",
+ "merdeka.com",
+ "yandex.by",
+ "tribalfusion.com",
+ "livedoor.biz",
+ "prezi.com",
+ "last.fm",
+ "sznews.com",
+ "junbi-tracker.com",
+ "so-net.ne.jp",
+ "cocolog-nifty.com",
+ "ocn.ne.jp",
+ "perezhilton.com",
+ "yaplakal.com",
+ "championat.com",
+ "ebay.ca",
+ "mangareader.net",
+ "donanimhaber.com",
+ "miniclip.com",
+ "vcommission.com",
+ "noaa.gov",
+ "imagefap.com",
+ "gumtree.com.au",
+ "liveperson.net",
+ "gfycat.com",
+ "hollywoodreporter.com",
+ "dropboxusercontent.com",
+ "akhbarak.net",
+ "sou300.com",
+ "kicker.de",
+ "livestream.com",
+ "tribunnews.com",
+ "kp.ru",
+ "techradar.com",
+ "315che.com",
+ "dw.de",
+ "codeproject.com",
+ "newsru.com",
+ "pconline.com.cn",
+ "aa.com",
+ "usaa.com",
+ "asahi.com",
+ "themetapicture.com",
+ "quicksprout.com",
+ "piriform.com",
+ "888poker.com",
+ "gittigidiyor.com",
+ "nhk.or.jp",
+ "statigr.am",
+ "ipage.com",
+ "gazzetta.it",
+ "letv.com",
+ "yourlust.com",
+ "freepik.com",
+ "trello.com",
+ "mixi.jp",
+ "livememe.com",
+ "ew.com",
+ "seosprint.net",
+ "doisongphapluat.com",
+ "autotrader.com",
+ "docstoc.com",
+ "viva.co.id",
+ "livestrong.com",
+ "inc.com",
+ "hunantv.com",
+ "bahn.de",
+ "depositphotos.com",
+ "rackspace.com",
+ "flippa.com",
+ "norton.com",
+ "lynda.com",
+ "teamviewer.com",
+ "vip.com",
+ "ksl.com",
+ "solarmovie.so",
+ "klout.com",
+ "pikabu.ru",
+ "vporn.com",
+ "apache.org",
+ "sportbox.ru",
+ "correios.com.br",
+ "toptenreviews.com",
+ "ea.com",
+ "thenextweb.com",
+ "superuser.com",
+ "delicious.com",
+ "zoosk.com",
+ "inbox.com",
+ "kongregate.com",
+ "starbaby.cn",
+ "888casino.com",
+ "brazzers.com",
+ "sockshare.com",
+ "megashare.info",
+ "vistaprint.com",
+ "porntube.com",
+ "seriesyonkis.com",
+ "20minutos.es",
+ "jagran.com",
+ "programme-tv.net",
+ "elcomercio.pe",
+ "blogspot.kr",
+ "t411.me",
+ "googleapis.com",
+ "blog.com",
+ "qingdaonews.com",
+ "sedo.com",
+ "itmedia.co.jp",
+ "mtv.com",
+ "ynet.co.il",
+ "playstation.com",
+ "pornhublive.com",
+ "thedailybeast.com",
+ "r7.com",
+ "sabah.com.tr",
+ "126.com",
+ "topix.com",
+ "liga.net",
+ "marriott.com",
+ "tvn24.pl",
+ "sitesell.com",
+ "netdna-cdn.com",
+ "startimes.com",
+ "hstpnetwork.com",
+ "blogspot.com.au",
+ "17u.cn",
+ "subscribe.ru",
+ "woot.com",
+ "rozblog.com",
+ "wimp.com",
+ "vg.no",
+ "t-mobile.com",
+ "bmi.ir",
+ "kankan.com",
+ "tsn.ua",
+ "gumtree.co.za",
+ "googleadservices.com",
+ "pnc.com",
+ "cars.com",
+ "soccerway.com",
+ "o2.pl",
+ "zeit.de",
+ "zopim.com",
+ "cloudflare.com",
+ "givemesport.com",
+ "statscrop.com",
+ "gravatar.com",
+ "flightradar24.com",
+ "ubuntu.com",
+ "salon.com",
+ "ytimg.com",
+ "trovigo.com",
+ "sunporno.com",
+ "libertagia.com",
+ "mihanwebads.com",
+ "shopathome.com",
+ "cdiscount.com",
+ "commbank.com.au",
+ "elwatannews.com",
+ "discovercard.com",
+ "infowars.com",
+ "blogimg.jp",
+ "portaldosites.com",
+ "fixya.com",
+ "drom.ru",
+ "fastpic.ru",
+ "pbs.org",
+ "kandao.com",
+ "okwave.jp",
+ "faz.net",
+ "sbnation.com",
+ "hilton.com",
+ "duba.com",
+ "homeshop18.com",
+ "ultimasnoticias.com.ve",
+ "bankrate.com",
+ "megasesso.com",
+ "studiopress.com",
+ "sports.ru",
+ "asriran.com",
+ "etoro.com",
+ "cafemom.com",
+ "dhl.de",
+ "indiegogo.com",
+ "tdcanadatrust.com",
+ "1tv.ru",
+ "gogvo.com",
+ "bt.com",
+ "blogspot.tw",
+ "zergnet.com",
+ "garanti.com.tr",
+ "privatbank.ua",
+ "sanook.com",
+ "travelocity.com",
+ "networksolutions.com",
+ "thqafawe3lom.com",
+ "trklnks.com",
+ "torchbrowser.com",
+ "logmein.com",
+ "williamhill.com",
+ "zhihu.com",
+ "auto.ru",
+ "craigslist.ca",
+ "olx.com.pk",
+ "smi2.ru",
+ "ukr.net",
+ "dpreview.com",
+ "boston.com",
+ "folha.uol.com.br",
+ "name.com",
+ "ashemaletube.com",
+ "slimspots.com",
+ "envato.com",
+ "6pm.com",
+ "fandango.com",
+ "sozcu.com.tr",
+ "nikkeibp.co.jp",
+ "aufeminin.com",
+ "baiducontent.com",
+ "buscape.com.br",
+ "funnyordie.com",
+ "337.com",
+ "sakshi.com",
+ "airasia.com",
+ "samanyoluhaber.com",
+ "picofile.com",
+ "blackberry.com",
+ "google.com.gt",
+ "io9.com",
+ "easyhits4u.com",
+ "qianyan001.com",
+ "flashx.tv",
+ "zap2it.com",
+ "dnsrsearch.com",
+ "patch.com",
+ "staticflickr.com",
+ "clicksor.com",
+ "mcafee.com",
+ "zerohedge.com",
+ "zara.com",
+ "freelotto.com",
+ "tutorialspoint.com",
+ "qone8.com",
+ "olx.com.br",
+ "axisbank.com",
+ "marketgid.com",
+ "your-server.de",
+ "game321.com",
+ "harvard.edu",
+ "indianexpress.com",
+ "fatwallet.com",
+ "nudevista.com",
+ "paper.li",
+ "opera.com",
+ "serving-sys.com",
+ "nowvideo.sx",
+ "theatlantic.com",
+ "cisco.com",
+ "bookmyshow.com",
+ "webmasterworld.com",
+ "metro.co.uk",
+ "leparisien.fr",
+ "orbitz.com",
+ "h2porn.com",
+ "4cdn.org",
+ "itar-tass.com",
+ "nasa.gov",
+ "macrumors.com",
+ "google.si",
+ "usnews.com",
+ "premierleague.com",
+ "largeporntube.com",
+ "blogsky.com",
+ "bufferapp.com",
+ "zeroredirect1.com",
+ "sendspace.com",
+ "stanford.edu",
+ "state.gov",
+ "yjc.ir",
+ "abc.net.au",
+ "pornsharing.com",
+ "4pda.ru",
+ "52pk.net",
+ "meituan.com",
+ "mmgp.ru",
+ "sponichi.co.jp",
+ "masrawy.com",
+ "whatismyipaddress.com",
+ "onlinewebfind.com",
+ "news24.com",
+ "zdnet.com",
+ "imagevenue.com",
+ "gameaholic.com",
+ "mediaplex.com",
+ "clip.vn",
+ "2mdn.net",
+ "nmisr.com",
+ "musica.com",
+ "networkedblogs.com",
+ "metrolyrics.com",
+ "chacha.com",
+ "internetdownloadmanager.com",
+ "legacy.com",
+ "wwe.com",
+ "icbc.com.cn",
+ "ny.gov",
+ "chomikuj.pl",
+ "alexa.com",
+ "pcworld.com",
+ "overthumbs.com",
+ "adp.com",
+ "ad2games.com",
+ "adme.ru",
+ "bidvertiser.com",
+ "rtl.de",
+ "sweetim.com",
+ "gaana.com",
+ "7k7k.com",
+ "livingsocial.com",
+ "netteller.com",
+ "rakuten.com",
+ "chess.com",
+ "blackboard.com",
+ "thekitchn.com",
+ "ilfattoquotidiano.it",
+ "20minutes.fr",
+ "soufun.com",
+ "nerdbux.com",
+ "breitbart.com",
+ "webtretho.com",
+ "tvguide.com",
+ "miralinks.ru",
+ "weather.com.cn",
+ "zalando.de",
+ "dangdang.com",
+ "bubblews.com",
+ "thoughtcatalog.com",
+ "114la.com",
+ "msn.ca",
+ "blogmura.com",
+ "americanas.com.br",
+ "elitedaily.com",
+ "lightinthebox.com",
+ "bizjournals.com",
+ "yixun.com",
+ "itau.com.br",
+ "51.la",
+ "doodle.com",
+ "arabyonline.com",
+ "opencart.com",
+ "bomnegocio.com",
+ "lego.com",
+ "pclady.com.cn",
+ "metacafe.com",
+ "kimiss.com",
+ "journaldunet.com",
+ "gnavi.co.jp",
+ "51auto.com",
+ "clickey.com",
+ "chekb.com",
+ "searchnu.com",
+ "diply.com",
+ "walgreens.com",
+ "descargar.es",
+ "mirrorcreator.com",
+ "pornerbros.com",
+ "askmen.com",
+ "shop.com",
+ "inmotionhosting.com",
+ "filmweb.pl",
+ "kbb.com",
+ "appround.biz",
+ "aljazeera.com",
+ "lumosity.com",
+ "sweet-page.com",
+ "pole-emploi.fr",
+ "fishki.net",
+ "rollingstone.com",
+ "kapanlagi.com",
+ "yandex.com",
+ "cnblogs.com",
+ "plaintube.com",
+ "intentmedia.net",
+ "about.me",
+ "torrentz.in",
+ "01net.com",
+ "gyazo.com",
+ "nic.ru",
+ "juicyads.com",
+ "trend.az",
+ "askubuntu.com",
+ "unam.mx",
+ "tradus.com",
+ "tigerdirect.com",
+ "letras.mus.br",
+ "imagetwist.com",
+ "perfectmoney.is",
+ "wpbeginner.com",
+ "thepiratetrader.com",
+ "victoriassecret.com",
+ "images-amazon.com",
+ "tusfiles.net",
+ "chefkoch.de",
+ "ojooo.com",
+ "alphaporno.com",
+ "betfair.com",
+ "tympanus.net",
+ "td.com",
+ "4tube.com",
+ "phonearena.com",
+ "bankmandiri.co.id",
+ "cox.net",
+ "ozon.ru",
+ "perfectgirls.net",
+ "asana.com",
+ "sprint.com",
+ "berniaga.com",
+ "vente-privee.com",
+ "ing.nl",
+ "finn.no",
+ "atwiki.jp",
+ "toysrus.com",
+ "petflow.com",
+ "reverbnation.com",
+ "freeones.com",
+ "abc.go.com",
+ "bradesco.com.br",
+ "yenisafak.com.tr",
+ "profit-partner.ru",
+ "redfin.com",
+ "mangafox.me",
+ "appnexus.com",
+ "sxc.hu",
+ "speedanalysis.net",
+ "n-tv.de",
+ "qidian.com",
+ "teespring.com",
+ "break.com",
+ "nailedhard.com",
+ "jalan.net",
+ "authorize.net",
+ "adultadworld.com",
+ "sootoo.com",
+ "roboform.com",
+ "kotaku.com",
+ "multitran.ru",
+ "food.com",
+ "twitpic.com",
+ "pogo.com",
+ "sabq.org",
+ "priceminister.com",
+ "lexpress.fr",
+ "livetv.sx",
+ "nikkansports.com",
+ "securepaynet.net",
+ "vodoumedia.com",
+ "airbnb.com",
+ "trafficholder.com",
+ "rr.com",
+ "expireddomains.net",
+ "bandcamp.com",
+ "wayfair.com",
+ "tut.by",
+ "maybank2u.com.my",
+ "similarweb.com",
+ "zol.com.cn",
+ "247realmedia.com",
+ "asp.net",
+ "lonelyplanet.com",
+ "seopult.ru",
+ "whois.net",
+ "academia.edu",
+ "univision.com",
+ "interfax.ru",
+ "amarillasinternet.com",
+ "miercn.com",
+ "barclays.co.uk",
+ "societe.com",
+ "khabaronline.ir",
+ "unity3d.com",
+ "nyaa.se",
+ "euronews.com",
+ "verizon.net",
+ "rutube.ru",
+ "wetter.com",
+ "imlive.com",
+ "ggpht.com",
+ "docin.com",
+ "yify-torrents.com",
+ "yhd.com",
+ "citibank.co.in",
+ "xdating.com",
+ "roblox.com",
+ "voyages-sncf.com",
+ "189.cn",
+ "identi.li",
+ "bayt.com",
+ "medicinenet.com",
+ "wmaraci.com",
+ "stern.de",
+ "eluniversal.com",
+ "zoopla.co.uk",
+ "easyjet.com",
+ "dhl.com",
+ "freakshare.com",
+ "rojadirecta.me",
+ "sp.gov.br",
+ "friendfeed.com",
+ "beamtele.com",
+ "searchenginejournal.com",
+ "nocookie.net",
+ "reliancenetconnect.co.in",
+ "google.co.ma",
+ "fanpop.com",
+ "adk2.co",
+ "tagesschau.de",
+ "nate.com",
+ "ole.com.ar",
+ "index.hu",
+ "aruba.it",
+ "eltiempo.com",
+ "resellerclub.com",
+ "qip.ru",
+ "xossip.com",
+ "siteground.com",
+ "royalbank.com",
+ "advfn.com",
+ "tebyan.net",
+ "iciba.com",
+ "bigcartel.com",
+ "sciencedirect.com",
+ "hepsiburada.com",
+ "cpasbien.me",
+ "alfabank.ru",
+ "microsoftstore.com",
+ "discogs.com",
+ "onliner.by",
+ "socialmediaexaminer.com",
+ "seasonvar.ru",
+ "tripadvisor.in",
+ "360doc.com",
+ "chinabroadcast.cn",
+ "realestate.com.au",
+ "avira.com",
+ "herokuapp.com",
+ "downloadsetup.net",
+ "torcache.net",
+ "uefa.com",
+ "rg.ru",
+ "qianlong.com",
+ "hugedomains.com",
+ "arstechnica.com",
+ "fifa.com",
+ "ryanair.com",
+ "i.ua",
+ "axisbank.co.in",
+ "alimama.com",
+ "wanggou.com",
+ "radikal.com.tr",
+ "echoroukonline.com",
+ "unian.net",
+ "slashdot.org",
+ "dmv.org",
+ "mayoclinic.org",
+ "newsmax.com",
+ "google.com.et",
+ "icontact.com",
+ "vanguardngr.com",
+ "infojobs.net",
+ "say-move.org",
+ "ileehoo.com",
+ "mirtesen.ru",
+ "yam.com",
+ "e-hentai.org",
+ "wikimapia.org",
+ "shop-pro.jp",
+ "bukalapak.com",
+ "jcpenney.com",
+ "ilmeteo.it",
+ "iltasanomat.fi",
+ "telecomitalia.it",
+ "kariyer.net",
+ "shutterfly.com",
+ "santabanta.com",
+ "softlayer.com",
+ "complex.com",
+ "mamba.ru",
+ "netshoes.com.br",
+ "theweathernetwork.com",
+ "politico.com",
+ "advego.ru",
+ "eroprofile.com",
+ "mainichi.jp",
+ "nta.go.jp",
+ "sfimg.com",
+ "ap.org",
+ "webex.com",
+ "hinet.net",
+ "skyscrapercity.com",
+ "affili.net",
+ "adplxmd.com",
+ "iltalehti.fi",
+ "impress.co.jp",
+ "jezebel.com",
+ "extremetube.com",
+ "digitaltrends.com",
+ "one.com",
+ "ranker.com",
+ "qiwi.com",
+ "collegehumor.com",
+ "nbc.com",
+ "boursorama.com",
+ "watch32.com",
+ "meetcheap.com",
+ "forums.wordpress.com",
+ "cvs.com",
+ "kenh14.vn",
+ "yallakora.com",
+ "plurk.com",
+ "xtool.ru",
+ "airtel.com",
+ "wp.com",
+ "sftimes.co",
+ "economist.com",
+ "rapidshare.com",
+ "redbox.com",
+ "audible.com",
+ "kissmetrics.com",
+ "atpanel.com",
+ "wargaming.net",
+ "1337x.org",
+ "shahrekhabar.com",
+ "bdnews24.com",
+ "tvrain.ru",
+ "wykop.pl",
+ "mts.ru",
+ "nnm-club.me",
+ "schwab.com",
+ "elconfidencial.com",
+ "modelmayhem.com",
+ "zhidao.baidu.com/user/admin",
+ "aastocks.com",
+ "tiscali.it",
+ "qadabra.com",
+ "autoscout24.de",
+ "vatanim.com.tr",
+ "gotowebinar.com",
+ "edmunds.com",
+ "ebaumsworld.com",
+ "megafilmeshd.net",
+ "poste.it",
+ "mcssl.com",
+ "aljazeera.net",
+ "netvibes.com",
+ "sme.sk",
+ "tesco.com",
+ "525j.com.cn",
+ "tf1.fr",
+ "ccidnet.com",
+ "ldblog.jp",
+ "blockchain.info",
+ "played.to",
+ "nthwall.com",
+ "justanswer.com",
+ "clickbank.net",
+ "fnac.com",
+ "gmarket.co.kr",
+ "clipconverter.cc",
+ "nextmedia.com",
+ "bb.com.br",
+ "learntotradethemarket.com",
+ "pornoid.com",
+ "downloadha.com",
+ "hellporno.com",
+ "ooo-sex.com",
+ "blocket.se",
+ "tubeplus.me",
+ "seek.com.au",
+ "filestube.to",
+ "ceneo.pl",
+ "walmart.com.br",
+ "sonymobile.com",
+ "dyndns.org",
+ "ulmart.ru",
+ "vrbo.com",
+ "sport.pl",
+ "ashleymadison.com",
+ "el-wlid.com",
+ "boredpanda.com",
+ "udemy.com",
+ "mobogenie.com",
+ "tubegalore.com",
+ "theglobeandmail.com",
+ "bancobrasil.com.br",
+ "888.com",
+ "adreactor.com",
+ "zomato.com",
+ "depositfiles.com",
+ "moneysavingexpert.com",
+ "dofus.com",
+ "oanda.com",
+ "sport1.de",
+ "justhost.com",
+ "longhoo.net",
+ "otomoto.pl",
+ "techrepublic.com",
+ "westpac.com.au",
+ "dreamhost.com",
+ "ilsole24ore.com",
+ "clubic.com",
+ "gamme.com.tw",
+ "doctissimo.fr",
+ "isna.ir",
+ "s2d6.com",
+ "tdbank.com",
+ "zwaar.net",
+ "slando.ua",
+ "segodnya.ua",
+ "appannie.com",
+ "bartarinha.ir",
+ "egotastic.com",
+ "ed.gov",
+ "lg.com",
+ "120ask.com",
+ "hostmonster.com",
+ "super.cz",
+ "mercola.com",
+ "bayproxy.me",
+ "day.az",
+ "dummies.com",
+ "azet.sk",
+ "huffingtonpost.co.uk",
+ "okezone.com",
+ "medu.ir",
+ "lavanguardia.com",
+ "espreso.tv",
+ "nymag.com",
+ "autotrader.co.uk",
+ "socialmediatoday.com",
+ "wn.com",
+ "rtbpop.com",
+ "99designs.com",
+ "sanspo.com",
+ "proboards.com",
+ "virginmedia.com",
+ "99acres.com",
+ "blic.rs",
+ "pingomatic.com",
+ "prnewswire.com",
+ "sony.com",
+ "seobuilding.ru",
+ "www.gov.uk",
+ "jugem.jp",
+ "watchtower.com",
+ "seoprofiler.com",
+ "centrum.cz",
+ "techbrowsing.com",
+ "almasryalyoum.com",
+ "lolking.net",
+ "nipic.com",
+ "fanfiction.net",
+ "bwin.com",
+ "anyporn.com",
+ "sulit.com.ph",
+ "quickmeme.com",
+ "carview.co.jp",
+ "haizhangs.com",
+ "airtelforum.com",
+ "flirt4free.com",
+ "billboard.com",
+ "trademe.co.nz",
+ "rapgenius.com",
+ "pchouse.com.cn",
+ "beforeitsnews.com",
+ "peopleperhour.com",
+ "basecamphq.com",
+ "onlinedown.net",
+ "bet365.es",
+ "fucked-tube.com",
+ "santander.co.uk",
+ "speedbit.com",
+ "gi-akademie.com",
+ "google.com.pr",
+ "winupdatevideos.com",
+ "bizrate.com",
+ "xxxbunker.com",
+ "coursera.org",
+ "zoominfo.com",
+ "rarbg.com",
+ "ahram.org.eg",
+ "howtogeek.com",
+ "focus.cn",
+ "duden.de",
+ "mufg.jp",
+ "ex.ua",
+ "titan24.com",
+ "greatandhra.com",
+ "qqbaobao.com",
+ "rtve.es",
+ "yandex.net",
+ "yle.fi",
+ "panoramio.com",
+ "google.com.af",
+ "scol.com.cn",
+ "gamestop.com",
+ "xiami.com",
+ "webpagetest.org",
+ "creativecommons.org",
+ "archive.is",
+ "timesjobs.com",
+ "centurylink.com",
+ "wowhead.com",
+ "wordstream.com",
+ "lloydsbank.co.uk",
+ "incredibar.com",
+ "vagalume.com.br",
+ "installerapplicationusa.com",
+ "shinobi.jp",
+ "ruvr.ru",
+ "natwest.com",
+ "roulettebotplus.com",
+ "wildberries.ru",
+ "huaban.com",
+ "buenosearch.com",
+ "reg.ru",
+ "tempo.co",
+ "qvc.com",
+ "mangahere.com",
+ "tv.com",
+ "boc.cn",
+ "fnb.co.za",
+ "made-in-china.com",
+ "eleconomista.es",
+ "ubuntuforums.org",
+ "derstandard.at",
+ "xml-sitemaps.com",
+ "jang.com.pk",
+ "jiayuan.com",
+ "credit-agricole.fr",
+ "androidcentral.com",
+ "urbanspoon.com",
+ "pornoxo.com",
+ "regnum.ru",
+ "bedbathandbeyond.com",
+ "skladchik.com",
+ "daily.co.jp",
+ "n-mobile.net",
+ "suntrust.com",
+ "justjared.com",
+ "vid2c.com",
+ "gettyimages.com",
+ "tubecup.com",
+ "kinogo.net",
+ "similarsites.com",
+ "fling.com",
+ "vine.co",
+ "banglanews24.com",
+ "pudelek.pl",
+ "support.wordpress.com",
+ "cox.com",
+ "xkcd.com",
+ "adbooth.com",
+ "anz.com",
+ "adxcore.com",
+ "google.com.sv",
+ "indeed.co.in",
+ "scottrade.com",
+ "v9.com",
+ "isohunt.to",
+ "srclick.ru",
+ "gharreh.com",
+ "zaman.com.tr",
+ "monsterindia.com",
+ "delfi.lt",
+ "chewen.com",
+ "empowernetwork.com/QUbsgqDwpjjbkpOgwgOeaw==",
+ "state.tx.us",
+ "segundamano.es",
+ "utro.ru",
+ "sitescout.com",
+ "justclick.ru",
+ "wnd.com",
+ "cosmopolitan.com",
+ "local.com",
+ "anitube.se",
+ "sport.es",
+ "google.com.qa",
+ "ads-id.com",
+ "google.lv",
+ "capitalone360.com",
+ "hattrick.org",
+ "qualtrics.com",
+ "inagist.com",
+ "filgoal.com",
+ "incredibar-search.com",
+ "adslgate.com",
+ "directv.com",
+ "ilivid.com",
+ "warthunder.ru",
+ "jasmin.com",
+ "cyberciti.biz",
+ "msn.co.jp",
+ "canalblog.com",
+ "boerse.bz",
+ "tnaflix.com",
+ "apa.az",
+ "prchecker.info",
+ "reclameaqui.com.br",
+ "onlyworldnews.com",
+ "submarino.com.br",
+ "kuronekoyamato.co.jp",
+ "paipai.com",
+ "realitykings.com",
+ "deadspin.com",
+ "islamweb.net",
+ "no-ip.com",
+ "lostfilm.tv",
+ "wattpad.com",
+ "wav.tv",
+ "citi.com",
+ "buysellads.com",
+ "prezentacya.ru",
+ "forocoches.com",
+ "donga.com",
+ "drive2.ru",
+ "netsuite.com",
+ "privalia.com",
+ "bidorbuy.co.za",
+ "cmbchina.com",
+ "searchresultsguide.com",
+ "odatv.com",
+ "skrill.com",
+ "en.wordpress.com",
+ "dojki.com",
+ "unibet.com",
+ "hotpepper.jp",
+ "simplyhired.com",
+ "vesti.ua",
+ "ibtimes.co.uk",
+ "creativebloq.com",
+ "filmesonlinegratis.net",
+ "videohive.net",
+ "kmart.com",
+ "metacritic.com",
+ "rikunabi.com",
+ "zozo.jp",
+ "venturebeat.com",
+ "1and1.es",
+ "banesconline.com",
+ "internethaber.com",
+ "rae.es",
+ "planetsuzy.org",
+ "wpengine.com",
+ "kizi.com",
+ "armorgames.com",
+ "argos.co.uk",
+ "dtiblog.com",
+ "diigo.com",
+ "forever21.com",
+ "flashscore.com",
+ "vedomosti.ru",
+ "ccavenue.com",
+ "att.net",
+ "esporte.uol.com.br",
+ "empowernetwork.com/PXQ7Uz1Kyg+LR1APrG7pKQ==",
+ "to8to.com",
+ "hotwire.com",
+ "all.biz",
+ "info.com",
+ "xhamster.com/user/video",
+ "000webhost.com",
+ "worldoftanks.ru",
+ "dagbladet.no",
+ "computerbild.de",
+ "nasdaq.com",
+ "chitika.com",
+ "ipeen.com.tw",
+ "abola.pt",
+ "wiley.com",
+ "lpcloudsvr303.com",
+ "tinsao.net",
+ "mehrnews.com",
+ "hugesex.tv",
+ "christian-dogma.com",
+ "search.us.com",
+ "garmin.com",
+ "tgbus.com",
+ "iherb.com",
+ "torntv-tvv.org",
+ "chosun.com",
+ "kinozal.tv",
+ "berkeley.edu",
+ "techtarget.com",
+ "labanquepostale.fr",
+ "fitbit.com",
+ "folkd.com",
+ "theonion.com",
+ "idealista.com",
+ "oscar.go.com",
+ "jiji.com",
+ "anonym.to",
+ "allabout.co.jp",
+ "wufoo.com",
+ "rantlifestyle.com",
+ "google.com.bo",
+ "28.com",
+ "rocketnews24.com",
+ "hotspotshield.com",
+ "opentable.com",
+ "admngronline.com",
+ "naturalnews.com",
+ "zeroredirect2.com",
+ "ero-video.net",
+ "dinamalar.com",
+ "fl.ru",
+ "mtsindia.in",
+ "kapook.com",
+ "theage.com.au",
+ "allmyvideos.net",
+ "dinodirect.com",
+ "videodownloadconverter.com",
+ "tripleclicks.com",
+ "brassring.com",
+ "fapdu.com",
+ "cafepress.com",
+ "infospace.com",
+ "express.com.pk",
+ "fumu.com",
+ "infibeam.com",
+ "etrade.com",
+ "meneame.net",
+ "seroundtable.com",
+ "bigpoint.com",
+ "chinadaily.com.cn",
+ "myfonts.com",
+ "ezdownloadpro.info",
+ "codeplex.com",
+ "xl.pt",
+ "kaspersky.com",
+ "khabarfarsi.com",
+ "admitad.com",
+ "flirchi.com",
+ "dpstream.net",
+ "miniinthebox.com",
+ "samsclub.com",
+ "charter.net",
+ "techbang.com",
+ "tiu.ru",
+ "fanpage.it",
+ "spokeo.com",
+ "imageshack.com",
+ "ijreview.com",
+ "bc.vc",
+ "lazada.co.id",
+ "gofirstrow.eu",
+ "uptobox.com",
+ "newsnow.co.uk",
+ "symantec.com",
+ "editor.wix.com",
+ "avaxhome.cc",
+ "canalplus.fr",
+ "copyblogger.com",
+ "vetogate.com",
+ "yahoo-mbga.jp",
+ "manoramaonline.com",
+ "ah-me.com",
+ "elheddaf.com",
+ "bitcointalk.org",
+ "haqaik.com",
+ "bbandt.com",
+ "linguee.de",
+ "blogspot.nl",
+ "minus.com",
+ "amarujala.com",
+ "openclassrooms.com",
+ "bigmir.net",
+ "koramgame.com",
+ "commonfloor.com",
+ "gayromeo.com",
+ "cleartrip.com",
+ "kompasiana.com",
+ "tankionline.com",
+ "google.co.tz",
+ "springer.com",
+ "lifenews.ru",
+ "sify.com",
+ "tvoyauda4a.ru",
+ "dfiles.ru",
+ "technorati.com",
+ "myorderbox.com",
+ "fanatik.com.tr",
+ "activesearchresults.com",
+ "laposte.net",
+ "whirlpool.net.au",
+ "stockcharts.com",
+ "leadimpact.com",
+ "cardekho.com",
+ "ryushare.com",
+ "blog.jp",
+ "fastcompany.com",
+ "eurosport.fr",
+ "emirates.com",
+ "lb.ua",
+ "serverfault.com",
+ "forbes.ru",
+ "bfmtv.com",
+ "google.jo",
+ "17173.com",
+ "wikispaces.com",
+ "tokopedia.com",
+ "liberation.fr",
+ "a10.com",
+ "kdnet.net",
+ "variety.com",
+ "blog.me",
+ "homeaway.com",
+ "ameritrade.com",
+ "adult-empire.com",
+ "national.com.au",
+ "haraj.com.sa",
+ "timewarnercable.com",
+ "casino.com",
+ "sheknows.com",
+ "google.com.uy",
+ "abv.bg",
+ "liputan6.com",
+ "etxt.ru",
+ "bigstockphoto.com",
+ "strato.de",
+ "cashtasks.com",
+ "columbia.edu",
+ "zdf.de",
+ "pptv.com",
+ "cricbuzz.com",
+ "sharesuper.info",
+ "radaronline.com",
+ "pornolab.net",
+ "google.ba",
+ "opensubtitles.org",
+ "abclocal.go.com",
+ "ansa.it",
+ "pbskids.org",
+ "vz.ru",
+ "iconfinder.com",
+ "vitaminl.tv",
+ "ntv.ru",
+ "peliculasyonkis.com",
+ "foto-hd.com",
+ "paytm.com",
+ "rantsports.com",
+ "optimum.net",
+ "postbank.de",
+ "index.hr",
+ "smugmug.com",
+ "haivl.com",
+ "arbeitsagentur.de",
+ "dailycaller.com",
+ "freshbooks.com",
+ "genieo.com",
+ "alnaddy.com",
+ "britishairways.com",
+ "20min.ch",
+ "findthebest.com",
+ "autoblog.com",
+ "warez-bb.org",
+ "iza.ne.jp",
+ "filmaffinity.com",
+ "megogo.net",
+ "soccermanager.com",
+ "dawanda.com",
+ "parallels.com",
+ "clickjogos.uol.com.br",
+ "12306.cn",
+ "jstv.com",
+ "cliphunter.com",
+ "pixabay.com",
+ "milenio.com",
+ "keybinary.com",
+ "suumo.jp",
+ "mediatakeout.com",
+ "vodafone.in",
+ "cheapoair.com",
+ "seobook.com",
+ "videoyoum7.com",
+ "yr.no",
+ "gofundme.com",
+ "ixbt.com",
+ "starbucks.com",
+ "conferenceplus.com",
+ "media1first.com",
+ "sergey-mavrodi.com",
+ "rafflecopter.com",
+ "591.com.tw",
+ "mangapanda.com",
+ "huffingtonpost.fr",
+ "tiboo.cn",
+ "bancomer.com.mx",
+ "handelsblatt.com",
+ "hpylgr.com",
+ "psu.edu",
+ "bancomercantil.com",
+ "sport-express.ru",
+ "codepen.io",
+ "foundationapi.com",
+ "ow.ly",
+ "vatgia.com",
+ "kommersant.ru",
+ "srvsinf.com",
+ "telderi.ru",
+ "mercadolibre.com.co",
+ "hsbc.com.hk",
+ "t3n.de",
+ "magicbricks.com",
+ "shopstyle.com",
+ "mudah.my",
+ "punchng.com",
+ "therichest.com",
+ "fansshare.com",
+ "lepoint.fr",
+ "vipzona.info",
+ "globaltestmarket.com",
+ "jqueryui.com",
+ "bcsh.com",
+ "mundodeportivo.com",
+ "newyorker.com",
+ "funnyjunk.com",
+ "gongchang.com",
+ "a8.net",
+ "ecollege.com",
+ "newhdplugin.net",
+ "befuck.com",
+ "elespectador.com",
+ "drugs.com",
+ "abplive.in",
+ "feelcars.com",
+ "psychologytoday.com",
+ "instaforex.com",
+ "strtsrv.com",
+ "atpworldtour.com",
+ "incruit.com",
+ "starwoodhotels.com",
+ "zone-telechargement.com",
+ "songspk.name",
+ "hatenablog.com",
+ "enfemenino.com",
+ "msnbc.com",
+ "freebitco.in",
+ "akairan.com",
+ "discovery.com",
+ "angieslist.com",
+ "lesechos.fr",
+ "transfermarkt.de",
+ "sephora.com",
+ "come.in",
+ "dailykos.com",
+ "deutsche-bank.de",
+ "warriorplus.com",
+ "awwwards.com",
+ "lomadee.com",
+ "365jia.cn",
+ "lotterypost.com",
+ "egrana.com.br",
+ "rivals.com",
+ "literotica.com",
+ "myfreshnet.com",
+ "ihg.com",
+ "fazenda.gov.br",
+ "tomnod.com",
+ "filesharefanatic.com",
+ "hotukdeals.com",
+ "bitsnoop.com",
+ "tenpay.com",
+ "putlocker.bz",
+ "ziddu.com",
+ "ntvmsnbc.com",
+ "surveyzrewardcenter.com",
+ "aliyun.com",
+ "media.net",
+ "comdirect.de",
+ "yoox.com",
+ "hotelscombined.com",
+ "vgsgaming-ads.com",
+ "robokassa.ru",
+ "webdesignerdepot.com",
+ "rotoworld.com",
+ "jmw.com.cn",
+ "seloger.com",
+ "dsdomination.com",
+ "affiliatewindow.com",
+ "abs-cbnnews.com",
+ "bmo.com",
+ "iconarchive.com",
+ "funshion.com",
+ "admin5.com",
+ "playhe.com",
+ "bigcommerce.com",
+ "yodobashi.com",
+ "bigfishgames.com",
+ "onlinecreditcenter6.com",
+ "homes.co.jp",
+ "gameninja.com",
+ "ebates.com",
+ "banamex.com.mx",
+ "google.com.lb",
+ "2chblog.jp",
+ "entertainment-factory.com",
+ "asg.to",
+ "walla.co.il",
+ "mktmobi.com",
+ "opensooq.com",
+ "adam4adam.com",
+ "expressen.se",
+ "elephanttube.com",
+ "ingdirect.es",
+ "clicrbs.com.br",
+ "seriespepito.com",
+ "skyscanner.net",
+ "shine.com",
+ "appround.us",
+ "washingtontimes.com",
+ "nrk.no",
+ "1stwebdesigner.com",
+ "gucheng.com",
+ "ghanaweb.com",
+ "jzip.com",
+ "rozetka.com.ua",
+ "wiziwig.tv",
+ "jobsdb.com",
+ "kitco.com",
+ "rpp.com.pe",
+ "aljaras.com",
+ "telecinco.es",
+ "storify.com",
+ "netease.com",
+ "business-standard.com",
+ "babble.com",
+ "noticias.uol.com.br",
+ "alice.it",
+ "bizdec.ru",
+ "voanews.com",
+ "freejobalert.com",
+ "origo.hu",
+ "list-manage2.com",
+ "gavick.com",
+ "national-lottery.co.uk",
+ "gazzetta.gr",
+ "freevideodownloadforpc.com",
+ "xmarks.com",
+ "wikibooks.org",
+ "sexad.net",
+ "alc.co.jp",
+ "emol.com",
+ "careesma.in",
+ "cdc.gov",
+ "toshiba.com",
+ "imgchili.net",
+ "rbcroyalbank.com",
+ "indowebster.com",
+ "zynga.com",
+ "telekom.com",
+ "jiameng.com",
+ "adsmarket.com",
+ "utorrent.com",
+ "aarp.org",
+ "cityadspix.com",
+ "ekstrabladet.dk",
+ "doc88.com",
+ "fetlife.com",
+ "fh21.com.cn",
+ "cambridge.org",
+ "tune.pk",
+ "auction.co.kr",
+ "patheos.com",
+ "search-results.com",
+ "lds.org",
+ "webrankinfo.com",
+ "newsit.gr",
+ "techtudo.com.br",
+ "moviepilot.com",
+ "mercador.ro",
+ "nguoiduatin.vn",
+ "tripadvisor.it",
+ "lurkmore.to",
+ "europapress.es",
+ "uspto.gov",
+ "excelsior.com.mx",
+ "myvideo.de",
+ "jetblue.com",
+ "camfrog.com",
+ "blick.ch",
+ "batepapo.uol.com.br",
+ "manager.co.th",
+ "goibibo.com",
+ "cornell.edu",
+ "apetube.com",
+ "nation.com",
+ "allmusic.com",
+ "naughtyamerica.com",
+ "obozrevatel.com",
+ "telegrafi.com",
+ "neimanmarcus.com",
+ "yabancidiziizle1.com",
+ "globalewallet.com",
+ "beeline.ru",
+ "hinkhoj.com",
+ "sitemeter.com",
+ "almesryoon.com",
+ "localmoxie.com",
+ "grotal.com",
+ "knowyourmeme.com",
+ "qiwi.ru",
+ "yieldmanager.com",
+ "yimg.com",
+ "horoscopedays.com",
+ "gfy.com",
+ "mxtoolbox.com",
+ "searchgol.com",
+ "inquirer.net",
+ "hollywoodlife.com",
+ "ebrun.com",
+ "shopbop.com",
+ "mysmartprice.com",
+ "kijiji.it",
+ "visual.ly",
+ "mop.com",
+ "1fichier.com",
+ "prlog.org",
+ "xjtour.com",
+ "shorouknews.com",
+ "thegioinet.net",
+ "hln.be",
+ "enom.com",
+ "thaqafnafsak.com",
+ "wahuu.com",
+ "ganji.com",
+ "russianpost.ru",
+ "myplaycity.com",
+ "dzone.com",
+ "dns-shop.ru",
+ "aif.ru",
+ "ssisurveys.com",
+ "uploadboy.com",
+ "madpandatv.net",
+ "pcauto.com.cn",
+ "meinestadt.de",
+ "tasnimnews.com",
+ "rockettheme.com",
+ "imesh.com",
+ "home.pl",
+ "lindaikeji.blogspot.com",
+ "zamunda.net",
+ "with2.net",
+ "calameo.com",
+ "myonlinearcade.com",
+ "xcams.com",
+ "unicredit.it",
+ "clip2net.com",
+ "mediatemple.net",
+ "nosub.tv",
+ "click.in",
+ "alluc.to",
+ "thestar.com.my",
+ "niksalehi.com",
+ "lastampa.it",
+ "itv.com",
+ "hihi2.com",
+ "digitalocean.com",
+ "tripadvisor.fr",
+ "willhaben.at",
+ "laodong.com.vn",
+ "591hx.com",
+ "tineye.com",
+ "ptt.cc",
+ "beatport.com",
+ "infoseek.co.jp",
+ "avangate.com",
+ "indiaproperty.com",
+ "books.com.tw",
+ "nj.com",
+ "avaaz.org",
+ "wikitravel.org",
+ "direct.gov.uk",
+ "wangtu.com",
+ "discover.com",
+ "slon.ru",
+ "startpage.com",
+ "thestar.com",
+ "meishichina.com",
+ "finanzen.net",
+ "estadao.com.br",
+ "indeed.co.uk",
+ "expansion.com",
+ "irpopup.ir",
+ "arvixe.com",
+ "secureinternetbank.com",
+ "csmonitor.com",
+ "carwale.com",
+ "mtime.com",
+ "ceconline.com",
+ "abchina.com",
+ "cgbchina.com.cn",
+ "mediotiempo.com",
+ "vic.gov.au",
+ "cnbeta.com",
+ "alarab.net",
+ "vietnamnet.vn",
+ "gay.com",
+ "watchmygf.net",
+ "myanimelist.net",
+ "bannersbroker.com",
+ "asklaila.com",
+ "heureka.cz",
+ "grepolis.com",
+ "meteofrance.com",
+ "bol.com",
+ "hasoffers.com",
+ "bigrock.in",
+ "ibanking-services.com",
+ "nos.nl",
+ "google.com.gh",
+ "beppegrillo.it",
+ "nhaccuatui.com",
+ "hamariweb.com",
+ "wikiquote.org",
+ "evite.com",
+ "jobdiagnosis.com",
+ "17track.net",
+ "baixing.com",
+ "awempire.com",
+ "healthgrades.com",
+ "unifiedlayer.com",
+ "thisav.com",
+ "himado.in",
+ "zcool.com.cn",
+ "tsn.ca",
+ "atlassian.net",
+ "binary500.com",
+ "alotporn.com",
+ "dnaindia.com",
+ "sherdog.com",
+ "www.nhs.uk",
+ "gruposantander.es",
+ "quantcast.com",
+ "usearchmedia.com",
+ "merchantcircle.com",
+ "blog.hu",
+ "wallstcheatsheet.com",
+ "iptorrents.com",
+ "apsense.com",
+ "redirsvc.com",
+ "indiarailinfo.com",
+ "mobile.ir",
+ "xvideo-jp.com",
+ "boxofficemojo.com",
+ "scamadviser.com",
+ "rotapost.ru",
+ "someecards.com",
+ "mydealz.de",
+ "lvye.cn",
+ "videoweed.es",
+ "xlovecam.com",
+ "pepperjamnetwork.com",
+ "khabarpu.com",
+ "mathrubhumi.com",
+ "online-convert.com",
+ "b92.net",
+ "tiptopsoft.org",
+ "el-balad.com",
+ "qihoo.com",
+ "iheart.com",
+ "campaign-archive1.com",
+ "photodune.net",
+ "labnol.org",
+ "kotobank.jp",
+ "medium.com",
+ "google.lu",
+ "tm1111.com",
+ "gigazine.net",
+ "mypcbackup.com",
+ "instantcheckmate.com",
+ "seemorgh.com",
+ "topky.sk",
+ "puu.sh",
+ "aeriagames.com",
+ "whatismyip.com",
+ "rising.cn",
+ "scotiabank.com",
+ "wo.com.cn",
+ "yootheme.com",
+ "channel4.com",
+ "heavy-r.com",
+ "omgpm.com",
+ "milli.az",
+ "bnpparibas.net",
+ "vmware.com",
+ "diretta.it",
+ "skycn.com",
+ "sap.com",
+ "zyalt.livejournal.com",
+ "bookryanair.com",
+ "kkbox.com",
+ "subtitleseeker.com",
+ "abckj123.com",
+ "mashreghnews.ir",
+ "websitewelcome.com",
+ "2ch-c.net",
+ "health.com",
+ "uproxx.com",
+ "uast.ac.ir",
+ "bol.uol.com.br",
+ "feedsportal.com",
+ "ip-adress.com",
+ "sedty.com",
+ "ilsistemabinario.com",
+ "nabble.com",
+ "hightail.com",
+ "superjob.ru",
+ "tokyo.jp",
+ "hrblock.com",
+ "china.cn",
+ "tsetmc.com",
+ "unfranchise.com.tw",
+ "bhg.com",
+ "htmlbook.ru",
+ "stardoll.com",
+ "crictime.com",
+ "hsn.com",
+ "royalmail.com",
+ "globallshare.com",
+ "wikiwiki.jp",
+ "petardas.com",
+ "usembassy.gov",
+ "rakuten-bank.co.jp",
+ "golem.de",
+ "stepstone.de",
+ "aucfan.com",
+ "stubhub.com",
+ "rbcdaily.ru",
+ "ro2.biz",
+ "huffingtonpost.ca",
+ "timeout.com",
+ "digitalspy.co.uk",
+ "foreningssparbanken.se",
+ "autodesk.com",
+ "98ia.com",
+ "gtbank.com",
+ "runetki.com",
+ "freshdesk.com",
+ "ieee.org",
+ "getpocket.com",
+ "jutarnji.hr",
+ "caisse-epargne.fr",
+ "profitcentr.com",
+ "51.com",
+ "oi.com.br",
+ "sina.com.tw",
+ "fontspace.com",
+ "dynamicdrive.com",
+ "maduradas.com",
+ "ligtv.com.tr",
+ "sport24.gr",
+ "stargazete.com",
+ "bola.net",
+ "template-help.com",
+ "codecademy.com",
+ "officedepot.com",
+ "researchgate.net",
+ "17u.com",
+ "gfxtra.com",
+ "weiphone.com",
+ "shoutmeloud.com",
+ "hc360.com",
+ "lintas.me",
+ "mk.ru",
+ "wplocker.com",
+ "thumbtack.com",
+ "szn.cz",
+ "yatra.com",
+ "societegenerale.fr",
+ "wyborcza.pl",
+ "demotywatory.pl",
+ "thomann.de",
+ "imperiaonline.org",
+ "magento.com",
+ "skillpages.com",
+ "cam4ads.com",
+ "spiceworks.com",
+ "homestead.com",
+ "locanto.in",
+ "hotelurbano.com",
+ "sinaimg.cn",
+ "chetxia.com",
+ "menshealth.com",
+ "ideacellular.com",
+ "snopes.com",
+ "newgrounds.com",
+ "autosottocosto.com",
+ "admob.com",
+ "linguee.fr",
+ "net-a-porter.com",
+ "text.ru",
+ "sharebeast.com",
+ "televisionfanatic.com",
+ "netlog.com",
+ "lufthansa.com",
+ "ngoisao.net",
+ "3911.net",
+ "worldssl.net",
+ "rabobank.nl",
+ "lvmama.com",
+ "sharethis.com",
+ "sambaporno.com",
+ "mci.ir",
+ "inosmi.ru",
+ "joyreactor.cc",
+ "cartfill.in",
+ "cooltext.com",
+ "qz.com",
+ "onthe.io",
+ "citilink.ru",
+ "apartmenttherapy.com",
+ "lloydsbank.com",
+ "metroer.com",
+ "koyotesoft.com",
+ "subdivx.com",
+ "alriyadh.com",
+ "backlinkwatch.com",
+ "coindesk.com",
+ "porntube1.xxx",
+ "zovi.com",
+ "thestreet.com",
+ "rtbstream.com",
+ "etnet.com.hk",
+ "creditkarma.com",
+ "lifebuzz.com",
+ "opodo.co.uk",
+ "developpez.net",
+ "tinydeal.com",
+ "nature.com",
+ "oxforddictionaries.com",
+ "anchorfree.net",
+ "tn.com.ar",
+ "findicons.com",
+ "joomlart.com",
+ "hmrc.gov.uk",
+ "btc-e.com",
+ "extra.com.br",
+ "ad.nl",
+ "megafon.ru",
+ "qafqazinfo.az",
+ "shahvani.com",
+ "googlecode.com",
+ "milliyet.tv",
+ "deadline.com",
+ "grindtv.com",
+ "logitech.com",
+ "nzherald.co.nz",
+ "ninisite.com",
+ "webgains.com",
+ "oschina.net",
+ "webmasters.ru",
+ "filmix.net",
+ "seowhy.com",
+ "met-art.com",
+ "discart.ru",
+ "keywordblocks.com",
+ "vodly.to",
+ "redvak.com",
+ "tomshardware.co.uk",
+ "2shared.com",
+ "zoznam.sk",
+ "icims.com",
+ "virtapay.com",
+ "blomaga.jp",
+ "wasu.cn",
+ "carsensor.net",
+ "sportsdirect.com",
+ "uservoice.com",
+ "livescience.com",
+ "gamebase.com.tw",
+ "persiangig.com",
+ "livesmi.com",
+ "eharmony.com",
+ "banorte.com",
+ "radiojavan.com",
+ "startv.com.tr",
+ "coolmath-games.com",
+ "downloadquick.net",
+ "worldoftanks.eu",
+ "filelist.ro",
+ "fontsquirrel.com",
+ "superpages.com",
+ "yolasite.com",
+ "funnie.st",
+ "51cto.com",
+ "goo-net.com",
+ "builtwith.com",
+ "shaparak.ir",
+ "nuomi.com",
+ "omegle.com",
+ "poringa.net",
+ "lan.com",
+ "desi-tashan.com",
+ "shabdkosh.com",
+ "freedigitalphotos.net",
+ "betradar.com",
+ "womenshealthmag.com",
+ "realsimple.com",
+ "maxbounty.com",
+ "bbva.es",
+ "sweetpacks.com",
+ "pinoy-ako.info",
+ "jobstreet.com",
+ "cafe24.com",
+ "goldenbirds.biz",
+ "anandtech.com",
+ "mapion.co.jp",
+ "rawstory.com",
+ "streamate.com",
+ "celebuzz.com",
+ "freepornvs.com",
+ "divyabhaskar.co.in",
+ "lifehack.org",
+ "holidaycheck.de",
+ "quizlet.com",
+ "zhibo8.cc",
+ "askmefast.com",
+ "manageflitter.com",
+ "campaign-archive2.com",
+ "cityheaven.net",
+ "uniqlo.com",
+ "seoclerks.com",
+ "tecmundo.com.br",
+ "the-binary-options-guide.com",
+ "gigaom.com",
+ "mywot.com",
+ "playcast.ru",
+ "tatadocomo.com",
+ "csfd.cz",
+ "ganool.com",
+ "kaschpo.ru",
+ "webdunia.com",
+ "philly.com",
+ "doctoroz.com",
+ "jumei.com",
+ "poponclick.com",
+ "rueducommerce.fr",
+ "fararu.com",
+ "po.st",
+ "nextag.com",
+ "manhunt.net",
+ "sistrix.com",
+ "woman.ru",
+ "appbank.net",
+ "iobit.com",
+ "joins.com",
+ "vidtomp3.com",
+ "un.org",
+ "volusion.com",
+ "lipsum.com",
+ "afkarnews.ir",
+ "goldenline.pl",
+ "clickansave.net",
+ "softgozar.com",
+ "thefind.com",
+ "mozzi.com",
+ "wenxuecity.com",
+ "up2c.com",
+ "searchfunmoods.com",
+ "cabelas.com",
+ "coffetube.com",
+ "otto.de",
+ "webalta.ru",
+ "tataindicom.com",
+ "ctvnews.ca",
+ "inlinkz.com",
+ "kajabi.com",
+ "greatergood.com",
+ "whmcs.com",
+ "telekom.de",
+ "christianpost.com",
+ "fiducia.de",
+ "bancsabadell.com",
+ "pirateproxy.net",
+ "woobox.com",
+ "google.cm",
+ "noulinx.com",
+ "nick.com",
+ "moviehuts.com",
+ "mvideo.ru",
+ "couchtuner.eu",
+ "wyborcza.biz",
+ "tradeindia.com",
+ "girlsgogames.com",
+ "healthcare.gov",
+ "videolan.org",
+ "sky.it",
+ "tuniu.com",
+ "ime.nu",
+ "n4g.com",
+ "cyberforum.ru",
+ "justin.tv",
+ "createspace.com",
+ "joemonster.org",
+ "registro.br",
+ "elkhabar.com",
+ "open24news.tv",
+ "irr.ru",
+ "sanjesh.org",
+ "standardbank.co.za",
+ "neogaf.com",
+ "doyo.cn",
+ "am15.net",
+ "ana.co.jp",
+ "amd.com",
+ "gidonlinekino.com",
+ "sitetalk.com",
+ "nesn.com",
+ "arabseed.com",
+ "ingbank.pl",
+ "webpronews.com",
+ "saavn.com",
+ "yourdictionary.com",
+ "mobile9.com",
+ "jagranjosh.com",
+ "www.net.cn",
+ "computerbase.de",
+ "3djuegos.com",
+ "htc.com",
+ "the-binary-theorem.com",
+ "google.com.np",
+ "n11.com",
+ "vivastreet.com",
+ "mthai.com",
+ "seomastering.com",
+ "mercadolibre.cl",
+ "searchmetrics.com",
+ "mentalfloss.com",
+ "russia.tv",
+ "ubi.com",
+ "dwnews.com",
+ "ecplaza.net",
+ "trafficfactory.biz",
+ "loopnet.com",
+ "refinery29.com",
+ "minecraftforum.net",
+ "moviefone.com",
+ "bom.gov.au",
+ "google.com.bh",
+ "eltiempo.es",
+ "cuantarazon.com",
+ "2258.com",
+ "google.ee",
+ "nwolb.com",
+ "bezaat.com",
+ "eelly.com",
+ "icmwebserv.com",
+ "techsmith.com",
+ "timeweb.ru",
+ "johnlewis.com",
+ "independent.ie",
+ "bankia.es",
+ "dkb.de",
+ "gilt.com",
+ "duolingo.com",
+ "3file.info",
+ "cam4.de.com",
+ "pcanalysis.net",
+ "br.de",
+ "vodlocker.com",
+ "adfoc.us",
+ "ymlp.com",
+ "dailyfx.com",
+ "business2community.com",
+ "banki.ru",
+ "yell.com",
+ "smartresponder.ru",
+ "yaske.to",
+ "bokra.net",
+ "mercadolibre.com",
+ "viewster.com",
+ "recipesfinder.com",
+ "rei.com",
+ "dogpile.com",
+ "caf.fr",
+ "sbrf.ru",
+ "soha.vn",
+ "voila.fr",
+ "rp-online.de",
+ "members.webs.com",
+ "duvamis.com",
+ "nazwa.pl",
+ "google.com.ni",
+ "ilovemobi.com",
+ "retrogamer.com",
+ "blogtalkradio.com",
+ "utexas.edu",
+ "sonyentertainmentnetwork.com",
+ "dr.dk",
+ "jjwxc.net",
+ "service-public.fr",
+ "care2.com",
+ "musavat.com",
+ "h12-media.com",
+ "smartfren.com",
+ "immowelt.de",
+ "discuz.net",
+ "m1905.com",
+ "cas.sk",
+ "bitcoinwisdom.com",
+ "monografias.com",
+ "mindbodygreen.com",
+ "getfirebug.com",
+ "godlikeproductions.com",
+ "mydrivers.com",
+ "voc.com.cn",
+ "truecaller.com",
+ "livemook.com",
+ "i8ti.com",
+ "agame.com",
+ "kurir-info.rs",
+ "urbanoutfitters.com",
+ "shopping.uol.com.br",
+ "2ip.ru",
+ "91.com",
+ "banquepopulaire.fr",
+ "rappler.com",
+ "mint.com",
+ "jz123.cn",
+ "zurb.com",
+ "sport.cz",
+ "justunfollow.com",
+ "billionuploads.com",
+ "thaivisa.com",
+ "seitwert.de",
+ "ciudad.com.ar",
+ "archdaily.com",
+ "jalopnik.com",
+ "1news.az",
+ "dailyfinance.com",
+ "okitspace.com",
+ "dn.se",
+ "el-nacional.com",
+ "larousse.fr",
+ "mojo-themes.com",
+ "draugiem.lv",
+ "teamtreehouse.com",
+ "xiu.com",
+ "ennaharonline.com",
+ "oricon.co.jp",
+ "openoffice.org",
+ "tny.cz",
+ "forumfree.it",
+ "youthwant.com.tw",
+ "khamsat.com",
+ "vitacost.com",
+ "alrakoba.net",
+ "marmiton.org",
+ "yebhi.com",
+ "the-binary-trader.biz",
+ "dominos.com",
+ "dice.com",
+ "like4like.org",
+ "tvmuse.com",
+ "standardchartered.com",
+ "bitbucket.org",
+ "driveropti.net",
+ "google.hn",
+ "indiblogger.in",
+ "torrenthound.com",
+ "wolframalpha.com",
+ "experienceproject.com",
+ "nsw.gov.au",
+ "olx.pt",
+ "sciencedaily.com",
+ "viglink.com",
+ "plala.or.jp",
+ "sxsw.com",
+ "mileroticos.com",
+ "namejet.com",
+ "1hai.cn",
+ "skroutz.gr",
+ "bilibili.tv",
+ "travelzoo.com",
+ "saksfifthavenue.com",
+ "get-a-fuck-tonight.com",
+ "barclaycardus.com",
+ "withgoogle.com",
+ "whitehouse.gov",
+ "oprah.com",
+ "fishwrapper.com",
+ "softbank.jp",
+ "slutload.com",
+ "latercera.cl",
+ "100bestbuy.com",
+ "nur.kz",
+ "topit.me",
+ "computerhope.com",
+ "snob.ru",
+ "rackcdn.com",
+ "3158.cn",
+ "artlebedev.ru",
+ "yobt.com",
+ "rai.it",
+ "hs.fi",
+ "tinhte.vn",
+ "fotocasa.es",
+ "nyu.edu",
+ "dawn.com",
+ "series.ly",
+ "movshare.net",
+ "fineartamerica.com",
+ "westernunion.com",
+ "leaseweb.com",
+ "wayn.com",
+ "ivi.ru",
+ "bloomingdales.com",
+ "pons.com",
+ "rapidtrk.com",
+ "bama.ir",
+ "hackforums.net",
+ "dfiles.eu",
+ "intercambiosvirtuales.org",
+ "sdo.com",
+ "homes.com",
+ "colissimo.fr",
+ "discuss.com.hk",
+ "afreeca.com",
+ "rbc.ua",
+ "novamov.com",
+ "jungle.gr",
+ "iol.co.za",
+ "btcclicks.com",
+ "mapsofindia.com",
+ "propellerads.com",
+ "fab.com",
+ "princeton.edu",
+ "reliancebroadband.co.in",
+ "xdf.cn",
+ "mako.co.il",
+ "protothema.gr",
+ "booloo.com",
+ "livrariasaraiva.com.br",
+ "efukt.com",
+ "acrobat.com",
+ "globovision.com",
+ "xero.com",
+ "sevenforums.com",
+ "semalt.com",
+ "audiojungle.net",
+ "e1.ru",
+ "quoka.de",
+ "chinaiiss.com",
+ "gonzoxxxmovies.com",
+ "wallpaperswide.com",
+ "fapvid.com",
+ "trk4.com",
+ "forosdelweb.com",
+ "fark.com",
+ "my.tv.sohu.com/user/video",
+ "kaixin001.com",
+ "ntvspor.net",
+ "mobafire.com",
+ "zigwheels.com",
+ "filmifullizle.com",
+ "8tracks.com",
+ "readmanga.eu",
+ "lelong.com.my",
+ "planetromeo.com",
+ "192.com",
+ "republika.co.id",
+ "in.gr",
+ "televisao.uol.com.br",
+ "kalerkantho.com",
+ "usairways.com",
+ "malaysiakini.com",
+ "anonymouse.org",
+ "xxxhost.me",
+ "stuff.co.nz",
+ "dek-d.com",
+ "bbvanet.com.mx",
+ "watchseries-online.eu",
+ "malaysiaairlines.com",
+ "policymic.com",
+ "serviporno.com",
+ "aprod.hu",
+ "gelocal.it",
+ "tradetracker.com",
+ "cibc.com",
+ "umich.edu",
+ "smartshe.com",
+ "sony.jp",
+ "taobaocdn.com",
+ "bestgfx.biz",
+ "irib.ir",
+ "aliimg.com",
+ "esuteru.com",
+ "healthline.com",
+ "cnnamador.com",
+ "sat.gob.mx",
+ "childsafedownloadx.asia",
+ "playmillion.com",
+ "strawberrynet.com",
+ "alnilin.com",
+ "trustedreviews.com",
+ "21cn.com",
+ "persianv.com",
+ "baomoi.com",
+ "firestorage.jp",
+ "google.co.ke",
+ "admaimai.com",
+ "sbnlife.com",
+ "surveyrouter.com",
+ "megaindex.ru",
+ "intodns.com",
+ "yiqifa.com",
+ "mixcloud.com",
+ "softonic.fr",
+ "bakecaincontrii.com",
+ "payu.in",
+ "rakuten-card.co.jp",
+ "almaany.com",
+ "grantland.com",
+ "ricardo.ch",
+ "heavy.com",
+ "niusnews.com",
+ "canstockphoto.com",
+ "acunn.com",
+ "diythemes.com",
+ "canalrcnmsn.com",
+ "ngs.ru",
+ "rassd.com",
+ "groupon.co.in",
+ "depositfiles.org",
+ "mango.com",
+ "theregister.co.uk",
+ "worldfree4u.com",
+ "f-lite.ru",
+ "boingboing.net",
+ "bangbros.com",
+ "neteller.com",
+ "tonicmovies.com",
+ "p2up.ir",
+ "cartoonnetwork.com",
+ "lun.com",
+ "nk.pl",
+ "webry.info",
+ "burningcamel.com",
+ "mplife.com",
+ "nationalreview.com",
+ "williamhill.es",
+ "sssc.cn",
+ "col3negoriginal.lk",
+ "yoast.com",
+ "svyaznoy.ru",
+ "chengdu.cn",
+ "listverse.com",
+ "lastminute.com",
+ "guardianlv.com",
+ "39yst.com",
+ "bahseazad.ir",
+ "debian.org",
+ "tokyo-porn-tube.com",
+ "ilbe.com",
+ "upsocl.com",
+ "balatarin.com",
+ "charter97.org",
+ "wpexplorer.com",
+ "immi.gov.au",
+ "yokamen.cn",
+ "esmas.com",
+ "hbr.org",
+ "livechatinc.com",
+ "crazyegg.com",
+ "palcomp3.com",
+ "calottery.com",
+ "wistia.com",
+ "locaweb.com.br",
+ "techspot.com",
+ "bit.ly",
+ "yammer.com",
+ "uscis.gov",
+ "bramjnet.com",
+ "linio.com.mx",
+ "tharunaya.co.uk",
+ "desirulez.net",
+ "madmimi.com",
+ "everydayhealth.com",
+ "secondlife.com",
+ "ceskatelevize.cz",
+ "enter.ru",
+ "glopart.ru",
+ "woso.cn",
+ "pitlap.info",
+ "worldoftanks.com",
+ "videarn.com",
+ "dafiti.com.br",
+ "segundamano.mx",
+ "eamroomsnacks.com",
+ "vulture.com",
+ "humblebundle.com",
+ "rockstargames.com",
+ "wsodownloads.info",
+ "yazete.com",
+ "pcadvisor.co.uk",
+ "07073.com",
+ "modcloth.com",
+ "attracta.com",
+ "iol.pt",
+ "travideos.com",
+ "sparkpeople.com",
+ "rankingsandreviews.com",
+ "entekhab.ir",
+ "goarticles.com",
+ "wonderhowto.com",
+ "kankanews.com",
+ "rzb.ir",
+ "p30download.com",
+ "infojobs.it",
+ "socialspark.com",
+ "picstopin.com",
+ "celebritynetworth.com",
+ "tweakers.net",
+ "gi-backoffice.com",
+ "isbank.com.tr",
+ "qiyou.com",
+ "templatic.com",
+ "cyberpresse.ca",
+ "consumerreports.org",
+ "focalprice.com",
+ "linkpad.ru",
+ "svd.se",
+ "desitvforum.net",
+ "bulbagarden.net",
+ "showup.tv",
+ "webgozar.com",
+ "3dnews.ru",
+ "spyfu.com",
+ "bikhir.ma",
+ "trovaprezzi.it",
+ "autov.com.cn",
+ "podnapisi.net",
+ "tocmai.ro",
+ "realitatea.net",
+ "geico.com",
+ "joydownload.com",
+ "kddi.com",
+ "unbounce.com",
+ "meb.gov.tr",
+ "anchorfree.us",
+ "gumtree.pl",
+ "dbs.com",
+ "ebayimg.com",
+ "ptcsolution.com",
+ "clip.dj",
+ "samplicio.us",
+ "47news.jp",
+ "todo1.com",
+ "anspress.com",
+ "24sata.hr",
+ "cineblog01.tv",
+ "sport-fm.gr",
+ "unetenet.com",
+ "tenki.jp",
+ "jia.com",
+ "filefactory.com",
+ "onedio.com",
+ "gendai.net",
+ "nickjr.com",
+ "finviz.com",
+ "bytes.com",
+ "inkthemes.com",
+ "oriflame.com",
+ "aporrea.org",
+ "mazika2day.com",
+ "baimao.com",
+ "logme.in",
+ "downloadactivate.com",
+ "vista.ir",
+ "duowan.com",
+ "sinaapp.com",
+ "proceso.com.mx",
+ "xxxconnect.com",
+ "dvdvideosoft.com",
+ "nomorerack.com",
+ "almubasher.com.sa",
+ "afisha.ru",
+ "clicksure.com",
+ "11st.co.kr",
+ "turkishairlines.com",
+ "freekaamaal.com",
+ "findwide.com",
+ "sbisec.co.jp",
+ "mythemeshop.com",
+ "webnode.com",
+ "cumhuriyet.com.tr",
+ "morningstar.com",
+ "trafficshop.com",
+ "gopro.com",
+ "jeevansathi.com",
+ "dasoertliche.de",
+ "markets.com",
+ "absa.co.za",
+ "ikman.lk",
+ "fmworld.net",
+ "hyatt.com",
+ "virgin-atlantic.com",
+ "tfl.gov.uk",
+ "immonet.de",
+ "haodf.com",
+ "thewrap.com",
+ "appgame.com",
+ "hdwallpapers.in",
+ "canon.com",
+ "newsle.com",
+ "jorudan.co.jp",
+ "pcwelt.de",
+ "coinbase.com",
+ "yourgirlfriends.com",
+ "djmaza.info",
+ "findagrave.com",
+ "lainformacion.com",
+ "teacup.com",
+ "ezilon.com",
+ "redbubble.com",
+ "guru.com",
+ "brothersoft.com",
+ "coinmarketcap.com",
+ "mediabistro.com",
+ "elfagr.org",
+ "glavcom.ua",
+ "jino.ru",
+ "1e100.net",
+ "g9g.com",
+ "join.me",
+ "ynet.com",
+ "news247.gr",
+ "rcom.co.in",
+ "baby.ru",
+ "argentglobalnetwork.com",
+ "hsselite.com",
+ "foxbusiness.com",
+ "cookmates.com",
+ "lidl.de",
+ "timesofindia.com",
+ "fakt.pl",
+ "bgr.com",
+ "ghatreh.com",
+ "woxikon.de",
+ "pontofrio.com.br",
+ "gizmag.com",
+ "signup.wordpress.com",
+ "tre.it",
+ "gardenweb.com",
+ "alfalfalfa.com",
+ "prcm.jp",
+ "freemail.hu",
+ "iteye.com",
+ "katproxy.com",
+ "kickassunblock.info",
+ "wisegeek.com",
+ "zaobao.com",
+ "vpsdomain4.eu",
+ "naij.com",
+ "olx.co.za",
+ "mihanstore.org",
+ "gezinti.com",
+ "vistaprint.in",
+ "dastelefonbuch.de",
+ "blackhatteam.com",
+ "yummly.com",
+ "minecraft.net",
+ "justcloud.com",
+ "biblehub.com",
+ "argentinawarez.com",
+ "gandul.info",
+ "trialpay.com",
+ "paruvendu.fr",
+ "khanacademy.org",
+ "topsy.com",
+ "angelfire.com",
+ "nseindia.com",
+ "seositecheckup.com",
+ "hostelworld.com",
+ "zalukaj.tv",
+ "animeflv.net",
+ "laptopmag.com",
+ "tripadvisor.de",
+ "sec.gov",
+ "tripadvisor.es",
+ "oreilly.com",
+ "kanald.com.tr",
+ "halifax-online.co.uk",
+ "extremetracking.com",
+ "reimageplus.com",
+ "jal.co.jp",
+ "vuiviet.net",
+ "yeslibertin.com",
+ "pichunter.com",
+ "empowernetwork.com/aI3zkH7s3g6tZH8TDmh8LA==",
+ "reforma.com",
+ "singlessalad.com",
+ "upenn.edu",
+ "1ting.com",
+ "hsbc.com.mx",
+ "sulia.com",
+ "yepporn.com",
+ "scrubtheweb.com",
+ "e-autopay.com",
+ "rechargeitnow.com",
+ "ppomppu.co.kr",
+ "zemtv.com",
+ "gofeminin.de",
+ "peoplestylewatch.com",
+ "france24.com",
+ "comodo.com",
+ "openmace.net",
+ "maultalk.com",
+ "fancy.com",
+ "vodafone.it",
+ "pokerstrategy.com",
+ "crunchyroll.com",
+ "aipai.com",
+ "3dcartstores.com",
+ "leancy.com",
+ "myblogguest.com",
+ "papajohns.com",
+ "tuolar.com",
+ "junkmail.co.za",
+ "nyc.gov",
+ "rentalcars.com",
+ "sovsport.ru",
+ "marketo.com",
+ "smbc.co.jp",
+ "yale.edu",
+ "pitchfork.com",
+ "thetoptens.com",
+ "joyme.com",
+ "linuxquestions.org",
+ "htmlgoodies.com",
+ "laredoute.fr",
+ "0427d7.se",
+ "journaldesfemmes.com",
+ "xici.net",
+ "alwafd.org",
+ "daniweb.com",
+ "mtgox.com",
+ "jetstar.com",
+ "plotek.pl",
+ "jobvite.com",
+ "adage.com",
+ "aukro.cz",
+ "ford.com",
+ "problogger.net",
+ "518.com.tw",
+ "blogbigtime.com",
+ "nieuwsblad.be",
+ "register.com",
+ "24tv.ua",
+ "aftenposten.no",
+ "weightwatchers.com",
+ "smartpassiveincome.com",
+ "radiosvoboda.org",
+ "web.com",
+ "caixin.com",
+ "digitalmarketer.com",
+ "soup.io",
+ "soft98.ir",
+ "muzofon.com",
+ "gao7.com",
+ "freefilmshd.com",
+ "hsbc.com",
+ "xhamsterhq.com",
+ "my.tv.sohu.com/user/reg",
+ "trade65.com",
+ "chow.com",
+ "google.com.kh",
+ "inps.it",
+ "seesaa.jp",
+ "hoovers.com",
+ "peru21.pe",
+ "sdpnoticias.com",
+ "schema.org",
+ "linode.com",
+ "theknot.com",
+ "blesk.cz",
+ "google.ci",
+ "loltrk.com",
+ "vod.pl",
+ "geenstijl.nl",
+ "moneymakergroup.com",
+ "tupaki.com",
+ "huvrtech.com",
+ "metafilter.com",
+ "jumia.com.ng",
+ "newsvine.com",
+ "mylant.com",
+ "accenture.com",
+ "feedjit.com",
+ "twipple.jp",
+ "getgoodlinks.ru",
+ "radiofarda.com",
+ "informador.com.mx",
+ "wisc.edu",
+ "windows.net",
+ "zamzar.com",
+ "nationalpost.com",
+ "epnet.com",
+ "naaptol.com",
+ "x-art.com",
+ "ebookbrowsee.net",
+ "marketingland.com",
+ "thedailyshow.com",
+ "s-oman.net",
+ "theme-fusion.com",
+ "immobiliare.it",
+ "allvoices.com",
+ "adroll.com",
+ "francetvinfo.fr",
+ "callandput.com",
+ "entireweb.com",
+ "instructure.com",
+ "megacinema.fr",
+ "djelfa.info",
+ "flightaware.com",
+ "magazineluiza.com.br",
+ "ighome.com",
+ "mature-beauty.com",
+ "yuku.com",
+ "peerfly.com",
+ "hardware.fr",
+ "dcinside.com",
+ "telerik.com",
+ "pengpeng.com",
+ "gazetaexpress.com",
+ "publico.es",
+ "nwsource.com",
+ "oneandone.co.uk",
+ "qoo10.sg",
+ "aboutus.org",
+ "adsupplyads.com",
+ "wa.gov",
+ "google.co.cr",
+ "benchmarkemail.com",
+ "valuedealshopper.com",
+ "hola.com",
+ "mizuhobank.co.jp",
+ "zzstream.li",
+ "kriesi.at",
+ "exist.ru",
+ "nvidia.com",
+ "giallozafferano.it",
+ "jusbrasil.com.br",
+ "konga.com",
+ "avclub.com",
+ "reed.co.uk",
+ "advertig.com",
+ "ripoffreport.com",
+ "gooddrama.net",
+ "pornyaz.com",
+ "budsgunshop.com",
+ "78.cn",
+ "livesurf.ru",
+ "99114.com",
+ "pornorama.com",
+ "marksandspencer.com",
+ "vmall.com",
+ "fatcow.com",
+ "mylife.com",
+ "irishtimes.com",
+ "medicalnewstoday.com",
+ "uiuc.edu",
+ "groupon.it",
+ "washington.edu",
+ "addictinggames.com",
+ "anonymz.com",
+ "kindgirls.com",
+ "jne.co.id",
+ "guiamais.com.br",
+ "lyricsfreak.com",
+ "uloz.to",
+ "tagesanzeiger.ch",
+ "fashionandyou.com",
+ "bollywoodhungama.com",
+ "nationwide.co.uk",
+ "kboing.com.br",
+ "python.org",
+ "theladbible.com",
+ "eurosport.com",
+ "webinarjam.com",
+ "theme.wordpress.com",
+ "myfxbook.com",
+ "allwomenstalk.com",
+ "ucla.edu",
+ "opendns.com",
+ "pornbb.org",
+ "money.pl",
+ "domain.com.au",
+ "standaard.be",
+ "wanelo.com",
+ "express.co.uk",
+ "exam8.com",
+ "zum.com",
+ "amtrak.com",
+ "boots.com",
+ "800notes.com",
+ "fabfurnish.com",
+ "amoureux.com",
+ "ebizmba.com",
+ "ujian.cc",
+ "stargames.at",
+ "panasonic.com",
+ "ge.tt",
+ "scout.com",
+ "tiexue.net",
+ "nanapi.jp",
+ "eclipse.org",
+ "searchquotes.com",
+ "wetplace.com",
+ "lpcloudbox300.com",
+ "hollyscoop.com",
+ "bdjobs.com",
+ "larepublica.pe",
+ "hizliresim.com",
+ "yepme.com",
+ "bitcoincharts.com",
+ "bsnl.co.in",
+ "ucwan87.net",
+ "tianji.com",
+ "hgtv.com",
+ "cleanfiles.net",
+ "moonsy.com",
+ "tomsguide.com",
+ "datpiff.com",
+ "net.hr",
+ "orange.pl",
+ "bankrate.com.cn",
+ "mafiashare.net",
+ "giaoduc.net.vn",
+ "sucuri.net",
+ "ringcentral.com",
+ "gamingwonderland.com",
+ "freenet.de",
+ "cian.ru",
+ "gayboystube.com",
+ "gog.com",
+ "gruenderszene.de",
+ "econsultancy.com",
+ "aktuality.sk",
+ "webrankstats.com",
+ "j-cast.com",
+ "popsugar.com",
+ "mr-guangdong.com",
+ "on.cc",
+ "jb51.net",
+ "lamoda.ru",
+ "sprashivai.ru",
+ "animoto.com",
+ "winzip.com",
+ "vanityfair.com",
+ "svt.se",
+ "noyapps.com",
+ "mnn.com",
+ "lancenet.com.br",
+ "e-monsite.com",
+ "gazeta.ua",
+ "cari.com.my",
+ "coub.com",
+ "veoh.com",
+ "kienthuc.net.vn",
+ "eldorado.ru",
+ "overclock.net",
+ "meetic.fr",
+ "tam.com.br",
+ "alfemminile.com",
+ "telmex.com",
+ "newsbomb.gr",
+ "funda.nl",
+ "netcoc.com",
+ "bhinneka.com",
+ "layalina.com",
+ "clubpenguin.com",
+ "talktalk.co.uk",
+ "dumpert.nl",
+ "almastba.com",
+ "clker.com",
+ "adweek.com",
+ "gigya.com",
+ "disponivel.uol.com.br",
+ "tomoson.com",
+ "w.org",
+ "rfi.fr",
+ "imgbox.com",
+ "omniture.com",
+ "n24.de",
+ "webdesignrazzi.com",
+ "medscape.com",
+ "playboy.com",
+ "usda.gov",
+ "cuevana.tv",
+ "trenitalia.com",
+ "explosm.net",
+ "mail.uol.com.br",
+ "delfi.lv",
+ "elektroda.pl",
+ "hulkshare.com",
+ "kotak.com",
+ "gi-akademie.ning.com",
+ "yelp.de",
+ "lrytas.lt",
+ "couchsurfing.org",
+ "drugstore.com",
+ "ssa.gov",
+ "seriescoco.com",
+ "iran-tejarat.com",
+ "hafiz.gov.sa",
+ "intellicast.com",
+ "sub.jp",
+ "paginasamarillas.es",
+ "anime44.com",
+ "babyschool.com.cn",
+ "advertisernets.com",
+ "vpsdomain2.eu",
+ "arcor.de",
+ "video2mp3.net",
+ "marthastewart.com",
+ "hawahome.com",
+ "articlesbase.com",
+ "spanishdict.com",
+ "meilishuo.com",
+ "grammarly.com",
+ "sportlemon.tv",
+ "zend.com",
+ "bigideamastermind.com",
+ "hawaaworld.com",
+ "pagseguro.uol.com.br",
+ "keywordspy.com",
+ "7search.com",
+ "cnki.net",
+ "aamaadmiparty.org",
+ "javaplayer.info",
+ "sidereel.com",
+ "azcentral.com",
+ "passportindia.gov.in",
+ "memurlar.net",
+ "bouyguestelecom.fr",
+ "buenastareas.com",
+ "ernmoneynow.com",
+ "eurosport.ru",
+ "blog.163.com",
+ "pizzahut.com",
+ "bossip.com",
+ "webdeveloper.com",
+ "add-anime.net",
+ "pimptubed.com",
+ "movistar.es",
+ "megashare.sh",
+ "empireavenue.com",
+ "btemplates.com",
+ "amkspor.com",
+ "payza.com",
+ "farfesh.com",
+ "mcgraw-hill.com",
+ "motor-talk.de",
+ "purepeople.com",
+ "i-gamer.net",
+ "sotmarket.ru",
+ "anthropologie.com",
+ "google.org",
+ "rai.tv",
+ "wikidot.com",
+ "canoe.ca",
+ "orange.es",
+ "umn.edu",
+ "emag.ro",
+ "webutations.org",
+ "ykb.com",
+ "canadapost.ca",
+ "zhubajie.com",
+ "nextcar.cn",
+ "next.co.uk",
+ "freemovie-hd.com",
+ "telegraf.com.ua",
+ "ajc.com",
+ "xsrv.jp",
+ "vanguard.com",
+ "mybroadband.co.za",
+ "999120.net",
+ "panet.co.il",
+ "bellemaison.jp",
+ "fonearena.com",
+ "playvid.com",
+ "purdue.edu",
+ "thesuperficial.com",
+ "114so.cn",
+ "irna.ir",
+ "websitetonight.com",
+ "edublogs.org",
+ "provincial.com",
+ "jahaniha.com",
+ "heroturko.me",
+ "dynadot.com",
+ "txtsrving.info",
+ "adclickxpress.com",
+ "sammobile.com",
+ "ebay.at",
+ "yaplog.jp",
+ "imtranslator.net",
+ "fotor.com",
+ "myvidster.com",
+ "williamhill.it",
+ "argaam.com",
+ "zoomby.ru",
+ "tcsbank.ru",
+ "origin.com",
+ "vov.vn",
+ "wrapbootstrap.com",
+ "imvu.com",
+ "fbsbx.com",
+ "elcorteingles.es",
+ "cerdas.com",
+ "google.com.om",
+ "dramasonline.com",
+ "businesswire.com",
+ "serpbook.com",
+ "santanderrio.com.ar",
+ "meta.ua",
+ "kenhgioitre.com",
+ "watchcartoononline.com",
+ "athome.co.jp",
+ "2checkout.com",
+ "moheet.com",
+ "jeu.info",
+ "ankieta-online.pl",
+ "triberr.com",
+ "wordtracker.com",
+ "blogher.com",
+ "colourlovers.com",
+ "maalaimalar.com",
+ "bakeca.it",
+ "thepostgame.com",
+ "beget.ru",
+ "abebooks.com",
+ "certified-toolbar.com",
+ "publico.pt",
+ "footmercato.net",
+ "indiabix.com",
+ "zakzak.co.jp",
+ "hotfile.com",
+ "virustotal.com",
+ "usgs.gov",
+ "tukif.com",
+ "banglamail24.com",
+ "graphicstock.com",
+ "svpressa.ru",
+ "sanalpazar.com",
+ "logsoku.com",
+ "loteriasyapuestas.es",
+ "youjizzlive.com",
+ "all-inkl.com",
+ "arcot.com",
+ "blogspot.fi",
+ "inbox.lv",
+ "anno-online.com",
+ "tikona.in",
+ "newsru.ua",
+ "centerblog.net",
+ "jahannews.com",
+ "joxi.ru",
+ "proxybay.eu",
+ "2gis.ru",
+ "indeed.fr",
+ "novayagazeta.ru",
+ "intelius.com",
+ "hosteurope.de",
+ "autoscout24.it",
+ "postjoint.com",
+ "pulsk.com",
+ "biobiochile.cl",
+ "homevv.com",
+ "zapbux.com",
+ "gsp.ro",
+ "priyo.com",
+ "jamnews.ir",
+ "addtoany.com",
+ "lookbook.nu",
+ "e-travel.com",
+ "themelock.com",
+ "bestsocialfeed.com",
+ "eqla3.com",
+ "klm.com",
+ "realtor.ca",
+ "tv2.no",
+ "jqueryrain.com",
+ "seo-fast.ru",
+ "academic.ru",
+ "clicksia.com",
+ "lpcloudbox30.com",
+ "worldpay.com",
+ "gogoanime.com",
+ "photoshelter.com",
+ "mlive.com",
+ "wetteronline.de",
+ "jkforum.net",
+ "secure.ipage.com",
+ "antena3.com",
+ "elsevier.com",
+ "thaiseoboard.com",
+ "addic7ed.com",
+ "rookee.ru",
+ "jstor.org",
+ "rajanews.com",
+ "uline.com",
+ "o2online.de",
+ "fbdownloader.com",
+ "wetpaint.com",
+ "nnm.me",
+ "50onred.com",
+ "tvtropes.org",
+ "philips.com",
+ "watchseries.to",
+ "perfectinter.net",
+ "progressive.com",
+ "stcn.com",
+ "golsearch.com",
+ "sarayanews.com",
+ "screenrant.com",
+ "macworld.com",
+ "classifiedads.com",
+ "ip138.com",
+ "izlesene.com",
+ "ovguide.com",
+ "gametop.com",
+ "urlm.co",
+ "isitdownrightnow.com",
+ "redhat.com",
+ "stafaband.info",
+ "biglion.ru",
+ "twitterfeed.com",
+ "ttnet.com.tr",
+ "panasonic.jp",
+ "loc.gov",
+ "telstra.com.au",
+ "jiathis.com",
+ "perfil.com.ar",
+ "inquisitr.com",
+ "ratp.fr",
+ "libertaddigital.com",
+ "bni.co.id",
+ "ycombinator.com",
+ "paginegialle.it",
+ "momoshop.com.tw",
+ "theweek.com",
+ "tuoitre.vn",
+ "scriptmafia.org",
+ "megavod.fr",
+ "indiavisiontv.com",
+ "history.com",
+ "flyeralarm.com",
+ "salespider.com",
+ "ard.de",
+ "dslreports.com",
+ "tokyo-tube.com",
+ "brazzersnetwork.com",
+ "bonanza.com",
+ "storenvy.com",
+ "37signals.com",
+ "jxnews.com.cn",
+ "1sale.com",
+ "allanalpass.com",
+ "yiiframework.com",
+ "kimsufi.com",
+ "nastygal.com",
+ "immoral.jp",
+ "icq.com",
+ "loxblog.com",
+ "jcrew.com",
+ "diamond.jp",
+ "nissen.co.jp",
+ "fxstreet.com",
+ "15min.lt",
+ "lifo.gr",
+ "alef.ir",
+ "iis.net",
+ "giphy.com",
+ "mypopup.ir",
+ "bsnl.in",
+ "distractify.com",
+ "foro20.com",
+ "chachaba.com",
+ "fx-trend.com",
+ "imanhua.com",
+ "playxn.com",
+ "gocomics.com",
+ "lcl.fr",
+ "hsw.cn",
+ "ellislab.com",
+ "persiantools.com",
+ "coupondunia.in",
+ "fengniao.com",
+ "coinmill.com",
+ "freelancer.in",
+ "blogdetik.com",
+ "data.com",
+ "trafficjunky.net",
+ "neverblue.com",
+ "flvto.com",
+ "lijit.com",
+ "zaycev.net",
+ "salamnews.org",
+ "siliconrus.com",
+ "dv37.com",
+ "conrad.de",
+ "ascii.jp",
+ "yesfreeporn.com",
+ "globalpost.com",
+ "d4000.com",
+ "dobreprogramy.pl",
+ "hammihan.com",
+ "wjunction.com",
+ "liverpoolfc.tv",
+ "nordea.fi",
+ "mail2web.com",
+ "songkick.com",
+ "comicbookresources.com",
+ "jwplayer.com",
+ "moi.gov.sa",
+ "iranecar.com",
+ "kayako.com",
+ "listal.com",
+ "technet.com",
+ "infonews.com",
+ "fun698.com",
+ "frys.com",
+ "vectorstock.com",
+ "vbox7.com",
+ "leroymerlin.fr",
+ "gpotato.eu",
+ "gulfnews.com",
+ "hot-sex-tube.com",
+ "buzzle.com",
+ "uludagsozluk.com",
+ "onlinefastpaydayloan.com",
+ "forumcommunity.net",
+ "potins.net",
+ "bwin.es",
+ "lobstertube.com",
+ "katestube.com",
+ "endomondo.com",
+ "navalny.livejournal.com",
+ "wayport.net",
+ "dealspl.us",
+ "pixhost.org",
+ "webopedia.com",
+ "flagcounter.com",
+ "hotnewhiphop.com",
+ "matomy.com",
+ "privat24.ua",
+ "fuq.com",
+ "readserver.net",
+ "haiwainet.cn",
+ "light-dark.net",
+ "decolar.com",
+ "tlbb8.com",
+ "tomtom.com",
+ "fontanka.ru",
+ "tchibo.de",
+ "slutfinder.com",
+ "rbc.cn",
+ "pepperfry.com",
+ "freshersworld.com",
+ "mob.org",
+ "brobible.com",
+ "phim3s.net",
+ "parsiblog.com",
+ "link-assistant.com",
+ "smotri.com",
+ "flyertalk.com",
+ "iefimerida.gr",
+ "pornyeah.com",
+ "trustpilot.com",
+ "wowslider.com",
+ "sekindo.com",
+ "shape.com",
+ "pizap.com",
+ "bluedart.com",
+ "cmu.edu",
+ "shueisha.co.jp",
+ "royal-search.com",
+ "123greetings.com",
+ "albawabhnews.com",
+ "holiday-weather.com",
+ "4travel.jp",
+ "lpcloudsvr203.com",
+ "panorama.com.ve",
+ "htcmania.com",
+ "skorer.tv",
+ "mymovies.it",
+ "fileice.net",
+ "1and1.fr",
+ "legiaodosherois.com.br",
+ "tomsguide.fr",
+ "baymirror.com",
+ "thesun.co.uk",
+ "huffingtonpost.es",
+ "61baobao.com",
+ "juegos.com",
+ "joyclub.de",
+ "qatarairways.com",
+ "ayosdito.ph",
+ "translate.ru",
+ "yithemes.com",
+ "buyvip.com",
+ "pearltrees.com",
+ "thinkprogress.org",
+ "twitcasting.tv",
+ "lusongsong.com",
+ "irecommend.ru",
+ "aukro.ua",
+ "eldiario.es",
+ "pop-music.ir",
+ "libertytimes.com.tw",
+ "themalaysianinsider.com",
+ "paddypower.it",
+ "delfi.ee",
+ "appthemes.com",
+ "tdameritrade.com",
+ "flashback.org",
+ "tubelib.com",
+ "claro.com.br",
+ "jotform.com",
+ "bigresource.com",
+ "libsyn.com",
+ "sendgrid.com",
+ "silikonvadisi.tv",
+ "geo.tv",
+ "pricegrabber.com",
+ "futhead.com",
+ "testberichte.de",
+ "skybet.com",
+ "wpcentral.com",
+ "lesnumeriques.com",
+ "clientoo.com",
+ "mathsisfun.com",
+ "expert.ru",
+ "maxptp.com",
+ "mediaite.com",
+ "regions.com",
+ "fast-torrent.ru",
+ "enlacespepito.com",
+ "redtram.com",
+ "benesse.ne.jp",
+ "jappy.de",
+ "wizzair.com",
+ "adevarul.ro",
+ "mhlw.go.jp",
+ "dev-point.com",
+ "ibtimes.co.in",
+ "coinwarz.com",
+ "slidesharecdn.com",
+ "classmates.com",
+ "tsite.jp",
+ "niazerooz.com",
+ "jma.go.jp",
+ "motherjones.com",
+ "easports.com",
+ "elbotola.com",
+ "tripadvisor.com.au",
+ "rozee.pk",
+ "vivanuncios.com.mx",
+ "lashou.com",
+ "theaustralian.com.au",
+ "superstarmagazine.com",
+ "zedge.net",
+ "hardwarezone.com.sg",
+ "yyets.com",
+ "nowgamez.com",
+ "blogspot.ch",
+ "gq.com",
+ "adidas.com",
+ "uyan.cc",
+ "dailydot.com",
+ "xenforo.com",
+ "ilmessaggero.it",
+ "state.nj.us",
+ "16888.com",
+ "searchengines.guru",
+ "nascar.com",
+ "dnb.no",
+ "smosh.com",
+ "shinyinnovation.com",
+ "who.int",
+ "mybet.com",
+ "yoo7.com",
+ "xrea.com",
+ "fotolog.net",
+ "smartprix.com",
+ "esquire.com",
+ "google.com.cy",
+ "santander.com.br",
+ "realclearpolitics.com",
+ "financereports24.com",
+ "onlinesoccermanager.com",
+ "noticiaaldia.com",
+ "kelkoo.com",
+ "drakulastream.eu",
+ "vodafone.de",
+ "bt.dk",
+ "greenwichmeantime.com",
+ "ufc.com",
+ "webstatsdomain.org",
+ "taoche.com",
+ "thinkgeek.com",
+ "caranddriver.com",
+ "123-reg.co.uk",
+ "translit.ru",
+ "w3school.com.cn",
+ "zwinky.com",
+ "inboxdollars.com",
+ "gratka.pl",
+ "vecernji.hr",
+ "taikang.com",
+ "bolshoyvopros.ru",
+ "urbita.com",
+ "api.ning.com",
+ "alltop.com",
+ "readwrite.com",
+ "medhelp.org",
+ "totaljobs.com",
+ "accorhotels.com",
+ "prom.ua",
+ "cuny.edu",
+ "livemint.com",
+ "berlin.de",
+ "blogspot.hk",
+ "orkut.com.br",
+ "lzjl.com",
+ "metric-conversions.org",
+ "nationalrail.co.uk",
+ "oxu.az",
+ "mql5.com",
+ "chinaluxus.com",
+ "linguee.es",
+ "saudiairlines.com",
+ "standardmedia.co.ke",
+ "alkislarlayasiyorum.com",
+ "apk.tw",
+ "lesoir.be",
+ "whatculture.com",
+ "indiewire.com",
+ "pccomponentes.com",
+ "paytm.in",
+ "ebaypartnernetwork.com",
+ "haivl.tv",
+ "e-junkie.com",
+ "tvp.pl",
+ "ifilez.org",
+ "aristeguinoticias.com",
+ "bangkokpost.com",
+ "whatmobile.com.pk",
+ "prodavalnik.com",
+ "arsenal.com",
+ "buyma.com",
+ "torrentday.com",
+ "sammydress.com",
+ "blogcu.com",
+ "imore.com",
+ "shitaraba.com",
+ "pasadrexam2014.in",
+ "songspk.at",
+ "eforosh.com",
+ "nocoty.pl",
+ "koreus.com",
+ "verticalresponse.com",
+ "arte.tv",
+ "ocnk.net",
+ "cryptsy.com",
+ "haaretz.com",
+ "straitstimes.com",
+ "2domains.ru",
+ "usnetads.com",
+ "pracuj.pl",
+ "edreams.it",
+ "sba.gov",
+ "instabang.com",
+ "domainnamesales.com",
+ "teensnow.com",
+ "visualwebsiteoptimizer.com",
+ "blogos.com",
+ "santander.com.mx",
+ "solidfiles.com",
+ "authorstream.com",
+ "teslamotors.com",
+ "tema.livejournal.com",
+ "kolesa.kz",
+ "startribune.com",
+ "vevo.com",
+ "clien.net",
+ "3asq.com",
+ "tvnet.lv",
+ "mouthshut.com",
+ "binary-machine.com",
+ "adultwork.com",
+ "hypebeast.com",
+ "itrack.it",
+ "network-tools.com",
+ "brandsoftheworld.com",
+ "comedycentral.com",
+ "hotscripts.com",
+ "meristation.com",
+ "rlsbb.com",
+ "uzai.com",
+ "volkskrant.nl",
+ "terra.com.mx",
+ "howtoforge.com",
+ "178.com",
+ "wickedfire.com",
+ "dilandau.eu",
+ "seriales.us",
+ "xataka.com",
+ "hktdc.com",
+ "express.pk",
+ "surfcanyon.com",
+ "buildhr.com",
+ "ouest-france.fr",
+ "stltoday.com",
+ "alternet.org",
+ "site5.com",
+ "payserve.com",
+ "society6.com",
+ "douguo.com",
+ "prosieben.de",
+ "verywed.com",
+ "enikos.gr",
+ "tubewolf.com",
+ "openrice.com",
+ "blankrefer.com",
+ "gouv.qc.ca",
+ "torrentfreak.com",
+ "craveonline.com",
+ "unfollowers.com",
+ "deser.pl",
+ "quanjing.com",
+ "runetki.tv",
+ "yepi.com",
+ "socialbakers.com",
+ "webmotors.com.br",
+ "mmo-champion.com",
+ "globososo.com",
+ "whois.sc",
+ "sportskeeda.com",
+ "socialblade.com",
+ "jin115.com",
+ "avjavjav.com",
+ "thenewstribe.com",
+ "pinkrod.com",
+ "blox.pl",
+ "mediamarkt.de",
+ "vivo.com.br",
+ "facilisimo.com",
+ "sinarharian.com.my",
+ "leguide.com",
+ "voegol.com.br",
+ "j.gs",
+ "okgj.com",
+ "revolveclothing.com",
+ "lolinez.com",
+ "go2cloud.org",
+ "vmoptions.com",
+ "myip.ms",
+ "ay.gy",
+ "liquidweb.com",
+ "sbi.co.in",
+ "alamaula.com",
+ "reshareable.tv",
+ "stirileprotv.ro",
+ "siriusxm.com",
+ "banvenez.com",
+ "sergey-mavrodi-mmm.net",
+ "ocj.com.cn",
+ "elderscrollsonline.com",
+ "webaslan.com",
+ "dereferer.org",
+ "newsbeast.gr",
+ "778669.com",
+ "yeucahat.com",
+ "guitarcenter.com",
+ "mercurynews.com",
+ "channeladvisor.com",
+ "go2000.com",
+ "google.ge",
+ "pandora.tv",
+ "haqqin.az",
+ "google.tt",
+ "32d1d3b9c.se",
+ "sexdatenow.net",
+ "befunky.com",
+ "micromaxinfo.com",
+ "jquerymobile.com",
+ "radikal.ru",
+ "wigetmedia.com",
+ "girlsplay.com",
+ "pureleverage.com",
+ "mathxl.com",
+ "themefuse.com",
+ "giga.de",
+ "freevideo.cz",
+ "stylebistro.com",
+ "iwriter.com",
+ "winporn.com",
+ "tripadvisor.ca",
+ "atresplayer.com",
+ "igma.tv",
+ "ravelry.com",
+ "semana.com",
+ "verycd.com",
+ "sblo.jp",
+ "fansided.com",
+ "goalunited.org",
+ "petfinder.com",
+ "worthofweb.com",
+ "memuruz.net",
+ "njuskalo.hr",
+ "yellowpages.ca",
+ "91jm.com",
+ "webconfs.com",
+ "interpals.net",
+ "erepublik.com",
+ "akismet.com",
+ "gaadi.com",
+ "casasbahia.com.br",
+ "techsupportalert.com",
+ "bostonglobe.com",
+ "uploadable.ch",
+ "smartprofitsystem.com",
+ "cimbclicks.com.my",
+ "uwants.com",
+ "gamestar.de",
+ "neowin.net",
+ "inilah.com",
+ "toster.ru",
+ "gosuslugi.ru",
+ "windguru.cz",
+ "3366.com",
+ "beinsports.net",
+ "vector.co.jp",
+ "memecenter.com",
+ "hotnews.ro",
+ "webgame.web.id",
+ "llnw.com",
+ "jobstreet.co.id",
+ "congratulations-you-won.com",
+ "libertatea.ro",
+ "app111.com",
+ "scientificamerican.com",
+ "strava.com",
+ "iranjib.ir",
+ "coneco.net",
+ "fdrmx.com",
+ "nps.gov",
+ "businessinsider.in",
+ "uniblue.com",
+ "proporn.com",
+ "dm5.com",
+ "qld.gov.au",
+ "nexusmods.com",
+ "mandatory.com",
+ "moskva.fm",
+ "prosperityteam.com",
+ "lent.az",
+ "appbrain.com",
+ "24smi.org",
+ "avaxsearch.com",
+ "gorillavid.in",
+ "realgm.com",
+ "favicon.cc",
+ "astro.com",
+ "joomlaforum.ru",
+ "joystiq.com",
+ "computerworld.com",
+ "tvspielfilm.de",
+ "centos.org",
+ "bugun.com.tr",
+ "amctv.com",
+ "relianceada.com",
+ "papystreaming.com",
+ "clickindia.com",
+ "sayyac.com",
+ "q.gs",
+ "bravoerotica.com",
+ "bibsonomy.org",
+ "netload.in",
+ "shopatron.com",
+ "iautos.cn",
+ "banggood.com",
+ "commerzbanking.de",
+ "legacyclix.com",
+ "intesasanpaolo.com",
+ "awesomescreenshot.com",
+ "desidime.com",
+ "eporner.com",
+ "alwatanvoice.com",
+ "ok.ru",
+ "europe1.fr",
+ "karnaval.com",
+ "tornn-tv.com",
+ "frmtr.com",
+ "pulscen.ru",
+ "groupon.co.uk",
+ "tradera.com",
+ "comingsoon.net",
+ "speckyboy.com",
+ "cargurus.com",
+ "citysearch.com",
+ "brother.com",
+ "acfun.tv",
+ "jamejamonline.ir",
+ "enterprise.com",
+ "elotrolado.net",
+ "userscripts.org",
+ "confirmit.com",
+ "compete.com",
+ "auctiva.com",
+ "potterybarn.com",
+ "ivoox.com",
+ "multiupload.nl",
+ "glavnoe.ua",
+ "p30world.com",
+ "snapnames.com",
+ "filmon.com",
+ "flipkey.com",
+ "rhhbschool.com",
+ "worldbank.org",
+ "proz.com",
+ "docusign.net",
+ "akakce.com",
+ "empflix.com",
+ "androidforums.com",
+ "mos.ru",
+ "contenko.com",
+ "malwarebytes.org",
+ "voyeurhit.com",
+ "filmvz.com",
+ "windowsazure.com",
+ "rlslog.net",
+ "zulagames.com",
+ "onlinefinder.net",
+ "blekko.com",
+ "tvb.com",
+ "mojomarketplace.com",
+ "warnerbros.com",
+ "rogers.com",
+ "sparkasse.at",
+ "bigcinema.tv",
+ "mattcutts.com",
+ "vemale.com",
+ "pgatour.com",
+ "bakusai.com",
+ "lavozdegalicia.es",
+ "style.com",
+ "torrentino.com",
+ "activeden.net",
+ "sweetpacks-search.com",
+ "pcstore.com.tw",
+ "starmedia.com",
+ "lycos.com",
+ "uncomo.com",
+ "caribbeancom.com",
+ "googleping.com",
+ "sondakika.com",
+ "premiumwp.com",
+ "tribune.com.pk",
+ "sc.com",
+ "91mobiles.com",
+ "elle.com",
+ "motortrend.com",
+ "starsports.com",
+ "otlan.com",
+ "planetminecraft.com",
+ "oregonlive.com",
+ "publichd.se",
+ "financialexpress.com",
+ "huxiu.com",
+ "hotwords.com",
+ "asda.com",
+ "impiego24.it",
+ "tunisia-sat.com",
+ "xojane.com",
+ "shiftdelete.net",
+ "hamshahrionline.ir",
+ "mp3.es",
+ "minutebuzz.com",
+ "footlocker.com",
+ "rusnovosti.ru",
+ "defencenet.gr",
+ "ndr.de",
+ "blogosfera.uol.com.br",
+ "quibids.com",
+ "soft32.com",
+ "davidwalsh.name",
+ "blogun.ru",
+ "webbirga.net",
+ "dict.cn",
+ "groupon.jp",
+ "abovetopsecret.com",
+ "contra.gr",
+ "zn.ua",
+ "jetbrains.com",
+ "myus.com",
+ "redbus.in",
+ "creativemarket.com",
+ "uainfo.org",
+ "rtbf.be",
+ "forexpf.ru",
+ "mainlink.ru",
+ "fantasti.cc",
+ "usagc.org",
+ "narutoget.com",
+ "trendyol.com",
+ "carsales.com.au",
+ "fujitv.co.jp",
+ "dardarkom.com",
+ "corrieredellosport.it",
+ "mcanime.net",
+ "nolo.com",
+ "beareyes.com.cn",
+ "familysearch.org",
+ "eprice.com.tw",
+ "indonetwork.co.id",
+ "geizhals.at",
+ "watchfreemovies.ch",
+ "siweiw.com",
+ "elnuevoherald.com",
+ "codecupdaters.com",
+ "p1.com",
+ "imhonet.ru",
+ "spox.com",
+ "spreadshirt.com",
+ "bittorrent.com",
+ "airberlin.com",
+ "epicurious.com",
+ "adverstitial.com",
+ "researchnow.com",
+ "lolnexus.com",
+ "xbabe.com",
+ "designmodo.com",
+ "hamusoku.com",
+ "radioshack.com",
+ "teamliquid.net",
+ "helpster.de",
+ "globalsources.com",
+ "fasttech.com",
+ "dickssportinggoods.com",
+ "j-sen.jp",
+ "smashwords.com",
+ "adversal.com",
+ "musiciansfriend.com",
+ "whoishostingthis.com",
+ "ads8.com",
+ "trend4pay.com",
+ "tribune.com",
+ "xsrving.com",
+ "youngleafs.com",
+ "gamersky.com",
+ "podio.com",
+ "state.pa.us",
+ "iphoneogram.com",
+ "datehookup.com",
+ "hbs.edu",
+ "ally.com",
+ "mitbbs.com",
+ "siasat.pk",
+ "miratuserie.tv",
+ "active.com",
+ "ricardoeletro.com.br",
+ "html.it",
+ "minnano-av.com",
+ "meetly.in",
+ "denverpost.com",
+ "supersport.com",
+ "grupobancolombia.com",
+ "freemake.com",
+ "bankier.pl",
+ "instapaper.com",
+ "derwesten.de",
+ "blogspot.hu",
+ "tamindir.com",
+ "play.pl",
+ "warthunder.com",
+ "team-bhp.com",
+ "freepeople.com",
+ "laposte.fr",
+ "cnews.ru",
+ "fayerwayer.com",
+ "hitta.se",
+ "hao123.com.eg",
+ "it-ebooks.info",
+ "freep.com",
+ "newser.com",
+ "lexilogos.com",
+ "polldaddy.com",
+ "auspost.com.au",
+ "aib.ie",
+ "cs.com.cn",
+ "providesupport.com",
+ "unblocksit.es",
+ "twittercounter.com",
+ "luisaviaroma.com",
+ "imgbabes.com",
+ "tharunee.lk",
+ "nexon.com",
+ "airliners.net",
+ "srf.ch",
+ "angel.co",
+ "tokyo-sports.co.jp",
+ "mt5.com",
+ "down1oads.com",
+ "vodonet.net",
+ "axar.az",
+ "taknaz.ir",
+ "google.com.py",
+ "ss.lv",
+ "stuffgate.com",
+ "giveawayoftheday.com",
+ "climatempo.com.br",
+ "xnxxmovies.com",
+ "heartinternet.co.uk",
+ "digikey.com",
+ "zimbra.free.fr",
+ "line.me",
+ "talkingpointsmemo.com",
+ "dyn.com",
+ "exacttarget.com",
+ "yourtango.com",
+ "shopping.com",
+ "king.com",
+ "crackberry.com",
+ "sm3na.com",
+ "matchesfashion.com",
+ "rk.com",
+ "ems.com.cn",
+ "xiaomi.cn",
+ "hillnews.com",
+ "geforce.com",
+ "internetslang.com",
+ "theoldreader.com",
+ "digitaljournal.com",
+ "aol.co.uk",
+ "straightdope.com",
+ "farfetch.com",
+ "lupoporno.com",
+ "ilgiornale.it",
+ "binzhi.com",
+ "loveplanet.ru",
+ "sogi.com.tw",
+ "googlevideo.com",
+ "nintendo.com",
+ "jreast.co.jp",
+ "coinad.com",
+ "keek.com",
+ "chegg.com",
+ "sparknotes.com",
+ "mywapblog.com",
+ "idlebrain.com",
+ "boardgamegeek.com",
+ "daserste.de",
+ "nicozon.net",
+ "ampnetzwerk.de",
+ "agenziaentrate.gov.it",
+ "apec.fr",
+ "redbull.com",
+ "listentoyoutube.com",
+ "diepresse.com",
+ "gohappy.com.tw",
+ "morguefile.com",
+ "dallasnews.com",
+ "adxpansion.com",
+ "almos3a.com",
+ "updatetube.com",
+ "lowyat.net",
+ "lolipop.jp",
+ "terafile.co",
+ "eversave.com",
+ "sportingnews.com",
+ "517dv.com",
+ "milfmovs.com",
+ "myflorida.com",
+ "brooonzyah.net",
+ "cdn-cachefront.net",
+ "ig.com",
+ "indiapost.gov.in",
+ "hangame.co.jp",
+ "ithemes.com",
+ "monova.org",
+ "udmserve.net",
+ "impactradius.com",
+ "teasernet.com",
+ "gmx.at",
+ "mmotraffic.com",
+ "citehr.com",
+ "viator.com",
+ "rt.ru",
+ "japannetbank.co.jp",
+ "zonealarm.com",
+ "ebayclassifieds.com",
+ "safecart.com",
+ "proptp.net",
+ "51hejia.com",
+ "telkomsel.com",
+ "deutschepost.de",
+ "startpagina.nl",
+ "alexaboostup.com",
+ "istgah.com",
+ "aufreeads.com",
+ "thinkstockphotos.com",
+ "similarsitesearch.com",
+ "gossiplankanews.com",
+ "venere.com",
+ "javascriptkit.com",
+ "square-enix.com",
+ "tvtoday.de",
+ "netaffiliation.com",
+ "computrabajo.com.mx",
+ "arioo.com",
+ "fromdoctopdf.com",
+ "lookany.com",
+ "bleepingcomputer.com",
+ "perfectmoney.com",
+ "dorkly.com",
+ "macmillandictionary.com",
+ "fotka.pl",
+ "porntubevidz.com",
+ "rj.gov.br",
+ "1.1.1.1",
+ "ebay.be",
+ "divxplanet.com",
+ "cyworld.com",
+ "biography.com",
+ "p1.cn",
+ "bazos.sk",
+ "55.la",
+ "lockerdome.com",
+ "yola.com",
+ "ccbill.com",
+ "groupon.de",
+ "okazii.ro",
+ "izismile.com",
+ "velvet.hu",
+ "news-postseven.com",
+ "ardmediathek.de",
+ "sagawa-exp.co.jp",
+ "sarzamindownload.com",
+ "pdfonline.com",
+ "gaaks.com",
+ "azhibo.com",
+ "pensador.uol.com.br",
+ "surveygizmo.com",
+ "familydoctor.com.cn",
+ "lazada.vn",
+ "guokr.com",
+ "enjoydressup.com",
+ "sky.de",
+ "afp.com",
+ "imujer.com",
+ "livescore.net",
+ "xinnet.com",
+ "mypageresults.com",
+ "safaribooksonline.com",
+ "extremetech.com",
+ "ecnavi.jp",
+ "babyblog.ru",
+ "practicalecommerce.com",
+ "vidspot.net",
+ "studymode.com",
+ "nation.co.ke",
+ "cpmrocket.com",
+ "es.wix.com",
+ "google.com.cu",
+ "pravda.ru",
+ "cda.pl",
+ "appszoom.com",
+ "selfhtml.org",
+ "zmovie.tw",
+ "dba.dk",
+ "domain.com",
+ "brightcove.com",
+ "lol55.com",
+ "textsale.ru",
+ "casualclub.com",
+ "gudvin.tv",
+ "torrentreactor.net",
+ "downloadcamp.com",
+ "eset.com",
+ "softonic.it",
+ "internations.org",
+ "retre.org",
+ "3quan.com",
+ "companieshouse.gov.uk",
+ "hautelook.com",
+ "edx.org",
+ "ono.es",
+ "jango.com",
+ "7sur7.be",
+ "spinrewriter.com",
+ "hqxnxx.com",
+ "elperiodico.com",
+ "arabiaweather.com",
+ "liansuo.com",
+ "pcgamer.com",
+ "offervault.com",
+ "mytheresa.com",
+ "memegenerator.net",
+ "gsm.ir",
+ "britannica.com",
+ "mensfitness.com",
+ "flaticon.com",
+ "newrelic.com",
+ "greatmmos.com",
+ "ifixit.com",
+ "aiyellow.com",
+ "my.tv.sohu.com/user/card",
+ "ce4arab.com",
+ "news-us.jp",
+ "slando.kz",
+ "redflagdeals.com",
+ "gsmhosting.com",
+ "raiffeisen.at",
+ "tagesspiegel.de",
+ "epravda.com.ua",
+ "bell.ca",
+ "sleazyneasy.com",
+ "dhnet.be",
+ "webcars.com.cn",
+ "freepik.es",
+ "androidpolice.com",
+ "cbr.ru",
+ "thanhnien.com.vn",
+ "shoptime.com.br",
+ "dailytelegraph.com.au",
+ "fastcodesign.com",
+ "full-stream.net",
+ "google.al",
+ "creativecow.net",
+ "centrum24.pl",
+ "openstat.ru",
+ "unfollowed.me",
+ "brb.to",
+ "babal.net",
+ "ibotoolbox.com",
+ "torrentdownloads.me",
+ "miami.com",
+ "mubasher.info",
+ "patient.co.uk",
+ "ayudawordpress.com",
+ "makepolo.com",
+ "exactseek.com",
+ "echosign.com",
+ "epson.com",
+ "somo.vn",
+ "tripadvisor.jp",
+ "bikroy.com",
+ "postimees.ee",
+ "band.uol.com.br",
+ "adopteunmec.com",
+ "imgserve.net",
+ "toofab.com",
+ "neeu.com",
+ "mailjet.com",
+ "kinja.com",
+ "qwertypay.com",
+ "cosme.net",
+ "dreammovies.com",
+ "avvo.com",
+ "wenyard.com",
+ "dir.bg",
+ "digital-photography-school.com",
+ "peru.com",
+ "thomsonreuters.com",
+ "grazia.com.cn",
+ "vivastreet.co.in",
+ "officemax.com",
+ "creditmutuel.fr",
+ "themify.me",
+ "ait-themes.com",
+ "share-links.biz",
+ "graphixshare.com",
+ "theoutnet.com",
+ "revolvermaps.com",
+ "careers360.com",
+ "tyroodr.com",
+ "escapistmagazine.com",
+ "ofreegames.com",
+ "surveryewadcentrez.eu",
+ "notebookcheck.net",
+ "k2s.cc",
+ "barstoolsports.com",
+ "townhall.com",
+ "mk.co.kr",
+ "epochtimes.com",
+ "arduino.cc",
+ "blogcms.jp",
+ "udacity.com",
+ "habervaktim.com",
+ "funweek.it",
+ "techtunes.com.bd",
+ "shopzilla.com",
+ "sun-sentinel.com",
+ "tfile.me",
+ "novafile.com",
+ "eurogamer.net",
+ "thenewporn.com",
+ "tuttosport.com",
+ "sverve.com",
+ "simplemachines.org",
+ "nginx.org",
+ "kepu.com.cn",
+ "jxedt.com",
+ "southparkstudios.com",
+ "gusuwang.com",
+ "utrace.de",
+ "peperonity.de",
+ "hvg.hu",
+ "cairodar.com",
+ "mappy.com",
+ "kouclo.com",
+ "my.tv.sohu.com/user/lucky",
+ "lushstories.com",
+ "stocktwits.com",
+ "atlantico.fr",
+ "baihe.com",
+ "wowkeren.com",
+ "v7n.com",
+ "mozilla.com",
+ "centurylink.net",
+ "1001freefonts.com",
+ "pubdirecte.com",
+ "mercadolibre.com.pe",
+ "vandelaydesign.com",
+ "cpaelites.com",
+ "wanyh.com",
+ "propertyguru.com.sg",
+ "esy.es",
+ "torrentbutler.eu",
+ "final.ir",
+ "53.com",
+ "clips4sale.com",
+ "freerepublic.com",
+ "huffingtonpost.de",
+ "boards.ie",
+ "fluege.de",
+ "parents.com",
+ "gimp.org",
+ "adorocinema.com",
+ "yelp.ca",
+ "twicsy.com",
+ "kuaibo.com",
+ "gnu.org",
+ "parsine.com",
+ "jpc.com",
+ "cloudapp.net",
+ "expatriates.com",
+ "sproutsocial.com",
+ "natemat.pl",
+ "livingrichwithcoupons.com",
+ "x-ho.com",
+ "adv-adserver.com",
+ "downloadchop.com",
+ "sagepub.com",
+ "eleconomista.com.mx",
+ "formula1.com",
+ "quackit.com",
+ "dlsite.com",
+ "powned.tv",
+ "stream-tv.me",
+ "mindbodyonline.com",
+ "mindmeister.com",
+ "twitlonger.com",
+ "ebay.ie",
+ "deccanchronicle.com",
+ "domaintuno.com",
+ "thethirdmedia.com",
+ "laiguana.tv",
+ "flurry.com",
+ "eloqua.com",
+ "createsend.com",
+ "hrloo.com",
+ "interfax.com.ua",
+ "admin.ch",
+ "zgzcw.com",
+ "bancoestado.cl",
+ "fda.gov",
+ "chinayes.com",
+ "beslist.nl",
+ "crossfit.com",
+ "skai.gr",
+ "covers.com",
+ "antpoker.com",
+ "perfectworld.com",
+ "momdot.com",
+ "1c-bitrix.ru",
+ "feiren.com",
+ "navitime.co.jp",
+ "siliconindia.com",
+ "warning.or.kr",
+ "qatarliving.com",
+ "uber.com",
+ "ing-diba.de",
+ "boldsky.com",
+ "animeid.tv",
+ "tom.com",
+ "whatsmyserp.com",
+ "ftbpro.com",
+ "yobt.tv",
+ "toluna.com",
+ "burrp.com",
+ "viber.com",
+ "df.eu",
+ "vatera.hu",
+ "songmeanings.com",
+ "smbc-card.com",
+ "hip2save.com",
+ "wmzona.com",
+ "banamex.com",
+ "chinaacc.com",
+ "t-online.hu",
+ "indianpornvideos.com",
+ "runescape.com",
+ "wapka.mobi",
+ "115.com",
+ "blogspot.no",
+ "aksam.com.tr",
+ "bankcomm.com",
+ "giantbomb.com",
+ "maxcdn.com",
+ "topshop.com",
+ "livescores.com",
+ "rosbalt.ru",
+ "gandi.net",
+ "ioffer.com",
+ "mihandownload.com",
+ "eweb4.com",
+ "britishcouncil.org",
+ "cheetahmail.com",
+ "vbulletin.com",
+ "bradsdeals.com",
+ "empowernetwork.com/commissionloophole",
+ "vueling.com",
+ "raventools.com",
+ "yext.com",
+ "everychina.com",
+ "reduxmediia.com",
+ "openstreetmap.org",
+ "wed114.cn",
+ "dzwww.com",
+ "miibeian.gov.cn",
+ "ufl.edu",
+ "deseretnews.com",
+ "presstv.ir",
+ "copy.com",
+ "fourhourworkweek.com",
+ "buzztheme.net",
+ "bollywoodlife.com",
+ "redtubelive.com",
+ "pengyou.com",
+ "antaranews.com",
+ "selectornews.com",
+ "lavoz.com.ar",
+ "avm.de",
+ "flalottery.com",
+ "jmp9.com",
+ "baltimoresun.com",
+ "mozillazine.org",
+ "dnevnik.hr",
+ "aebn.net",
+ "mightydeals.com",
+ "livescore.eu",
+ "publipt.com",
+ "xbmc.org",
+ "scmp.com",
+ "sbobet.com",
+ "alpari.ru",
+ "harborfreight.com",
+ "linio.com.pe",
+ "2500sz.com",
+ "rdio.com",
+ "bearshare.com",
+ "thetrainline.com",
+ "888poker.es",
+ "filecrop.com",
+ "twiends.com",
+ "elnuevodia.com",
+ "rasekhoon.net",
+ "36.cn",
+ "axeso5.com",
+ "mzamin.com",
+ "webmastersitesi.com",
+ "thinkdigit.com",
+ "lifescript.com",
+ "experian.com",
+ "adorama.com",
+ "d1net.com",
+ "torrentz.pro",
+ "fullhdfilmizle.org",
+ "space.com",
+ "collider.com",
+ "zalando.it",
+ "slate.fr",
+ "carmax.com",
+ "recode.net",
+ "gfan.com",
+ "fonts.com",
+ "honda.com",
+ "ecwid.com",
+ "debate.com.mx",
+ "bmail.uol.com.br",
+ "santandernet.com.br",
+ "coderanch.com",
+ "lyricsmode.com",
+ "gametrailers.com",
+ "3600.com",
+ "designboom.com",
+ "131.com",
+ "finam.ru",
+ "df.gob.mx",
+ "85dcf732d593.se",
+ "coches.net",
+ "dhs.gov",
+ "neurs.com",
+ "poppen.de",
+ "public-api.wordpress.com",
+ "magnovideo.com",
+ "squareup.com",
+ "balagana.net",
+ "goodsearch.com",
+ "blog.ir",
+ "ne10.uol.com.br",
+ "di.se",
+ "sinembargo.mx",
+ "k618.cn",
+ "eventim.de",
+ "mysavings.com",
+ "futureshop.ca",
+ "spinding.com",
+ "landsend.com",
+ "oqenadserving.com",
+ "here.com",
+ "upi.com",
+ "picresize.com",
+ "abnamro.nl",
+ "filenuke.com",
+ "yxku.com",
+ "mypearson.com",
+ "dinakaran.com",
+ "correos.es",
+ "hotchatdirect.com",
+ "markafoni.com",
+ "gofuckbiz.com",
+ "webfindpage.com",
+ "cancan.ro",
+ "hostgator.in",
+ "latribune.fr",
+ "adxite.com",
+ "mofos.com",
+ "bluewin.ch",
+ "24ur.com",
+ "dion.ne.jp",
+ "vpsdomain3.eu",
+ "newsweek.com",
+ "oasgames.com",
+ "mtv3.fi",
+ "internetworld.de",
+ "yatedo.com",
+ "globaltimes.cn",
+ "paddypower.com",
+ "berlin1.de",
+ "norwegian.com",
+ "opteck.com",
+ "zenfolio.com",
+ "kakprosto.ru",
+ "ecosia.org",
+ "check24.de",
+ "idbibank.co.in",
+ "zoomit.ir",
+ "notebooksbilliger.de",
+ "torontosun.com",
+ "egopay.com",
+ "cnnexpansion.com",
+ "emoneyspace.com",
+ "rsport.ru",
+ "fok.nl",
+ "mql4.com",
+ "inhabitat.com",
+ "tqn.com",
+ "noticierodigital.com",
+ "wrike.com",
+ "bazos.cz",
+ "phonegap.com",
+ "microlancer.com",
+ "anipo.jp",
+ "fotocommunity.de",
+ "kuwo.cn",
+ "chinacaipu.com",
+ "terra.cl",
+ "500px.org",
+ "qantas.com.au",
+ "advertising.com",
+ "push2check.net",
+ "livefyre.com",
+ "philstar.com",
+ "erail.in",
+ "mywebgrocer.com",
+ "der-postillon.com",
+ "ru-board.com",
+ "saramin.co.kr",
+ "yjbys.com",
+ "aaa.com",
+ "flavorwire.com",
+ "fcbarcelona.com",
+ "lacentrale.fr",
+ "googlegroups.com",
+ "luck4.me",
+ "catho.com.br",
+ "centauro.com.br",
+ "sia.az",
+ "forumactif.com",
+ "paltalk.com",
+ "beyond.com",
+ "occ.com.mx",
+ "stamps.com",
+ "getoffmyinternets.net",
+ "mbok.jp",
+ "cleveland.com",
+ "ucdavis.edu",
+ "tielabs.com",
+ "hkgolden.com",
+ "vandal.net",
+ "lyst.com",
+ "mrskin.com",
+ "bunshun.jp",
+ "netcarshow.com",
+ "b1.org",
+ "hromadske.tv",
+ "sf-express.com",
+ "pirateproxy.ca",
+ "getcashforsurveys.com",
+ "clikz4freakz.com",
+ "adsupply.com",
+ "truste.org",
+ "boxuu.com",
+ "webartex.ru",
+ "usc.edu",
+ "moo.com",
+ "winkal.com",
+ "deloitte.com",
+ "xvideos-field5.com",
+ "suomi24.fi",
+ "flexmls.com",
+ "weeklystandard.com",
+ "debenhams.com",
+ "mejortorrent.com",
+ "vconnect.com",
+ "ligatus.com",
+ "skynewsarabia.com",
+ "herschina.com",
+ "92lux.cn",
+ "care.com",
+ "chip.com.tr",
+ "tangdou.com",
+ "vatanbilgisayar.com",
+ "uppit.com",
+ "metronews.fr",
+ "parenting.com.tw",
+ "meteo.gr",
+ "meetgee.com",
+ "ldlc.com",
+ "ubs.com",
+ "elcolombiano.com",
+ "mafengwo.cn",
+ "moodle.org",
+ "asiaone.com",
+ "huffingtonpost.it",
+ "ipas2free.com",
+ "casa.it",
+ "kaiserpermanente.org",
+ "listindiario.com",
+ "treehugger.com",
+ "payeer.com",
+ "mypoints.com",
+ "pjmedia.com",
+ "foreca.com",
+ "luxup.ru",
+ "halifax.co.uk",
+ "webinarjam.net",
+ "webmeup.com",
+ "webdesignledger.com",
+ "rte.ie",
+ "18andabused.com",
+ "vbulletin.org",
+ "apne.tv",
+ "immoweb.be",
+ "colonelcassad.livejournal.com",
+ "atlassian.com",
+ "investors.com",
+ "globalbux.net",
+ "wechat.com",
+ "kanoon.ir",
+ "mawaly.com",
+ "self.com",
+ "drive.ru",
+ "autozone.com",
+ "creditonebank.com",
+ "fdj.fr",
+ "hsbc.com.br",
+ "desk.com",
+ "dlvr.it",
+ "wpml.org",
+ "newmobilelife.com",
+ "crosswalk.com",
+ "thehun.com",
+ "hobbyking.com",
+ "tiantian.com",
+ "hichina.com",
+ "cyanogenmod.org",
+ "horoscope.com",
+ "bizsugar.com",
+ "popularmechanics.com",
+ "egaliteetreconciliation.fr",
+ "eol.cn",
+ "rzd.ru",
+ "escalatenetwork.net",
+ "yad2.co.il",
+ "cna.com.tw",
+ "zi-m.com",
+ "leonardo.it",
+ "ap.gov.in",
+ "rakuten.de",
+ "wallsave.com",
+ "netzwelt.de",
+ "bitrix24.ru",
+ "techinasia.com",
+ "bitstamp.net",
+ "hostelbookers.com",
+ "shoplocal.com",
+ "200please.com",
+ "tune-up.com",
+ "mapy.cz",
+ "dealnews.com",
+ "livescore.co.uk",
+ "seocentro.com",
+ "rstyle.me",
+ "neoseeker.com",
+ "kaban.tv",
+ "visualstudio.com",
+ "cinetux.org",
+ "groupon.com.br",
+ "lastpass.com",
+ "rincondelvago.com",
+ "popsci.com",
+ "2144.cn",
+ "clickfair.com",
+ "dsebd.org",
+ "banesco.com",
+ "spi0n.com",
+ "blogspot.cz",
+ "tnews.ir",
+ "nme.com",
+ "paperblog.com",
+ "firstcry.com",
+ "tophotels.ru",
+ "liepin.com",
+ "korabia.com",
+ "ifttt.com",
+ "aemet.es",
+ "alot.com",
+ "manutd.com",
+ "edreams.es",
+ "turkcell.com.tr",
+ "eva.vn",
+ "techpowerup.com",
+ "vkrugudruzei.ru",
+ "feed2all.eu",
+ "thehindubusinessline.com",
+ "express.de",
+ "ixquick.com",
+ "thrillist.com",
+ "iqilu.com",
+ "seriouseats.com",
+ "edgesuite.net",
+ "telexads.com",
+ "alza.cz",
+ "en-japan.com",
+ "al.com",
+ "dota2lounge.com",
+ "totalping.com",
+ "seocheki.net",
+ "iceporn.com",
+ "col3negoriginel.lk",
+ "porsyar.com",
+ "property24.com",
+ "madamenoire.com",
+ "markethealth.com",
+ "alphacoders.com",
+ "webempresa.com",
+ "empireonline.com",
+ "downforeveryoneorjustme.com",
+ "lankadeepa.lk",
+ "darty.com",
+ "census.gov",
+ "wapka.me",
+ "kdslife.com",
+ "jpost.com",
+ "cricfree.tv",
+ "7xxxtube.com",
+ "businesscatalyst.com",
+ "dilbert.com",
+ "gaymaletube.com",
+ "bellanaija.com",
+ "renfe.es",
+ "equifax.com",
+ "pornmaki.com",
+ "lolesports.com",
+ "yunfan.com",
+ "everybitcity.com",
+ "9yao.com",
+ "avantlink.com",
+ "paginebianche.it",
+ "xrosview.com",
+ "newsday.com",
+ "usportnews.com",
+ "petapixel.com",
+ "pistonheads.com",
+ "lidovky.cz",
+ "cvent.com",
+ "adlandpro.com",
+ "wikisource.org",
+ "ename.com",
+ "prosport.ro",
+ "sharebuilder.com",
+ "prisjakt.nu",
+ "cw.com.tw",
+ "datafilehost.com",
+ "aircanada.com",
+ "osu.edu",
+ "linuxmint.com",
+ "toyota.com",
+ "google.am",
+ "adobeconnect.com",
+ "h33t.to",
+ "companycheck.co.uk",
+ "juno.com",
+ "beitaichufang.com",
+ "alaskaair.com",
+ "tipsandtricks-hq.com",
+ "yourstory.com",
+ "wow-impulse.ru",
+ "wishpond.com",
+ "promosite.ru",
+ "weddingwire.com",
+ "icicidirect.com",
+ "mouser.com",
+ "shopstyle.co.uk",
+ "sinemalar.com",
+ "addurl.nu",
+ "seccionamarilla.com.mx",
+ "yllix.com",
+ "motorola.com",
+ "huawei.com",
+ "mp3juices.com",
+ "fitday.com",
+ "pakwheels.com",
+ "uploading.com",
+ "snapwidget.com",
+ "rsb.ru",
+ "mturk.com",
+ "libreoffice.org",
+ "acer.com",
+ "rd.com",
+ "aa.com.tr",
+ "glamour.com",
+ "docnhat.net",
+ "cnbb.com.cn",
+ "piwik.org",
+ "mycompanyadmin.com",
+ "ohozaa.com",
+ "fox.com",
+ "mastercard.com.au",
+ "microsofttranslator.com",
+ "myhabit.com",
+ "acesso.uol.com.br",
+ "cqnews.net",
+ "default-search.net",
+ "juntadeandalucia.es",
+ "carigold.com",
+ "tweepi.com",
+ "gamedog.cn",
+ "videomega.tv",
+ "softarchive.net",
+ "akamai.com",
+ "adorika.net",
+ "zorpia.com",
+ "bitdefender.com",
+ "formstack.com",
+ "al3abbarq.com",
+ "ruelala.com",
+ "andhrajyothy.com",
+ "siteheart.com",
+ "spankbang.com",
+ "buxp.org",
+ "subtlepatterns.com",
+ "cucirca.eu",
+ "apontador.com.br",
+ "sbs.co.kr",
+ "rong360.com",
+ "billmelater.com",
+ "nowdownload.ch",
+ "pingmyurl.com",
+ "main.jp",
+ "allabolag.se",
+ "fastspring.com",
+ "20d625b48e.se",
+ "wpzoom.com",
+ "dl-protect.com",
+ "onvista.de",
+ "iberia.com",
+ "learni.st",
+ "minijuegos.com",
+ "ae.com",
+ "india-forums.com",
+ "port.hu",
+ "truelocal.com.au",
+ "ziprecruiter.com",
+ "toyokeizai.net",
+ "24timezones.com",
+ "tzetze.it",
+ "the-village.ru",
+ "ptcapusa.com",
+ "indiaresults.com",
+ "desjardins.com",
+ "nchsoftware.com",
+ "yasdl.com",
+ "delo.ua",
+ "baskino.com",
+ "salary.com",
+ "freecontact.com",
+ "wumii.com",
+ "ssc.nic.in",
+ "synology.com",
+ "nttdocomo.co.jp",
+ "racing-games.com",
+ "freeonlinegames.com",
+ "aftabnews.ir",
+ "zumi.pl",
+ "efshop.com.tw",
+ "hawamer.com",
+ "eastbay.com",
+ "izvestia.ru",
+ "mosaiquefm.net",
+ "twitchy.com",
+ "slaati.com",
+ "bookingbuddy.com",
+ "networksolutionsemail.com",
+ "etsystatic.com",
+ "sina.com",
+ "asiandatingbeauties.com",
+ "blogs.com",
+ "france3.fr",
+ "healthcentral.com",
+ "downloadatoz.com",
+ "matthewwoodward.co.uk",
+ "legalzoom.com",
+ "phun.org",
+ "campaignmonitor.com",
+ "cifraclub.com.br",
+ "hir24.hu",
+ "twoplustwo.com",
+ "hotshame.com",
+ "arvixededicated.com",
+ "designcrowd.com",
+ "mrexcel.com",
+ "blu-ray.com",
+ "bundesliga.de",
+ "comments.ua",
+ "filmstarts.de",
+ "3sk.tv",
+ "donedeal.ie",
+ "natunbarta.com",
+ "forex-mmcis.com",
+ "lifehacker.ru",
+ "sitepronews.com",
+ "tudogostoso.com.br",
+ "titanfall.com",
+ "brainpickings.org",
+ "saharareporters.com",
+ "vidto.me",
+ "mlit.go.jp",
+ "terapeak.com",
+ "techweb.com.cn",
+ "premiere.fr",
+ "kanui.com.br",
+ "asianetnews.tv",
+ "cric.lk",
+ "exxxtrasmall.com",
+ "hiphopdx.com",
+ "5617.com",
+ "namepros.com",
+ "humanmetrics.com",
+ "allin1convert.com",
+ "ox.ac.uk",
+ "msecnd.net",
+ "cathaypacific.com",
+ "bet365affiliates.com",
+ "tcs.com",
+ "trafficestimate.com",
+ "lmgtfy.com",
+ "finance.ua",
+ "find404.com",
+ "pagesperso-orange.fr",
+ "curbed.com",
+ "tasteofhome.com",
+ "ar15.com",
+ "mydigitallife.info",
+ "promiflash.de",
+ "technobuffalo.com",
+ "gamestorrents.com",
+ "labirint.ru",
+ "pclab.pl",
+ "indiatvnews.com",
+ "finya.de",
+ "redmondpie.com",
+ "rabota.ru",
+ "share-online.biz",
+ "packtpub.com",
+ "techgig.com",
+ "shaw.ca",
+ "apkmania.co",
+ "bet-at-home.com",
+ "barclaycard.co.uk",
+ "onefloorserve.com",
+ "raiffeisen.ru",
+ "t-nation.com",
+ "mbalib.com",
+ "staseraintv.com",
+ "uswitch.com",
+ "smartadserver.com",
+ "bbcgoodfood.com",
+ "elitetorrent.net",
+ "backlinko.com",
+ "naszemiasto.pl",
+ "submitexpress.com",
+ "savings.com",
+ "gem.pl",
+ "ahlamontada.com",
+ "fotomac.com.tr",
+ "gougou.com",
+ "payamsara.com",
+ "klix.ba",
+ "doostiha.ir",
+ "bibliocommons.com",
+ "wealthyaffiliate.com",
+ "emgn.com",
+ "sifyitest.com",
+ "washingtonexaminer.com",
+ "rakuten-sec.co.jp",
+ "mysurvey.com",
+ "uuu9.com",
+ "uscourts.gov",
+ "showroomprive.com",
+ "cargocollective.com",
+ "hsoub.com",
+ "afterbuy.de",
+ "marunadanmalayali.com",
+ "jumponhottie.com",
+ "avon.com",
+ "lazada.com.my",
+ "51netu.com.cn",
+ "ria.com",
+ "sankakucomplex.com",
+ "tvline.com",
+ "devshed.com",
+ "superherohype.com",
+ "tv-series.me",
+ "stylecraze.com",
+ "wizards.com",
+ "linkcollider.com",
+ "xinjunshi.com",
+ "bestchange.ru",
+ "1111.com.tw",
+ "fakenamegenerator.com",
+ "newsmth.net",
+ "noupe.com",
+ "marketingprofs.com",
+ "bluestacks.com",
+ "jemtube.com",
+ "bestbuy.ca",
+ "backcountry.com",
+ "designshack.net",
+ "pond5.com",
+ "highsnobiety.com",
+ "rtl.fr",
+ "pearsoncmg.com",
+ "hellowork.go.jp",
+ "koimoi.com",
+ "soali.ir",
+ "incentria.com",
+ "vagas.com.br",
+ "huaxi100.com",
+ "cheaa.com",
+ "lohaco.jp",
+ "gov.on.ca",
+ "fabthemes.com",
+ "pipl.com",
+ "comscore.com",
+ "pcfinancial.ca",
+ "craigslist.co.in",
+ "michaels.com",
+ "jibjab.com",
+ "sankeibiz.jp",
+ "dominos.co.in",
+ "supermoney.eu",
+ "itusozluk.com",
+ "sdchina.com",
+ "allkpop.com",
+ "cam4.com.br",
+ "stayfriends.de",
+ "futbol24.com",
+ "searchina.net",
+ "sgcpanel.com",
+ "informe21.com",
+ "alsacreations.com",
+ "crateandbarrel.com",
+ "alliancewarfare.com",
+ "filerio.in",
+ "emailsrvr.com",
+ "reventmedia.com",
+ "vietcombank.com.vn",
+ "rxlist.com",
+ "acidcow.com",
+ "orange.co.uk",
+ "hellocoton.fr",
+ "boldchat.com",
+ "psychcentral.com",
+ "surfline.com",
+ "xxxkinky.com",
+ "es.wordpress.com",
+ "publika.az",
+ "shufoo.net",
+ "hertz.com",
+ "businessweekly.com.tw",
+ "virgula.uol.com.br",
+ "linkis.com",
+ "ixwebhosting.com",
+ "usa.gov",
+ "linguee.com",
+ "yengo.com",
+ "huffingtonpost.jp",
+ "1x3x.com",
+ "mediametrics.ru",
+ "ec21.com",
+ "80018.cn",
+ "get-tune.net",
+ "yupoo.com",
+ "moviepilot.de",
+ "ihned.cz",
+ "fio.cz",
+ "pubted.com",
+ "cinemablend.com",
+ "stooorage.com",
+ "thevault.bz",
+ "journaldugeek.com",
+ "sommer-sommer.com",
+ "travelchannel.com",
+ "softonic.de",
+ "petsmart.com",
+ "ufxmarkets.com",
+ "e24.no",
+ "spirit.com",
+ "dabi.ir",
+ "admin5.net",
+ "serialu.net",
+ "vancouversun.com",
+ "submanga.com",
+ "sbicard.com",
+ "affaritaliani.it",
+ "idownloadblog.com",
+ "castorama.fr",
+ "sudouest.fr",
+ "payscale.com",
+ "serebii.net",
+ "storypick.com",
+ "jobkorea.co.kr",
+ "gowildcasino.com",
+ "hmetro.com.my",
+ "parimatch.com",
+ "51pinwei.com",
+ "globalnews.ca",
+ "mercadopago.com",
+ "sixrevisions.com",
+ "saisoncard.co.jp",
+ "gov.kz",
+ "gossip-tv.gr",
+ "zbozi.cz",
+ "aliorbank.pl",
+ "huanqiuauto.com",
+ "okaz.com.sa",
+ "cplusplus.com",
+ "mochimedia.com",
+ "google.sn",
+ "jquery-plugins.net",
+ "peoplesmart.com",
+ "mmafighting.com",
+ "ponpare.jp",
+ "porsche.com",
+ "charter.com",
+ "scrabblefinder.com",
+ "unpcn.com",
+ "loveaholics.com",
+ "geocities.co.jp",
+ "ladbrokes.com",
+ "52che.com",
+ "swansonvitamins.com",
+ "sweetwater.com",
+ "ali213.net",
+ "savenkeep.com",
+ "hotair.com",
+ "orgasmatrix.com",
+ "runrun.es",
+ "filezilla-project.org",
+ "looti.net",
+ "pagesix.com",
+ "twentytwowords.com",
+ "gingersoftware.com",
+ "youxiduo.com",
+ "isimtescil.net",
+ "rui.jp",
+ "d1g.com",
+ "2dbook.com",
+ "zigzig.ir",
+ "123telugu.com",
+ "wdr.de",
+ "hankyung.com",
+ "pr.com",
+ "search.ch",
+ "iranproud.com",
+ "raaga.com",
+ "alt1040.com",
+ "okpay.com",
+ "recordchina.co.jp",
+ "dreamincode.net",
+ "bendibao.com",
+ "creativelive.com",
+ "socialoomph.com",
+ "cssdeck.com",
+ "taxactonline.com",
+ "pb.com",
+ "fnac.es",
+ "ucsd.edu",
+ "tmart.com",
+ "whorush.com",
+ "spicejet.com",
+ "socialadr.com",
+ "tutorialzine.com",
+ "christianmingle.com",
+ "torrentleech.org",
+ "statefarm.com",
+ "orkut.com",
+ "whoscored.com",
+ "truthaboutonlinesluts.com",
+ "32red.com",
+ "wp-themes.com",
+ "adpost.com",
+ "cnr.cn",
+ "180upload.com",
+ "snagajob.com",
+ "textbroker.com",
+ "freshome.com",
+ "talkgold.com",
+ "dudamobile.com",
+ "weblancer.net",
+ "newone.org",
+ "nacion.com",
+ "takepart.com",
+ "voici.fr",
+ "gizmodo.jp",
+ "viki.com",
+ "symbaloo.com",
+ "topface.com",
+ "businessdictionary.com",
+ "adtech.info",
+ "elandroidelibre.com",
+ "fux.com",
+ "21-sun.com",
+ "cpmfx.com",
+ "siemens.com",
+ "edmodo.com",
+ "notitarde.com",
+ "babypips.com",
+ "silkroad.com",
+ "onextrapixel.com",
+ "notdoppler.com",
+ "walmart.ca",
+ "marvel.com",
+ "groupon.fr",
+ "us1.com",
+ "bunte.de",
+ "findlaw.com",
+ "topito.com",
+ "carrefour.fr",
+ "aawsat.com",
+ "super.ae",
+ "kicktipp.de",
+ "simplyrecipes.com",
+ "i-mobile.co.jp",
+ "podrobnosti.ua",
+ "snn.ir",
+ "successfactors.com",
+ "paixie.net",
+ "wiwo.de",
+ "glowgaze.com",
+ "mapsofworld.com",
+ "limetorrents.com",
+ "plarium.com",
+ "tvi.ua",
+ "corel.com",
+ "adhitprofits.com",
+ "findthecompany.com",
+ "noticiasaldiayalahora.co",
+ "160by2.com",
+ "jobberman.com",
+ "rus.ec",
+ "fujitsu.com",
+ "ladepeche.fr",
+ "pravda.sk",
+ "wwtdd.com",
+ "b9dm.com",
+ "marathonbet.com",
+ "sexlunch.com",
+ "komputronik.pl",
+ "gutenberg.org",
+ "dizo.com.cn",
+ "comunio.de",
+ "naked.com",
+ "gamesradar.com",
+ "moneysupermarket.com",
+ "cheaptickets.com",
+ "assembla.com",
+ "timesonline.co.uk",
+ "mckinsey.com",
+ "ebook3000.com",
+ "videoblocks.com",
+ "ruseller.com",
+ "pideo.net",
+ "joomlacode.org",
+ "pciconcursos.com.br",
+ "channelnewsasia.com",
+ "cnnturk.com",
+ "consultant.ru",
+ "michigan.gov",
+ "manoto1.com",
+ "10010.com",
+ "wholefoodsmarket.com",
+ "globalgrind.com",
+ "pichak.net",
+ "morpakampus.com",
+ "crazydomains.com.au",
+ "uptodown.com",
+ "polygon.com",
+ "raspberrypi.org",
+ "atmarkit.co.jp",
+ "heftig.co",
+ "informationweek.com",
+ "trendhunter.com",
+ "state.ny.us",
+ "pornpros.com",
+ "tnt.com",
+ "sportal.bg",
+ "spritzinc.com",
+ "theladders.com",
+ "lulu.com",
+ "applesfera.com",
+ "qoo10.jp",
+ "notebookreview.com",
+ "startertv.fr",
+ "healthkart.com",
+ "imgsin.com",
+ "mp3olimp.net",
+ "readms.com",
+ "casadellibro.com",
+ "nalog.ru",
+ "4gamer.net",
+ "jquery4u.com",
+ "betfred.com",
+ "3dwwwgame.com",
+ "appleinsider.com",
+ "dailystar.co.uk",
+ "swalif.com",
+ "hushmail.com",
+ "worldtimebuddy.com",
+ "sportschau.de",
+ "mediatraffic.com",
+ "gismeteo.ua",
+ "record.com.mx",
+ "putnik1.livejournal.com",
+ "nextbigwhat.com",
+ "vinescope.com",
+ "jarchi.ir",
+ "yidio.com",
+ "dunyanews.tv",
+ "hangseng.com",
+ "interpark.com",
+ "scholastic.com",
+ "penny-arcade.com",
+ "geilundlive.com",
+ "budbi.com",
+ "stop55.com",
+ "jaidefinichon.com",
+ "smartsheet.com",
+ "vector.me",
+ "farecompare.com",
+ "vodafone.com.eg",
+ "craftsy.com",
+ "theresumator.com",
+ "downloadab.com",
+ "abendzeitung-muenchen.de",
+ "dicio.com.br",
+ "fobshanghai.com",
+ "2dehands.be",
+ "thethao247.vn",
+ "cams.com",
+ "gothamist.com",
+ "moneynews.com",
+ "zocdoc.com",
+ "rol.ro",
+ "nic.ar",
+ "avenues.info",
+ "cleverbridge.com",
+ "usajobs.gov",
+ "divxstage.eu",
+ "jsticket.net",
+ "himasoku.com",
+ "thrivethemes.com",
+ "orientaltrading.com",
+ "premiumpress.com",
+ "house365.com",
+ "drugoi.livejournal.com",
+ "monster.co.uk",
+ "quickanddirtytips.com",
+ "virtuemart.net",
+ "huffpost.com",
+ "real.com",
+ "teacherspayteachers.com",
+ "t24.com.tr",
+ "zakon.kz",
+ "shoppinglifestyle.com",
+ "trendmicro.com",
+ "surfingbird.ru",
+ "cam.ac.uk",
+ "navyfederal.org",
+ "rateyourmusic.com",
+ "bravenet.com",
+ "polo.com",
+ "cl.ly",
+ "nanacast.com",
+ "cnfol.com",
+ "24option.com",
+ "myscienceacademy.org",
+ "getsoftfree.com",
+ "cba.pl",
+ "templateism.com",
+ "actudesfinances.org",
+ "1.254.254.254",
+ "jobtalk.jp",
+ "barbie.com",
+ "rahnama.com",
+ "gigporno.com",
+ "buddypress.org",
+ "corporationwiki.com",
+ "enorth.com.cn",
+ "thepioneerwoman.com",
+ "cam4ultimate.com",
+ "phpclasses.org",
+ "uplus.metroer.com/~content",
+ "komando.com",
+ "iha.com.tr",
+ "televisa.com",
+ "tmtpost.com",
+ "classifiedsgiant.com",
+ "sportinglife.com",
+ "askul.co.jp",
+ "travelagency.travel",
+ "jqueryscript.net",
+ "rusfolder.com",
+ "netcq.net",
+ "irangrand.ir",
+ "interaztv.com",
+ "downvids.net",
+ "mongodb.org",
+ "nasgo.net",
+ "thesitewizard.com",
+ "songspk.cc",
+ "travelandleisure.com",
+ "d-h.st",
+ "wasanga.com",
+ "cgg.gov.in",
+ "silverclix.com",
+ "almogaz.com",
+ "sexmob.es",
+ "mistreci.com",
+ "nukistream.com",
+ "postaffiliatepro.com",
+ "dish.com",
+ "ulta.com",
+ "worldcat.org",
+ "crackle.com",
+ "cineblog01.net",
+ "parispornmovies.com",
+ "avito.ma",
+ "nethouse.ru",
+ "elfinanciero.com.mx",
+ "ab-in-den-urlaub.de",
+ "pixeden.com",
+ "thetimenow.com",
+ "divar.ir",
+ "coolrom.com",
+ "akbank.com",
+ "saturn.de",
+ "dstv.com",
+ "mttbsystem.com",
+ "hujiang.com",
+ "bash.im",
+ "sextgem.com",
+ "subaonet.com",
+ "cnsnews.com",
+ "informationng.com",
+ "utoronto.ca",
+ "hetzner.de",
+ "vend-o.com",
+ "cybozu.com",
+ "autotimes.com.cn",
+ "5giay.vn",
+ "theepochtimes.com",
+ "penesalud.com",
+ "livenation.com",
+ "qoinpro.com",
+ "myway.com",
+ "safe-swaps.com",
+ "elephantjournal.com",
+ "curse.com",
+ "17zwd.com",
+ "hitleap.com",
+ "mec.gov.br",
+ "freewebcams.com",
+ "westelm.com",
+ "imagegals.com",
+ "streeteasy.com",
+ "ekitan.com",
+ "git-scm.com",
+ "p30day.com",
+ "kapaza.be",
+ "svoboda.org",
+ "google.mg",
+ "timesofisrael.com",
+ "roodo.com",
+ "malwaretips.com",
+ "dumpaday.com",
+ "dha.com.tr",
+ "diary.ru",
+ "epa.gov",
+ "jonloomer.com",
+ "holidaylettings.co.uk",
+ "oem.com.mx",
+ "oxfordjournals.org",
+ "3bmeteo.com",
+ "iwebtool.com",
+ "yinyuetai.com",
+ "ixl.com",
+ "rezultati.com",
+ "51sole.com",
+ "moudamepo.com",
+ "macromill.com",
+ "nzz.ch",
+ "buzznet.com",
+ "roku.com",
+ "posta.com.tr",
+ "letsbonus.com",
+ "theoatmeal.com",
+ "artofmanliness.com",
+ "tubepornkiss.com",
+ "aviny.com",
+ "sabresonicweb.com",
+ "tech-wd.com",
+ "qbank.ru",
+ "getsatisfaction.com",
+ "prokerala.com",
+ "ebc.com.br",
+ "typiol.com",
+ "photo.net",
+ "rockpapershotgun.com",
+ "netgear.com",
+ "mg.co.za",
+ "impressrd.jp",
+ "jkbk.cn",
+ "bakufu.jp",
+ "lgmi.com",
+ "tnt-online.ru",
+ "frequency.com",
+ "zip-codes.com",
+ "sport.ro",
+ "wolfram.com",
+ "pgmediaserve.com",
+ "icann.org",
+ "twistedsifter.com",
+ "mopo.de",
+ "vogue.co.uk",
+ "chatrandom.com",
+ "checkpagerank.net",
+ "colorzilla.com",
+ "autobip.com",
+ "laban.vn",
+ "pricecheck.co.za",
+ "notimex.com.mx",
+ "pik.ba",
+ "monster.de",
+ "google.cd",
+ "economia.uol.com.br",
+ "vsnl.net.in",
+ "futura-sciences.com",
+ "appstorm.net",
+ "icefilms.info",
+ "dicelacancion.com",
+ "hypovereinsbank.de",
+ "piratestreaming.tv",
+ "101domain.com",
+ "google.mn",
+ "rutgers.edu",
+ "behindwoods.com",
+ "downloadmaster.ru",
+ "smartinsights.com",
+ "wiziq.com",
+ "ftc.gov",
+ "animenewsnetwork.com",
+ "tandfonline.com",
+ "seagate.com",
+ "famitsu.com",
+ "onekingslane.com",
+ "zalando.fr",
+ "convio.com",
+ "seochat.com",
+ "qq163.com",
+ "capital.gr",
+ "tamin.ir",
+ "phpfreaks.com",
+ "cricketcountry.com",
+ "ubersuggest.org",
+ "ntv.co.jp",
+ "olark.com",
+ "1001fonts.com",
+ "appsgeyser.com",
+ "elsiglodetorreon.com.mx",
+ "lyricsmint.com",
+ "tovima.gr",
+ "petco.com",
+ "campograndenews.com.br",
+ "amadeus.com",
+ "tinychat.com",
+ "astrology.com",
+ "idg.se",
+ "nordea.se",
+ "gelbeseiten.de",
+ "nrc.nl",
+ "houseoffraser.co.uk",
+ "hepsibahis3.com",
+ "empowernetwork.com/almostasecret",
+ "phpnuke.org",
+ "xfwed.com",
+ "gulte.com",
+ "msi.com",
+ "netfirms.com",
+ "ovcanada.com",
+ "smzdm.com",
+ "wwwhatsnew.com",
+ "mydomainadvisor.com",
+ "newindianexpress.com",
+ "luxtarget.com",
+ "evz.ro",
+ "otodom.pl",
+ "linkin.net",
+ "moneysavingmom.com",
+ "uploadbaz.com",
+ "egyup.com",
+ "three.co.uk",
+ "co-operativebank.co.uk",
+ "redad.ru",
+ "ipsosinteractive.com",
+ "all-union.com",
+ "trustlink.ru",
+ "softango.com",
+ "toucharcade.com",
+ "tv2.dk",
+ "thisissouthwales.co.uk",
+ "jra.go.jp",
+ "alfavita.gr",
+ "ibigdan.livejournal.com",
+ "gtarcade.com",
+ "jc001.cn",
+ "microcenter.com",
+ "optimizepress.com",
+ "beyebe.com",
+ "muyzorras.com",
+ "expedia.co.uk",
+ "volvocars.com",
+ "lyd.com.cn",
+ "korben.info",
+ "disput.az",
+ "aeroflot.ru",
+ "betanews.com",
+ "avangard.ru",
+ "wrzko.eu",
+ "cakephp.org",
+ "majorgeeks.com",
+ "dreamteammoney.com",
+ "foroactivo.com",
+ "ut.ac.ir",
+ "eonet.jp",
+ "vn-zoom.com",
+ "footytube.com",
+ "expedia.de",
+ "barneys.com",
+ "lieyunwang.com",
+ "gartner.com",
+ "lazada.com.ph",
+ "ourtime.com",
+ "ohnotheydidnt.livejournal.com",
+ "e-rewards.com",
+ "updatestar.com",
+ "cafef.vn",
+ "cookinglight.com",
+ "expressdownload.net",
+ "shockmansion.com",
+ "adserverpub.com",
+ "ipko.pl",
+ "gsa-online.de",
+ "car.gr",
+ "cqcounter.com",
+ "thenews.com.pk",
+ "gnc.com",
+ "teambeachbody.com",
+ "kobobooks.com",
+ "cwan.com",
+ "ca.com",
+ "list.ly",
+ "baijob.com",
+ "gunbroker.com",
+ "rtl.be",
+ "myadvertisingpays.com",
+ "mediapost.com",
+ "groupalia.com",
+ "anquan.org",
+ "mixshowblast.com",
+ "myscore.ru",
+ "bancochile.cl",
+ "a2hosting.com",
+ "hayneedle.com",
+ "myfc.ir",
+ "aktifhaber.com",
+ "eater.com",
+ "anymeeting.com",
+ "cylex.de",
+ "sayidaty.net",
+ "synonym.com",
+ "comprendrechoisir.com",
+ "prlog.ru",
+ "solidtrustpay.com",
+ "cinejosh.com",
+ "yelp.co.uk",
+ "olx.com.ar",
+ "dihitt.com",
+ "donkeymails.com",
+ "chainreactioncycles.com",
+ "wearehairy.com",
+ "ebuyer.com",
+ "bplans.com",
+ "ponparemall.com",
+ "readthedocs.org",
+ "tehparadox.com",
+ "source-wave.com",
+ "tbs.co.jp",
+ "redcoon.de",
+ "francetv.fr",
+ "freelogoservices.com",
+ "ogone.com",
+ "jeanmarcmorandini.com",
+ "lasexta.com",
+ "sponsoredreviews.com",
+ "govome.com",
+ "vecteezy.com",
+ "alhayat.com",
+ "cnhubei.com",
+ "mumayi.com",
+ "webfail.com",
+ "eluniverso.com",
+ "moddb.com",
+ "gaiaonline.com",
+ "gordonua.com",
+ "liveadexchanger.com",
+ "zhe800.com",
+ "softonic.com.br",
+ "cnyes.com",
+ "cumlouder.com",
+ "krakow.pl",
+ "nullrefer.com",
+ "zaluu.com",
+ "diretube.com",
+ "seattlepi.com",
+ "eanswers.com",
+ "gostorego.com",
+ "play.com",
+ "lenskart.com",
+ "unblog.fr",
+ "chatwork.com",
+ "bronto.com",
+ "jobisjob.co.in",
+ "mercadolibre.com.uy",
+ "overdrive.com",
+ "runkeeper.com",
+ "smartshopping.com",
+ "getrichradio.com",
+ "grader.com",
+ "101greatgoals.com",
+ "elbilad.net",
+ "kopp-verlag.de",
+ "ranksignals.com",
+ "trome.pe",
+ "jobstreet.com.my",
+ "farnell.com",
+ "fastmail.fm",
+ "faithit.com",
+ "blogdohotelurbano.com",
+ "sencha.com",
+ "daisycon.com",
+ "random.org",
+ "tportal.hr",
+ "rkanr.com",
+ "fc2-erodouga.com",
+ "youngpornvideos.com",
+ "bravoteens.com",
+ "mobile.free.fr",
+ "mitele.es",
+ "edis.at",
+ "questionablecontent.net",
+ "indiangilma.com",
+ "comunio.es",
+ "bitnami.com",
+ "sliptalk.com",
+ "sourceforge.jp",
+ "lyoness.net",
+ "nespresso.com",
+ "ultrafarma.com.br",
+ "lik.cl",
+ "jsoftj.com",
+ "metoffice.gov.uk",
+ "androidauthority.com",
+ "360safe.com",
+ "wikimart.ru",
+ "tutu.ru",
+ "truetwit.com",
+ "xinruijunshi.com",
+ "online-sweepstakes.com",
+ "singaporeair.com",
+ "cwtv.com",
+ "politiken.dk",
+ "alaan.tv",
+ "tuttomercatoweb.com",
+ "imagehost123.com",
+ "drakensang.com",
+ "frenchweb.fr",
+ "syosetu.com",
+ "zhifang.com",
+ "viptube.com",
+ "theme123.net",
+ "statista.com",
+ "51bi.com",
+ "clickz.com",
+ "kingworldnews.com",
+ "qunar.com",
+ "pimpandhost.com",
+ "pagina12.com.ar",
+ "xinmin.cn",
+ "kidshealth.org",
+ "pics.livejournal.com",
+ "kabum.com.br",
+ "anandabazar.com",
+ "pnu.ac.ir",
+ "scene7.com",
+ "paperpkads.com",
+ "mylikes.com",
+ "longtailvideo.com",
+ "firmy.cz",
+ "bitcoinity.org",
+ "inopressa.ru",
+ "expat-blog.com",
+ "governmentjobs.com",
+ "airdroid.com",
+ "mid-day.com",
+ "frandroid.com",
+ "webceo.com",
+ "cadenaser.com",
+ "minutouno.com",
+ "onamae.com",
+ "onlinekhabar.com",
+ "williams-sonoma.com",
+ "freewebsubmission.com",
+ "vozforums.com",
+ "bigpicture.ru",
+ "mymodernmet.com",
+ "presseportal.de",
+ "licindia.in",
+ "ismedia.jp",
+ "depor.pe",
+ "sing365.com",
+ "v2cigs.com",
+ "postimage.org",
+ "gencat.cat",
+ "west263.com",
+ "alohatube.com",
+ "eenadupratibha.net",
+ "terra.com",
+ "bri.co.id",
+ "silktide.com",
+ "anyang.gov.cn",
+ "speedanalysis.com",
+ "bitcoin.org",
+ "toodledo.com",
+ "topgear.com",
+ "rtvslo.si",
+ "hotpads.com",
+ "nedsecure.co.za",
+ "expedia.ca",
+ "thairath.co.th",
+ "gizbot.com",
+ "naukrigulf.com",
+ "guffins.com",
+ "twilio.com",
+ "avsforum.com",
+ "sharpnews.ru",
+ "inoreader.com",
+ "stgeorge.com.au",
+ "shoebuy.com",
+ "sbwire.com",
+ "bfm.ru",
+ "dongtaiwang.com",
+ "mandrillapp.com",
+ "176.com",
+ "olx.com",
+ "trustpilot.co.uk",
+ "tgju.org",
+ "pap.fr",
+ "iphonehacks.com",
+ "gry-online.pl",
+ "mp3xd.com",
+ "viabcp.com",
+ "bizcommunity.com",
+ "chillingeffects.org",
+ "thomasnet.com",
+ "performersoft.com",
+ "paymaster.ru",
+ "comdotgame.com",
+ "bseindia.com",
+ "foodgawker.com",
+ "clicktale.com",
+ "dot.tk",
+ "smbc-comics.com",
+ "vvmembers.co",
+ "c-sharpcorner.com",
+ "acdcads.com",
+ "goldporntube.com",
+ "abakus-internet-marketing.de",
+ "babbel.com",
+ "fzg360.com",
+ "99inf.com",
+ "cduniverse.com",
+ "autobild.de",
+ "tvrage.com",
+ "phoenix.edu",
+ "hurriyetemlak.com",
+ "va.gov",
+ "maxmind.com",
+ "lifehacker.jp",
+ "nola.com",
+ "niroensani.ir",
+ "ihotelier.com",
+ "mianbao.com",
+ "powerball.com",
+ "express.com",
+ "freshdesignweb.com",
+ "o2.co.uk",
+ "utusan.com.my",
+ "overclockers.ru",
+ "fsiblog.com",
+ "launchpad.net",
+ "prizee.com",
+ "alalam.ir",
+ "imtalk.org",
+ "vavel.com",
+ "nyc.ny.us",
+ "youmob.com",
+ "dailythanthi.com",
+ "ksu.edu.sa",
+ "nlayer.net",
+ "kurier.at",
+ "expert-offers.com",
+ "marry52.com",
+ "cityads.ru",
+ "darkorbit.com",
+ "cio.com",
+ "a9.com",
+ "symfony.com",
+ "crobo.com",
+ "shatel.ir",
+ "opposingviews.com",
+ "myvoffice.com",
+ "vkmag.com",
+ "starpulse.com",
+ "bls.gov",
+ "lifebettering.com",
+ "fanhuan.com",
+ "upload7.ir",
+ "infoplease.com",
+ "suruga-ya.jp",
+ "deredactie.be",
+ "shangdu.com",
+ "portail.free.fr",
+ "smartaddons.com",
+ "w3layouts.com",
+ "wallstreet-online.de",
+ "yapo.cl",
+ "standard.co.uk",
+ "atlas.sk",
+ "seowizard.ru",
+ "currys.co.uk",
+ "nova.cz",
+ "mygully.com",
+ "favstar.fm",
+ "themuse.com",
+ "yudu.com",
+ "urlopener.com",
+ "ellentv.com",
+ "imgsrc.ru",
+ "km.ru",
+ "guildwars2.com",
+ "google.mu",
+ "androidpit.de",
+ "mrporter.com",
+ "ttt4.com",
+ "cbox.ws",
+ "hf365.com",
+ "1mobile.com",
+ "punjabkesari.in",
+ "msu.edu",
+ "grasscity.com",
+ "abduzeedo.com",
+ "sublimetext.com",
+ "jtb.co.jp",
+ "mensxp.com",
+ "myheritage.com",
+ "onvasortir.com",
+ "safeway.com",
+ "comicvine.com",
+ "cpubenchmark.net",
+ "nn.ru",
+ "animefreak.tv",
+ "angularjs.org",
+ "managewp.com",
+ "ameli.fr",
+ "merrjep.com",
+ "christianbook.com",
+ "nubiles.net",
+ "klmty.net",
+ "247sports.com",
+ "aramex.com",
+ "tubent.com",
+ "cognitiveseo.com",
+ "bankpasargad.com",
+ "pingler.com",
+ "compareja.com.br",
+ "surveyzrewardcenter.eu",
+ "allyes.com",
+ "graaam.com",
+ "poriborton.com",
+ "seslisozluk.net",
+ "shopyourway.com",
+ "awd.ru",
+ "wa.gov.au",
+ "slrclub.com",
+ "apollo.lv",
+ "girls-ly.com",
+ "totalfilm.com",
+ "cam4.it",
+ "gogecapital.com",
+ "sketchup.com",
+ "muscleandfitness.com",
+ "m24.ru",
+ "blinklist.com",
+ "artisteer.com",
+ "nettavisen.no",
+ "enjin.com",
+ "pc6.com",
+ "citrix.com",
+ "indgovtjobs.in",
+ "phpbb.com",
+ "laughingsquid.com",
+ "fblife.com",
+ "stansberryresearch.com",
+ "hugefiles.net",
+ "mp3monkey.net",
+ "mcdonalds.com",
+ "vodafone.co.uk",
+ "t-mobile.de",
+ "tp-link.com.cn",
+ "iflscience.com",
+ "nst.com.my",
+ "zoom.com.br",
+ "dsw.com",
+ "tigerair.com",
+ "doityourself.com",
+ "bongdainfo.com",
+ "imacros.net",
+ "paperlesspost.com",
+ "sprinthost.ru",
+ "lovoo.net",
+ "kadinlarkulubu.com",
+ "championselect.net",
+ "jcb.co.jp",
+ "miui.com",
+ "impots.gouv.fr",
+ "linkshop.com.cn",
+ "pando.com",
+ "ckeditor.com",
+ "arabylife.com",
+ "ml.com",
+ "sheldonsfans.com",
+ "freecharge.in",
+ "magicmovies.com",
+ "laweekly.com",
+ "highrisehq.com",
+ "tr.gg",
+ "vidbull.com",
+ "diy.com",
+ "yieldtraffic.com",
+ "cima4u.com",
+ "gendama.jp",
+ "netpnb.com",
+ "kannaway.com",
+ "soft112.com",
+ "die-boersenformel.com",
+ "movie25.so",
+ "footyroom.com",
+ "dostor.org",
+ "aol.de",
+ "desimartini.com",
+ "themeko.org",
+ "danarimedia.com",
+ "toroporno.com",
+ "stylemepretty.com",
+ "urlm.de",
+ "demotivation.me",
+ "gentside.com",
+ "carfax.com",
+ "huzhou.gov.cn",
+ "hotline.ua",
+ "fullmoneysystem.com",
+ "pornomovies.com",
+ "fsymbols.com",
+ "blog.de",
+ "clickpoint.com",
+ "tv-asahi.co.jp",
+ "flightstats.com",
+ "sonico.com",
+ "afamily.vn",
+ "anadolu.edu.tr",
+ "rs-online.com",
+ "androidpit.com",
+ "a-telecharger.com",
+ "wikifeet.com",
+ "nix.ru",
+ "tvmao.com",
+ "groupon.es",
+ "hitfix.com",
+ "weathernews.jp",
+ "dig.do",
+ "googledrive.com",
+ "fodors.com",
+ "melon.com",
+ "testflightapp.com",
+ "markt.de",
+ "mahua.com",
+ "sedo.co.uk",
+ "tuenti.com",
+ "comm100.com",
+ "olx.co.id",
+ "lefrecce.it",
+ "gov.cl",
+ "wplift.com",
+ "unn.com.ua",
+ "arizona.edu",
+ "msn.com.cn",
+ "k7x.com",
+ "techz.vn",
+ "jobomas.com",
+ "extranetinvestment.com",
+ "tengrinews.kz",
+ "comicbookmovie.com",
+ "4porn.com",
+ "rubiconproject.com",
+ "gametracker.com",
+ "otcmarkets.com",
+ "mismarcadores.com",
+ "trojmiasto.pl",
+ "cleverreach.com",
+ "contactform7.com",
+ "weloveshopping.com",
+ "runnersworld.com",
+ "falabella.com",
+ "airtelbroadband.in",
+ "twistys.com",
+ "ebesucher.de",
+ "belastingdienst.nl",
+ "orlandosentinel.com",
+ "th3professional.com",
+ "duke.edu",
+ "opensubtitles.us",
+ "clickme.net",
+ "infor.pl",
+ "unesco.org",
+ "socialfabric.us",
+ "ename.net",
+ "alternativeto.net",
+ "rotahaber.com",
+ "johnchow.com",
+ "pervclips.com",
+ "linkfeed.ru",
+ "dtvideo.com",
+ "kinoman.tv",
+ "siteprice.org",
+ "lacuerda.net",
+ "amulyam.in",
+ "mandghomebusiness.com",
+ "infojobs.com.br",
+ "hirufm.lk",
+ "mybloggertricks.com",
+ "athemes.com",
+ "moikrug.ru",
+ "fybersearch.com",
+ "wine-searcher.com",
+ "davidicke.com",
+ "dotabuff.com",
+ "sainsburys.co.uk",
+ "ovaustralia.com",
+ "updatesoftnow.com",
+ "desarrolloweb.com",
+ "elaph.com",
+ "icc-cricket.com",
+ "gaytube.com",
+ "di.fm",
+ "99wed.com",
+ "c-and-a.com",
+ "mlxchange.com",
+ "realgfporn.com",
+ "synxis.com",
+ "optymalizacja.com",
+ "ibtesama.com",
+ "hankooki.com",
+ "shiksha.com",
+ "anoox.com",
+ "seamless.com",
+ "stripe.com",
+ "ets.org",
+ "fresherslive.com",
+ "webcoinpay.net",
+ "oscommerce.com",
+ "gratisprogramas.org",
+ "football365.com",
+ "mkyong.com",
+ "antichat.ru",
+ "spamarrest.com",
+ "ubc.ca",
+ "36kr.com",
+ "startv.in",
+ "shoutcast.com",
+ "heureka.sk",
+ "entheosweb.com",
+ "51wan.com",
+ "madadsmedia.com",
+ "parse.com",
+ "ngacn.cc",
+ "techbargains.com",
+ "tvmovie.de",
+ "cpmstar.com",
+ "torproject.org",
+ "residentadvisor.net",
+ "genbeta.com",
+ "hulu.jp",
+ "pluralsight.com",
+ "postini.com",
+ "zombie.jp",
+ "skimlinks.com",
+ "liverail.com",
+ "phys.org",
+ "slashfilm.com",
+ "livemaster.ru",
+ "idwebgame.com",
+ "pho.to",
+ "dealfish.co.th",
+ "s1979.com",
+ "designfloat.com",
+ "live365.com",
+ "pbase.com",
+ "eniro.se",
+ "irannaz.com",
+ "socialmonkee.com",
+ "uidai.gov.in",
+ "joomlashine.com",
+ "allhyipmon.ru",
+ "upbulk.com",
+ "diapers.com",
+ "flypgs.com",
+ "hotmart.com.br",
+ "globus-inter.com",
+ "airfrance.fr",
+ "t3.com",
+ "unetepubli.com",
+ "yahoo-help.jp",
+ "iphones.ru",
+ "95559.com.cn",
+ "glamsham.com",
+ "gophoto.it",
+ "statmyweb.com",
+ "aftermarket.pl",
+ "forumotion.com",
+ "iafd.com",
+ "hotlog.ru",
+ "drclix.com",
+ "wawa-mania.ec",
+ "nichepursuits.com",
+ "imp.free.fr",
+ "baofeng.com",
+ "binsearch.info",
+ "neswangy.net",
+ "parperfeito.com.br",
+ "theeroticreview.com",
+ "sabayacafe.com",
+ "maplestage.com",
+ "icook.tw",
+ "customerhub.net",
+ "uid.me",
+ "viperchill.com",
+ "askfrank.net",
+ "juegosjuegos.com",
+ "debonairblog.com",
+ "coingeneration.com",
+ "onetravel.com",
+ "slutroulette.com",
+ "jetpack.me",
+ "embedupload.com",
+ "bancodevenezuela.com",
+ "mysavingsmedia.net",
+ "smallbiztrends.com",
+ "emirates247.com",
+ "bu.edu",
+ "fineco.it",
+ "netbarg.com",
+ "gatech.edu",
+ "zik.ua",
+ "peliculascoco.com",
+ "hkjc.com",
+ "turkiyegazetesi.com.tr",
+ "cooperativa.cl",
+ "challenges.fr",
+ "usingenglish.com",
+ "vouchercodes.co.uk",
+ "bonprix.de",
+ "disneylatino.com",
+ "townwork.net",
+ "rentanything.com",
+ "krypt.com",
+ "wral.com",
+ "globes.co.il",
+ "designtaxi.com",
+ "mp-success.com",
+ "invisionpower.com",
+ "liontravel.com",
+ "classicrummy.com",
+ "mt.co.kr",
+ "inccel.com",
+ "santander.cl",
+ "afip.gov.ar",
+ "yellowpages.com.au",
+ "osclass.org",
+ "couriermail.com.au",
+ "stream.cz",
+ "wizaz.pl",
+ "linkresearchtools.com",
+ "cam4.co.uk",
+ "allafrica.com",
+ "gezginler.net",
+ "free-ebooks.net",
+ "hopesandfears.com",
+ "ticketmaster.com.mx",
+ "ohio.gov",
+ "liberoquotidiano.it",
+ "neurs.net",
+ "forumophilia.com",
+ "odnako.org",
+ "gamekult.com",
+ "vh1.com",
+ "zxart.cn",
+ "mass.gov",
+ "tv-tokyo.co.jp",
+ "mundopromocion.com",
+ "theme-junkie.com",
+ "asu.edu",
+ "lalibre.be",
+ "pornokopilka.info",
+ "fx678.com",
+ "netbeans.org",
+ "chinabidding.com.cn",
+ "lunapic.com",
+ "dramafever.com",
+ "hbogo.com",
+ "torrents.net",
+ "woopra.com",
+ "justfab.com",
+ "fitnessmagazine.com",
+ "tripadvisor.com.mx",
+ "183.com.cn",
+ "adscendmedia.com",
+ "geek.com",
+ "thepetitionsite.com",
+ "skyscanner.ru",
+ "morningpost.com.cn",
+ "concursolutions.com",
+ "camplace.com",
+ "smarturl.it",
+ "browsershots.org",
+ "piktochart.com",
+ "elcorreo.com",
+ "collegeboard.org",
+ "kasikornbank.com",
+ "adsoftheworld.com",
+ "fakku.net",
+ "jpn.org",
+ "sahafah.net",
+ "rubias19.com",
+ "fc2web.com",
+ "redsurf.ru",
+ "iproperty.com.my",
+ "browsersafeguard.com",
+ "mmajunkie.com",
+ "bangkokbank.com",
+ "ovi.com",
+ "fap.to",
+ "filmygyan.in",
+ "edaily.vn",
+ "affilorama.com",
+ "valuecommerce.ne.jp",
+ "softaculous.com",
+ "exchanger.ru",
+ "html-color-codes.info",
+ "hd-xvideos.com",
+ "realself.com",
+ "geocaching.com",
+ "mom.me",
+ "stc.com.sa",
+ "video-i365.com",
+ "umd.edu",
+ "jeffbullas.com",
+ "kora.com",
+ "cyberchimps.com",
+ "popupads.ir",
+ "chatango.com",
+ "gearslutz.com",
+ "fout.jp",
+ "contactmusic.com",
+ "linkcrypt.ws",
+ "sophos.com",
+ "forum-auto.com",
+ "svtplay.se",
+ "newsbusters.org",
+ "fileswap.com",
+ "phpfox.com",
+ "denic.de",
+ "riverisland.com",
+ "encuentra24.com",
+ "foxnewsinsider.com",
+ "dtdc.com",
+ "tayyar.org",
+ "thepushbuttonmillionaire.com",
+ "brokenlinkcheck.com",
+ "ju51.com",
+ "stihi.ru",
+ "psdgraphics.com",
+ "mommyfucktube.com",
+ "mangocity.com",
+ "routard.com",
+ "whicdn.com",
+ "socialtriggers.com",
+ "e-bookspdf.org",
+ "songspk3.in",
+ "paginasamarillas.com",
+ "webgame.in.th",
+ "xxxdessert.com",
+ "materiel.net",
+ "skillshare.com",
+ "tubepleasure.com",
+ "paypal.de",
+ "yeahmobi.com",
+ "torrentz-proxy.com",
+ "aircel.com",
+ "openask.com",
+ "trafficg.com",
+ "anthem.com",
+ "aleseriale.pl",
+ "f-page.ru",
+ "hrsmart.com",
+ "cbengine.com",
+ "startlap.com",
+ "spamhaus.org",
+ "trovit.com",
+ "sporcle.com",
+ "xs8.cn",
+ "romwe.com",
+ "powtoon.com",
+ "cybozulive.com",
+ "zbiornik.com",
+ "cebit.de",
+ "flipboard.com",
+ "news.am",
+ "wm-panel.com",
+ "topnews.ru",
+ "usp.br",
+ "realmadrid.com",
+ "fastdist.net",
+ "unian.ua",
+ "youtube.com/user/PewDiePie",
+ "unc.edu",
+ "tamu.edu",
+ "ip2location.com",
+ "americanapparel.net",
+ "virtualedge.com",
+ "vikatan.com",
+ "goodlayers.com",
+ "feedblitz.com",
+ "dateinasia.com",
+ "freepdfconvert.com",
+ "iweb.com",
+ "lachainemeteo.com",
+ "aetna.com",
+ "ti.com",
+ "gratisjuegos.org",
+ "webhostinghub.com",
+ "preev.com",
+ "holidayiq.com",
+ "elpais.com.uy",
+ "uchicago.edu",
+ "telcel.com",
+ "feebbo.com",
+ "webhallen.com",
+ "dmir.ru",
+ "emailmg.ipage.com",
+ "hrs.de",
+ "propakistani.pk",
+ "theme.co",
+ "bigpara.com",
+ "finishline.com",
+ "fardanews.com",
+ "nat.gov.tw",
+ "stoloto.ru",
+ "sermepa.es",
+ "radaris.com",
+ "softportal.com",
+ "turkiye.gov.tr",
+ "nnn.ru",
+ "e-familynet.com",
+ "wenkang.cn",
+ "teamworkpm.net",
+ "videohelp.com",
+ "pixmania.com",
+ "games.com",
+ "guns.ru",
+ "plus28.com",
+ "pf.pl",
+ "pbworks.com",
+ "sedo.de",
+ "freedownloadscenter.com",
+ "backpackers.com.tw",
+ "mycokerewards.com",
+ "chinaunix.net",
+ "invisionapp.com",
+ "wordhippo.com",
+ "unitezz.com",
+ "yan.vn",
+ "sonhoo.com",
+ "spielaffe.de",
+ "d.pr",
+ "technologyreview.com",
+ "democraticunderground.com",
+ "molotok.ru",
+ "watchever.de",
+ "wdc.com",
+ "torg.com",
+ "ivillage.com",
+ "portableapps.com",
+ "ovh.es",
+ "vse.kz",
+ "alrajhibank.com.sa",
+ "dhl-usa.com",
+ "pingan.com",
+ "excite.com",
+ "cincodias.com",
+ "marksdailyapple.com",
+ "bter.com",
+ "nationaljournal.com",
+ "fao.org",
+ "oddee.com",
+ "digitalriver.com",
+ "livescore.in",
+ "siilu.com",
+ "gofirstrowus.eu",
+ "alquds.co.uk",
+ "autoevolution.com",
+ "zerx.ru",
+ "trovit.it",
+ "hvylya.org",
+ "carters.com",
+ "shejis.com",
+ "radio-canada.ca",
+ "vodafone.es",
+ "sky.fm",
+ "maturetube.com",
+ "virtualtourist.com",
+ "line25.com",
+ "rzeczpospolita.pl",
+ "megacurioso.com.br",
+ "beliefnet.com",
+ "eklablog.com",
+ "hbo.com",
+ "bsi.ir",
+ "fastweb.it",
+ "webrazzi.com",
+ "telam.com.ar",
+ "downloadming.me",
+ "bluefly.com",
+ "thewire.com",
+ "erotube.org",
+ "vt.edu",
+ "jsbin.com",
+ "ibosocial.com",
+ "brides.com.cn",
+ "jn.pt",
+ "togetter.com",
+ "olhardigital.uol.com.br",
+ "ebookee.org",
+ "socialgamenet.com",
+ "romaniatv.net",
+ "epweike.com",
+ "pronto.com",
+ "blog.pl",
+ "top81.cn",
+ "flagfox.wordpress.com",
+ "unionbank.com",
+ "visitkorea.or.kr",
+ "blogspot.dk",
+ "fermasosedi.ru",
+ "inmobi.com",
+ "abc.com.py",
+ "iqoo.me",
+ "17k.com",
+ "onlineapplicationsdownloads.com",
+ "komli.com",
+ "tala.ir",
+ "videopremium.me",
+ "job.ru",
+ "sunbiz.org",
+ "tw116.com",
+ "browserstack.com",
+ "youtu.be",
+ "yardbarker.com",
+ "flvmplayer.com",
+ "kulichki.net",
+ "gravity.com",
+ "levelclix.com",
+ "kissanime.com",
+ "insightexpressai.com",
+ "colorhexa.com",
+ "citizensbankonline.com",
+ "hjenglish.com",
+ "voeazul.com.br",
+ "paraskhnio.gr",
+ "es.tl",
+ "busuu.com",
+ "appsumo.com",
+ "metacrawler.com",
+ "ciku5.com",
+ "android-hilfe.de",
+ "laterooms.com",
+ "google.com.bn",
+ "gamefront.com",
+ "rev2pub.com",
+ "bharatiyamobile.com",
+ "publicidees.com",
+ "jossandmain.com",
+ "babycentre.co.uk",
+ "zetabux.com",
+ "movieweb.com",
+ "timescity.com",
+ "dnevnik.ru",
+ "nlcafe.hu",
+ "magazine3k.com",
+ "irancell.ir",
+ "kalaydo.de",
+ "e5.ru",
+ "lecai.com",
+ "sbs.com.au",
+ "sierratradingpost.com",
+ "girlfriendvideos.com",
+ "ink361.com",
+ "corporate-ir.net",
+ "allgameshome.com",
+ "povarenok.ru",
+ "typo3.org",
+ "turbosquid.com",
+ "miniurls.co",
+ "thinkwithgoogle.com",
+ "haber3.com",
+ "newsmeback.com",
+ "sipse.com",
+ "osxdaily.com",
+ "9lessons.info",
+ "cyclopaedia.net",
+ "reallifecam.com",
+ "gameblog.fr",
+ "colourbox.com",
+ "mixedmartialarts.com",
+ "prostoporno.net",
+ "chanel.com",
+ "maxim.com",
+ "cam4.es",
+ "olx.com.mx",
+ "newscientist.com",
+ "netcombo.com.br",
+ "serienjunkies.org",
+ "shablol.com",
+ "bnpparibasfortis.be",
+ "canada.com",
+ "timeslive.co.za",
+ "cinematoday.jp",
+ "21cineplex.com",
+ "bodisparking.com",
+ "cruisecritic.com",
+ "vertoz.com",
+ "glosbe.com",
+ "nstarikov.ru",
+ "epinions.com",
+ "colbertnation.com",
+ "marketglory.com",
+ "emailmeform.com",
+ "angloinfo.com",
+ "filfan.com",
+ "yougetsignal.com",
+ "broker.to",
+ "quickbux.net",
+ "gottabemobile.com",
+ "beyondtherack.com",
+ "tripadvisor.ru",
+ "jschina.com.cn",
+ "registraduria.gov.co",
+ "thisoldhouse.com",
+ "appcelerator.com",
+ "noticias24carabobo.com",
+ "skelbiu.lt",
+ "ru.wix.com",
+ "iransong.com",
+ "i-sux.com",
+ "telerama.fr",
+ "mydala.com",
+ "pia.jp",
+ "fusebux.com",
+ "biquge.com",
+ "microworkers.com",
+ "onlywire.com",
+ "fanbox.com",
+ "ambitoweb.com",
+ "tripadvisor.com.br",
+ "postgresql.org",
+ "telenet.be",
+ "thegeekstuff.com",
+ "primelocation.com",
+ "ee.co.uk",
+ "phoenixads.co.in",
+ "brigitte.de",
+ "360kad.com",
+ "kathimerini.gr",
+ "batoto.net",
+ "babebuns.com",
+ "webimpresion.com",
+ "olx.com.ng",
+ "which.co.uk",
+ "f5haber.com",
+ "cic.fr",
+ "talkfusion.com",
+ "ctrlq.org",
+ "caracol.com.co",
+ "wer-weiss-was.de",
+ "invisionzone.com",
+ "head-fi.org",
+ "thingiverse.com",
+ "manager-magazin.de",
+ "bzwbk.pl",
+ "f1news.ru",
+ "tweetreach.com",
+ "sj998.com",
+ "streetdirectory.com",
+ "asos.fr",
+ "kalahari.com",
+ "classiccars.com",
+ "bitacoras.com",
+ "bravotv.com",
+ "beanfun.com",
+ "bonappetit.com",
+ "fashionara.com",
+ "techdirt.com",
+ "newlook.com",
+ "iyinet.com",
+ "mogujie.com",
+ "carros.com.br",
+ "starfall.com",
+ "rp5.ru",
+ "pocket-lint.com",
+ "homeadvisor.com",
+ "webhostbox.net",
+ "cameraboys.com",
+ "pricerunner.com",
+ "worldcarfans.com",
+ "meganovosti.net",
+ "taxheaven.gr",
+ "freewebsitetemplates.com",
+ "mr90.ir",
+ "cheapflights.co.uk",
+ "bankinter.com",
+ "euroresidentes.com",
+ "bettycrocker.com",
+ "filmey.com",
+ "sheinside.com",
+ "2ememain.be",
+ "tu.tv",
+ "kugou.com",
+ "destructoid.com",
+ "todoist.com",
+ "karmaloop.com",
+ "appadvice.com",
+ "html5rocks.com",
+ "osdir.com",
+ "webisgreat.info",
+ "dailyblogtips.com",
+ "mca.gov.in",
+ "e-estekhdam.com",
+ "hlntv.com",
+ "proprofs.com",
+ "his-j.com",
+ "im286.com",
+ "mmorpg.com",
+ "shooshtime.com",
+ "terra.es",
+ "lpcloudbox301.com",
+ "tubepornstars.com",
+ "tableausoftware.com",
+ "soccersuck.com",
+ "websurf.ru",
+ "indiafreestuff.in",
+ "pimei.com",
+ "colatour.com.tw",
+ "fssnet.co.in",
+ "maxpark.com",
+ "foodandwine.com",
+ "apachefriends.org",
+ "standardchartered.co.in",
+ "waveapps.com",
+ "gosong.net",
+ "spring.me",
+ "weatherbug.com",
+ "iw33.com",
+ "apserver.net",
+ "thenationonlineng.net",
+ "tjournal.ru",
+ "greatschools.net",
+ "3movs.com",
+ "61.com",
+ "directpaybiz.com",
+ "w3snoop.com",
+ "jsonline.com",
+ "grainger.com",
+ "prevention.com",
+ "blizzard.com",
+ "baseball-reference.com",
+ "cjn.cn",
+ "fasthosts.co.uk",
+ "kym-cdn.com",
+ "cuponation.in",
+ "cam4.fr",
+ "lalawan67.net",
+ "videovantage.co",
+ "elimparcial.com",
+ "edlen24.com",
+ "donya-e-eqtesad.com",
+ "englishforums.com",
+ "dom2.ru",
+ "cinepolis.com",
+ "healthtap.com",
+ "astroawani.com",
+ "autosport.com",
+ "finalfantasyxiv.com",
+ "valueclickmedia.com",
+ "vitaminshoppe.com",
+ "apartmentguide.com",
+ "notjustok.com",
+ "gratispeliculas.org",
+ "intporn.com",
+ "eroticbeauties.net",
+ "egloos.com",
+ "nujij.nl",
+ "godvine.com",
+ "punishtube.com",
+ "wisegeek.org",
+ "somuch.com",
+ "taz.de",
+ "zetaboards.com",
+ "gravityforms.com",
+ "telegraf.rs",
+ "odn.ne.jp",
+ "topeleven.com",
+ "peekyou.com",
+ "razerzone.com",
+ "furaffinity.net",
+ "mobikwik.com",
+ "eventful.com",
+ "sextube.fm",
+ "treccani.it",
+ "phatograph.com",
+ "feedthebot.com",
+ "netdoctor.co.uk",
+ "collarme.com",
+ "reformal.ru",
+ "hemnet.se",
+ "jacquieetmicheltv.net",
+ "9ku.com",
+ "kraloyun.com",
+ "directadmin.com",
+ "bongda.com.vn",
+ "ddizi.org",
+ "tedata.net",
+ "fb.org",
+ "pagemodo.com",
+ "satu.kz",
+ "nodejs.org",
+ "tiberiumalliances.com",
+ "wallst.com",
+ "dezeen.com",
+ "rense.com",
+ "hawkhost.com",
+ "vonage.com",
+ "zjol.com.cn",
+ "housefun.com.tw",
+ "ad1.ru",
+ "myredbook.com",
+ "rarlab.com",
+ "audiopoisk.com",
+ "pbebank.com",
+ "whocallsme.com",
+ "playground.ru",
+ "tnr.com",
+ "firstdirect.com",
+ "xinhua.jp",
+ "gmane.org",
+ "verseriesynovelas.com",
+ "broadwayworld.com",
+ "thefrisky.com",
+ "rapmls.com",
+ "skapiec.pl",
+ "wholesale-dress.net",
+ "alison.com",
+ "n4hr.com",
+ "prefiles.com",
+ "vtc.vn",
+ "coral.co.uk",
+ "azyya.com",
+ "smithsonianmag.com",
+ "ticksy.com",
+ "theync.com",
+ "pcinpact.com",
+ "eventbrite.co.uk",
+ "buenosaires.gob.ar",
+ "a5cee7.se",
+ "bazingamob.com",
+ "pp.cc",
+ "shortnews.de",
+ "responsinator.com",
+ "filepost.com",
+ "securefreedom.com",
+ "notepad-plus-plus.org",
+ "thekrazycouponlady.com",
+ "apktops.ir",
+ "nr2.ru",
+ "timinternet.it",
+ "man.lv",
+ "forexpeacearmy.com",
+ "plius.lt",
+ "vcp.ir",
+ "mysitecost.ru",
+ "yourfiledownloader.com",
+ "dealguardian.com",
+ "sql.ru",
+ "laravel.com",
+ "shape5.com",
+ "visa.com",
+ "vocus.com",
+ "stackthatmoney.com",
+ "pornicom.com",
+ "my.tv.sohu.com/user/cc128",
+ "urban-rivals.com",
+ "robotstxt.org",
+ "colorlabsproject.com",
+ "mg.gov.br",
+ "local.ch",
+ "adbooth.net",
+ "se.pl",
+ "al-akhbar.com",
+ "he.net",
+ "covoiturage.fr",
+ "sakshieducation.com",
+ "thisdaylive.com",
+ "thestudentroom.co.uk",
+ "pzy.be",
+ "designyoutrust.com",
+ "forbes.ua",
+ "fandongxi.com",
+ "expertreviews.co.uk",
+ "dream-demo.com",
+ "barchart.com",
+ "ht.ly",
+ "burbuja.info",
+ "edgecastcdn.net",
+ "amazinglytimedphotos.com",
+ "value-domain.com",
+ "shareaholic.com",
+ "promptfile.com",
+ "voetbalzone.nl",
+ "ziare.com",
+ "trafficbroker.com",
+ "coolsport.tv",
+ "vanguardia.com.mx",
+ "makeshop.jp",
+ "mobilism.org",
+ "rebelmouse.com",
+ "brisbanetimes.com.au",
+ "publimetro.com.mx",
+ "coolkora.com",
+ "realsparrow.com",
+ "honda.co.jp",
+ "dealcatcher.com",
+ "sinoptik.ua",
+ "lefeng.com",
+ "mamaclub.com",
+ "bezuzyteczna.pl",
+ "smn.gov.ar",
+ "manhub.com",
+ "pcgameshardware.de",
+ "shipstation.com",
+ "zive.cz",
+ "disneystore.com",
+ "despegar.com.mx",
+ "addictivetips.com",
+ "path.com",
+ "pathofexile.com",
+ "seitenreport.de",
+ "pardot.com",
+ "decathlon.fr",
+ "flvrunner.com",
+ "xat.com",
+ "matchendirect.fr",
+ "roem.ru",
+ "wat.tv",
+ "edline.net",
+ "znds.com",
+ "northwestern.edu",
+ "friendscout24.de",
+ "movoto.com",
+ "dengiprosto.info",
+ "dlisted.com",
+ "sports.fr",
+ "maxifoot.fr",
+ "hubspot.net",
+ "natalie.mu",
+ "tabloidpulsa.co.id",
+ "polki.pl",
+ "gamasutra.com",
+ "matomeantena.com",
+ "adwords-community.com",
+ "gallup.com",
+ "redtubenacional.com",
+ "mangastream.com",
+ "zulutrade.com",
+ "wunderlist.com",
+ "taste.com.au",
+ "myhosting.com",
+ "totalbeauty.com",
+ "8pic.ir",
+ "sltrib.com",
+ "88db.com",
+ "minikoyuncu.com",
+ "net4.in",
+ "nuevoloquo.com",
+ "cago365.com",
+ "afip.gob.ar",
+ "keep2share.cc",
+ "kw.com",
+ "terra.com.pe",
+ "profi-forex.org",
+ "filecloud.io",
+ "peliculas4.com",
+ "mysitemyway.com",
+ "ilmattino.it",
+ "geizhals.de",
+ "sheershanews.com",
+ "whatwpthemeisthat.com",
+ "teknosa.com",
+ "myshopping.com.au",
+ "teamskeet.com",
+ "gandalfporn.com",
+ "2670.com",
+ "peoplefinders.com",
+ "elo7.com.br",
+ "sofoot.com",
+ "uhaul.com",
+ "sagepay.com",
+ "unb.br",
+ "jhu.edu",
+ "barrons.com",
+ "hasznaltauto.hu",
+ "winfxstrategy.com",
+ "spamcop.net",
+ "az.pl",
+ "op.fi",
+ "istruzione.it",
+ "eveonline.com",
+ "imgnip.com",
+ "jjoobb.cn",
+ "itesm.mx",
+ "wptavern.com",
+ "kproxy.com",
+ "pulptastic.com",
+ "quidco.com",
+ "ekantipur.com",
+ "joann.com",
+ "whattoexpect.com",
+ "tomshw.it",
+ "internetbookshop.it",
+ "followerwonk.com",
+ "cisionpoint.com",
+ "cint.com",
+ "quondos.com",
+ "suntimes.com",
+ "saveinter.net",
+ "eiga.com",
+ "jdzj.com",
+ "goldprice.org",
+ "websitemagazine.com",
+ "051jk.com",
+ "inweb24.com",
+ "gamgos.ae",
+ "elog-ch.com",
+ "trovit.com.mx",
+ "webnode.cz",
+ "ethnos.gr",
+ "oodle.com",
+ "subtitulos.es",
+ "gameinformer.com",
+ "9to5mac.com",
+ "youwatch.org",
+ "ibps.in",
+ "biggerpockets.com",
+ "sport24.co.za",
+ "my.tv.sohu.com/user/cc133",
+ "capsulecrm.com",
+ "fuett.mx",
+ "poznan.pl",
+ "melateiran.com",
+ "divxtotal.com",
+ "aftabir.com",
+ "cyberlink.com",
+ "ulozto.cz",
+ "jetswap.com",
+ "premium.wix.com",
+ "eprize.com",
+ "huntington.com",
+ "careerlink.vn",
+ "allhyipmonitors.com",
+ "autorambler.ru",
+ "jamieoliver.com",
+ "minube.com",
+ "credomatic.com",
+ "oddschecker.com",
+ "listia.com",
+ "mrrebates.com",
+ "8684.cn",
+ "kabam.com",
+ "tripit.com",
+ "gry.pl",
+ "ecvv.com",
+ "utanbaby.com",
+ "lavoixdunord.fr",
+ "just-eat.co.uk",
+ "go-for-files.com",
+ "afpbb.com",
+ "mybb.com",
+ "madmoizelle.com",
+ "sensacine.com",
+ "jtl-software.de",
+ "worldtimeserver.com",
+ "sunmaker.com",
+ "marieforleo.com",
+ "123sdfsdfsdfsd.ru",
+ "duga.jp",
+ "avery.com",
+ "tvguide.co.uk",
+ "salliemae.com",
+ "zap.com.br",
+ "my.tv.sohu.com/user/cc112",
+ "bookmark4you.com",
+ "twodollarclick.com",
+ "encontreinarede.com",
+ "joomshaper.com",
+ "marinetraffic.com",
+ "feedermatrix.com",
+ "nowvideo.at",
+ "millenium.org",
+ "newalbumreleases.net",
+ "frankkern.com",
+ "onlineconversion.com",
+ "ahlalhdeeth.com",
+ "mediawiki.org",
+ "xseo.in",
+ "generation-nt.com",
+ "naftemporiki.gr",
+ "hardforum.com",
+ "hornbunny.com",
+ "my.tv.sohu.com/user/cc124",
+ "housing.com",
+ "vogue.es",
+ "safemls.net",
+ "cuisineaz.com",
+ "estekhtam.com",
+ "coqnu.com",
+ "despegar.com.ar",
+ "fedoraproject.org",
+ "france2.fr",
+ "autovit.ro",
+ "tradetang.com",
+ "levelupgames.uol.com.br",
+ "dnforum.com",
+ "homebank.kz",
+ "carnival.com",
+ "hzycsj.com",
+ "army.mil",
+ "bootsnipp.com",
+ "istockimg.com",
+ "po-kaki-to.com",
+ "qiushibaike.com",
+ "tsb.co.uk",
+ "gzmama.com",
+ "aitnews.com",
+ "tripwiremagazine.com",
+ "torrenty.org",
+ "djangoproject.com",
+ "chelseafc.com",
+ "gamesgames.com",
+ "herold.at",
+ "baur.de",
+ "kauppalehti.fi",
+ "nrelate.com",
+ "clickwebinar.com",
+ "entropay.com",
+ "gridserver.com",
+ "virginia.gov",
+ "tuan800.com",
+ "trueactivist.com",
+ "caras.uol.com.br",
+ "fontawesome.io",
+ "haodou.com",
+ "reshareworthy.com",
+ "royalcaribbean.com",
+ "crakrevenue.com",
+ "motika.com.mk",
+ "xovi.de",
+ "deutsche-startups.de",
+ "inven.co.kr",
+ "atrapalo.com",
+ "ictv.ua",
+ "muji.net",
+ "kingplayer.com",
+ "adworkmedia.com",
+ "xjtu.edu.cn",
+ "thenounproject.com",
+ "professionali.ru",
+ "xizhi.com",
+ "boo-box.com",
+ "customink.com",
+ "groupon.my",
+ "spartoo.com",
+ "bannersdontwork.com",
+ "ncore.cc",
+ "reklama5.mk",
+ "macrojuegos.com",
+ "zenhabits.net",
+ "te3p.com",
+ "utah.gov",
+ "telesurtv.net",
+ "101.ru",
+ "5yi.com",
+ "lide.cz",
+ "ancestry.co.uk",
+ "sana.sy",
+ "siteslike.com",
+ "vg247.com",
+ "tyzhden.ua",
+ "ncsu.edu",
+ "apherald.com",
+ "taaza.com",
+ "traffic-delivery.com",
+ "uuyoyo.com",
+ "hwupgrade.it",
+ "game-debate.com",
+ "jetpack.wordpress.com",
+ "anycodes.com",
+ "femina.hu",
+ "zattoo.com",
+ "acm.org",
+ "comenity.net",
+ "tarot.com",
+ "azadliq.org",
+ "advertiserdigital.com",
+ "osym.gov.tr",
+ "empornium.me",
+ "netzero.net",
+ "myfico.com",
+ "nolix.ru",
+ "cnwnews.com",
+ "springpad.com",
+ "ahangestan.in",
+ "localbitcoins.com",
+ "nikkei.co.jp",
+ "youlikehits.com",
+ "boyfriendtv.com",
+ "wampserver.com",
+ "elnorte.com",
+ "codeschool.com",
+ "si.edu",
+ "nosis.com",
+ "downloadhelper.net",
+ "global-free-classified-ads.com",
+ "flagmantube.com",
+ "elnuevodiario.com.ni",
+ "handelsbanken.se",
+ "sverigesradio.se",
+ "femjoy.com",
+ "444.hu",
+ "calcalist.co.il",
+ "asiatech.ir",
+ "tv.nu",
+ "installmac.com",
+ "programmableweb.com",
+ "fotki.com",
+ "vidivodo.com",
+ "websquash.com",
+ "selfgrowth.com",
+ "wehkamp.nl",
+ "amawebs.com",
+ "3dlat.com",
+ "comunidades.net",
+ "streamin.to",
+ "idbi.com",
+ "cshtracker.com",
+ "cdbaby.com",
+ "mycommerce.com",
+ "united-domains.de",
+ "tradingview.com",
+ "niniweblog.com",
+ "avn.info.ve",
+ "apa.tv",
+ "pinnaclesports.com",
+ "adafruit.com",
+ "ipower.com",
+ "lebuteur.com",
+ "utah.edu",
+ "mobeoffice.com",
+ "lingualeo.com",
+ "fuub.net",
+ "tvmongol.com",
+ "namasthetelangaana.com",
+ "secretsearchenginelabs.com",
+ "whowhatwear.com",
+ "hiapk.com",
+ "torrentz.sx",
+ "php.su",
+ "sodahead.com",
+ "sbb.ch",
+ "k12.ca.us",
+ "jecontacte.com",
+ "thehollywoodgossip.com",
+ "pekao24.pl",
+ "yourtest-india.com",
+ "screwfix.com",
+ "humoron.com",
+ "yiwugou.com",
+ "mulher.uol.com.br",
+ "thehackernews.com",
+ "shopmania.ro",
+ "dlink.com",
+ "despegar.com",
+ "archlinux.org",
+ "nielsen.com",
+ "rosnet.ru",
+ "appsapk.com",
+ "funfarsi.ir",
+ "4over.com",
+ "subscribe.wordpress.com",
+ "lewrockwell.com",
+ "portalnet.cl",
+ "antenam.info",
+ "letribunaldunet.fr",
+ "see-tube.com",
+ "tureng.com",
+ "topcashback.co.uk",
+ "contactcars.com",
+ "jeux.fr",
+ "khan.co.kr",
+ "ffffound.com",
+ "gmail.com",
+ "laprensa.com.ni",
+ "jizzhut.com",
+ "liilas.com",
+ "muare.vn",
+ "kting.cn",
+ "heteml.jp",
+ "genericsteps.com",
+ "searchcompletion.com",
+ "dwayir.com",
+ "dicionarioinformal.com.br",
+ "vcita.com",
+ "fitsugar.com",
+ "kleiderkreisel.de",
+ "collective-evolution.com",
+ "ethz.ch",
+ "sendreach.com",
+ "abidjan.net",
+ "islamicfinder.org",
+ "elong.com",
+ "yonhapnews.co.kr",
+ "seratnews.ir",
+ "stream2watch.me",
+ "content-watch.ru",
+ "seotechnocrat.com",
+ "todaoferta.uol.com.br",
+ "toyota.jp",
+ "purevid.com",
+ "incredimail.com",
+ "kia.com",
+ "intensedebate.com",
+ "kaufmich.com",
+ "servis24.cz",
+ "brusheezy.com",
+ "rtbtraf.com",
+ "tejiawang.com",
+ "expedia.co.in",
+ "food52.com",
+ "top-channel.tv",
+ "jpnn.com",
+ "desitorrents.com",
+ "faxingw.cn",
+ "crutchfield.com",
+ "seneweb.com",
+ "usenet.nl",
+ "aviasales.ru",
+ "nesine.com",
+ "appshopper.com",
+ "dressupgamesite.com",
+ "lowendtalk.com",
+ "muslima.com",
+ "v-webs.com",
+ "linkomanija.net",
+ "geniuzz.com",
+ "caringbridge.org",
+ "gooya.com",
+ "dospy.com",
+ "siol.net",
+ "games.co.id",
+ "archiveofourown.org",
+ "rocketlawyer.com",
+ "free-downloadz.net",
+ "pastemagazine.com",
+ "invest-system.net",
+ "el-ahly.com",
+ "todayhumor.co.kr",
+ "racingpost.com",
+ "stereogum.com",
+ "soompi.com",
+ "pof.com.br",
+ "brainabundance.com",
+ "fontpalace.com",
+ "canon.jp",
+ "eldeforma.com",
+ "sacbee.com",
+ "jobscore.com",
+ "fashionista.com",
+ "mywork.vn",
+ "thisis50.com",
+ "cubadebate.cu",
+ "healthguru.com",
+ "instatheme.com",
+ "apotheken-umschau.de",
+ "blizko.ru",
+ "tinymce.com",
+ "virtualbox.org",
+ "tehran.ir",
+ "pr.gov.br",
+ "mlmleadsystempro.com",
+ "resbux.com",
+ "komonews.com",
+ "childrensplace.com",
+ "yoyopress.com",
+ "cloudify.cc",
+ "24livenewspaper.com",
+ "w4.com",
+ "islamway.net",
+ "fantagazzetta.com",
+ "imgspice.com",
+ "bovada.lv",
+ "payback.de",
+ "peb.pl",
+ "hotnigerianjobs.com",
+ "dev7studios.com",
+ "tejaratbank.net",
+ "takuhai.jp",
+ "travelmath.com",
+ "cultofmac.com",
+ "wakeupnow.com",
+ "insidefacebook.com",
+ "mediamarkt.es",
+ "500wan.com",
+ "rumah123.com",
+ "contentmarketinginstitute.com",
+ "ed.ac.uk",
+ "phimvang.com",
+ "womansday.com",
+ "lookatme.ru",
+ "citizensbank.com",
+ "esam.ir",
+ "phandroid.com",
+ "canadiantire.ca",
+ "serienjunkies.de",
+ "bbspink.com",
+ "yaranehkala.ir",
+ "vesti.bg",
+ "el-carabobeno.com",
+ "smarty.net",
+ "6tie.com",
+ "antpedia.com",
+ "p-world.co.jp",
+ "camelcamelcamel.com",
+ "sudu.cn",
+ "priberam.pt",
+ "infoworld.com",
+ "myrecipes.com",
+ "metrodeal.com",
+ "widgetbox.com",
+ "krone.at",
+ "outfox.tv",
+ "mymp4.in",
+ "685wo.com",
+ "sadanduseless.com",
+ "cgd.pt",
+ "mrmlsmatrix.com",
+ "parenting.com",
+ "tradepub.com",
+ "linkvehicle.com",
+ "mobiledia.com",
+ "rghost.ru",
+ "xxsy.net",
+ "goanimate.com",
+ "pikacn.com",
+ "metropcs.com",
+ "byu.edu",
+ "bitelia.com",
+ "designscrazed.com",
+ "wpde.org",
+ "paheal.net",
+ "nulled.cc",
+ "hmv.co.jp",
+ "openx.com",
+ "hyundai.com",
+ "vvvdj.com",
+ "reason.com",
+ "livesports.pl",
+ "polskieradio.pl",
+ "oszone.net",
+ "chinhphu.vn",
+ "performancehorizon.com",
+ "internetretailer.com",
+ "skoob.com.br",
+ "mediaworld.it",
+ "imgrind.com",
+ "bancopopular.es",
+ "seogadget.ru",
+ "m6.fr",
+ "rongbay.com",
+ "niazpardaz.com",
+ "rewity.com",
+ "ssense.com",
+ "sky-fire.com",
+ "flibusta.net",
+ "eat24hours.com",
+ "lotto.pl",
+ "cnw.com.cn",
+ "takvim.com.tr",
+ "englishtown.com",
+ "letudiant.fr",
+ "peliculasmas.com",
+ "askme.com",
+ "linksmanagement.com",
+ "webseoanalytics.com",
+ "presse-citron.net",
+ "eldiariodeamerica.com",
+ "instantshift.com",
+ "ampxchange.com",
+ "xe.gr",
+ "experts-exchange.com",
+ "sportcategory.com",
+ "sharecash.org",
+ "linksys.com",
+ "yninfo.com",
+ "onlinelic.in",
+ "aflamneek.com",
+ "22.cn",
+ "ubuntu-fr.org",
+ "cjs.com.cn",
+ "mp3clan.com",
+ "grani.ru",
+ "zen-cart.com",
+ "shippingchina.com",
+ "jsfor.net",
+ "wanadoo.es",
+ "zurker.com",
+ "chotot.vn",
+ "masaladesi.com",
+ "insight.ly",
+ "trivago.de",
+ "neue-sexpartner.com",
+ "boe.es",
+ "military.com",
+ "moonbasa.com",
+ "langlaoda.com",
+ "tnooz.com",
+ "zacks.com",
+ "liverpool.com.mx",
+ "internic.net",
+ "ecuavisa.com",
+ "autonews.ru",
+ "mcafeesecure.com",
+ "peopleclick.com",
+ "madthumbs.com",
+ "hot-live-chat.com",
+ "sugarcrm.com",
+ "notonthehighstreet.com",
+ "linio.com.co",
+ "smartbrief.com",
+ "auto-motor-und-sport.de",
+ "kyivpost.com",
+ "instantteleseminar.com",
+ "dillards.com",
+ "5i5j.com",
+ "runtastic.com",
+ "danawa.com",
+ "ladunliadi.blogspot.com",
+ "getnews.jp",
+ "romedic.ro",
+ "rodfile.com",
+ "instyle.com",
+ "swoodoo.com",
+ "bannersnack.com",
+ "evolife.cn",
+ "ktonanovenkogo.ru",
+ "office.com",
+ "zamalekfans.com",
+ "magiran.com",
+ "ithome.com",
+ "ktrmr.com",
+ "spoonful.com",
+ "olleh.com",
+ "bgr.in",
+ "industrialthemes.com",
+ "adbkm.com",
+ "tsa-algerie.com",
+ "bloggang.com",
+ "mojang.com",
+ "geoiptool.com",
+ "autocarindia.com",
+ "ajansspor.com",
+ "onmeda.de",
+ "midwayusa.com",
+ "alicdn.com",
+ "sportdog.gr",
+ "ideeli.com",
+ "haspa.de",
+ "gladbux.com",
+ "porn-star.com",
+ "experiandirect.com",
+ "yicheshi.com",
+ "acervoamador.com",
+ "designwall.com",
+ "balkanweb.com",
+ "response.jp",
+ "nettoos.com",
+ "beruby.com",
+ "manageyourloans.com",
+ "kidstaff.com.ua",
+ "indeed.co.za",
+ "monoprice.com",
+ "chsi.com.cn",
+ "boorsekala.com",
+ "mstaml.com",
+ "trafficvance.com",
+ "tatatele.in",
+ "startbootstrap.com",
+ "graphicburger.com",
+ "ad-vid-webs.com",
+ "jp.dk",
+ "one.co.il",
+ "athensvoice.gr",
+ "payu2blog.com",
+ "epidemz.net",
+ "dondominio.com",
+ "doviz.com",
+ "disquscdn.com",
+ "work.ua",
+ "vsemayki.ru",
+ "ikyu.com",
+ "songlyrics.com",
+ "onlinebank.com",
+ "thebump.com",
+ "travian.com.tr",
+ "java2s.com",
+ "twittmate.com",
+ "ignou.ac.in",
+ "relink.us",
+ "4738.com",
+ "printvenue.com",
+ "tekstowo.pl",
+ "natro.com",
+ "dengi-tut.info",
+ "freeservers.com",
+ "inbound.org",
+ "free-press-release.com",
+ "mydirtyhobby.com",
+ "gamefly.com",
+ "overclockers.co.uk",
+ "eci.nic.in",
+ "196.1.211.6",
+ "versus.com",
+ "batdongsan.com.vn",
+ "vrisko.gr",
+ "albayan.ae",
+ "trendcounter.com",
+ "500.com",
+ "pagomiscuentas.com",
+ "wankoz.com",
+ "duote.com",
+ "javascript.ru",
+ "chevrolet.com",
+ "coach.com",
+ "decidatriunfar.net",
+ "rememberthemilk.com",
+ "virginmobileusa.com",
+ "google.com.jm",
+ "ucm.es",
+ "ninja.co.jp",
+ "rqzao.com",
+ "periodistadigital.com",
+ "heritage.org",
+ "momtubesex.xxx",
+ "vocabulary.com",
+ "kupujemprodajem.com",
+ "e-cigarette-forum.com",
+ "paxum.com",
+ "ilpost.it",
+ "abercrombie.com",
+ "pearsonmylabandmastering.com",
+ "echoecho.com",
+ "expedia.co.jp",
+ "ticketfly.com",
+ "colostate.edu",
+ "sjtu.edu.cn",
+ "seobudget.ru",
+ "gigabyte.com",
+ "gsmspain.com",
+ "misr5.com",
+ "enterfactory.com",
+ "ciao.de",
+ "wuv.de",
+ "dagospia.com",
+ "slashgear.com",
+ "urdupoint.com",
+ "themepunch.com",
+ "travian.com",
+ "discuz.com",
+ "pixroute.com",
+ "otzovik.com",
+ "ubergizmo.com",
+ "edreams.fr",
+ "internet-positif.org",
+ "asmcentral.com",
+ "copadomundo.uol.com.br",
+ "adjal.com",
+ "gotomypc.com",
+ "partycity.com",
+ "leggo.it",
+ "blogosfere.it",
+ "teamcoco.com",
+ "pricedealsindia.com",
+ "glennbeck.com",
+ "allyou.com",
+ "china.org.cn",
+ "xitek.com",
+ "photoshopessentials.com",
+ "infopraca.pl",
+ "boardingarea.com",
+ "geni.com",
+ "rotaban.ru",
+ "foxtab.com",
+ "sadistic.pl",
+ "socialbro.com",
+ "tradesparq.com",
+ "itp.ne.jp",
+ "swefilmer.com",
+ "jobsite.co.uk",
+ "topwar.ru",
+ "yemeksepeti.com",
+ "tokfm.pl",
+ "businessinsider.com.au",
+ "moe.gov.eg",
+ "swedbank.lt",
+ "jxgdw.com",
+ "bayern.de",
+ "alistapart.com",
+ "bebinin.com",
+ "annunci69.it",
+ "plimus.com",
+ "cuevana2.tv",
+ "viamichelin.fr",
+ "whatsmydns.net",
+ "tarad.com",
+ "hostgator.com.br",
+ "hasbro.com",
+ "hi-chic.com",
+ "driverscollection.com",
+ "onetad.com",
+ "game2.com.cn",
+ "elitepvpers.com",
+ "tvuol.uol.com.br",
+ "caclubindia.com",
+ "diariocorreo.pe",
+ "c-rewards.com",
+ "business.gov.au",
+ "chooseauto.com.cn",
+ "timetrade.com",
+ "alternate.de",
+ "syracuse.com",
+ "advanceautoparts.com",
+ "shopware.de",
+ "newpct.com",
+ "proranktracker.com",
+ "cex.io",
+ "thebot.net",
+ "tradekorea.com",
+ "legifrance.gouv.fr",
+ "cpan.org",
+ "rightel.ir",
+ "247wallst.com",
+ "goldentowns.com",
+ "bankifsccode.com",
+ "color-hex.com",
+ "consumerist.com",
+ "juegosdiarios.com",
+ "on24.com",
+ "stockfreeimages.com",
+ "m4.cn",
+ "sponsoredtweets.com",
+ "open.ac.uk",
+ "bilyoner.com",
+ "lexisnexis.com",
+ "gsu.edu",
+ "popscreen.com",
+ "stiftung-warentest.de",
+ "education.com",
+ "leckerficken.de",
+ "hostinger.ru",
+ "staples.ca",
+ "greenpeace.org",
+ "mes-meilleurs-films.fr",
+ "delish.com",
+ "register.it",
+ "idiva.com",
+ "static.squarespace.com",
+ "ololo.fm",
+ "basketball-reference.com",
+ "tro-ma-ktiko.blogspot.gr",
+ "arabianbusiness.com",
+ "avianca.com",
+ "watchuseek.com",
+ "6play.fr",
+ "kora-online.tv",
+ "armagedomfilmes.biz",
+ "531314.com",
+ "craigslist.co.uk",
+ "inchallah.com",
+ "bongdaso.com",
+ "toprankblog.com",
+ "k12.com",
+ "itimes.com",
+ "html.net",
+ "utsandiego.com",
+ "gyakorikerdesek.hu",
+ "viddyhddownload.com",
+ "wannonce.com",
+ "qudong.com",
+ "ibicn.com",
+ "w3resource.com",
+ "socialsecurity.gov",
+ "tvn.pl",
+ "momsexclipz.com",
+ "fstoppers.com",
+ "kafeteria.pl",
+ "boulanger.fr",
+ "guj.nic.in",
+ "divaina.com",
+ "desktopnexus.com",
+ "topseda.ir",
+ "payumoney.com",
+ "klicktel.de",
+ "foxtv.es",
+ "cuatro.com",
+ "publix.com",
+ "astrosage.com",
+ "kompass.com",
+ "web-hosting.com",
+ "nus.edu.sg",
+ "jamiiforums.com",
+ "lancers.jp",
+ "peixeurbano.com.br",
+ "buysub.com",
+ "yp.com",
+ "enstage.com",
+ "6eat.com",
+ "1ent.com.cn",
+ "unionpaysecure.com",
+ "pcgames.de",
+ "ccidcom.com",
+ "lavenir.net",
+ "novaposhta.ua",
+ "hotpornshow.com",
+ "telebank.ru",
+ "avaz.ba",
+ "doit.com.cn",
+ "setlinks.ru",
+ "zagat.com",
+ "sportmaster.ru",
+ "utarget.ru",
+ "lingualeo.ru",
+ "compucalitv.com",
+ "anastasiadate.com",
+ "webmaster-rank.info",
+ "fastcoexist.com",
+ "lavasoft.com",
+ "ppvguru.com",
+ "greatist.com",
+ "knack.be",
+ "wowwiki.com",
+ "ilcorsaronero.info",
+ "jword.jp",
+ "750g.com",
+ "pantipmarket.com",
+ "top.de",
+ "photofunia.com",
+ "dryicons.com",
+ "alweeam.com.sa",
+ "dnfight.com",
+ "wpolityce.pl",
+ "vimeocdn.com",
+ "visit-x.net",
+ "takungpao.com",
+ "perfectworld.eu",
+ "kat.ph",
+ "hefei.cc",
+ "cmse.ru",
+ "virginia.edu",
+ "fudan.edu.cn",
+ "sethgodin.typepad.com",
+ "caracaschronicles.com",
+ "18qt.com",
+ "be2.com.br",
+ "rakuten.tw",
+ "bukkit.org",
+ "miss-no1.com",
+ "nts.org.pk",
+ "ulozto.net",
+ "mixpanel.com",
+ "glavred.info",
+ "vui.vn",
+ "mindspark.com",
+ "worldmarket.com",
+ "walmart.com.mx",
+ "deperu.com",
+ "taxact.com",
+ "m5zn.com",
+ "navy.mil",
+ "hibapress.com",
+ "cpasbien.com",
+ "interjet.com.mx",
+ "llbean.com",
+ "kenrockwell.com",
+ "japan-guide.com",
+ "financialpost.com",
+ "rankingsinstitute.com",
+ "master-x.com",
+ "pandawill.com",
+ "marketingweek.co.uk",
+ "freeforums.org",
+ "ysear.ch",
+ "pokerstars.com",
+ "wired.co.uk",
+ "amino.dk",
+ "rapidcrush.com",
+ "vivanuncios.com",
+ "blogsvertise.com",
+ "cwb.gov.tw",
+ "piter.tv",
+ "gistmania.com",
+ "topdocumentaryfilms.com",
+ "shoghlanty.com",
+ "bankmillennium.pl",
+ "burberry.com",
+ "youporngay.com",
+ "webresourcesdepot.com",
+ "beachbody.com",
+ "asstr.org",
+ "pwc.com",
+ "competitor.com",
+ "rss2search.com",
+ "vocuspr.com",
+ "behindthename.com",
+ "moniker.com",
+ "jayde.com",
+ "opensuse.org",
+ "poemhunter.com",
+ "toranoana.jp",
+ "interaksyon.com",
+ "aeon.co.jp",
+ "gungho.jp",
+ "fgov.be",
+ "xpg.uol.com.br",
+ "logic-immo.com",
+ "worldsex.com",
+ "watchonlineseries.eu",
+ "google.co.mz",
+ "discas.net",
+ "chmail.ir",
+ "consumercomplaints.in",
+ "allstate.com",
+ "twelveskip.com",
+ "ibibo.com",
+ "noelshack.com",
+ "bonprix.ru",
+ "directupload.net",
+ "equipobimlatino.com",
+ "weather2umbrella.com",
+ "aibang.com",
+ "blog.wordpress.com",
+ "turner.com",
+ "mediapart.fr",
+ "bloog.pl",
+ "monotaro.com",
+ "online.net",
+ "bodmillenium.com",
+ "distancesfrom.com",
+ "naosalvo.com.br",
+ "ap7am.com",
+ "focus.ua",
+ "cokeandpopcorn.ch",
+ "qwant.com",
+ "megaplan.ru",
+ "sinhvienit.net",
+ "dream-marriage.com",
+ "voicefive.com",
+ "forex.com.cn",
+ "xabbs.com",
+ "netmums.com",
+ "tuxboard.com",
+ "cs-cart.com",
+ "bitcoin.it",
+ "boblil.com",
+ "nirsoft.net",
+ "neopets.com",
+ "spin.com",
+ "costco.ca",
+ "mirraw.com",
+ "ara.cat",
+ "klamm.de",
+ "glam.com",
+ "guenstiger.de",
+ "citruspay.com",
+ "dnslink.com",
+ "guyism.com",
+ "shopotam.ru",
+ "tim.it",
+ "3suisses.fr",
+ "gooroops.com",
+ "kau.edu.sa",
+ "ukbusinessforums.co.uk",
+ "gree.jp",
+ "komikid.com",
+ "redakcja.pl",
+ "qpic.cn",
+ "voyeurweb.com",
+ "mathworks.com",
+ "monster.fr",
+ "seniat.gob.ve",
+ "computrabajo.com.co",
+ "xilu.com",
+ "madrid.org",
+ "ostraining.com",
+ "bharian.com.my",
+ "telegram.org",
+ "sumofus.org",
+ "whosdatedwho.com",
+ "moreofit.com",
+ "meetic.it",
+ "femina.mk",
+ "itworld.com",
+ "indiaglitz.com",
+ "cheatcc.com",
+ "filmfanatic.com",
+ "the-bux.net",
+ "very.co.uk",
+ "fetishshrine.com",
+ "speakingtree.in",
+ "iu.edu",
+ "modern.az",
+ "tak.ru",
+ "internetmarketingninjas.com",
+ "example.com",
+ "sportgeza.hu",
+ "wrestlezone.com",
+ "jameda.de",
+ "caikuu.com",
+ "gioco.it",
+ "yourtv.com.au",
+ "euro.com.pl",
+ "anz.co.nz",
+ "daft.ie",
+ "tirerack.com",
+ "vivareal.com.br",
+ "definebabe.com",
+ "ittefaq.com.bd",
+ "lastfm.es",
+ "zocalo.com.mx",
+ "dpd.de",
+ "somethingawful.com",
+ "virgin.com",
+ "shtyle.fm",
+ "viralforest.com",
+ "dntrck.com",
+ "its-mo.com",
+ "q.cc",
+ "kinghost.net",
+ "elpais.com.co",
+ "joomlaspanish.org",
+ "sopitas.com",
+ "wallbase.cc",
+ "cpalead.com",
+ "torrentfunk.com",
+ "bizcom.com.ru",
+ "quizony.com",
+ "rcgroups.com",
+ "spring.io",
+ "kuaidi100.com",
+ "xatakandroid.com",
+ "mlstatic.com",
+ "borsaat.com",
+ "jagobd.com",
+ "cosmiq.de",
+ "crucial.com",
+ "cdstm.cn",
+ "betclic.fr",
+ "telewebion.com",
+ "exhentai.org",
+ "gnezdo.ru",
+ "cebupacificair.com",
+ "fusionmls.com",
+ "shafaf.ir",
+ "ticketmaster.co.uk",
+ "adslzone.net",
+ "k8.cn",
+ "recipdonor.com",
+ "in.gov",
+ "mforos.com",
+ "asscj.com",
+ "linkconnector.com",
+ "ohfreesex.com",
+ "cntraveler.com",
+ "scambioetico.org",
+ "ladenzeile.de",
+ "ntn24.com",
+ "beyazperde.com",
+ "motherearthnews.com",
+ "yupptv.com",
+ "220tube.com",
+ "fizzle.co",
+ "lakii.com",
+ "deutsche-wirtschafts-nachrichten.de",
+ "saaid.net",
+ "bimlatino.com",
+ "verisign.com",
+ "funpatogh.com",
+ "matadornetwork.com",
+ "seatguru.com",
+ "lululemon.com",
+ "uzise.com",
+ "networkworld.com",
+ "hottube.me",
+ "jobsdb.com.hk",
+ "life.hu",
+ "bonusvid.com",
+ "incometaxindiaefiling.gov.in",
+ "ey.com",
+ "alraimedia.com",
+ "allposters.com",
+ "authorityroi.com",
+ "bmwusa.com",
+ "ebaystatic.com",
+ "entertainmentcrave.com",
+ "ehow.com.br",
+ "prisonplanet.com",
+ "elnashra.com",
+ "email.cz",
+ "yes123.com.tw",
+ "uitzendinggemist.nl",
+ "mindtools.com",
+ "atv.com.tr",
+ "shoes.net.cn",
+ "joomlaportal.de",
+ "themoneyconverter.com",
+ "meteomedia.com",
+ "bankaustria.at",
+ "advertise.com",
+ "trafficswarm.com",
+ "aztecaporno.com",
+ "fourseasons.com",
+ "movie-blog.org",
+ "govdelivery.com",
+ "didigames.com",
+ "invideo.biz",
+ "linux.org.ru",
+ "omelete.uol.com.br",
+ "babybus.cn",
+ "oursogo.com",
+ "ero-an.com",
+ "mediafax.ro",
+ "football.ua",
+ "sii.cl",
+ "dreamamateurs.com",
+ "cheaperthandirt.com",
+ "iplocation.net",
+ "insideview.com",
+ "hihe.vn",
+ "stop-sex.com",
+ "fubiz.net",
+ "url.org",
+ "greenmangaming.com",
+ "pornup.me",
+ "indofeed.com",
+ "forumhouse.ru",
+ "restaurant.com",
+ "key.com",
+ "windstream.net",
+ "brightedge.com",
+ "foreignpolicy.com",
+ "noticiasdatv.uol.com.br",
+ "logopond.com",
+ "datemule.com",
+ "webrootanywhere.com",
+ "stomp.com.sg",
+ "trthaber.com",
+ "bitterstrawberry.com",
+ "turbo.az",
+ "kbs.co.kr",
+ "joblo.com",
+ "seatimes.com.vn",
+ "kuwait.tt",
+ "258.com",
+ "kp.ua",
+ "moviesmobile.net",
+ "flamingtext.com",
+ "youngt.com",
+ "etradenow.cn",
+ "copart.com",
+ "tuanweihui.com",
+ "zinkwaphd.com",
+ "adsl.free.fr",
+ "infomaniak.ch",
+ "re-direcciona.me",
+ "mejorenvo.com",
+ "instantservice.com",
+ "harpersbazaar.com",
+ "colorado.edu",
+ "belboon.com",
+ "telelistas.net",
+ "photofans.cn",
+ "51seer.com",
+ "danjur.com",
+ "wunderweib.de",
+ "extratorrentlive.com",
+ "serpfox.com",
+ "androidkade.com",
+ "raja.ir",
+ "tampabay.com",
+ "ser-mujer.org",
+ "imasters.com.br",
+ "coachfactory.com",
+ "mojopages.com",
+ "makezine.com",
+ "forexschoolonline.com",
+ "bochk.com",
+ "siamsport.co.th",
+ "mdpr.jp",
+ "serialssolutions.com",
+ "videosexarchive.com",
+ "enlnks.com",
+ "cision.com",
+ "scratchinginfo.com",
+ "skidrowgames.net",
+ "optimizely.com",
+ "video2brain.com",
+ "ariva.de",
+ "audiomack.com",
+ "pimproll.com",
+ "house.gov",
+ "acs.org",
+ "pijamasurf.com",
+ "autoc-one.jp",
+ "southcn.com",
+ "vesti.az",
+ "300mbfilms.com",
+ "speedmystream.com",
+ "wooservers.com",
+ "siteliner.com",
+ "tinmoi.vn",
+ "extremepornvideos.com",
+ "cqsq.com",
+ "hello-today.com",
+ "turkcealtyazi.org",
+ "tvyo.com",
+ "dealmoon.com",
+ "openenglish.com",
+ "golfchannel.com",
+ "irancloob.com",
+ "ebs.in",
+ "portalcorreio.uol.com.br",
+ "beemp3s.org",
+ "condenast.com",
+ "mtwebcenters.com.tw",
+ "hatelabo.jp",
+ "pathci.net",
+ "mamsy.ru",
+ "noticiasdelmundo.org",
+ "guru3d.com",
+ "logomaker.com",
+ "adhitz.com",
+ "swiki.jp",
+ "turnitin.com",
+ "patoghu.com",
+ "carnaval.uol.com.br",
+ "cancer.org",
+ "clickprime8.com",
+ "fahrinfo-berlin.de",
+ "unisender.com",
+ "flashkhor.com",
+ "goodfon.ru",
+ "ethiotube.net",
+ "cunbang.com",
+ "ti-da.net",
+ "1phads.com",
+ "bien.hu",
+ "home77.com",
+ "mbabycare.com",
+ "vudu.com",
+ "fantasy8.com",
+ "landrover.com",
+ "opencartforum.ru",
+ "antena3.ro",
+ "getapp.com",
+ "torlock.com",
+ "wind.it",
+ "expatads.com",
+ "bloglines.com",
+ "sexytube.me",
+ "frontier.com",
+ "asandownload.com",
+ "groupon.pl",
+ "storesonlinepro.com",
+ "brands4friends.de",
+ "infogr.am",
+ "webeffector.ru",
+ "google.com.mm",
+ "ppchero.com",
+ "privacystar.com",
+ "ocregister.com",
+ "liex.ru",
+ "kopatheme.com",
+ "toggl.com",
+ "raywenderlich.com",
+ "hecha.cn",
+ "vpls.net",
+ "manpianyi.com",
+ "1881.no",
+ "scbeasy.com",
+ "plex.tv",
+ "selfridges.com",
+ "anumex.com",
+ "postplanner.com",
+ "thisiscolossal.com",
+ "you-will-date.com",
+ "idealist.org",
+ "emarketer.com",
+ "anibis.ch",
+ "dansmovies.com",
+ "footballitarin.com",
+ "fragrantica.com",
+ "10minutemail.com",
+ "ntu.edu.tw",
+ "clasicooo.com",
+ "onsugar.com",
+ "vr-zone.com",
+ "walkerplus.com",
+ "easymobilerecharge.com",
+ "cz001.com.cn",
+ "sportsseoul.com",
+ "inazumanews2.com",
+ "marketingdirecto.com",
+ "chartboost.com",
+ "unblocked.co",
+ "rhymezone.com",
+ "portalinmobiliario.com",
+ "afrointroductions.com",
+ "transunion.com",
+ "panorama.it",
+ "powershow.com",
+ "avval.ir",
+ "onlinemeetingnow.com",
+ "xoom.com",
+ "wnbc.com",
+ "tlen.pl",
+ "jetairways.com",
+ "vtb24.ru",
+ "offcn.com",
+ "crx7601.com",
+ "adverts.ie",
+ "kasserver.com",
+ "minhavida.com.br",
+ "jkpj.com",
+ "123contactform.com",
+ "imgtiger.com",
+ "folha.com.br",
+ "npcgo.com",
+ "semprot.com",
+ "moonfruit.com",
+ "jizzbell.com",
+ "online-stopwatch.com",
+ "allhiphop.com",
+ "hackaday.com",
+ "digitalplayground.com",
+ "careers24.com",
+ "cwq.com",
+ "wondershare.com",
+ "filesend.to",
+ "puromarketing.com",
+ "workopolis.com",
+ "mudainodocument.com",
+ "home.ne.jp",
+ "shorte.st",
+ "tanea.gr",
+ "sporza.be",
+ "vgorode.ua",
+ "google.co.zm",
+ "argumentua.com",
+ "3m.com",
+ "komputerswiat.pl",
+ "bongdaplus.vn",
+ "supersonicads.com",
+ "soundclick.com",
+ "lollipop-network.com",
+ "lpcloudsvr304.com",
+ "313.cn",
+ "rtl2.de",
+ "ts.cn",
+ "mglradio.com",
+ "diynetwork.com",
+ "komikcaps.net",
+ "all-that-is-interesting.com",
+ "ultipro.com",
+ "frombar.com",
+ "sitedeals.nl",
+ "codingforums.com",
+ "kansascity.com",
+ "twtrland.com",
+ "cengage.com",
+ "lolspotsarticles.com",
+ "jackthreads.com",
+ "jobstreet.com.sg",
+ "diffen.com",
+ "eme2000.com",
+ "superbru.com",
+ "droid-life.com",
+ "itb-berlin.de",
+ "estibot.com",
+ "yourepeat.com",
+ "112.ua",
+ "70e.com",
+ "grid.mk",
+ "cromaretail.com",
+ "jobstreet.com.ph",
+ "gloadmarket.com",
+ "gemius.com",
+ "huuto.net",
+ "vogue.it",
+ "divxonline.info",
+ "mytoys.de",
+ "cashnhits.com",
+ "minkchan.com",
+ "talabat.com",
+ "helpareporter.com",
+ "grandascent.com",
+ "catalunyacaixa.com",
+ "sparwelt.de",
+ "tvboxnow.com",
+ "imagecurl.org",
+ "coocan.jp",
+ "eatingwell.com",
+ "truelife.com",
+ "binaryoptionsbrands.com",
+ "foxsportsla.com",
+ "jjshouse.com",
+ "makaan.com",
+ "yamaha.com",
+ "activerain.com",
+ "excelforum.com",
+ "mobinnet.ir",
+ "kasikornbankgroup.com",
+ "googleplex.com",
+ "medianama.com",
+ "fullsail.edu",
+ "makeupandbeauty.com",
+ "marketwired.com",
+ "beachbodycoach.com",
+ "taloussanomat.fi",
+ "youngliving.us",
+ "dana.ir",
+ "adsgostar.com",
+ "esquire.com.cn",
+ "meyerweb.com",
+ "positivemed.com",
+ "harvestapp.com",
+ "tim.com.br",
+ "sumorobo.net",
+ "zbigz.com",
+ "schulferien.org",
+ "quzhao.com",
+ "tsinghua.edu.cn",
+ "vogue.com",
+ "ecrater.com",
+ "internetbs.net",
+ "oper.ru",
+ "kingstone.com.tw",
+ "olympic.org",
+ "code.org",
+ "wp.tv",
+ "adchakra.net",
+ "passarela.com.br",
+ "damn.com",
+ "spn.com.cn",
+ "sacitaslan.com",
+ "uplod.ir",
+ "kununu.com",
+ "englishclub.com",
+ "ibood.com",
+ "buzzfed.com",
+ "peopledaily.com.cn",
+ "vivastreet.it",
+ "adshostnet.com",
+ "npmjs.org",
+ "lovethatsex.com",
+ "garena.tw",
+ "hq-sex-tube.com",
+ "tvsubtitles.net",
+ "trademarkia.com",
+ "96down.com",
+ "morhipo.com",
+ "chuguoqu.com",
+ "free-css.com",
+ "getsecuredfiles.com",
+ "justia.com",
+ "paypal-community.com",
+ "wezoner.com",
+ "google-analytics.com",
+ "outsideonline.com",
+ "simplymeasured.com",
+ "wattsupwiththat.com",
+ "vancl.com",
+ "leadership.ng",
+ "plaisio.gr",
+ "fastcocreate.com",
+ "fewo-direkt.de",
+ "dedecms.com",
+ "bostonherald.com",
+ "elmundo.com.ve",
+ "idhostinger.com",
+ "animaljam.com",
+ "infoq.com",
+ "exler.ru",
+ "leprosorium.ru",
+ "avis.com",
+ "ulusalpost.com",
+ "namnak.com",
+ "goindigo.in",
+ "activeboard.com",
+ "fatsecret.com",
+ "4umf.com",
+ "porn-w.org",
+ "sarkariexam.co.in",
+ "patagonia.com",
+ "3u5.net",
+ "roshd.ir",
+ "netechangisme.com",
+ "ojogo.pt",
+ "ujipin.com",
+ "topuniversities.com",
+ "consequenceofsound.net",
+ "no-ip.biz",
+ "webdesignerwall.com",
+ "fin24.com",
+ "openculture.com",
+ "pbh2.com",
+ "dota2.com",
+ "secureupload.eu",
+ "alfajertv.com",
+ "canlidizihdtv.com",
+ "muffingroup.com",
+ "imageforum.com",
+ "paris.fr",
+ "kaufda.de",
+ "pelis24.com",
+ "ixian.cn",
+ "ebenpagan.com",
+ "sportsauthority.com",
+ "wish.com",
+ "ganeshaspeaks.com",
+ "meritnation.com",
+ "ijie.com",
+ "vodafone.com.tr",
+ "trovit.es",
+ "farsisubtitle.com",
+ "musawvir.com",
+ "resellerratings.com",
+ "soyentrepreneur.com",
+ "samakal.net",
+ "dietnavi.com",
+ "55tuan.com",
+ "elcomercio.com",
+ "hereisthecity.com",
+ "buienradar.nl",
+ "arenabg.com",
+ "indiansexstories.net",
+ "slideboom.com",
+ "findsection.net",
+ "rankrecon.com",
+ "e-radio.gr",
+ "cnn.co.jp",
+ "gucci.com",
+ "natura.net",
+ "googlesyndication.com",
+ "advancedwebranking.com",
+ "lib.ru",
+ "sfora.pl",
+ "uci.edu",
+ "haaretz.co.il",
+ "ing.be",
+ "yokboylebirsey.com.tr",
+ "myfact.tv",
+ "yenibiris.com",
+ "stuff.tv",
+ "dn.pt",
+ "whydontyoutrythis.com",
+ "nediyor.com",
+ "worldoftanks.asia",
+ "megamillions.com",
+ "elemanonline.net",
+ "computrabajo.com.pe",
+ "arxiv.org",
+ "livescore.tv",
+ "aintitcool.com",
+ "girlschannel.net",
+ "madbid.com",
+ "tadawul.com.sa",
+ "liqpay.com",
+ "softonic.jp",
+ "alhilal.com",
+ "bizpowa.com",
+ "thatguywiththeglasses.com",
+ "yemeneconomist.com",
+ "pazar3.mk",
+ "repai.com",
+ "1jux.net",
+ "solvusoft.com",
+ "yotpo.com",
+ "cuantocabron.com",
+ "ba.gov.br",
+ "arin.net",
+ "loginza.ru",
+ "homebank.ro",
+ "0755car.com",
+ "carscoops.com",
+ "antarvasna.com",
+ "tizag.com",
+ "offerpop.com",
+ "techmeme.com",
+ "ipress.ua",
+ "emuparadise.me",
+ "sexvidx.com",
+ "whatseek.com",
+ "become.co.jp",
+ "snapfish.com",
+ "gsis.gr",
+ "speedyshare.com",
+ "uncrate.com",
+ "doda.jp",
+ "straighttalk.com",
+ "rsjoomla.com",
+ "vozpopuli.com",
+ "gotprint.net",
+ "finansbank.com.tr",
+ "chinatrust.com.tw",
+ "stratoserver.net",
+ "icnetwork.co.uk",
+ "getpopcornti.me",
+ "pornper.com",
+ "3dmgame.com",
+ "squirt.org",
+ "mbusa.com",
+ "katespade.com",
+ "skat.dk",
+ "radiko.jp",
+ "dexonline.ro",
+ "bicaps.net",
+ "bitsoma.com",
+ "brasil247.com",
+ "alittlemarket.com",
+ "bd-pratidin.com",
+ "amorincontro.com",
+ "bigxvideos.com",
+ "nissan.co.jp",
+ "incomediary.com",
+ "theranking.com",
+ "el7l.co",
+ "webcamtoy.com",
+ "steamgifts.com",
+ "miles-and-more.com",
+ "szonline.net",
+ "blocked-website.com",
+ "kaztorka.org",
+ "avforums.com",
+ "indulgy.com",
+ "extendcp.co.uk",
+ "yonkis.com",
+ "ad1111.com",
+ "unionbankph.com",
+ "job.com",
+ "samanepay.com",
+ "aceona.com",
+ "kar.nic.in",
+ "tipico.com",
+ "sa.ae",
+ "froma.com",
+ "songza.com",
+ "calciomercato.com",
+ "besaba.com",
+ "x-rates.com",
+ "arsys.es",
+ "sisal.it",
+ "amateur.tv",
+ "designyourway.net",
+ "alpha.gr",
+ "nimble.com",
+ "livefreefun.com",
+ "wipo.int",
+ "webssearches.com",
+ "vodjk.com",
+ "91tiger.com",
+ "swisscom.com",
+ "tuvaro.com",
+ "parsonline.net",
+ "uolhost.com.br",
+ "cnwest.com",
+ "roksa.pl",
+ "socialmention.com",
+ "unibytes.com",
+ "screamingfrog.co.uk",
+ "owncloud.org",
+ "jacquielawson.com",
+ "openclipart.org",
+ "zimbra.com",
+ "poczta-polska.pl",
+ "hayah.cc",
+ "ringtonematcher.com",
+ "emai.com",
+ "wealink.com",
+ "celebzen.com",
+ "pichost.me",
+ "rediffmail.com",
+ "dinos.co.jp",
+ "netvasco.com.br",
+ "meilele.com",
+ "career.ru",
+ "signupgenius.com",
+ "screencast-o-matic.com",
+ "nav.no",
+ "reactiongifs.com",
+ "italki.com",
+ "mo.gov",
+ "bandsintown.com",
+ "elwatan.com",
+ "jdate.com",
+ "quiente.net",
+ "skynet.be",
+ "googlekeywordtool.com",
+ "nubilefilms.com",
+ "memedeportes.com",
+ "rewardingzonez.com",
+ "litmus.com",
+ "iyaxin.com",
+ "collegeconfidential.com",
+ "semperplugins.com",
+ "sofort.com",
+ "ineedhits.com",
+ "live24.gr",
+ "acronymfinder.com",
+ "jobui.com",
+ "9show.com",
+ "thedirty.com",
+ "tsutaya.co.jp",
+ "9787.com",
+ "brighthouse.com",
+ "boxingscene.com",
+ "indeed.com.br",
+ "morazzia.com",
+ "privatejobshub.blogspot.in",
+ "searchenginepeople.com",
+ "pozdravok.ru",
+ "watchstore.com.cn",
+ "rts.ch",
+ "pluska.sk",
+ "villagevoice.com",
+ "sprintrade.com",
+ "conversionxl.com",
+ "evsuite.com",
+ "bci.cl",
+ "lampsplus.com",
+ "gossipcop.com",
+ "valuecommerce.com",
+ "zalora.co.id",
+ "fastshop.com.br",
+ "hockeysfuture.com",
+ "bootply.com",
+ "chinavasion.com",
+ "menards.com",
+ "kinobar.net",
+ "tokyodisneyresort.jp",
+ "knownhost.com",
+ "ozbargain.com.au",
+ "olx.com.ve",
+ "sgk.gov.tr",
+ "berliner-sparkasse.de",
+ "bancogalicia.com.ar",
+ "joomla-master.org",
+ "augsburger-allgemeine.de",
+ "kroger.com",
+ "pulse.ng",
+ "putlocker.com",
+ "jrtj.com",
+ "tapuz.co.il",
+ "madhyamam.com",
+ "donews.com",
+ "showhaber.com",
+ "allxnxx.com",
+ "uned.es",
+ "adsharebux.com",
+ "d-addicts.com",
+ "banki.ir",
+ "levi.com",
+ "e97527f0.se",
+ "entertainmentwise.com",
+ "xvideos-field.com",
+ "naver.net",
+ "urbia.de",
+ "fashionsfriend.com",
+ "emuch.net",
+ "yelp.fr",
+ "metatube.com",
+ "sina.com.hk",
+ "omb100.com",
+ "grameenphone.com",
+ "stylebook.de",
+ "funny-games.biz",
+ "googlewebmastercentral.blogspot.com",
+ "vogella.com",
+ "surveymonkey.net",
+ "forex4you.org",
+ "mex.tl",
+ "online-fish-games.com",
+ "millenniumbcp.pt",
+ "fileom.com",
+ "friendorfollow.com",
+ "downloads.nl",
+ "typekit.com",
+ "gongkong.com",
+ "iqoption.com",
+ "tori.fi",
+ "smartsource.com",
+ "1616.net",
+ "1shoppingcart.com",
+ "novosti.rs",
+ "yofond.com",
+ "idokep.hu",
+ "motor.ru",
+ "xbiao.com",
+ "colorcombos.com",
+ "pway.cn",
+ "egynews.net",
+ "elshaab.org",
+ "telus.com",
+ "olx.com.co",
+ "cctvcj.com",
+ "kpopstarz.com",
+ "razorsocial.com",
+ "ncrypt.in",
+ "zonetheme.com",
+ "gumroad.com",
+ "e-shop.gr",
+ "kugli.com",
+ "levif.be",
+ "bookfi.org",
+ "globalresearch.ca",
+ "sas.com",
+ "cloudaccess.net",
+ "uplooder.net",
+ "exposedwebcams.com",
+ "1prime.ru",
+ "webappers.com",
+ "crocko.com",
+ "remax.com",
+ "ikco.com",
+ "dinside.no",
+ "winbank.gr",
+ "mijnwoordenboek.nl",
+ "weatherzone.com.au",
+ "allday2.com",
+ "sunat.gob.pe",
+ "getit.in",
+ "entrance-exam.net",
+ "i2ya.com",
+ "tlife.gr",
+ "qyer.com",
+ "calibre-ebook.com",
+ "internetcorkboard.com",
+ "unitedhyipleague.com",
+ "spyrestudios.com",
+ "metal-archives.com",
+ "aeromexico.com",
+ "cv-library.co.uk",
+ "bdr1.net",
+ "aremo.com.br",
+ "blip.tv",
+ "afilio.com.br",
+ "renewalcoupons.com",
+ "proxfree.com",
+ "magix.com",
+ "jobs.net",
+ "souism.com",
+ "adtcstrk.com",
+ "goodhousekeeping.com",
+ "lastfm.ru",
+ "sharecare.com",
+ "porn.xxx",
+ "deathandtaxesmag.com",
+ "unocero.com",
+ "wer-kennt-wen.de",
+ "hotfrog.com",
+ "intraship.de",
+ "press24.mk",
+ "yournewscorner.com",
+ "rbc.com",
+ "eventure.com",
+ "minglebox.com",
+ "legendas.tv",
+ "drp.su",
+ "voicefrom.me",
+ "venezuelaaldia.com",
+ "cooks.com",
+ "numbeo.com",
+ "chilehardware.cl",
+ "cryptocointalk.com",
+ "venusfactor.com",
+ "recruitmentcareer.in",
+ "larazon.es",
+ "sptechs.com",
+ "asx.com.au",
+ "ahlife.com",
+ "st001.com",
+ "actudesfinances.info",
+ "talkarcades.com",
+ "nitori-net.jp",
+ "chinahr.com",
+ "websitetestlink.com",
+ "hypem.com",
+ "demorgen.be",
+ "sharefile.com",
+ "prensalibre.com",
+ "eldia.com.ar",
+ "billiger.de",
+ "3docean.net",
+ "streamsend.com",
+ "tuaw.com",
+ "portafolio.co",
+ "trivago.com",
+ "olxpix.com",
+ "geotrust.com",
+ "torrentgun.net",
+ "enha.kr",
+ "pcastuces.com",
+ "t.cn",
+ "dimsemenov.com",
+ "cam4.nl",
+ "basspro.com",
+ "macupdate.com",
+ "strawpoll.me",
+ "elintransigente.com",
+ "homeaway.co.uk",
+ "my.ecwid.com",
+ "graphpaperpress.com",
+ "architonic.com",
+ "flowplayer.org",
+ "syshl.com",
+ "18schoolgirlz.com"
+ });
+
+ return urls;
+}
diff --git a/src/boost/libs/beast/example/http/client/crawl/urls_large_data.hpp b/src/boost/libs/beast/example/http/client/crawl/urls_large_data.hpp
new file mode 100644
index 000000000..06be4acd9
--- /dev/null
+++ b/src/boost/libs/beast/example/http/client/crawl/urls_large_data.hpp
@@ -0,0 +1,18 @@
+//
+// Copyright (c) 2016-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 BOOST_BEAST_EXAMPLE_HTTP_CLIENT_CRAWL_URLS_LARGE_DATA_HPP
+#define BOOST_BEAST_EXAMPLE_HTTP_CLIENT_CRAWL_URLS_LARGE_DATA_HPP
+
+#include <vector>
+
+std::vector<char const*> const&
+urls_large_data();
+
+#endif
diff --git a/src/boost/libs/beast/example/http/client/sync-ssl/CMakeLists.txt b/src/boost/libs/beast/example/http/client/sync-ssl/CMakeLists.txt
new file mode 100644
index 000000000..0e0fbea07
--- /dev/null
+++ b/src/boost/libs/beast/example/http/client/sync-ssl/CMakeLists.txt
@@ -0,0 +1,31 @@
+#
+# 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
+#
+
+if (OPENSSL_FOUND)
+ GroupSources(include/boost/beast beast)
+ GroupSources(example/common common)
+ GroupSources(example/http/client/sync-ssl "/")
+
+ add_executable (http-client-sync-ssl
+ ${BOOST_BEAST_FILES}
+ ${PROJECT_SOURCE_DIR}/example/common/root_certificates.hpp
+ Jamfile
+ http_client_sync_ssl.cpp
+ )
+
+ set_property(TARGET http-client-sync-ssl PROPERTY FOLDER "example-http-client")
+
+ target_link_libraries (http-client-sync-ssl
+ OpenSSL::SSL OpenSSL::Crypto
+ lib-asio
+ lib-asio-ssl
+ lib-beast
+ )
+
+endif()
diff --git a/src/boost/libs/beast/example/http/client/sync-ssl/Jamfile b/src/boost/libs/beast/example/http/client/sync-ssl/Jamfile
new file mode 100644
index 000000000..c1fabf479
--- /dev/null
+++ b/src/boost/libs/beast/example/http/client/sync-ssl/Jamfile
@@ -0,0 +1,22 @@
+#
+# 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
+#
+
+import ac ;
+
+project
+ : requirements
+ [ ac.check-library /boost/beast//lib-asio-ssl : <library>/boost/beast//lib-asio-ssl/<link>static : <build>no ]
+ ;
+
+exe http-client-sync-ssl :
+ http_client_sync_ssl.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ ;
diff --git a/src/boost/libs/beast/example/http/client/sync-ssl/http_client_sync_ssl.cpp b/src/boost/libs/beast/example/http/client/sync-ssl/http_client_sync_ssl.cpp
new file mode 100644
index 000000000..726c84204
--- /dev/null
+++ b/src/boost/libs/beast/example/http/client/sync-ssl/http_client_sync_ssl.cpp
@@ -0,0 +1,128 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: HTTP SSL client, synchronous
+//
+//------------------------------------------------------------------------------
+
+#include "example/common/root_certificates.hpp"
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/http.hpp>
+#include <boost/beast/ssl.hpp>
+#include <boost/beast/version.hpp>
+#include <boost/asio/connect.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/ssl/error.hpp>
+#include <boost/asio/ssl/stream.hpp>
+#include <cstdlib>
+#include <iostream>
+#include <string>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+namespace ssl = net::ssl; // from <boost/asio/ssl.hpp>
+using tcp = net::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+// Performs an HTTP GET and prints the response
+int main(int argc, char** argv)
+{
+ try
+ {
+ // Check command line arguments.
+ if(argc != 4 && argc != 5)
+ {
+ std::cerr <<
+ "Usage: http-client-sync-ssl <host> <port> <target> [<HTTP version: 1.0 or 1.1(default)>]\n" <<
+ "Example:\n" <<
+ " http-client-sync-ssl www.example.com 443 /\n" <<
+ " http-client-sync-ssl www.example.com 443 / 1.0\n";
+ return EXIT_FAILURE;
+ }
+ auto const host = argv[1];
+ auto const port = argv[2];
+ auto const target = argv[3];
+ int version = argc == 5 && !std::strcmp("1.0", argv[4]) ? 10 : 11;
+
+ // The io_context is required for all I/O
+ net::io_context ioc;
+
+ // The SSL context is required, and holds certificates
+ ssl::context ctx(ssl::context::tlsv12_client);
+
+ // This holds the root certificate used for verification
+ load_root_certificates(ctx);
+
+ // Verify the remote server's certificate
+ ctx.set_verify_mode(ssl::verify_peer);
+
+ // These objects perform our I/O
+ tcp::resolver resolver(ioc);
+ beast::ssl_stream<beast::tcp_stream> stream(ioc, ctx);
+
+ // Set SNI Hostname (many hosts need this to handshake successfully)
+ if(! SSL_set_tlsext_host_name(stream.native_handle(), host))
+ {
+ beast::error_code ec{static_cast<int>(::ERR_get_error()), net::error::get_ssl_category()};
+ throw beast::system_error{ec};
+ }
+
+ // Look up the domain name
+ auto const results = resolver.resolve(host, port);
+
+ // Make the connection on the IP address we get from a lookup
+ beast::get_lowest_layer(stream).connect(results);
+
+ // Perform the SSL handshake
+ stream.handshake(ssl::stream_base::client);
+
+ // Set up an HTTP GET request message
+ http::request<http::string_body> req{http::verb::get, target, version};
+ req.set(http::field::host, host);
+ req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
+
+ // Send the HTTP request to the remote host
+ http::write(stream, req);
+
+ // This buffer is used for reading and must be persisted
+ beast::flat_buffer buffer;
+
+ // Declare a container to hold the response
+ http::response<http::dynamic_body> res;
+
+ // Receive the HTTP response
+ http::read(stream, buffer, res);
+
+ // Write the message to standard out
+ std::cout << res << std::endl;
+
+ // Gracefully close the stream
+ beast::error_code ec;
+ stream.shutdown(ec);
+ if(ec == net::error::eof)
+ {
+ // Rationale:
+ // http://stackoverflow.com/questions/25587403/boost-asio-ssl-async-shutdown-always-finishes-with-an-error
+ ec = {};
+ }
+ if(ec)
+ throw beast::system_error{ec};
+
+ // If we get here then the connection is closed gracefully
+ }
+ catch(std::exception const& e)
+ {
+ std::cerr << "Error: " << e.what() << std::endl;
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/http/client/sync/CMakeLists.txt b/src/boost/libs/beast/example/http/client/sync/CMakeLists.txt
new file mode 100644
index 000000000..ea877ec4f
--- /dev/null
+++ b/src/boost/libs/beast/example/http/client/sync/CMakeLists.txt
@@ -0,0 +1,23 @@
+#
+# 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
+#
+
+GroupSources(include/boost/beast beast)
+GroupSources(example/http/client/sync "/")
+
+add_executable (http-client-sync
+ ${BOOST_BEAST_FILES}
+ Jamfile
+ http_client_sync.cpp
+)
+
+target_link_libraries(http-client-sync
+ lib-asio
+ lib-beast)
+
+set_property(TARGET http-client-sync PROPERTY FOLDER "example-http-client")
diff --git a/src/boost/libs/beast/example/http/client/sync/Jamfile b/src/boost/libs/beast/example/http/client/sync/Jamfile
new file mode 100644
index 000000000..969246f65
--- /dev/null
+++ b/src/boost/libs/beast/example/http/client/sync/Jamfile
@@ -0,0 +1,15 @@
+#
+# 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
+#
+
+exe http-client-sync :
+ http_client_sync.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ ;
diff --git a/src/boost/libs/beast/example/http/client/sync/http_client_sync.cpp b/src/boost/libs/beast/example/http/client/sync/http_client_sync.cpp
new file mode 100644
index 000000000..795618161
--- /dev/null
+++ b/src/boost/libs/beast/example/http/client/sync/http_client_sync.cpp
@@ -0,0 +1,105 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: HTTP client, synchronous
+//
+//------------------------------------------------------------------------------
+
+//[example_http_client
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/http.hpp>
+#include <boost/beast/version.hpp>
+#include <boost/asio/connect.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <cstdlib>
+#include <iostream>
+#include <string>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+using tcp = net::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+// Performs an HTTP GET and prints the response
+int main(int argc, char** argv)
+{
+ try
+ {
+ // Check command line arguments.
+ if(argc != 4 && argc != 5)
+ {
+ std::cerr <<
+ "Usage: http-client-sync <host> <port> <target> [<HTTP version: 1.0 or 1.1(default)>]\n" <<
+ "Example:\n" <<
+ " http-client-sync www.example.com 80 /\n" <<
+ " http-client-sync www.example.com 80 / 1.0\n";
+ return EXIT_FAILURE;
+ }
+ auto const host = argv[1];
+ auto const port = argv[2];
+ auto const target = argv[3];
+ int version = argc == 5 && !std::strcmp("1.0", argv[4]) ? 10 : 11;
+
+ // The io_context is required for all I/O
+ net::io_context ioc;
+
+ // These objects perform our I/O
+ tcp::resolver resolver(ioc);
+ beast::tcp_stream stream(ioc);
+
+ // Look up the domain name
+ auto const results = resolver.resolve(host, port);
+
+ // Make the connection on the IP address we get from a lookup
+ stream.connect(results);
+
+ // Set up an HTTP GET request message
+ http::request<http::string_body> req{http::verb::get, target, version};
+ req.set(http::field::host, host);
+ req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
+
+ // Send the HTTP request to the remote host
+ http::write(stream, req);
+
+ // This buffer is used for reading and must be persisted
+ beast::flat_buffer buffer;
+
+ // Declare a container to hold the response
+ http::response<http::dynamic_body> res;
+
+ // Receive the HTTP response
+ http::read(stream, buffer, res);
+
+ // Write the message to standard out
+ std::cout << res << std::endl;
+
+ // Gracefully close the socket
+ beast::error_code ec;
+ stream.socket().shutdown(tcp::socket::shutdown_both, ec);
+
+ // not_connected happens sometimes
+ // so don't bother reporting it.
+ //
+ if(ec && ec != beast::errc::not_connected)
+ throw beast::system_error{ec};
+
+ // If we get here then the connection is closed gracefully
+ }
+ catch(std::exception const& e)
+ {
+ std::cerr << "Error: " << e.what() << std::endl;
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
+}
+
+//]
diff --git a/src/boost/libs/beast/example/http/server/CMakeLists.txt b/src/boost/libs/beast/example/http/server/CMakeLists.txt
new file mode 100644
index 000000000..350b465a7
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/CMakeLists.txt
@@ -0,0 +1,23 @@
+#
+# Copyright (c) 2013-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
+#
+
+add_subdirectory (async)
+add_subdirectory (coro)
+add_subdirectory (fast)
+add_subdirectory (small)
+add_subdirectory (stackless)
+add_subdirectory (sync)
+
+if (OPENSSL_FOUND)
+ add_subdirectory (async-ssl)
+ add_subdirectory (coro-ssl)
+ add_subdirectory (flex)
+ add_subdirectory (stackless-ssl)
+ add_subdirectory (sync-ssl)
+endif()
diff --git a/src/boost/libs/beast/example/http/server/Jamfile b/src/boost/libs/beast/example/http/server/Jamfile
new file mode 100644
index 000000000..cb8ab104f
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/Jamfile
@@ -0,0 +1,22 @@
+#
+# Copyright (c) 2013-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
+#
+
+build-project async ;
+build-project coro ;
+build-project fast ;
+build-project small ;
+build-project stackless ;
+build-project sync ;
+
+# SSL
+build-project async-ssl ;
+build-project coro-ssl ;
+build-project flex ;
+build-project stackless-ssl ;
+build-project sync-ssl ;
diff --git a/src/boost/libs/beast/example/http/server/async-ssl/CMakeLists.txt b/src/boost/libs/beast/example/http/server/async-ssl/CMakeLists.txt
new file mode 100644
index 000000000..4c1e2cd02
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/async-ssl/CMakeLists.txt
@@ -0,0 +1,31 @@
+#
+# 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
+#
+
+if (OPENSSL_FOUND)
+ GroupSources(include/boost/beast beast)
+ GroupSources(example/common common)
+ GroupSources(example/http/server/async-ssl "/")
+
+ add_executable (http-server-async-ssl
+ ${BOOST_BEAST_FILES}
+ ${PROJECT_SOURCE_DIR}/example/common/server_certificate.hpp
+ Jamfile
+ http_server_async_ssl.cpp
+ )
+
+ set_property(TARGET http-server-async-ssl PROPERTY FOLDER "example-http-server")
+
+ target_link_libraries (http-server-async-ssl
+ OpenSSL::SSL OpenSSL::Crypto
+ lib-asio
+ lib-asio-ssl
+ lib-beast
+ )
+
+endif()
diff --git a/src/boost/libs/beast/example/http/server/async-ssl/Jamfile b/src/boost/libs/beast/example/http/server/async-ssl/Jamfile
new file mode 100644
index 000000000..f4cf0204e
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/async-ssl/Jamfile
@@ -0,0 +1,22 @@
+#
+# 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
+#
+
+import ac ;
+
+project
+ : requirements
+ [ ac.check-library /boost/beast//lib-asio-ssl : <library>/boost/beast//lib-asio-ssl/<link>static : <build>no ]
+ ;
+
+exe http-server-async-ssl :
+ http_server_async_ssl.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ ;
diff --git a/src/boost/libs/beast/example/http/server/async-ssl/http_server_async_ssl.cpp b/src/boost/libs/beast/example/http/server/async-ssl/http_server_async_ssl.cpp
new file mode 100644
index 000000000..f6c66c90f
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/async-ssl/http_server_async_ssl.cpp
@@ -0,0 +1,564 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: HTTP SSL server, asynchronous
+//
+//------------------------------------------------------------------------------
+
+#include "example/common/server_certificate.hpp"
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/http.hpp>
+#include <boost/beast/ssl.hpp>
+#include <boost/beast/version.hpp>
+#include <boost/asio/dispatch.hpp>
+#include <boost/asio/strand.hpp>
+#include <boost/config.hpp>
+#include <algorithm>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <thread>
+#include <vector>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+// Return a reasonable mime type based on the extension of a file.
+beast::string_view
+mime_type(beast::string_view path)
+{
+ using beast::iequals;
+ auto const ext = [&path]
+ {
+ auto const pos = path.rfind(".");
+ if(pos == beast::string_view::npos)
+ return beast::string_view{};
+ return path.substr(pos);
+ }();
+ if(iequals(ext, ".htm")) return "text/html";
+ if(iequals(ext, ".html")) return "text/html";
+ if(iequals(ext, ".php")) return "text/html";
+ if(iequals(ext, ".css")) return "text/css";
+ if(iequals(ext, ".txt")) return "text/plain";
+ if(iequals(ext, ".js")) return "application/javascript";
+ if(iequals(ext, ".json")) return "application/json";
+ if(iequals(ext, ".xml")) return "application/xml";
+ if(iequals(ext, ".swf")) return "application/x-shockwave-flash";
+ if(iequals(ext, ".flv")) return "video/x-flv";
+ if(iequals(ext, ".png")) return "image/png";
+ if(iequals(ext, ".jpe")) return "image/jpeg";
+ if(iequals(ext, ".jpeg")) return "image/jpeg";
+ if(iequals(ext, ".jpg")) return "image/jpeg";
+ if(iequals(ext, ".gif")) return "image/gif";
+ if(iequals(ext, ".bmp")) return "image/bmp";
+ if(iequals(ext, ".ico")) return "image/vnd.microsoft.icon";
+ if(iequals(ext, ".tiff")) return "image/tiff";
+ if(iequals(ext, ".tif")) return "image/tiff";
+ if(iequals(ext, ".svg")) return "image/svg+xml";
+ if(iequals(ext, ".svgz")) return "image/svg+xml";
+ return "application/text";
+}
+
+// Append an HTTP rel-path to a local filesystem path.
+// The returned path is normalized for the platform.
+std::string
+path_cat(
+ beast::string_view base,
+ beast::string_view path)
+{
+ if(base.empty())
+ return std::string(path);
+ std::string result(base);
+#ifdef BOOST_MSVC
+ char constexpr path_separator = '\\';
+ if(result.back() == path_separator)
+ result.resize(result.size() - 1);
+ result.append(path.data(), path.size());
+ for(auto& c : result)
+ if(c == '/')
+ c = path_separator;
+#else
+ char constexpr path_separator = '/';
+ if(result.back() == path_separator)
+ result.resize(result.size() - 1);
+ result.append(path.data(), path.size());
+#endif
+ return result;
+}
+
+// This function produces an HTTP response for the given
+// request. The type of the response object depends on the
+// contents of the request, so the interface requires the
+// caller to pass a generic lambda for receiving the response.
+template<
+ class Body, class Allocator,
+ class Send>
+void
+handle_request(
+ beast::string_view doc_root,
+ http::request<Body, http::basic_fields<Allocator>>&& req,
+ Send&& send)
+{
+ // Returns a bad request response
+ auto const bad_request =
+ [&req](beast::string_view why)
+ {
+ http::response<http::string_body> res{http::status::bad_request, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = std::string(why);
+ res.prepare_payload();
+ return res;
+ };
+
+ // Returns a not found response
+ auto const not_found =
+ [&req](beast::string_view target)
+ {
+ http::response<http::string_body> res{http::status::not_found, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = "The resource '" + std::string(target) + "' was not found.";
+ res.prepare_payload();
+ return res;
+ };
+
+ // Returns a server error response
+ auto const server_error =
+ [&req](beast::string_view what)
+ {
+ http::response<http::string_body> res{http::status::internal_server_error, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = "An error occurred: '" + std::string(what) + "'";
+ res.prepare_payload();
+ return res;
+ };
+
+ // Make sure we can handle the method
+ if( req.method() != http::verb::get &&
+ req.method() != http::verb::head)
+ return send(bad_request("Unknown HTTP-method"));
+
+ // Request path must be absolute and not contain "..".
+ if( req.target().empty() ||
+ req.target()[0] != '/' ||
+ req.target().find("..") != beast::string_view::npos)
+ return send(bad_request("Illegal request-target"));
+
+ // Build the path to the requested file
+ std::string path = path_cat(doc_root, req.target());
+ if(req.target().back() == '/')
+ path.append("index.html");
+
+ // Attempt to open the file
+ beast::error_code ec;
+ http::file_body::value_type body;
+ body.open(path.c_str(), beast::file_mode::scan, ec);
+
+ // Handle the case where the file doesn't exist
+ if(ec == beast::errc::no_such_file_or_directory)
+ return send(not_found(req.target()));
+
+ // Handle an unknown error
+ if(ec)
+ return send(server_error(ec.message()));
+
+ // Cache the size since we need it after the move
+ auto const size = body.size();
+
+ // Respond to HEAD request
+ if(req.method() == http::verb::head)
+ {
+ http::response<http::empty_body> res{http::status::ok, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, mime_type(path));
+ res.content_length(size);
+ res.keep_alive(req.keep_alive());
+ return send(std::move(res));
+ }
+
+ // Respond to GET request
+ http::response<http::file_body> res{
+ std::piecewise_construct,
+ std::make_tuple(std::move(body)),
+ std::make_tuple(http::status::ok, req.version())};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, mime_type(path));
+ res.content_length(size);
+ res.keep_alive(req.keep_alive());
+ return send(std::move(res));
+}
+
+//------------------------------------------------------------------------------
+
+// Report a failure
+void
+fail(beast::error_code ec, char const* what)
+{
+ // ssl::error::stream_truncated, also known as an SSL "short read",
+ // indicates the peer closed the connection without performing the
+ // required closing handshake (for example, Google does this to
+ // improve performance). Generally this can be a security issue,
+ // but if your communication protocol is self-terminated (as
+ // it is with both HTTP and WebSocket) then you may simply
+ // ignore the lack of close_notify.
+ //
+ // https://github.com/boostorg/beast/issues/38
+ //
+ // https://security.stackexchange.com/questions/91435/how-to-handle-a-malicious-ssl-tls-shutdown
+ //
+ // When a short read would cut off the end of an HTTP message,
+ // Beast returns the error beast::http::error::partial_message.
+ // Therefore, if we see a short read here, it has occurred
+ // after the message has been completed, so it is safe to ignore it.
+
+ if(ec == net::ssl::error::stream_truncated)
+ return;
+
+ std::cerr << what << ": " << ec.message() << "\n";
+}
+
+// Handles an HTTP server connection
+class session : public std::enable_shared_from_this<session>
+{
+ // This is the C++11 equivalent of a generic lambda.
+ // The function object is used to send an HTTP message.
+ struct send_lambda
+ {
+ session& self_;
+
+ explicit
+ send_lambda(session& self)
+ : self_(self)
+ {
+ }
+
+ template<bool isRequest, class Body, class Fields>
+ void
+ operator()(http::message<isRequest, Body, Fields>&& msg) const
+ {
+ // The lifetime of the message has to extend
+ // for the duration of the async operation so
+ // we use a shared_ptr to manage it.
+ auto sp = std::make_shared<
+ http::message<isRequest, Body, Fields>>(std::move(msg));
+
+ // Store a type-erased version of the shared
+ // pointer in the class to keep it alive.
+ self_.res_ = sp;
+
+ // Write the response
+ http::async_write(
+ self_.stream_,
+ *sp,
+ beast::bind_front_handler(
+ &session::on_write,
+ self_.shared_from_this(),
+ sp->need_eof()));
+ }
+ };
+
+ beast::ssl_stream<beast::tcp_stream> stream_;
+ beast::flat_buffer buffer_;
+ std::shared_ptr<std::string const> doc_root_;
+ http::request<http::string_body> req_;
+ std::shared_ptr<void> res_;
+ send_lambda lambda_;
+
+public:
+ // Take ownership of the socket
+ explicit
+ session(
+ tcp::socket&& socket,
+ ssl::context& ctx,
+ std::shared_ptr<std::string const> const& doc_root)
+ : stream_(std::move(socket), ctx)
+ , doc_root_(doc_root)
+ , lambda_(*this)
+ {
+ }
+
+ // Start the asynchronous operation
+ void
+ run()
+ {
+ // We need to be executing within a strand to perform async operations
+ // on the I/O objects in this session. Although not strictly necessary
+ // for single-threaded contexts, this example code is written to be
+ // thread-safe by default.
+ net::dispatch(
+ stream_.get_executor(),
+ beast::bind_front_handler(
+ &session::on_run,
+ shared_from_this()));
+ }
+
+ void
+ on_run()
+ {
+ // Set the timeout.
+ beast::get_lowest_layer(stream_).expires_after(
+ std::chrono::seconds(30));
+
+ // Perform the SSL handshake
+ stream_.async_handshake(
+ ssl::stream_base::server,
+ beast::bind_front_handler(
+ &session::on_handshake,
+ shared_from_this()));
+ }
+
+ void
+ on_handshake(beast::error_code ec)
+ {
+ if(ec)
+ return fail(ec, "handshake");
+
+ do_read();
+ }
+
+ void
+ do_read()
+ {
+ // Make the request empty before reading,
+ // otherwise the operation behavior is undefined.
+ req_ = {};
+
+ // Set the timeout.
+ beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30));
+
+ // Read a request
+ http::async_read(stream_, buffer_, req_,
+ beast::bind_front_handler(
+ &session::on_read,
+ shared_from_this()));
+ }
+
+ void
+ on_read(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ // This means they closed the connection
+ if(ec == http::error::end_of_stream)
+ return do_close();
+
+ if(ec)
+ return fail(ec, "read");
+
+ // Send the response
+ handle_request(*doc_root_, std::move(req_), lambda_);
+ }
+
+ void
+ on_write(
+ bool close,
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ if(ec)
+ return fail(ec, "write");
+
+ if(close)
+ {
+ // This means we should close the connection, usually because
+ // the response indicated the "Connection: close" semantic.
+ return do_close();
+ }
+
+ // We're done with the response so delete it
+ res_ = nullptr;
+
+ // Read another request
+ do_read();
+ }
+
+ void
+ do_close()
+ {
+ // Set the timeout.
+ beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30));
+
+ // Perform the SSL shutdown
+ stream_.async_shutdown(
+ beast::bind_front_handler(
+ &session::on_shutdown,
+ shared_from_this()));
+ }
+
+ void
+ on_shutdown(beast::error_code ec)
+ {
+ if(ec)
+ return fail(ec, "shutdown");
+
+ // At this point the connection is closed gracefully
+ }
+};
+
+//------------------------------------------------------------------------------
+
+// Accepts incoming connections and launches the sessions
+class listener : public std::enable_shared_from_this<listener>
+{
+ net::io_context& ioc_;
+ ssl::context& ctx_;
+ tcp::acceptor acceptor_;
+ std::shared_ptr<std::string const> doc_root_;
+
+public:
+ listener(
+ net::io_context& ioc,
+ ssl::context& ctx,
+ tcp::endpoint endpoint,
+ std::shared_ptr<std::string const> const& doc_root)
+ : ioc_(ioc)
+ , ctx_(ctx)
+ , acceptor_(ioc)
+ , doc_root_(doc_root)
+ {
+ beast::error_code ec;
+
+ // Open the acceptor
+ acceptor_.open(endpoint.protocol(), ec);
+ if(ec)
+ {
+ fail(ec, "open");
+ return;
+ }
+
+ // Allow address reuse
+ acceptor_.set_option(net::socket_base::reuse_address(true), ec);
+ if(ec)
+ {
+ fail(ec, "set_option");
+ return;
+ }
+
+ // Bind to the server address
+ acceptor_.bind(endpoint, ec);
+ if(ec)
+ {
+ fail(ec, "bind");
+ return;
+ }
+
+ // Start listening for connections
+ acceptor_.listen(
+ net::socket_base::max_listen_connections, ec);
+ if(ec)
+ {
+ fail(ec, "listen");
+ return;
+ }
+ }
+
+ // Start accepting incoming connections
+ void
+ run()
+ {
+ do_accept();
+ }
+
+private:
+ void
+ do_accept()
+ {
+ // The new connection gets its own strand
+ acceptor_.async_accept(
+ net::make_strand(ioc_),
+ beast::bind_front_handler(
+ &listener::on_accept,
+ shared_from_this()));
+ }
+
+ void
+ on_accept(beast::error_code ec, tcp::socket socket)
+ {
+ if(ec)
+ {
+ fail(ec, "accept");
+ }
+ else
+ {
+ // Create the session and run it
+ std::make_shared<session>(
+ std::move(socket),
+ ctx_,
+ doc_root_)->run();
+ }
+
+ // Accept another connection
+ do_accept();
+ }
+};
+
+//------------------------------------------------------------------------------
+
+int main(int argc, char* argv[])
+{
+ // Check command line arguments.
+ if (argc != 5)
+ {
+ std::cerr <<
+ "Usage: http-server-async-ssl <address> <port> <doc_root> <threads>\n" <<
+ "Example:\n" <<
+ " http-server-async-ssl 0.0.0.0 8080 . 1\n";
+ return EXIT_FAILURE;
+ }
+ auto const address = net::ip::make_address(argv[1]);
+ auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
+ auto const doc_root = std::make_shared<std::string>(argv[3]);
+ auto const threads = std::max<int>(1, std::atoi(argv[4]));
+
+ // The io_context is required for all I/O
+ net::io_context ioc{threads};
+
+ // The SSL context is required, and holds certificates
+ ssl::context ctx{ssl::context::tlsv12};
+
+ // This holds the self-signed certificate used by the server
+ load_server_certificate(ctx);
+
+ // Create and launch a listening port
+ std::make_shared<listener>(
+ ioc,
+ ctx,
+ tcp::endpoint{address, port},
+ doc_root)->run();
+
+ // Run the I/O service on the requested number of threads
+ std::vector<std::thread> v;
+ v.reserve(threads - 1);
+ for(auto i = threads - 1; i > 0; --i)
+ v.emplace_back(
+ [&ioc]
+ {
+ ioc.run();
+ });
+ ioc.run();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/http/server/async/CMakeLists.txt b/src/boost/libs/beast/example/http/server/async/CMakeLists.txt
new file mode 100644
index 000000000..b94c0521f
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/async/CMakeLists.txt
@@ -0,0 +1,24 @@
+#
+# 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
+#
+
+GroupSources(include/boost/beast beast)
+GroupSources(example/http/server/async "/")
+
+add_executable (http-server-async
+ ${BOOST_BEAST_FILES}
+ Jamfile
+ http_server_async.cpp
+)
+
+target_link_libraries(http-server-async
+ lib-asio
+ lib-asio-ssl
+ lib-beast)
+
+set_property(TARGET http-server-async PROPERTY FOLDER "example-http-server")
diff --git a/src/boost/libs/beast/example/http/server/async/Jamfile b/src/boost/libs/beast/example/http/server/async/Jamfile
new file mode 100644
index 000000000..f36d1ad47
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/async/Jamfile
@@ -0,0 +1,15 @@
+#
+# 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
+#
+
+exe http-server-async :
+ http_server_async.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ ;
diff --git a/src/boost/libs/beast/example/http/server/async/http_server_async.cpp b/src/boost/libs/beast/example/http/server/async/http_server_async.cpp
new file mode 100644
index 000000000..55fd234bb
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/async/http_server_async.cpp
@@ -0,0 +1,490 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: HTTP server, asynchronous
+//
+//------------------------------------------------------------------------------
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/http.hpp>
+#include <boost/beast/version.hpp>
+#include <boost/asio/dispatch.hpp>
+#include <boost/asio/strand.hpp>
+#include <boost/config.hpp>
+#include <algorithm>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <thread>
+#include <vector>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+// Return a reasonable mime type based on the extension of a file.
+beast::string_view
+mime_type(beast::string_view path)
+{
+ using beast::iequals;
+ auto const ext = [&path]
+ {
+ auto const pos = path.rfind(".");
+ if(pos == beast::string_view::npos)
+ return beast::string_view{};
+ return path.substr(pos);
+ }();
+ if(iequals(ext, ".htm")) return "text/html";
+ if(iequals(ext, ".html")) return "text/html";
+ if(iequals(ext, ".php")) return "text/html";
+ if(iequals(ext, ".css")) return "text/css";
+ if(iequals(ext, ".txt")) return "text/plain";
+ if(iequals(ext, ".js")) return "application/javascript";
+ if(iequals(ext, ".json")) return "application/json";
+ if(iequals(ext, ".xml")) return "application/xml";
+ if(iequals(ext, ".swf")) return "application/x-shockwave-flash";
+ if(iequals(ext, ".flv")) return "video/x-flv";
+ if(iequals(ext, ".png")) return "image/png";
+ if(iequals(ext, ".jpe")) return "image/jpeg";
+ if(iequals(ext, ".jpeg")) return "image/jpeg";
+ if(iequals(ext, ".jpg")) return "image/jpeg";
+ if(iequals(ext, ".gif")) return "image/gif";
+ if(iequals(ext, ".bmp")) return "image/bmp";
+ if(iequals(ext, ".ico")) return "image/vnd.microsoft.icon";
+ if(iequals(ext, ".tiff")) return "image/tiff";
+ if(iequals(ext, ".tif")) return "image/tiff";
+ if(iequals(ext, ".svg")) return "image/svg+xml";
+ if(iequals(ext, ".svgz")) return "image/svg+xml";
+ return "application/text";
+}
+
+// Append an HTTP rel-path to a local filesystem path.
+// The returned path is normalized for the platform.
+std::string
+path_cat(
+ beast::string_view base,
+ beast::string_view path)
+{
+ if(base.empty())
+ return std::string(path);
+ std::string result(base);
+#ifdef BOOST_MSVC
+ char constexpr path_separator = '\\';
+ if(result.back() == path_separator)
+ result.resize(result.size() - 1);
+ result.append(path.data(), path.size());
+ for(auto& c : result)
+ if(c == '/')
+ c = path_separator;
+#else
+ char constexpr path_separator = '/';
+ if(result.back() == path_separator)
+ result.resize(result.size() - 1);
+ result.append(path.data(), path.size());
+#endif
+ return result;
+}
+
+// This function produces an HTTP response for the given
+// request. The type of the response object depends on the
+// contents of the request, so the interface requires the
+// caller to pass a generic lambda for receiving the response.
+template<
+ class Body, class Allocator,
+ class Send>
+void
+handle_request(
+ beast::string_view doc_root,
+ http::request<Body, http::basic_fields<Allocator>>&& req,
+ Send&& send)
+{
+ // Returns a bad request response
+ auto const bad_request =
+ [&req](beast::string_view why)
+ {
+ http::response<http::string_body> res{http::status::bad_request, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = std::string(why);
+ res.prepare_payload();
+ return res;
+ };
+
+ // Returns a not found response
+ auto const not_found =
+ [&req](beast::string_view target)
+ {
+ http::response<http::string_body> res{http::status::not_found, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = "The resource '" + std::string(target) + "' was not found.";
+ res.prepare_payload();
+ return res;
+ };
+
+ // Returns a server error response
+ auto const server_error =
+ [&req](beast::string_view what)
+ {
+ http::response<http::string_body> res{http::status::internal_server_error, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = "An error occurred: '" + std::string(what) + "'";
+ res.prepare_payload();
+ return res;
+ };
+
+ // Make sure we can handle the method
+ if( req.method() != http::verb::get &&
+ req.method() != http::verb::head)
+ return send(bad_request("Unknown HTTP-method"));
+
+ // Request path must be absolute and not contain "..".
+ if( req.target().empty() ||
+ req.target()[0] != '/' ||
+ req.target().find("..") != beast::string_view::npos)
+ return send(bad_request("Illegal request-target"));
+
+ // Build the path to the requested file
+ std::string path = path_cat(doc_root, req.target());
+ if(req.target().back() == '/')
+ path.append("index.html");
+
+ // Attempt to open the file
+ beast::error_code ec;
+ http::file_body::value_type body;
+ body.open(path.c_str(), beast::file_mode::scan, ec);
+
+ // Handle the case where the file doesn't exist
+ if(ec == beast::errc::no_such_file_or_directory)
+ return send(not_found(req.target()));
+
+ // Handle an unknown error
+ if(ec)
+ return send(server_error(ec.message()));
+
+ // Cache the size since we need it after the move
+ auto const size = body.size();
+
+ // Respond to HEAD request
+ if(req.method() == http::verb::head)
+ {
+ http::response<http::empty_body> res{http::status::ok, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, mime_type(path));
+ res.content_length(size);
+ res.keep_alive(req.keep_alive());
+ return send(std::move(res));
+ }
+
+ // Respond to GET request
+ http::response<http::file_body> res{
+ std::piecewise_construct,
+ std::make_tuple(std::move(body)),
+ std::make_tuple(http::status::ok, req.version())};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, mime_type(path));
+ res.content_length(size);
+ res.keep_alive(req.keep_alive());
+ return send(std::move(res));
+}
+
+//------------------------------------------------------------------------------
+
+// Report a failure
+void
+fail(beast::error_code ec, char const* what)
+{
+ std::cerr << what << ": " << ec.message() << "\n";
+}
+
+// Handles an HTTP server connection
+class session : public std::enable_shared_from_this<session>
+{
+ // This is the C++11 equivalent of a generic lambda.
+ // The function object is used to send an HTTP message.
+ struct send_lambda
+ {
+ session& self_;
+
+ explicit
+ send_lambda(session& self)
+ : self_(self)
+ {
+ }
+
+ template<bool isRequest, class Body, class Fields>
+ void
+ operator()(http::message<isRequest, Body, Fields>&& msg) const
+ {
+ // The lifetime of the message has to extend
+ // for the duration of the async operation so
+ // we use a shared_ptr to manage it.
+ auto sp = std::make_shared<
+ http::message<isRequest, Body, Fields>>(std::move(msg));
+
+ // Store a type-erased version of the shared
+ // pointer in the class to keep it alive.
+ self_.res_ = sp;
+
+ // Write the response
+ http::async_write(
+ self_.stream_,
+ *sp,
+ beast::bind_front_handler(
+ &session::on_write,
+ self_.shared_from_this(),
+ sp->need_eof()));
+ }
+ };
+
+ beast::tcp_stream stream_;
+ beast::flat_buffer buffer_;
+ std::shared_ptr<std::string const> doc_root_;
+ http::request<http::string_body> req_;
+ std::shared_ptr<void> res_;
+ send_lambda lambda_;
+
+public:
+ // Take ownership of the stream
+ session(
+ tcp::socket&& socket,
+ std::shared_ptr<std::string const> const& doc_root)
+ : stream_(std::move(socket))
+ , doc_root_(doc_root)
+ , lambda_(*this)
+ {
+ }
+
+ // Start the asynchronous operation
+ void
+ run()
+ {
+ // We need to be executing within a strand to perform async operations
+ // on the I/O objects in this session. Although not strictly necessary
+ // for single-threaded contexts, this example code is written to be
+ // thread-safe by default.
+ net::dispatch(stream_.get_executor(),
+ beast::bind_front_handler(
+ &session::do_read,
+ shared_from_this()));
+ }
+
+ void
+ do_read()
+ {
+ // Make the request empty before reading,
+ // otherwise the operation behavior is undefined.
+ req_ = {};
+
+ // Set the timeout.
+ stream_.expires_after(std::chrono::seconds(30));
+
+ // Read a request
+ http::async_read(stream_, buffer_, req_,
+ beast::bind_front_handler(
+ &session::on_read,
+ shared_from_this()));
+ }
+
+ void
+ on_read(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ // This means they closed the connection
+ if(ec == http::error::end_of_stream)
+ return do_close();
+
+ if(ec)
+ return fail(ec, "read");
+
+ // Send the response
+ handle_request(*doc_root_, std::move(req_), lambda_);
+ }
+
+ void
+ on_write(
+ bool close,
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ if(ec)
+ return fail(ec, "write");
+
+ if(close)
+ {
+ // This means we should close the connection, usually because
+ // the response indicated the "Connection: close" semantic.
+ return do_close();
+ }
+
+ // We're done with the response so delete it
+ res_ = nullptr;
+
+ // Read another request
+ do_read();
+ }
+
+ void
+ do_close()
+ {
+ // Send a TCP shutdown
+ beast::error_code ec;
+ stream_.socket().shutdown(tcp::socket::shutdown_send, ec);
+
+ // At this point the connection is closed gracefully
+ }
+};
+
+//------------------------------------------------------------------------------
+
+// Accepts incoming connections and launches the sessions
+class listener : public std::enable_shared_from_this<listener>
+{
+ net::io_context& ioc_;
+ tcp::acceptor acceptor_;
+ std::shared_ptr<std::string const> doc_root_;
+
+public:
+ listener(
+ net::io_context& ioc,
+ tcp::endpoint endpoint,
+ std::shared_ptr<std::string const> const& doc_root)
+ : ioc_(ioc)
+ , acceptor_(net::make_strand(ioc))
+ , doc_root_(doc_root)
+ {
+ beast::error_code ec;
+
+ // Open the acceptor
+ acceptor_.open(endpoint.protocol(), ec);
+ if(ec)
+ {
+ fail(ec, "open");
+ return;
+ }
+
+ // Allow address reuse
+ acceptor_.set_option(net::socket_base::reuse_address(true), ec);
+ if(ec)
+ {
+ fail(ec, "set_option");
+ return;
+ }
+
+ // Bind to the server address
+ acceptor_.bind(endpoint, ec);
+ if(ec)
+ {
+ fail(ec, "bind");
+ return;
+ }
+
+ // Start listening for connections
+ acceptor_.listen(
+ net::socket_base::max_listen_connections, ec);
+ if(ec)
+ {
+ fail(ec, "listen");
+ return;
+ }
+ }
+
+ // Start accepting incoming connections
+ void
+ run()
+ {
+ do_accept();
+ }
+
+private:
+ void
+ do_accept()
+ {
+ // The new connection gets its own strand
+ acceptor_.async_accept(
+ net::make_strand(ioc_),
+ beast::bind_front_handler(
+ &listener::on_accept,
+ shared_from_this()));
+ }
+
+ void
+ on_accept(beast::error_code ec, tcp::socket socket)
+ {
+ if(ec)
+ {
+ fail(ec, "accept");
+ }
+ else
+ {
+ // Create the session and run it
+ std::make_shared<session>(
+ std::move(socket),
+ doc_root_)->run();
+ }
+
+ // Accept another connection
+ do_accept();
+ }
+};
+
+//------------------------------------------------------------------------------
+
+int main(int argc, char* argv[])
+{
+ // Check command line arguments.
+ if (argc != 5)
+ {
+ std::cerr <<
+ "Usage: http-server-async <address> <port> <doc_root> <threads>\n" <<
+ "Example:\n" <<
+ " http-server-async 0.0.0.0 8080 . 1\n";
+ return EXIT_FAILURE;
+ }
+ auto const address = net::ip::make_address(argv[1]);
+ auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
+ auto const doc_root = std::make_shared<std::string>(argv[3]);
+ auto const threads = std::max<int>(1, std::atoi(argv[4]));
+
+ // The io_context is required for all I/O
+ net::io_context ioc{threads};
+
+ // Create and launch a listening port
+ std::make_shared<listener>(
+ ioc,
+ tcp::endpoint{address, port},
+ doc_root)->run();
+
+ // Run the I/O service on the requested number of threads
+ std::vector<std::thread> v;
+ v.reserve(threads - 1);
+ for(auto i = threads - 1; i > 0; --i)
+ v.emplace_back(
+ [&ioc]
+ {
+ ioc.run();
+ });
+ ioc.run();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/http/server/coro-ssl/CMakeLists.txt b/src/boost/libs/beast/example/http/server/coro-ssl/CMakeLists.txt
new file mode 100644
index 000000000..9bbf294cf
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/coro-ssl/CMakeLists.txt
@@ -0,0 +1,31 @@
+#
+# 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
+#
+
+if (OPENSSL_FOUND)
+ GroupSources(include/boost/beast beast)
+ GroupSources(example/common common)
+ GroupSources(example/http/server/coro-ssl "/")
+
+ add_executable (http-server-coro-ssl
+ ${BOOST_BEAST_FILES}
+ ${PROJECT_SOURCE_DIR}/example/common/server_certificate.hpp
+ Jamfile
+ http_server_coro_ssl.cpp
+ )
+
+ set_property(TARGET http-server-coro-ssl PROPERTY FOLDER "example-http-server")
+
+ target_link_libraries (http-server-coro-ssl
+ OpenSSL::SSL OpenSSL::Crypto
+ lib-asio
+ lib-asio-ssl
+ lib-beast
+ )
+
+endif()
diff --git a/src/boost/libs/beast/example/http/server/coro-ssl/Jamfile b/src/boost/libs/beast/example/http/server/coro-ssl/Jamfile
new file mode 100644
index 000000000..8870f65d2
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/coro-ssl/Jamfile
@@ -0,0 +1,23 @@
+#
+# 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
+#
+
+import ac ;
+
+project
+ : requirements
+ [ ac.check-library /boost/beast//lib-asio-ssl : <library>/boost/beast//lib-asio-ssl/<link>static : <build>no ]
+ ;
+
+exe http-server-coro-ssl :
+ http_server_coro_ssl.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ <library>/boost/coroutine//boost_coroutine
+ ;
diff --git a/src/boost/libs/beast/example/http/server/coro-ssl/http_server_coro_ssl.cpp b/src/boost/libs/beast/example/http/server/coro-ssl/http_server_coro_ssl.cpp
new file mode 100644
index 000000000..a733c6244
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/coro-ssl/http_server_coro_ssl.cpp
@@ -0,0 +1,432 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: HTTP SSL server, coroutine
+//
+//------------------------------------------------------------------------------
+
+#include "example/common/server_certificate.hpp"
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/http.hpp>
+#include <boost/beast/ssl.hpp>
+#include <boost/beast/version.hpp>
+#include <boost/asio/spawn.hpp>
+#include <boost/config.hpp>
+#include <algorithm>
+#include <cstdlib>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <thread>
+#include <vector>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+// Return a reasonable mime type based on the extension of a file.
+beast::string_view
+mime_type(beast::string_view path)
+{
+ using beast::iequals;
+ auto const ext = [&path]
+ {
+ auto const pos = path.rfind(".");
+ if(pos == beast::string_view::npos)
+ return beast::string_view{};
+ return path.substr(pos);
+ }();
+ if(iequals(ext, ".htm")) return "text/html";
+ if(iequals(ext, ".html")) return "text/html";
+ if(iequals(ext, ".php")) return "text/html";
+ if(iequals(ext, ".css")) return "text/css";
+ if(iequals(ext, ".txt")) return "text/plain";
+ if(iequals(ext, ".js")) return "application/javascript";
+ if(iequals(ext, ".json")) return "application/json";
+ if(iequals(ext, ".xml")) return "application/xml";
+ if(iequals(ext, ".swf")) return "application/x-shockwave-flash";
+ if(iequals(ext, ".flv")) return "video/x-flv";
+ if(iequals(ext, ".png")) return "image/png";
+ if(iequals(ext, ".jpe")) return "image/jpeg";
+ if(iequals(ext, ".jpeg")) return "image/jpeg";
+ if(iequals(ext, ".jpg")) return "image/jpeg";
+ if(iequals(ext, ".gif")) return "image/gif";
+ if(iequals(ext, ".bmp")) return "image/bmp";
+ if(iequals(ext, ".ico")) return "image/vnd.microsoft.icon";
+ if(iequals(ext, ".tiff")) return "image/tiff";
+ if(iequals(ext, ".tif")) return "image/tiff";
+ if(iequals(ext, ".svg")) return "image/svg+xml";
+ if(iequals(ext, ".svgz")) return "image/svg+xml";
+ return "application/text";
+}
+
+// Append an HTTP rel-path to a local filesystem path.
+// The returned path is normalized for the platform.
+std::string
+path_cat(
+ beast::string_view base,
+ beast::string_view path)
+{
+ if(base.empty())
+ return std::string(path);
+ std::string result(base);
+#ifdef BOOST_MSVC
+ char constexpr path_separator = '\\';
+ if(result.back() == path_separator)
+ result.resize(result.size() - 1);
+ result.append(path.data(), path.size());
+ for(auto& c : result)
+ if(c == '/')
+ c = path_separator;
+#else
+ char constexpr path_separator = '/';
+ if(result.back() == path_separator)
+ result.resize(result.size() - 1);
+ result.append(path.data(), path.size());
+#endif
+ return result;
+}
+
+// This function produces an HTTP response for the given
+// request. The type of the response object depends on the
+// contents of the request, so the interface requires the
+// caller to pass a generic lambda for receiving the response.
+template<
+ class Body, class Allocator,
+ class Send>
+void
+handle_request(
+ beast::string_view doc_root,
+ http::request<Body, http::basic_fields<Allocator>>&& req,
+ Send&& send)
+{
+ // Returns a bad request response
+ auto const bad_request =
+ [&req](beast::string_view why)
+ {
+ http::response<http::string_body> res{http::status::bad_request, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = std::string(why);
+ res.prepare_payload();
+ return res;
+ };
+
+ // Returns a not found response
+ auto const not_found =
+ [&req](beast::string_view target)
+ {
+ http::response<http::string_body> res{http::status::not_found, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = "The resource '" + std::string(target) + "' was not found.";
+ res.prepare_payload();
+ return res;
+ };
+
+ // Returns a server error response
+ auto const server_error =
+ [&req](beast::string_view what)
+ {
+ http::response<http::string_body> res{http::status::internal_server_error, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = "An error occurred: '" + std::string(what) + "'";
+ res.prepare_payload();
+ return res;
+ };
+
+ // Make sure we can handle the method
+ if( req.method() != http::verb::get &&
+ req.method() != http::verb::head)
+ return send(bad_request("Unknown HTTP-method"));
+
+ // Request path must be absolute and not contain "..".
+ if( req.target().empty() ||
+ req.target()[0] != '/' ||
+ req.target().find("..") != beast::string_view::npos)
+ return send(bad_request("Illegal request-target"));
+
+ // Build the path to the requested file
+ std::string path = path_cat(doc_root, req.target());
+ if(req.target().back() == '/')
+ path.append("index.html");
+
+ // Attempt to open the file
+ beast::error_code ec;
+ http::file_body::value_type body;
+ body.open(path.c_str(), beast::file_mode::scan, ec);
+
+ // Handle the case where the file doesn't exist
+ if(ec == beast::errc::no_such_file_or_directory)
+ return send(not_found(req.target()));
+
+ // Handle an unknown error
+ if(ec)
+ return send(server_error(ec.message()));
+
+ // Cache the size since we need it after the move
+ auto const size = body.size();
+
+ // Respond to HEAD request
+ if(req.method() == http::verb::head)
+ {
+ http::response<http::empty_body> res{http::status::ok, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, mime_type(path));
+ res.content_length(size);
+ res.keep_alive(req.keep_alive());
+ return send(std::move(res));
+ }
+
+ // Respond to GET request
+ http::response<http::file_body> res{
+ std::piecewise_construct,
+ std::make_tuple(std::move(body)),
+ std::make_tuple(http::status::ok, req.version())};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, mime_type(path));
+ res.content_length(size);
+ res.keep_alive(req.keep_alive());
+ return send(std::move(res));
+}
+
+//------------------------------------------------------------------------------
+
+// Report a failure
+void
+fail(beast::error_code ec, char const* what)
+{
+ // ssl::error::stream_truncated, also known as an SSL "short read",
+ // indicates the peer closed the connection without performing the
+ // required closing handshake (for example, Google does this to
+ // improve performance). Generally this can be a security issue,
+ // but if your communication protocol is self-terminated (as
+ // it is with both HTTP and WebSocket) then you may simply
+ // ignore the lack of close_notify.
+ //
+ // https://github.com/boostorg/beast/issues/38
+ //
+ // https://security.stackexchange.com/questions/91435/how-to-handle-a-malicious-ssl-tls-shutdown
+ //
+ // When a short read would cut off the end of an HTTP message,
+ // Beast returns the error beast::http::error::partial_message.
+ // Therefore, if we see a short read here, it has occurred
+ // after the message has been completed, so it is safe to ignore it.
+
+ if(ec == net::ssl::error::stream_truncated)
+ return;
+
+ std::cerr << what << ": " << ec.message() << "\n";
+}
+
+// This is the C++11 equivalent of a generic lambda.
+// The function object is used to send an HTTP message.
+struct send_lambda
+{
+ beast::ssl_stream<beast::tcp_stream>& stream_;
+ bool& close_;
+ beast::error_code& ec_;
+ net::yield_context yield_;
+
+ send_lambda(
+ beast::ssl_stream<beast::tcp_stream>& stream,
+ bool& close,
+ beast::error_code& ec,
+ net::yield_context yield)
+ : stream_(stream)
+ , close_(close)
+ , ec_(ec)
+ , yield_(yield)
+ {
+ }
+
+ template<bool isRequest, class Body, class Fields>
+ void
+ operator()(http::message<isRequest, Body, Fields>&& msg) const
+ {
+ // Determine if we should close the connection after
+ close_ = msg.need_eof();
+
+ // We need the serializer here because the serializer requires
+ // a non-const file_body, and the message oriented version of
+ // http::write only works with const messages.
+ http::serializer<isRequest, Body, Fields> sr{msg};
+ http::async_write(stream_, sr, yield_[ec_]);
+ }
+};
+
+// Handles an HTTP server connection
+void
+do_session(
+ beast::ssl_stream<beast::tcp_stream>& stream,
+ std::shared_ptr<std::string const> const& doc_root,
+ net::yield_context yield)
+{
+ bool close = false;
+ beast::error_code ec;
+
+ // Set the timeout.
+ beast::get_lowest_layer(stream).expires_after(std::chrono::seconds(30));
+
+ // Perform the SSL handshake
+ stream.async_handshake(ssl::stream_base::server, yield[ec]);
+ if(ec)
+ return fail(ec, "handshake");
+
+ // This buffer is required to persist across reads
+ beast::flat_buffer buffer;
+
+ // This lambda is used to send messages
+ send_lambda lambda{stream, close, ec, yield};
+
+ for(;;)
+ {
+ // Set the timeout.
+ beast::get_lowest_layer(stream).expires_after(std::chrono::seconds(30));
+
+ // Read a request
+ http::request<http::string_body> req;
+ http::async_read(stream, buffer, req, yield[ec]);
+ if(ec == http::error::end_of_stream)
+ break;
+ if(ec)
+ return fail(ec, "read");
+
+ // Send the response
+ handle_request(*doc_root, std::move(req), lambda);
+ if(ec)
+ return fail(ec, "write");
+ if(close)
+ {
+ // This means we should close the connection, usually because
+ // the response indicated the "Connection: close" semantic.
+ break;
+ }
+ }
+
+ // Set the timeout.
+ beast::get_lowest_layer(stream).expires_after(std::chrono::seconds(30));
+
+ // Perform the SSL shutdown
+ stream.async_shutdown(yield[ec]);
+ if(ec)
+ return fail(ec, "shutdown");
+
+ // At this point the connection is closed gracefully
+}
+
+//------------------------------------------------------------------------------
+
+// Accepts incoming connections and launches the sessions
+void
+do_listen(
+ net::io_context& ioc,
+ ssl::context& ctx,
+ tcp::endpoint endpoint,
+ std::shared_ptr<std::string const> const& doc_root,
+ net::yield_context yield)
+{
+ beast::error_code ec;
+
+ // Open the acceptor
+ tcp::acceptor acceptor(ioc);
+ acceptor.open(endpoint.protocol(), ec);
+ if(ec)
+ return fail(ec, "open");
+
+ // Allow address reuse
+ acceptor.set_option(net::socket_base::reuse_address(true), ec);
+ if(ec)
+ return fail(ec, "set_option");
+
+ // Bind to the server address
+ acceptor.bind(endpoint, ec);
+ if(ec)
+ return fail(ec, "bind");
+
+ // Start listening for connections
+ acceptor.listen(net::socket_base::max_listen_connections, ec);
+ if(ec)
+ return fail(ec, "listen");
+
+ for(;;)
+ {
+ tcp::socket socket(ioc);
+ acceptor.async_accept(socket, yield[ec]);
+ if(ec)
+ fail(ec, "accept");
+ else
+ boost::asio::spawn(
+ acceptor.get_executor(),
+ std::bind(
+ &do_session,
+ beast::ssl_stream<beast::tcp_stream>(
+ std::move(socket), ctx),
+ doc_root,
+ std::placeholders::_1));
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ // Check command line arguments.
+ if (argc != 5)
+ {
+ std::cerr <<
+ "Usage: http-server-coro-ssl <address> <port> <doc_root> <threads>\n" <<
+ "Example:\n" <<
+ " http-server-coro-ssl 0.0.0.0 8080 . 1\n";
+ return EXIT_FAILURE;
+ }
+ auto const address = net::ip::make_address(argv[1]);
+ auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
+ auto const doc_root = std::make_shared<std::string>(argv[3]);
+ auto const threads = std::max<int>(1, std::atoi(argv[4]));
+
+ // The io_context is required for all I/O
+ net::io_context ioc{threads};
+
+ // The SSL context is required, and holds certificates
+ ssl::context ctx{ssl::context::tlsv12};
+
+ // This holds the self-signed certificate used by the server
+ load_server_certificate(ctx);
+
+ // Spawn a listening port
+ boost::asio::spawn(ioc,
+ std::bind(
+ &do_listen,
+ std::ref(ioc),
+ std::ref(ctx),
+ tcp::endpoint{address, port},
+ doc_root,
+ std::placeholders::_1));
+
+ // Run the I/O service on the requested number of threads
+ std::vector<std::thread> v;
+ v.reserve(threads - 1);
+ for(auto i = threads - 1; i > 0; --i)
+ v.emplace_back(
+ [&ioc]
+ {
+ ioc.run();
+ });
+ ioc.run();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/http/server/coro/CMakeLists.txt b/src/boost/libs/beast/example/http/server/coro/CMakeLists.txt
new file mode 100644
index 000000000..6cc8244a8
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/coro/CMakeLists.txt
@@ -0,0 +1,23 @@
+#
+# 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
+#
+
+GroupSources(include/boost/beast beast)
+GroupSources(example/http/server/coro "/")
+
+add_executable (http-server-coro
+ ${BOOST_BEAST_FILES}
+ Jamfile
+ http_server_coro.cpp
+)
+
+target_link_libraries(http-server-coro
+ lib-asio
+ lib-beast)
+
+set_property(TARGET http-server-coro PROPERTY FOLDER "example-http-server")
diff --git a/src/boost/libs/beast/example/http/server/coro/Jamfile b/src/boost/libs/beast/example/http/server/coro/Jamfile
new file mode 100644
index 000000000..600b0fa09
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/coro/Jamfile
@@ -0,0 +1,16 @@
+#
+# 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
+#
+
+exe http-server-coro :
+ http_server_coro.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ <library>/boost/coroutine//boost_coroutine
+ ;
diff --git a/src/boost/libs/beast/example/http/server/coro/http_server_coro.cpp b/src/boost/libs/beast/example/http/server/coro/http_server_coro.cpp
new file mode 100644
index 000000000..a8baae640
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/coro/http_server_coro.cpp
@@ -0,0 +1,387 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: HTTP server, coroutine
+//
+//------------------------------------------------------------------------------
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/http.hpp>
+#include <boost/beast/version.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/spawn.hpp>
+#include <boost/config.hpp>
+#include <algorithm>
+#include <cstdlib>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <thread>
+#include <vector>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+// Return a reasonable mime type based on the extension of a file.
+beast::string_view
+mime_type(beast::string_view path)
+{
+ using beast::iequals;
+ auto const ext = [&path]
+ {
+ auto const pos = path.rfind(".");
+ if(pos == beast::string_view::npos)
+ return beast::string_view{};
+ return path.substr(pos);
+ }();
+ if(iequals(ext, ".htm")) return "text/html";
+ if(iequals(ext, ".html")) return "text/html";
+ if(iequals(ext, ".php")) return "text/html";
+ if(iequals(ext, ".css")) return "text/css";
+ if(iequals(ext, ".txt")) return "text/plain";
+ if(iequals(ext, ".js")) return "application/javascript";
+ if(iequals(ext, ".json")) return "application/json";
+ if(iequals(ext, ".xml")) return "application/xml";
+ if(iequals(ext, ".swf")) return "application/x-shockwave-flash";
+ if(iequals(ext, ".flv")) return "video/x-flv";
+ if(iequals(ext, ".png")) return "image/png";
+ if(iequals(ext, ".jpe")) return "image/jpeg";
+ if(iequals(ext, ".jpeg")) return "image/jpeg";
+ if(iequals(ext, ".jpg")) return "image/jpeg";
+ if(iequals(ext, ".gif")) return "image/gif";
+ if(iequals(ext, ".bmp")) return "image/bmp";
+ if(iequals(ext, ".ico")) return "image/vnd.microsoft.icon";
+ if(iequals(ext, ".tiff")) return "image/tiff";
+ if(iequals(ext, ".tif")) return "image/tiff";
+ if(iequals(ext, ".svg")) return "image/svg+xml";
+ if(iequals(ext, ".svgz")) return "image/svg+xml";
+ return "application/text";
+}
+
+// Append an HTTP rel-path to a local filesystem path.
+// The returned path is normalized for the platform.
+std::string
+path_cat(
+ beast::string_view base,
+ beast::string_view path)
+{
+ if(base.empty())
+ return std::string(path);
+ std::string result(base);
+#ifdef BOOST_MSVC
+ char constexpr path_separator = '\\';
+ if(result.back() == path_separator)
+ result.resize(result.size() - 1);
+ result.append(path.data(), path.size());
+ for(auto& c : result)
+ if(c == '/')
+ c = path_separator;
+#else
+ char constexpr path_separator = '/';
+ if(result.back() == path_separator)
+ result.resize(result.size() - 1);
+ result.append(path.data(), path.size());
+#endif
+ return result;
+}
+
+// This function produces an HTTP response for the given
+// request. The type of the response object depends on the
+// contents of the request, so the interface requires the
+// caller to pass a generic lambda for receiving the response.
+template<
+ class Body, class Allocator,
+ class Send>
+void
+handle_request(
+ beast::string_view doc_root,
+ http::request<Body, http::basic_fields<Allocator>>&& req,
+ Send&& send)
+{
+ // Returns a bad request response
+ auto const bad_request =
+ [&req](beast::string_view why)
+ {
+ http::response<http::string_body> res{http::status::bad_request, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = std::string(why);
+ res.prepare_payload();
+ return res;
+ };
+
+ // Returns a not found response
+ auto const not_found =
+ [&req](beast::string_view target)
+ {
+ http::response<http::string_body> res{http::status::not_found, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = "The resource '" + std::string(target) + "' was not found.";
+ res.prepare_payload();
+ return res;
+ };
+
+ // Returns a server error response
+ auto const server_error =
+ [&req](beast::string_view what)
+ {
+ http::response<http::string_body> res{http::status::internal_server_error, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = "An error occurred: '" + std::string(what) + "'";
+ res.prepare_payload();
+ return res;
+ };
+
+ // Make sure we can handle the method
+ if( req.method() != http::verb::get &&
+ req.method() != http::verb::head)
+ return send(bad_request("Unknown HTTP-method"));
+
+ // Request path must be absolute and not contain "..".
+ if( req.target().empty() ||
+ req.target()[0] != '/' ||
+ req.target().find("..") != beast::string_view::npos)
+ return send(bad_request("Illegal request-target"));
+
+ // Build the path to the requested file
+ std::string path = path_cat(doc_root, req.target());
+ if(req.target().back() == '/')
+ path.append("index.html");
+
+ // Attempt to open the file
+ beast::error_code ec;
+ http::file_body::value_type body;
+ body.open(path.c_str(), beast::file_mode::scan, ec);
+
+ // Handle the case where the file doesn't exist
+ if(ec == beast::errc::no_such_file_or_directory)
+ return send(not_found(req.target()));
+
+ // Handle an unknown error
+ if(ec)
+ return send(server_error(ec.message()));
+
+ // Cache the size since we need it after the move
+ auto const size = body.size();
+
+ // Respond to HEAD request
+ if(req.method() == http::verb::head)
+ {
+ http::response<http::empty_body> res{http::status::ok, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, mime_type(path));
+ res.content_length(size);
+ res.keep_alive(req.keep_alive());
+ return send(std::move(res));
+ }
+
+ // Respond to GET request
+ http::response<http::file_body> res{
+ std::piecewise_construct,
+ std::make_tuple(std::move(body)),
+ std::make_tuple(http::status::ok, req.version())};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, mime_type(path));
+ res.content_length(size);
+ res.keep_alive(req.keep_alive());
+ return send(std::move(res));
+}
+
+//------------------------------------------------------------------------------
+
+// Report a failure
+void
+fail(beast::error_code ec, char const* what)
+{
+ std::cerr << what << ": " << ec.message() << "\n";
+}
+
+// This is the C++11 equivalent of a generic lambda.
+// The function object is used to send an HTTP message.
+struct send_lambda
+{
+ beast::tcp_stream& stream_;
+ bool& close_;
+ beast::error_code& ec_;
+ net::yield_context yield_;
+
+ send_lambda(
+ beast::tcp_stream& stream,
+ bool& close,
+ beast::error_code& ec,
+ net::yield_context yield)
+ : stream_(stream)
+ , close_(close)
+ , ec_(ec)
+ , yield_(yield)
+ {
+ }
+
+ template<bool isRequest, class Body, class Fields>
+ void
+ operator()(http::message<isRequest, Body, Fields>&& msg) const
+ {
+ // Determine if we should close the connection after
+ close_ = msg.need_eof();
+
+ // We need the serializer here because the serializer requires
+ // a non-const file_body, and the message oriented version of
+ // http::write only works with const messages.
+ http::serializer<isRequest, Body, Fields> sr{msg};
+ http::async_write(stream_, sr, yield_[ec_]);
+ }
+};
+
+// Handles an HTTP server connection
+void
+do_session(
+ beast::tcp_stream& stream,
+ std::shared_ptr<std::string const> const& doc_root,
+ net::yield_context yield)
+{
+ bool close = false;
+ beast::error_code ec;
+
+ // This buffer is required to persist across reads
+ beast::flat_buffer buffer;
+
+ // This lambda is used to send messages
+ send_lambda lambda{stream, close, ec, yield};
+
+ for(;;)
+ {
+ // Set the timeout.
+ stream.expires_after(std::chrono::seconds(30));
+
+ // Read a request
+ http::request<http::string_body> req;
+ http::async_read(stream, buffer, req, yield[ec]);
+ if(ec == http::error::end_of_stream)
+ break;
+ if(ec)
+ return fail(ec, "read");
+
+ // Send the response
+ handle_request(*doc_root, std::move(req), lambda);
+ if(ec)
+ return fail(ec, "write");
+ if(close)
+ {
+ // This means we should close the connection, usually because
+ // the response indicated the "Connection: close" semantic.
+ break;
+ }
+ }
+
+ // Send a TCP shutdown
+ stream.socket().shutdown(tcp::socket::shutdown_send, ec);
+
+ // At this point the connection is closed gracefully
+}
+
+//------------------------------------------------------------------------------
+
+// Accepts incoming connections and launches the sessions
+void
+do_listen(
+ net::io_context& ioc,
+ tcp::endpoint endpoint,
+ std::shared_ptr<std::string const> const& doc_root,
+ net::yield_context yield)
+{
+ beast::error_code ec;
+
+ // Open the acceptor
+ tcp::acceptor acceptor(ioc);
+ acceptor.open(endpoint.protocol(), ec);
+ if(ec)
+ return fail(ec, "open");
+
+ // Allow address reuse
+ acceptor.set_option(net::socket_base::reuse_address(true), ec);
+ if(ec)
+ return fail(ec, "set_option");
+
+ // Bind to the server address
+ acceptor.bind(endpoint, ec);
+ if(ec)
+ return fail(ec, "bind");
+
+ // Start listening for connections
+ acceptor.listen(net::socket_base::max_listen_connections, ec);
+ if(ec)
+ return fail(ec, "listen");
+
+ for(;;)
+ {
+ tcp::socket socket(ioc);
+ acceptor.async_accept(socket, yield[ec]);
+ if(ec)
+ fail(ec, "accept");
+ else
+ boost::asio::spawn(
+ acceptor.get_executor(),
+ std::bind(
+ &do_session,
+ beast::tcp_stream(std::move(socket)),
+ doc_root,
+ std::placeholders::_1));
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ // Check command line arguments.
+ if (argc != 5)
+ {
+ std::cerr <<
+ "Usage: http-server-coro <address> <port> <doc_root> <threads>\n" <<
+ "Example:\n" <<
+ " http-server-coro 0.0.0.0 8080 . 1\n";
+ return EXIT_FAILURE;
+ }
+ auto const address = net::ip::make_address(argv[1]);
+ auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
+ auto const doc_root = std::make_shared<std::string>(argv[3]);
+ auto const threads = std::max<int>(1, std::atoi(argv[4]));
+
+ // The io_context is required for all I/O
+ net::io_context ioc{threads};
+
+ // Spawn a listening port
+ boost::asio::spawn(ioc,
+ std::bind(
+ &do_listen,
+ std::ref(ioc),
+ tcp::endpoint{address, port},
+ doc_root,
+ std::placeholders::_1));
+
+ // Run the I/O service on the requested number of threads
+ std::vector<std::thread> v;
+ v.reserve(threads - 1);
+ for(auto i = threads - 1; i > 0; --i)
+ v.emplace_back(
+ [&ioc]
+ {
+ ioc.run();
+ });
+ ioc.run();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/http/server/fast/CMakeLists.txt b/src/boost/libs/beast/example/http/server/fast/CMakeLists.txt
new file mode 100644
index 000000000..ecc8f7bdc
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/fast/CMakeLists.txt
@@ -0,0 +1,26 @@
+#
+# 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
+#
+
+GroupSources(include/boost/beast beast)
+GroupSources(example/common common)
+GroupSources(example/http/server/fast "/")
+
+add_executable (http-server-fast
+ ${BOOST_BEAST_FILES}
+ ${COMMON_FILES}
+ Jamfile
+ fields_alloc.hpp
+ http_server_fast.cpp
+)
+
+target_link_libraries(http-server-fast
+ lib-asio
+ lib-beast)
+
+set_property(TARGET http-server-fast PROPERTY FOLDER "example-http-server")
diff --git a/src/boost/libs/beast/example/http/server/fast/Jamfile b/src/boost/libs/beast/example/http/server/fast/Jamfile
new file mode 100644
index 000000000..8a9dd44d6
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/fast/Jamfile
@@ -0,0 +1,15 @@
+#
+# 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
+#
+
+exe http-server-fast :
+ http_server_fast.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ ;
diff --git a/src/boost/libs/beast/example/http/server/fast/fields_alloc.hpp b/src/boost/libs/beast/example/http/server/fast/fields_alloc.hpp
new file mode 100644
index 000000000..d60c1c499
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/fast/fields_alloc.hpp
@@ -0,0 +1,205 @@
+//
+// Copyright (c) 2016-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 BOOST_BEAST_EXAMPLE_FIELDS_ALLOC_HPP
+#define BOOST_BEAST_EXAMPLE_FIELDS_ALLOC_HPP
+
+#include <boost/throw_exception.hpp>
+#include <cstdlib>
+#include <memory>
+#include <stdexcept>
+
+namespace detail {
+
+struct static_pool
+{
+ std::size_t size_;
+ std::size_t refs_ = 1;
+ std::size_t count_ = 0;
+ char* p_;
+
+ char*
+ end()
+ {
+ return reinterpret_cast<char*>(this + 1) + size_;
+ }
+
+ explicit
+ static_pool(std::size_t size)
+ : size_(size)
+ , p_(reinterpret_cast<char*>(this + 1))
+ {
+ }
+
+public:
+ static
+ static_pool&
+ construct(std::size_t size)
+ {
+ auto p = new char[sizeof(static_pool) + size];
+ return *(::new(p) static_pool{size});
+ }
+
+ static_pool&
+ share()
+ {
+ ++refs_;
+ return *this;
+ }
+
+ void
+ destroy()
+ {
+ if(refs_--)
+ return;
+ this->~static_pool();
+ delete[] reinterpret_cast<char*>(this);
+ }
+
+ void*
+ alloc(std::size_t n)
+ {
+ auto last = p_ + n;
+ if(last >= end())
+ BOOST_THROW_EXCEPTION(std::bad_alloc{});
+ ++count_;
+ auto p = p_;
+ p_ = last;
+ return p;
+ }
+
+ void
+ dealloc()
+ {
+ if(--count_)
+ return;
+ p_ = reinterpret_cast<char*>(this + 1);
+ }
+};
+
+} // detail
+
+/** A non-thread-safe allocator optimized for @ref basic_fields.
+
+ This allocator obtains memory from a pre-allocated memory block
+ of a given size. It does nothing in deallocate until all
+ previously allocated blocks are deallocated, upon which it
+ resets the internal memory block for re-use.
+
+ To use this allocator declare an instance persistent to the
+ connection or session, and construct with the block size.
+ A good rule of thumb is 20% more than the maximum allowed
+ header size. For example if the application only allows up
+ to an 8,000 byte header, the block size could be 9,600.
+
+ Then, for every instance of `message` construct the header
+ with a copy of the previously declared allocator instance.
+*/
+template<class T>
+struct fields_alloc
+{
+ detail::static_pool* pool_;
+
+public:
+ using value_type = T;
+ using is_always_equal = std::false_type;
+ using pointer = T*;
+ using reference = T&;
+ using const_pointer = T const*;
+ using const_reference = T const&;
+ using size_type = std::size_t;
+ using difference_type = std::ptrdiff_t;
+
+ template<class U>
+ struct rebind
+ {
+ using other = fields_alloc<U>;
+ };
+
+#if defined(_GLIBCXX_USE_CXX11_ABI) && (_GLIBCXX_USE_CXX11_ABI == 0)
+ // Workaround for g++
+ // basic_string assumes that allocators are default-constructible
+ // See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56437
+ fields_alloc() = default;
+#endif
+
+ explicit
+ fields_alloc(std::size_t size)
+ : pool_(&detail::static_pool::construct(size))
+ {
+ }
+
+ fields_alloc(fields_alloc const& other)
+ : pool_(&other.pool_->share())
+ {
+ }
+
+ template<class U>
+ fields_alloc(fields_alloc<U> const& other)
+ : pool_(&other.pool_->share())
+ {
+ }
+
+ ~fields_alloc()
+ {
+ pool_->destroy();
+ }
+
+ value_type*
+ allocate(size_type n)
+ {
+ return static_cast<value_type*>(
+ pool_->alloc(n * sizeof(T)));
+ }
+
+ void
+ deallocate(value_type*, size_type)
+ {
+ pool_->dealloc();
+ }
+
+#if defined(BOOST_LIBSTDCXX_VERSION) && BOOST_LIBSTDCXX_VERSION < 60000
+ template<class U, class... Args>
+ void
+ construct(U* ptr, Args&&... args)
+ {
+ ::new(static_cast<void*>(ptr)) U(
+ std::forward<Args>(args)...);
+ }
+
+ template<class U>
+ void
+ destroy(U* ptr)
+ {
+ ptr->~U();
+ }
+#endif
+
+ template<class U>
+ friend
+ bool
+ operator==(
+ fields_alloc const& lhs,
+ fields_alloc<U> const& rhs)
+ {
+ return &lhs.pool_ == &rhs.pool_;
+ }
+
+ template<class U>
+ friend
+ bool
+ operator!=(
+ fields_alloc const& lhs,
+ fields_alloc<U> const& rhs)
+ {
+ return ! (lhs == rhs);
+ }
+};
+
+#endif
diff --git a/src/boost/libs/beast/example/http/server/fast/http_server_fast.cpp b/src/boost/libs/beast/example/http/server/fast/http_server_fast.cpp
new file mode 100644
index 000000000..66c27cade
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/fast/http_server_fast.cpp
@@ -0,0 +1,352 @@
+//
+// Copyright (c) 2017 Christopher M. Kohlhoff (chris at kohlhoff 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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: HTTP server, fast
+//
+//------------------------------------------------------------------------------
+
+#include "fields_alloc.hpp"
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/http.hpp>
+#include <boost/beast/version.hpp>
+#include <boost/asio.hpp>
+#include <chrono>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <list>
+#include <memory>
+#include <string>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+// Return a reasonable mime type based on the extension of a file.
+beast::string_view
+mime_type(beast::string_view path)
+{
+ using beast::iequals;
+ auto const ext = [&path]
+ {
+ auto const pos = path.rfind(".");
+ if(pos == beast::string_view::npos)
+ return beast::string_view{};
+ return path.substr(pos);
+ }();
+ if(iequals(ext, ".htm")) return "text/html";
+ if(iequals(ext, ".html")) return "text/html";
+ if(iequals(ext, ".php")) return "text/html";
+ if(iequals(ext, ".css")) return "text/css";
+ if(iequals(ext, ".txt")) return "text/plain";
+ if(iequals(ext, ".js")) return "application/javascript";
+ if(iequals(ext, ".json")) return "application/json";
+ if(iequals(ext, ".xml")) return "application/xml";
+ if(iequals(ext, ".swf")) return "application/x-shockwave-flash";
+ if(iequals(ext, ".flv")) return "video/x-flv";
+ if(iequals(ext, ".png")) return "image/png";
+ if(iequals(ext, ".jpe")) return "image/jpeg";
+ if(iequals(ext, ".jpeg")) return "image/jpeg";
+ if(iequals(ext, ".jpg")) return "image/jpeg";
+ if(iequals(ext, ".gif")) return "image/gif";
+ if(iequals(ext, ".bmp")) return "image/bmp";
+ if(iequals(ext, ".ico")) return "image/vnd.microsoft.icon";
+ if(iequals(ext, ".tiff")) return "image/tiff";
+ if(iequals(ext, ".tif")) return "image/tiff";
+ if(iequals(ext, ".svg")) return "image/svg+xml";
+ if(iequals(ext, ".svgz")) return "image/svg+xml";
+ return "application/text";
+}
+
+class http_worker
+{
+public:
+ http_worker(http_worker const&) = delete;
+ http_worker& operator=(http_worker const&) = delete;
+
+ http_worker(tcp::acceptor& acceptor, const std::string& doc_root) :
+ acceptor_(acceptor),
+ doc_root_(doc_root)
+ {
+ }
+
+ void start()
+ {
+ accept();
+ check_deadline();
+ }
+
+private:
+ using alloc_t = fields_alloc<char>;
+ //using request_body_t = http::basic_dynamic_body<beast::flat_static_buffer<1024 * 1024>>;
+ using request_body_t = http::string_body;
+
+ // The acceptor used to listen for incoming connections.
+ tcp::acceptor& acceptor_;
+
+ // The path to the root of the document directory.
+ std::string doc_root_;
+
+ // The socket for the currently connected client.
+ tcp::socket socket_{acceptor_.get_executor()};
+
+ // The buffer for performing reads
+ beast::flat_static_buffer<8192> buffer_;
+
+ // The allocator used for the fields in the request and reply.
+ alloc_t alloc_{8192};
+
+ // The parser for reading the requests
+ boost::optional<http::request_parser<request_body_t, alloc_t>> parser_;
+
+ // The timer putting a time limit on requests.
+ net::steady_timer request_deadline_{
+ acceptor_.get_executor(), (std::chrono::steady_clock::time_point::max)()};
+
+ // The string-based response message.
+ boost::optional<http::response<http::string_body, http::basic_fields<alloc_t>>> string_response_;
+
+ // The string-based response serializer.
+ boost::optional<http::response_serializer<http::string_body, http::basic_fields<alloc_t>>> string_serializer_;
+
+ // The file-based response message.
+ boost::optional<http::response<http::file_body, http::basic_fields<alloc_t>>> file_response_;
+
+ // The file-based response serializer.
+ boost::optional<http::response_serializer<http::file_body, http::basic_fields<alloc_t>>> file_serializer_;
+
+ void accept()
+ {
+ // Clean up any previous connection.
+ beast::error_code ec;
+ socket_.close(ec);
+ buffer_.consume(buffer_.size());
+
+ acceptor_.async_accept(
+ socket_,
+ [this](beast::error_code ec)
+ {
+ if (ec)
+ {
+ accept();
+ }
+ else
+ {
+ // Request must be fully processed within 60 seconds.
+ request_deadline_.expires_after(
+ std::chrono::seconds(60));
+
+ read_request();
+ }
+ });
+ }
+
+ void read_request()
+ {
+ // On each read the parser needs to be destroyed and
+ // recreated. We store it in a boost::optional to
+ // achieve that.
+ //
+ // Arguments passed to the parser constructor are
+ // forwarded to the message object. A single argument
+ // is forwarded to the body constructor.
+ //
+ // We construct the dynamic body with a 1MB limit
+ // to prevent vulnerability to buffer attacks.
+ //
+ parser_.emplace(
+ std::piecewise_construct,
+ std::make_tuple(),
+ std::make_tuple(alloc_));
+
+ http::async_read(
+ socket_,
+ buffer_,
+ *parser_,
+ [this](beast::error_code ec, std::size_t)
+ {
+ if (ec)
+ accept();
+ else
+ process_request(parser_->get());
+ });
+ }
+
+ void process_request(http::request<request_body_t, http::basic_fields<alloc_t>> const& req)
+ {
+ switch (req.method())
+ {
+ case http::verb::get:
+ send_file(req.target());
+ break;
+
+ default:
+ // We return responses indicating an error if
+ // we do not recognize the request method.
+ send_bad_response(
+ http::status::bad_request,
+ "Invalid request-method '" + std::string(req.method_string()) + "'\r\n");
+ break;
+ }
+ }
+
+ void send_bad_response(
+ http::status status,
+ std::string const& error)
+ {
+ string_response_.emplace(
+ std::piecewise_construct,
+ std::make_tuple(),
+ std::make_tuple(alloc_));
+
+ string_response_->result(status);
+ string_response_->keep_alive(false);
+ string_response_->set(http::field::server, "Beast");
+ string_response_->set(http::field::content_type, "text/plain");
+ string_response_->body() = error;
+ string_response_->prepare_payload();
+
+ string_serializer_.emplace(*string_response_);
+
+ http::async_write(
+ socket_,
+ *string_serializer_,
+ [this](beast::error_code ec, std::size_t)
+ {
+ socket_.shutdown(tcp::socket::shutdown_send, ec);
+ string_serializer_.reset();
+ string_response_.reset();
+ accept();
+ });
+ }
+
+ void send_file(beast::string_view target)
+ {
+ // Request path must be absolute and not contain "..".
+ if (target.empty() || target[0] != '/' || target.find("..") != std::string::npos)
+ {
+ send_bad_response(
+ http::status::not_found,
+ "File not found\r\n");
+ return;
+ }
+
+ std::string full_path = doc_root_;
+ full_path.append(
+ target.data(),
+ target.size());
+
+ http::file_body::value_type file;
+ beast::error_code ec;
+ file.open(
+ full_path.c_str(),
+ beast::file_mode::read,
+ ec);
+ if(ec)
+ {
+ send_bad_response(
+ http::status::not_found,
+ "File not found\r\n");
+ return;
+ }
+
+ file_response_.emplace(
+ std::piecewise_construct,
+ std::make_tuple(),
+ std::make_tuple(alloc_));
+
+ file_response_->result(http::status::ok);
+ file_response_->keep_alive(false);
+ file_response_->set(http::field::server, "Beast");
+ file_response_->set(http::field::content_type, mime_type(std::string(target)));
+ file_response_->body() = std::move(file);
+ file_response_->prepare_payload();
+
+ file_serializer_.emplace(*file_response_);
+
+ http::async_write(
+ socket_,
+ *file_serializer_,
+ [this](beast::error_code ec, std::size_t)
+ {
+ socket_.shutdown(tcp::socket::shutdown_send, ec);
+ file_serializer_.reset();
+ file_response_.reset();
+ accept();
+ });
+ }
+
+ void check_deadline()
+ {
+ // The deadline may have moved, so check it has really passed.
+ if (request_deadline_.expiry() <= std::chrono::steady_clock::now())
+ {
+ // Close socket to cancel any outstanding operation.
+ beast::error_code ec;
+ socket_.close();
+
+ // Sleep indefinitely until we're given a new deadline.
+ request_deadline_.expires_at(
+ std::chrono::steady_clock::time_point::max());
+ }
+
+ request_deadline_.async_wait(
+ [this](beast::error_code)
+ {
+ check_deadline();
+ });
+ }
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ // Check command line arguments.
+ if (argc != 6)
+ {
+ std::cerr << "Usage: http_server_fast <address> <port> <doc_root> <num_workers> {spin|block}\n";
+ std::cerr << " For IPv4, try:\n";
+ std::cerr << " http_server_fast 0.0.0.0 80 . 100 block\n";
+ std::cerr << " For IPv6, try:\n";
+ std::cerr << " http_server_fast 0::0 80 . 100 block\n";
+ return EXIT_FAILURE;
+ }
+
+ auto const address = net::ip::make_address(argv[1]);
+ unsigned short port = static_cast<unsigned short>(std::atoi(argv[2]));
+ std::string doc_root = argv[3];
+ int num_workers = std::atoi(argv[4]);
+ bool spin = (std::strcmp(argv[5], "spin") == 0);
+
+ net::io_context ioc{1};
+ tcp::acceptor acceptor{ioc, {address, port}};
+
+ std::list<http_worker> workers;
+ for (int i = 0; i < num_workers; ++i)
+ {
+ workers.emplace_back(acceptor, doc_root);
+ workers.back().start();
+ }
+
+ if (spin)
+ for (;;) ioc.poll();
+ else
+ ioc.run();
+ }
+ catch (const std::exception& e)
+ {
+ std::cerr << "Error: " << e.what() << std::endl;
+ return EXIT_FAILURE;
+ }
+}
diff --git a/src/boost/libs/beast/example/http/server/flex/CMakeLists.txt b/src/boost/libs/beast/example/http/server/flex/CMakeLists.txt
new file mode 100644
index 000000000..0920953b3
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/flex/CMakeLists.txt
@@ -0,0 +1,31 @@
+#
+# 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
+#
+
+if (OPENSSL_FOUND)
+ GroupSources(include/boost/beast beast)
+ GroupSources(example/common common)
+ GroupSources(example/http/server/flex "/")
+
+ add_executable (http-server-flex
+ ${BOOST_BEAST_FILES}
+ ${PROJECT_SOURCE_DIR}/example/common/server_certificate.hpp
+ Jamfile
+ http_server_flex.cpp
+ )
+
+ set_property(TARGET http-server-flex PROPERTY FOLDER "example-http-server")
+
+ target_link_libraries (http-server-flex
+ OpenSSL::SSL OpenSSL::Crypto
+ lib-asio
+ lib-asio-ssl
+ lib-beast
+ )
+
+endif()
diff --git a/src/boost/libs/beast/example/http/server/flex/Jamfile b/src/boost/libs/beast/example/http/server/flex/Jamfile
new file mode 100644
index 000000000..f094caa27
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/flex/Jamfile
@@ -0,0 +1,22 @@
+#
+# 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
+#
+
+import ac ;
+
+project
+ : requirements
+ [ ac.check-library /boost/beast//lib-asio-ssl : <library>/boost/beast//lib-asio-ssl/<link>static : <build>no ]
+ ;
+
+exe http-server-flex :
+ http_server_flex.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ ;
diff --git a/src/boost/libs/beast/example/http/server/flex/http_server_flex.cpp b/src/boost/libs/beast/example/http/server/flex/http_server_flex.cpp
new file mode 100644
index 000000000..dd4b4ccd0
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/flex/http_server_flex.cpp
@@ -0,0 +1,712 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: HTTP flex server (plain and SSL), asynchronous
+//
+//------------------------------------------------------------------------------
+
+#include "example/common/server_certificate.hpp"
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/http.hpp>
+#include <boost/beast/ssl.hpp>
+#include <boost/beast/version.hpp>
+#include <boost/asio/dispatch.hpp>
+#include <boost/asio/strand.hpp>
+#include <boost/config.hpp>
+#include <algorithm>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <thread>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+// Return a reasonable mime type based on the extension of a file.
+beast::string_view
+mime_type(beast::string_view path)
+{
+ using beast::iequals;
+ auto const ext = [&path]
+ {
+ auto const pos = path.rfind(".");
+ if(pos == beast::string_view::npos)
+ return beast::string_view{};
+ return path.substr(pos);
+ }();
+ if(iequals(ext, ".htm")) return "text/html";
+ if(iequals(ext, ".html")) return "text/html";
+ if(iequals(ext, ".php")) return "text/html";
+ if(iequals(ext, ".css")) return "text/css";
+ if(iequals(ext, ".txt")) return "text/plain";
+ if(iequals(ext, ".js")) return "application/javascript";
+ if(iequals(ext, ".json")) return "application/json";
+ if(iequals(ext, ".xml")) return "application/xml";
+ if(iequals(ext, ".swf")) return "application/x-shockwave-flash";
+ if(iequals(ext, ".flv")) return "video/x-flv";
+ if(iequals(ext, ".png")) return "image/png";
+ if(iequals(ext, ".jpe")) return "image/jpeg";
+ if(iequals(ext, ".jpeg")) return "image/jpeg";
+ if(iequals(ext, ".jpg")) return "image/jpeg";
+ if(iequals(ext, ".gif")) return "image/gif";
+ if(iequals(ext, ".bmp")) return "image/bmp";
+ if(iequals(ext, ".ico")) return "image/vnd.microsoft.icon";
+ if(iequals(ext, ".tiff")) return "image/tiff";
+ if(iequals(ext, ".tif")) return "image/tiff";
+ if(iequals(ext, ".svg")) return "image/svg+xml";
+ if(iequals(ext, ".svgz")) return "image/svg+xml";
+ return "application/text";
+}
+
+// Append an HTTP rel-path to a local filesystem path.
+// The returned path is normalized for the platform.
+std::string
+path_cat(
+ beast::string_view base,
+ beast::string_view path)
+{
+ if(base.empty())
+ return std::string(path);
+ std::string result(base);
+#ifdef BOOST_MSVC
+ char constexpr path_separator = '\\';
+ if(result.back() == path_separator)
+ result.resize(result.size() - 1);
+ result.append(path.data(), path.size());
+ for(auto& c : result)
+ if(c == '/')
+ c = path_separator;
+#else
+ char constexpr path_separator = '/';
+ if(result.back() == path_separator)
+ result.resize(result.size() - 1);
+ result.append(path.data(), path.size());
+#endif
+ return result;
+}
+
+// This function produces an HTTP response for the given
+// request. The type of the response object depends on the
+// contents of the request, so the interface requires the
+// caller to pass a generic lambda for receiving the response.
+template<
+ class Body, class Allocator,
+ class Send>
+void
+handle_request(
+ beast::string_view doc_root,
+ http::request<Body, http::basic_fields<Allocator>>&& req,
+ Send&& send)
+{
+ // Returns a bad request response
+ auto const bad_request =
+ [&req](beast::string_view why)
+ {
+ http::response<http::string_body> res{http::status::bad_request, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = std::string(why);
+ res.prepare_payload();
+ return res;
+ };
+
+ // Returns a not found response
+ auto const not_found =
+ [&req](beast::string_view target)
+ {
+ http::response<http::string_body> res{http::status::not_found, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = "The resource '" + std::string(target) + "' was not found.";
+ res.prepare_payload();
+ return res;
+ };
+
+ // Returns a server error response
+ auto const server_error =
+ [&req](beast::string_view what)
+ {
+ http::response<http::string_body> res{http::status::internal_server_error, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = "An error occurred: '" + std::string(what) + "'";
+ res.prepare_payload();
+ return res;
+ };
+
+ // Make sure we can handle the method
+ if( req.method() != http::verb::get &&
+ req.method() != http::verb::head)
+ return send(bad_request("Unknown HTTP-method"));
+
+ // Request path must be absolute and not contain "..".
+ if( req.target().empty() ||
+ req.target()[0] != '/' ||
+ req.target().find("..") != beast::string_view::npos)
+ return send(bad_request("Illegal request-target"));
+
+ // Build the path to the requested file
+ std::string path = path_cat(doc_root, req.target());
+ if(req.target().back() == '/')
+ path.append("index.html");
+
+ // Attempt to open the file
+ beast::error_code ec;
+ http::file_body::value_type body;
+ body.open(path.c_str(), beast::file_mode::scan, ec);
+
+ // Handle the case where the file doesn't exist
+ if(ec == beast::errc::no_such_file_or_directory)
+ return send(not_found(req.target()));
+
+ // Handle an unknown error
+ if(ec)
+ return send(server_error(ec.message()));
+
+ // Cache the size since we need it after the move
+ auto const size = body.size();
+
+ // Respond to HEAD request
+ if(req.method() == http::verb::head)
+ {
+ http::response<http::empty_body> res{http::status::ok, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, mime_type(path));
+ res.content_length(size);
+ res.keep_alive(req.keep_alive());
+ return send(std::move(res));
+ }
+
+ // Respond to GET request
+ http::response<http::file_body> res{
+ std::piecewise_construct,
+ std::make_tuple(std::move(body)),
+ std::make_tuple(http::status::ok, req.version())};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, mime_type(path));
+ res.content_length(size);
+ res.keep_alive(req.keep_alive());
+ return send(std::move(res));
+}
+
+//------------------------------------------------------------------------------
+
+// Report a failure
+void
+fail(beast::error_code ec, char const* what)
+{
+ // ssl::error::stream_truncated, also known as an SSL "short read",
+ // indicates the peer closed the connection without performing the
+ // required closing handshake (for example, Google does this to
+ // improve performance). Generally this can be a security issue,
+ // but if your communication protocol is self-terminated (as
+ // it is with both HTTP and WebSocket) then you may simply
+ // ignore the lack of close_notify.
+ //
+ // https://github.com/boostorg/beast/issues/38
+ //
+ // https://security.stackexchange.com/questions/91435/how-to-handle-a-malicious-ssl-tls-shutdown
+ //
+ // When a short read would cut off the end of an HTTP message,
+ // Beast returns the error beast::http::error::partial_message.
+ // Therefore, if we see a short read here, it has occurred
+ // after the message has been completed, so it is safe to ignore it.
+
+ if(ec == net::ssl::error::stream_truncated)
+ return;
+
+ std::cerr << what << ": " << ec.message() << "\n";
+}
+
+// Handles an HTTP server connection.
+// This uses the Curiously Recurring Template Pattern so that
+// the same code works with both SSL streams and regular sockets.
+template<class Derived>
+class session
+{
+ // Access the derived class, this is part of
+ // the Curiously Recurring Template Pattern idiom.
+ Derived&
+ derived()
+ {
+ return static_cast<Derived&>(*this);
+ }
+
+ // This is the C++11 equivalent of a generic lambda.
+ // The function object is used to send an HTTP message.
+ struct send_lambda
+ {
+ session& self_;
+
+ explicit
+ send_lambda(session& self)
+ : self_(self)
+ {
+ }
+
+ template<bool isRequest, class Body, class Fields>
+ void
+ operator()(http::message<isRequest, Body, Fields>&& msg) const
+ {
+ // The lifetime of the message has to extend
+ // for the duration of the async operation so
+ // we use a shared_ptr to manage it.
+ auto sp = std::make_shared<
+ http::message<isRequest, Body, Fields>>(std::move(msg));
+
+ // Store a type-erased version of the shared
+ // pointer in the class to keep it alive.
+ self_.res_ = sp;
+
+ // Write the response
+ http::async_write(
+ self_.derived().stream(),
+ *sp,
+ beast::bind_front_handler(
+ &session::on_write,
+ self_.derived().shared_from_this(),
+ sp->need_eof()));
+ }
+ };
+
+ std::shared_ptr<std::string const> doc_root_;
+ http::request<http::string_body> req_;
+ std::shared_ptr<void> res_;
+ send_lambda lambda_;
+
+protected:
+ beast::flat_buffer buffer_;
+
+public:
+ // Take ownership of the buffer
+ session(
+ beast::flat_buffer buffer,
+ std::shared_ptr<std::string const> const& doc_root)
+ : doc_root_(doc_root)
+ , lambda_(*this)
+ , buffer_(std::move(buffer))
+ {
+ }
+
+ void
+ do_read()
+ {
+ // Set the timeout.
+ beast::get_lowest_layer(
+ derived().stream()).expires_after(std::chrono::seconds(30));
+
+ // Read a request
+ http::async_read(
+ derived().stream(),
+ buffer_,
+ req_,
+ beast::bind_front_handler(
+ &session::on_read,
+ derived().shared_from_this()));
+ }
+
+ void
+ on_read(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ // This means they closed the connection
+ if(ec == http::error::end_of_stream)
+ return derived().do_eof();
+
+ if(ec)
+ return fail(ec, "read");
+
+ // Send the response
+ handle_request(*doc_root_, std::move(req_), lambda_);
+ }
+
+ void
+ on_write(
+ bool close,
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ if(ec)
+ return fail(ec, "write");
+
+ if(close)
+ {
+ // This means we should close the connection, usually because
+ // the response indicated the "Connection: close" semantic.
+ return derived().do_eof();
+ }
+
+ // We're done with the response so delete it
+ res_ = nullptr;
+
+ // Read another request
+ do_read();
+ }
+};
+
+// Handles a plain HTTP connection
+class plain_session
+ : public session<plain_session>
+ , public std::enable_shared_from_this<plain_session>
+{
+ beast::tcp_stream stream_;
+
+public:
+ // Create the session
+ plain_session(
+ tcp::socket&& socket,
+ beast::flat_buffer buffer,
+ std::shared_ptr<std::string const> const& doc_root)
+ : session<plain_session>(
+ std::move(buffer),
+ doc_root)
+ , stream_(std::move(socket))
+ {
+ }
+
+ // Called by the base class
+ beast::tcp_stream&
+ stream()
+ {
+ return stream_;
+ }
+
+ // Start the asynchronous operation
+ void
+ run()
+ {
+ // We need to be executing within a strand to perform async operations
+ // on the I/O objects in this session. Although not strictly necessary
+ // for single-threaded contexts, this example code is written to be
+ // thread-safe by default.
+ net::dispatch(stream_.get_executor(),
+ beast::bind_front_handler(
+ &session::do_read,
+ shared_from_this()));
+ }
+
+ void
+ do_eof()
+ {
+ // Send a TCP shutdown
+ beast::error_code ec;
+ stream_.socket().shutdown(tcp::socket::shutdown_send, ec);
+
+ // At this point the connection is closed gracefully
+ }
+};
+
+// Handles an SSL HTTP connection
+class ssl_session
+ : public session<ssl_session>
+ , public std::enable_shared_from_this<ssl_session>
+{
+ beast::ssl_stream<beast::tcp_stream> stream_;
+
+public:
+ // Create the session
+ ssl_session(
+ tcp::socket&& socket,
+ ssl::context& ctx,
+ beast::flat_buffer buffer,
+ std::shared_ptr<std::string const> const& doc_root)
+ : session<ssl_session>(
+ std::move(buffer),
+ doc_root)
+ , stream_(std::move(socket), ctx)
+ {
+ }
+
+ // Called by the base class
+ beast::ssl_stream<beast::tcp_stream>&
+ stream()
+ {
+ return stream_;
+ }
+
+ // Start the asynchronous operation
+ void
+ run()
+ {
+ auto self = shared_from_this();
+ // We need to be executing within a strand to perform async operations
+ // on the I/O objects in this session.
+ net::dispatch(stream_.get_executor(), [self]() {
+ // Set the timeout.
+ beast::get_lowest_layer(self->stream_).expires_after(
+ std::chrono::seconds(30));
+
+ // Perform the SSL handshake
+ // Note, this is the buffered version of the handshake.
+ self->stream_.async_handshake(
+ ssl::stream_base::server,
+ self->buffer_.data(),
+ beast::bind_front_handler(
+ &ssl_session::on_handshake,
+ self));
+ });
+ }
+
+ void
+ on_handshake(
+ beast::error_code ec,
+ std::size_t bytes_used)
+ {
+ if(ec)
+ return fail(ec, "handshake");
+
+ // Consume the portion of the buffer used by the handshake
+ buffer_.consume(bytes_used);
+
+ do_read();
+ }
+
+ void
+ do_eof()
+ {
+ // Set the timeout.
+ beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30));
+
+ // Perform the SSL shutdown
+ stream_.async_shutdown(
+ beast::bind_front_handler(
+ &ssl_session::on_shutdown,
+ shared_from_this()));
+ }
+
+ void
+ on_shutdown(beast::error_code ec)
+ {
+ if(ec)
+ return fail(ec, "shutdown");
+
+ // At this point the connection is closed gracefully
+ }
+};
+
+//------------------------------------------------------------------------------
+
+// Detects SSL handshakes
+class detect_session : public std::enable_shared_from_this<detect_session>
+{
+ beast::tcp_stream stream_;
+ ssl::context& ctx_;
+ std::shared_ptr<std::string const> doc_root_;
+ beast::flat_buffer buffer_;
+
+public:
+ detect_session(
+ tcp::socket&& socket,
+ ssl::context& ctx,
+ std::shared_ptr<std::string const> const& doc_root)
+ : stream_(std::move(socket))
+ , ctx_(ctx)
+ , doc_root_(doc_root)
+ {
+ }
+
+ // Launch the detector
+ void
+ run()
+ {
+ // Set the timeout.
+ beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30));
+
+ // Detect a TLS handshake
+ async_detect_ssl(
+ stream_,
+ buffer_,
+ beast::bind_front_handler(
+ &detect_session::on_detect,
+ shared_from_this()));
+ }
+
+ void
+ on_detect(beast::error_code ec, bool result)
+ {
+ if(ec)
+ return fail(ec, "detect");
+
+ if(result)
+ {
+ // Launch SSL session
+ std::make_shared<ssl_session>(
+ stream_.release_socket(),
+ ctx_,
+ std::move(buffer_),
+ doc_root_)->run();
+ return;
+ }
+
+ // Launch plain session
+ std::make_shared<plain_session>(
+ stream_.release_socket(),
+ std::move(buffer_),
+ doc_root_)->run();
+ }
+};
+
+// Accepts incoming connections and launches the sessions
+class listener : public std::enable_shared_from_this<listener>
+{
+ net::io_context& ioc_;
+ ssl::context& ctx_;
+ tcp::acceptor acceptor_;
+ std::shared_ptr<std::string const> doc_root_;
+
+public:
+ listener(
+ net::io_context& ioc,
+ ssl::context& ctx,
+ tcp::endpoint endpoint,
+ std::shared_ptr<std::string const> const& doc_root)
+ : ioc_(ioc)
+ , ctx_(ctx)
+ , acceptor_(net::make_strand(ioc))
+ , doc_root_(doc_root)
+ {
+ beast::error_code ec;
+
+ // Open the acceptor
+ acceptor_.open(endpoint.protocol(), ec);
+ if(ec)
+ {
+ fail(ec, "open");
+ return;
+ }
+
+ // Allow address reuse
+ acceptor_.set_option(net::socket_base::reuse_address(true), ec);
+ if(ec)
+ {
+ fail(ec, "set_option");
+ return;
+ }
+
+ // Bind to the server address
+ acceptor_.bind(endpoint, ec);
+ if(ec)
+ {
+ fail(ec, "bind");
+ return;
+ }
+
+ // Start listening for connections
+ acceptor_.listen(
+ net::socket_base::max_listen_connections, ec);
+ if(ec)
+ {
+ fail(ec, "listen");
+ return;
+ }
+ }
+
+ // Start accepting incoming connections
+ void
+ run()
+ {
+ do_accept();
+ }
+
+private:
+ void
+ do_accept()
+ {
+ // The new connection gets its own strand
+ acceptor_.async_accept(
+ net::make_strand(ioc_),
+ beast::bind_front_handler(
+ &listener::on_accept,
+ shared_from_this()));
+ }
+
+ void
+ on_accept(beast::error_code ec, tcp::socket socket)
+ {
+ if(ec)
+ {
+ fail(ec, "accept");
+ }
+ else
+ {
+ // Create the detector session and run it
+ std::make_shared<detect_session>(
+ std::move(socket),
+ ctx_,
+ doc_root_)->run();
+ }
+
+ // Accept another connection
+ do_accept();
+ }
+};
+
+//------------------------------------------------------------------------------
+
+int main(int argc, char* argv[])
+{
+ // Check command line arguments.
+ if (argc != 5)
+ {
+ std::cerr <<
+ "Usage: http-server-flex <address> <port> <doc_root> <threads>\n" <<
+ "Example:\n" <<
+ " http-server-flex 0.0.0.0 8080 .\n";
+ return EXIT_FAILURE;
+ }
+ auto const address = net::ip::make_address(argv[1]);
+ auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
+ auto const doc_root = std::make_shared<std::string>(argv[3]);
+ auto const threads = std::max<int>(1, std::atoi(argv[4]));
+
+ // The io_context is required for all I/O
+ net::io_context ioc{threads};
+
+ // The SSL context is required, and holds certificates
+ ssl::context ctx{ssl::context::tlsv12};
+
+ // This holds the self-signed certificate used by the server
+ load_server_certificate(ctx);
+
+ // Create and launch a listening port
+ std::make_shared<listener>(
+ ioc,
+ ctx,
+ tcp::endpoint{address, port},
+ doc_root)->run();
+
+ // Run the I/O service on the requested number of threads
+ std::vector<std::thread> v;
+ v.reserve(threads - 1);
+ for(auto i = threads - 1; i > 0; --i)
+ v.emplace_back(
+ [&ioc]
+ {
+ ioc.run();
+ });
+ ioc.run();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/http/server/small/CMakeLists.txt b/src/boost/libs/beast/example/http/server/small/CMakeLists.txt
new file mode 100644
index 000000000..c443dec5c
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/small/CMakeLists.txt
@@ -0,0 +1,23 @@
+#
+# 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
+#
+
+GroupSources(include/boost/beast beast)
+GroupSources(example/http/server/small "/")
+
+add_executable (http-server-small
+ ${BOOST_BEAST_FILES}
+ Jamfile
+ http_server_small.cpp
+)
+
+target_link_libraries(http-server-small
+ lib-asio
+ lib-beast)
+
+set_property(TARGET http-server-small PROPERTY FOLDER "example-http-server")
diff --git a/src/boost/libs/beast/example/http/server/small/Jamfile b/src/boost/libs/beast/example/http/server/small/Jamfile
new file mode 100644
index 000000000..48e9fd138
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/small/Jamfile
@@ -0,0 +1,15 @@
+#
+# 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
+#
+
+exe http-server-small :
+ http_server_small.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ ;
diff --git a/src/boost/libs/beast/example/http/server/small/http_server_small.cpp b/src/boost/libs/beast/example/http/server/small/http_server_small.cpp
new file mode 100644
index 000000000..53b6a2b3e
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/small/http_server_small.cpp
@@ -0,0 +1,251 @@
+//
+// Copyright (c) 2017 Christopher M. Kohlhoff (chris at kohlhoff 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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: HTTP server, small
+//
+//------------------------------------------------------------------------------
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/http.hpp>
+#include <boost/beast/version.hpp>
+#include <boost/asio.hpp>
+#include <chrono>
+#include <cstdlib>
+#include <ctime>
+#include <iostream>
+#include <memory>
+#include <string>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+namespace my_program_state
+{
+ std::size_t
+ request_count()
+ {
+ static std::size_t count = 0;
+ return ++count;
+ }
+
+ std::time_t
+ now()
+ {
+ return std::time(0);
+ }
+}
+
+class http_connection : public std::enable_shared_from_this<http_connection>
+{
+public:
+ http_connection(tcp::socket socket)
+ : socket_(std::move(socket))
+ {
+ }
+
+ // Initiate the asynchronous operations associated with the connection.
+ void
+ start()
+ {
+ read_request();
+ check_deadline();
+ }
+
+private:
+ // The socket for the currently connected client.
+ tcp::socket socket_;
+
+ // The buffer for performing reads.
+ beast::flat_buffer buffer_{8192};
+
+ // The request message.
+ http::request<http::dynamic_body> request_;
+
+ // The response message.
+ http::response<http::dynamic_body> response_;
+
+ // The timer for putting a deadline on connection processing.
+ net::steady_timer deadline_{
+ socket_.get_executor(), std::chrono::seconds(60)};
+
+ // Asynchronously receive a complete request message.
+ void
+ read_request()
+ {
+ auto self = shared_from_this();
+
+ http::async_read(
+ socket_,
+ buffer_,
+ request_,
+ [self](beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+ if(!ec)
+ self->process_request();
+ });
+ }
+
+ // Determine what needs to be done with the request message.
+ void
+ process_request()
+ {
+ response_.version(request_.version());
+ response_.keep_alive(false);
+
+ switch(request_.method())
+ {
+ case http::verb::get:
+ response_.result(http::status::ok);
+ response_.set(http::field::server, "Beast");
+ create_response();
+ break;
+
+ default:
+ // We return responses indicating an error if
+ // we do not recognize the request method.
+ response_.result(http::status::bad_request);
+ response_.set(http::field::content_type, "text/plain");
+ beast::ostream(response_.body())
+ << "Invalid request-method '"
+ << std::string(request_.method_string())
+ << "'";
+ break;
+ }
+
+ write_response();
+ }
+
+ // Construct a response message based on the program state.
+ void
+ create_response()
+ {
+ if(request_.target() == "/count")
+ {
+ response_.set(http::field::content_type, "text/html");
+ beast::ostream(response_.body())
+ << "<html>\n"
+ << "<head><title>Request count</title></head>\n"
+ << "<body>\n"
+ << "<h1>Request count</h1>\n"
+ << "<p>There have been "
+ << my_program_state::request_count()
+ << " requests so far.</p>\n"
+ << "</body>\n"
+ << "</html>\n";
+ }
+ else if(request_.target() == "/time")
+ {
+ response_.set(http::field::content_type, "text/html");
+ beast::ostream(response_.body())
+ << "<html>\n"
+ << "<head><title>Current time</title></head>\n"
+ << "<body>\n"
+ << "<h1>Current time</h1>\n"
+ << "<p>The current time is "
+ << my_program_state::now()
+ << " seconds since the epoch.</p>\n"
+ << "</body>\n"
+ << "</html>\n";
+ }
+ else
+ {
+ response_.result(http::status::not_found);
+ response_.set(http::field::content_type, "text/plain");
+ beast::ostream(response_.body()) << "File not found\r\n";
+ }
+ }
+
+ // Asynchronously transmit the response message.
+ void
+ write_response()
+ {
+ auto self = shared_from_this();
+
+ response_.set(http::field::content_length, response_.body().size());
+
+ http::async_write(
+ socket_,
+ response_,
+ [self](beast::error_code ec, std::size_t)
+ {
+ self->socket_.shutdown(tcp::socket::shutdown_send, ec);
+ self->deadline_.cancel();
+ });
+ }
+
+ // Check whether we have spent enough time on this connection.
+ void
+ check_deadline()
+ {
+ auto self = shared_from_this();
+
+ deadline_.async_wait(
+ [self](beast::error_code ec)
+ {
+ if(!ec)
+ {
+ // Close socket to cancel any outstanding operation.
+ self->socket_.close(ec);
+ }
+ });
+ }
+};
+
+// "Loop" forever accepting new connections.
+void
+http_server(tcp::acceptor& acceptor, tcp::socket& socket)
+{
+ acceptor.async_accept(socket,
+ [&](beast::error_code ec)
+ {
+ if(!ec)
+ std::make_shared<http_connection>(std::move(socket))->start();
+ http_server(acceptor, socket);
+ });
+}
+
+int
+main(int argc, char* argv[])
+{
+ try
+ {
+ // Check command line arguments.
+ if(argc != 3)
+ {
+ std::cerr << "Usage: " << argv[0] << " <address> <port>\n";
+ std::cerr << " For IPv4, try:\n";
+ std::cerr << " receiver 0.0.0.0 80\n";
+ std::cerr << " For IPv6, try:\n";
+ std::cerr << " receiver 0::0 80\n";
+ return EXIT_FAILURE;
+ }
+
+ auto const address = net::ip::make_address(argv[1]);
+ unsigned short port = static_cast<unsigned short>(std::atoi(argv[2]));
+
+ net::io_context ioc{1};
+
+ tcp::acceptor acceptor{ioc, {address, port}};
+ tcp::socket socket{ioc};
+ http_server(acceptor, socket);
+
+ ioc.run();
+ }
+ catch(std::exception const& e)
+ {
+ std::cerr << "Error: " << e.what() << std::endl;
+ return EXIT_FAILURE;
+ }
+}
diff --git a/src/boost/libs/beast/example/http/server/stackless-ssl/CMakeLists.txt b/src/boost/libs/beast/example/http/server/stackless-ssl/CMakeLists.txt
new file mode 100644
index 000000000..f25b9b3d6
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/stackless-ssl/CMakeLists.txt
@@ -0,0 +1,31 @@
+#
+# 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
+#
+
+if (OPENSSL_FOUND)
+ GroupSources(include/boost/beast beast)
+ GroupSources(example/common common)
+ GroupSources(example/http/server/stackless-ssl "/")
+
+ add_executable (http-server-stackless-ssl
+ ${BOOST_BEAST_FILES}
+ ${PROJECT_SOURCE_DIR}/example/common/server_certificate.hpp
+ Jamfile
+ http_server_stackless_ssl.cpp
+ )
+
+ set_property(TARGET http-server-stackless-ssl PROPERTY FOLDER "example-http-server")
+
+ target_link_libraries (http-server-stackless-ssl
+ OpenSSL::SSL OpenSSL::Crypto
+ lib-asio
+ lib-asio-ssl
+ lib-beast
+ )
+
+endif()
diff --git a/src/boost/libs/beast/example/http/server/stackless-ssl/Jamfile b/src/boost/libs/beast/example/http/server/stackless-ssl/Jamfile
new file mode 100644
index 000000000..b47524646
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/stackless-ssl/Jamfile
@@ -0,0 +1,22 @@
+#
+# 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
+#
+
+import ac ;
+
+project
+ : requirements
+ [ ac.check-library /boost/beast//lib-asio-ssl : <library>/boost/beast//lib-asio-ssl/<link>static : <build>no ]
+ ;
+
+exe http-server-stackless-ssl :
+ http_server_stackless_ssl.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ ;
diff --git a/src/boost/libs/beast/example/http/server/stackless-ssl/http_server_stackless_ssl.cpp b/src/boost/libs/beast/example/http/server/stackless-ssl/http_server_stackless_ssl.cpp
new file mode 100644
index 000000000..7786cbb42
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/stackless-ssl/http_server_stackless_ssl.cpp
@@ -0,0 +1,560 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: HTTP SSL server, stackless coroutine
+//
+//------------------------------------------------------------------------------
+
+#include "example/common/server_certificate.hpp"
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/http.hpp>
+#include <boost/beast/ssl.hpp>
+#include <boost/beast/version.hpp>
+#include <boost/asio/coroutine.hpp>
+#include <boost/asio/dispatch.hpp>
+#include <boost/asio/strand.hpp>
+#include <boost/config.hpp>
+#include <algorithm>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <thread>
+#include <vector>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+// Return a reasonable mime type based on the extension of a file.
+beast::string_view
+mime_type(beast::string_view path)
+{
+ using beast::iequals;
+ auto const ext = [&path]
+ {
+ auto const pos = path.rfind(".");
+ if(pos == beast::string_view::npos)
+ return beast::string_view{};
+ return path.substr(pos);
+ }();
+ if(iequals(ext, ".htm")) return "text/html";
+ if(iequals(ext, ".html")) return "text/html";
+ if(iequals(ext, ".php")) return "text/html";
+ if(iequals(ext, ".css")) return "text/css";
+ if(iequals(ext, ".txt")) return "text/plain";
+ if(iequals(ext, ".js")) return "application/javascript";
+ if(iequals(ext, ".json")) return "application/json";
+ if(iequals(ext, ".xml")) return "application/xml";
+ if(iequals(ext, ".swf")) return "application/x-shockwave-flash";
+ if(iequals(ext, ".flv")) return "video/x-flv";
+ if(iequals(ext, ".png")) return "image/png";
+ if(iequals(ext, ".jpe")) return "image/jpeg";
+ if(iequals(ext, ".jpeg")) return "image/jpeg";
+ if(iequals(ext, ".jpg")) return "image/jpeg";
+ if(iequals(ext, ".gif")) return "image/gif";
+ if(iequals(ext, ".bmp")) return "image/bmp";
+ if(iequals(ext, ".ico")) return "image/vnd.microsoft.icon";
+ if(iequals(ext, ".tiff")) return "image/tiff";
+ if(iequals(ext, ".tif")) return "image/tiff";
+ if(iequals(ext, ".svg")) return "image/svg+xml";
+ if(iequals(ext, ".svgz")) return "image/svg+xml";
+ return "application/text";
+}
+
+// Append an HTTP rel-path to a local filesystem path.
+// The returned path is normalized for the platform.
+std::string
+path_cat(
+ beast::string_view base,
+ beast::string_view path)
+{
+ if(base.empty())
+ return std::string(path);
+ std::string result(base);
+#ifdef BOOST_MSVC
+ char constexpr path_separator = '\\';
+ if(result.back() == path_separator)
+ result.resize(result.size() - 1);
+ result.append(path.data(), path.size());
+ for(auto& c : result)
+ if(c == '/')
+ c = path_separator;
+#else
+ char constexpr path_separator = '/';
+ if(result.back() == path_separator)
+ result.resize(result.size() - 1);
+ result.append(path.data(), path.size());
+#endif
+ return result;
+}
+
+// This function produces an HTTP response for the given
+// request. The type of the response object depends on the
+// contents of the request, so the interface requires the
+// caller to pass a generic lambda for receiving the response.
+template<
+ class Body, class Allocator,
+ class Send>
+void
+handle_request(
+ beast::string_view doc_root,
+ http::request<Body, http::basic_fields<Allocator>>&& req,
+ Send&& send)
+{
+ // Returns a bad request response
+ auto const bad_request =
+ [&req](beast::string_view why)
+ {
+ http::response<http::string_body> res{http::status::bad_request, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = std::string(why);
+ res.prepare_payload();
+ return res;
+ };
+
+ // Returns a not found response
+ auto const not_found =
+ [&req](beast::string_view target)
+ {
+ http::response<http::string_body> res{http::status::not_found, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = "The resource '" + std::string(target) + "' was not found.";
+ res.prepare_payload();
+ return res;
+ };
+
+ // Returns a server error response
+ auto const server_error =
+ [&req](beast::string_view what)
+ {
+ http::response<http::string_body> res{http::status::internal_server_error, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = "An error occurred: '" + std::string(what) + "'";
+ res.prepare_payload();
+ return res;
+ };
+
+ // Make sure we can handle the method
+ if( req.method() != http::verb::get &&
+ req.method() != http::verb::head)
+ return send(bad_request("Unknown HTTP-method"));
+
+ // Request path must be absolute and not contain "..".
+ if( req.target().empty() ||
+ req.target()[0] != '/' ||
+ req.target().find("..") != beast::string_view::npos)
+ return send(bad_request("Illegal request-target"));
+
+ // Build the path to the requested file
+ std::string path = path_cat(doc_root, req.target());
+ if(req.target().back() == '/')
+ path.append("index.html");
+
+ // Attempt to open the file
+ beast::error_code ec;
+ http::file_body::value_type body;
+ body.open(path.c_str(), beast::file_mode::scan, ec);
+
+ // Handle the case where the file doesn't exist
+ if(ec == beast::errc::no_such_file_or_directory)
+ return send(not_found(req.target()));
+
+ // Handle an unknown error
+ if(ec)
+ return send(server_error(ec.message()));
+
+ // Cache the size since we need it after the move
+ auto const size = body.size();
+
+ // Respond to HEAD request
+ if(req.method() == http::verb::head)
+ {
+ http::response<http::empty_body> res{http::status::ok, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, mime_type(path));
+ res.content_length(size);
+ res.keep_alive(req.keep_alive());
+ return send(std::move(res));
+ }
+
+ // Respond to GET request
+ http::response<http::file_body> res{
+ std::piecewise_construct,
+ std::make_tuple(std::move(body)),
+ std::make_tuple(http::status::ok, req.version())};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, mime_type(path));
+ res.content_length(size);
+ res.keep_alive(req.keep_alive());
+ return send(std::move(res));
+}
+
+//------------------------------------------------------------------------------
+
+// Report a failure
+void
+fail(beast::error_code ec, char const* what)
+{
+ // ssl::error::stream_truncated, also known as an SSL "short read",
+ // indicates the peer closed the connection without performing the
+ // required closing handshake (for example, Google does this to
+ // improve performance). Generally this can be a security issue,
+ // but if your communication protocol is self-terminated (as
+ // it is with both HTTP and WebSocket) then you may simply
+ // ignore the lack of close_notify.
+ //
+ // https://github.com/boostorg/beast/issues/38
+ //
+ // https://security.stackexchange.com/questions/91435/how-to-handle-a-malicious-ssl-tls-shutdown
+ //
+ // When a short read would cut off the end of an HTTP message,
+ // Beast returns the error beast::http::error::partial_message.
+ // Therefore, if we see a short read here, it has occurred
+ // after the message has been completed, so it is safe to ignore it.
+
+ if(ec == net::ssl::error::stream_truncated)
+ return;
+
+ std::cerr << what << ": " << ec.message() << "\n";
+}
+
+// Handles an HTTP server connection
+class session
+ : public boost::asio::coroutine
+ , public std::enable_shared_from_this<session>
+{
+ // This is the C++11 equivalent of a generic lambda.
+ // The function object is used to send an HTTP message.
+ struct send_lambda
+ {
+ session& self_;
+
+ explicit
+ send_lambda(session& self)
+ : self_(self)
+ {
+ }
+
+ template<bool isRequest, class Body, class Fields>
+ void
+ operator()(http::message<isRequest, Body, Fields>&& msg) const
+ {
+ // The lifetime of the message has to extend
+ // for the duration of the async operation so
+ // we use a shared_ptr to manage it.
+ auto sp = std::make_shared<
+ http::message<isRequest, Body, Fields>>(std::move(msg));
+
+ // Store a type-erased version of the shared
+ // pointer in the class to keep it alive.
+ self_.res_ = sp;
+
+ // Write the response
+ http::async_write(
+ self_.stream_,
+ *sp,
+ std::bind(
+ &session::loop,
+ self_.shared_from_this(),
+ std::placeholders::_1,
+ std::placeholders::_2,
+ sp->need_eof()));
+ }
+ };
+
+ beast::ssl_stream<beast::tcp_stream> stream_;
+ beast::flat_buffer buffer_;
+ std::shared_ptr<std::string const> doc_root_;
+ http::request<http::string_body> req_;
+ std::shared_ptr<void> res_;
+ send_lambda lambda_;
+
+public:
+ // Take ownership of the socket
+ explicit
+ session(
+ tcp::socket&& socket,
+ ssl::context& ctx,
+ std::shared_ptr<std::string const> const& doc_root)
+ : stream_(std::move(socket), ctx)
+ , doc_root_(doc_root)
+ , lambda_(*this)
+ {
+ }
+
+ // Start the asynchronous operation
+ void
+ run()
+ {
+ // We need to be executing within a strand to perform async operations
+ // on the I/O objects in this session.Although not strictly necessary
+ // for single-threaded contexts, this example code is written to be
+ // thread-safe by default.
+ net::dispatch(stream_.get_executor(),
+ beast::bind_front_handler(&session::loop,
+ shared_from_this(),
+ beast::error_code{},
+ 0,
+ false));
+ }
+
+ #include <boost/asio/yield.hpp>
+
+ void
+ loop(
+ beast::error_code ec,
+ std::size_t bytes_transferred,
+ bool close)
+ {
+ boost::ignore_unused(bytes_transferred);
+ reenter(*this)
+ {
+ // Set the timeout.
+ beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30));
+
+ // Perform the SSL handshake
+ yield stream_.async_handshake(
+ ssl::stream_base::server,
+ std::bind(
+ &session::loop,
+ shared_from_this(),
+ std::placeholders::_1,
+ 0,
+ false));
+ if(ec)
+ return fail(ec, "handshake");
+
+ for(;;)
+ {
+ // Set the timeout.
+ beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30));
+
+ // Make the request empty before reading,
+ // otherwise the operation behavior is undefined.
+ req_ = {};
+
+ // Read a request
+ yield http::async_read(stream_, buffer_, req_,
+ std::bind(
+ &session::loop,
+ shared_from_this(),
+ std::placeholders::_1,
+ std::placeholders::_2,
+ false));
+ if(ec == http::error::end_of_stream)
+ {
+ // The remote host closed the connection
+ break;
+ }
+ if(ec)
+ return fail(ec, "read");
+
+ // Send the response
+ yield handle_request(*doc_root_, std::move(req_), lambda_);
+ if(ec)
+ return fail(ec, "write");
+ if(close)
+ {
+ // This means we should close the connection, usually because
+ // the response indicated the "Connection: close" semantic.
+ break;
+ }
+
+ // We're done with the response so delete it
+ res_ = nullptr;
+ }
+
+ // Set the timeout.
+ beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30));
+
+ // Perform the SSL shutdown
+ yield stream_.async_shutdown(
+ std::bind(
+ &session::loop,
+ shared_from_this(),
+ std::placeholders::_1,
+ 0,
+ false));
+ if(ec)
+ return fail(ec, "shutdown");
+
+ // At this point the connection is closed gracefully
+ }
+ }
+
+ #include <boost/asio/unyield.hpp>
+};
+
+//------------------------------------------------------------------------------
+
+// Accepts incoming connections and launches the sessions
+class listener
+ : public boost::asio::coroutine
+ , public std::enable_shared_from_this<listener>
+{
+ net::io_context& ioc_;
+ ssl::context& ctx_;
+ tcp::acceptor acceptor_;
+ tcp::socket socket_;
+ std::shared_ptr<std::string const> doc_root_;
+
+public:
+ listener(
+ net::io_context& ioc,
+ ssl::context& ctx,
+ tcp::endpoint endpoint,
+ std::shared_ptr<std::string const> const& doc_root)
+ : ioc_(ioc)
+ , ctx_(ctx)
+ , acceptor_(net::make_strand(ioc))
+ , socket_(net::make_strand(ioc))
+ , doc_root_(doc_root)
+ {
+ beast::error_code ec;
+
+ // Open the acceptor
+ acceptor_.open(endpoint.protocol(), ec);
+ if(ec)
+ {
+ fail(ec, "open");
+ return;
+ }
+
+ // Allow address reuse
+ acceptor_.set_option(net::socket_base::reuse_address(true), ec);
+ if(ec)
+ {
+ fail(ec, "set_option");
+ return;
+ }
+
+ // Bind to the server address
+ acceptor_.bind(endpoint, ec);
+ if(ec)
+ {
+ fail(ec, "bind");
+ return;
+ }
+
+ // Start listening for connections
+ acceptor_.listen(
+ net::socket_base::max_listen_connections, ec);
+ if(ec)
+ {
+ fail(ec, "listen");
+ return;
+ }
+ }
+
+ // Start accepting incoming connections
+ void
+ run()
+ {
+ loop();
+ }
+
+private:
+
+ #include <boost/asio/yield.hpp>
+
+ void
+ loop(beast::error_code ec = {})
+ {
+ reenter(*this)
+ {
+ for(;;)
+ {
+ yield acceptor_.async_accept(
+ socket_,
+ std::bind(
+ &listener::loop,
+ shared_from_this(),
+ std::placeholders::_1));
+ if(ec)
+ {
+ fail(ec, "accept");
+ }
+ else
+ {
+ // Create the session and run it
+ std::make_shared<session>(
+ std::move(socket_),
+ ctx_,
+ doc_root_)->run();
+ }
+
+ // Make sure each session gets its own strand
+ socket_ = tcp::socket(net::make_strand(ioc_));
+ }
+ }
+ }
+
+ #include <boost/asio/unyield.hpp>
+};
+
+//------------------------------------------------------------------------------
+
+int main(int argc, char* argv[])
+{
+ // Check command line arguments.
+ if (argc != 5)
+ {
+ std::cerr <<
+ "Usage: http-server-stackless-ssl <address> <port> <doc_root> <threads>\n" <<
+ "Example:\n" <<
+ " http-server-stackless-ssl 0.0.0.0 8080 . 1\n";
+ return EXIT_FAILURE;
+ }
+ auto const address = net::ip::make_address(argv[1]);
+ auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
+ auto const doc_root = std::make_shared<std::string>(argv[3]);
+ auto const threads = std::max<int>(1, std::atoi(argv[4]));
+
+ // The io_context is required for all I/O
+ net::io_context ioc{threads};
+
+ // The SSL context is required, and holds certificates
+ ssl::context ctx{ssl::context::tlsv12};
+
+ // This holds the self-signed certificate used by the server
+ load_server_certificate(ctx);
+
+ // Create and launch a listening port
+ std::make_shared<listener>(
+ ioc,
+ ctx,
+ tcp::endpoint{address, port},
+ doc_root)->run();
+
+ // Run the I/O service on the requested number of threads
+ std::vector<std::thread> v;
+ v.reserve(threads - 1);
+ for(auto i = threads - 1; i > 0; --i)
+ v.emplace_back(
+ [&ioc]
+ {
+ ioc.run();
+ });
+ ioc.run();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/http/server/stackless/CMakeLists.txt b/src/boost/libs/beast/example/http/server/stackless/CMakeLists.txt
new file mode 100644
index 000000000..1f82d391f
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/stackless/CMakeLists.txt
@@ -0,0 +1,23 @@
+#
+# 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
+#
+
+GroupSources(include/boost/beast beast)
+GroupSources(example/http/server/stackless "/")
+
+add_executable (http-server-stackless
+ ${BOOST_BEAST_FILES}
+ Jamfile
+ http_server_stackless.cpp
+)
+
+target_link_libraries(http-server-stackless
+ lib-asio
+ lib-beast)
+
+set_property(TARGET http-server-stackless PROPERTY FOLDER "example-http-server")
diff --git a/src/boost/libs/beast/example/http/server/stackless/Jamfile b/src/boost/libs/beast/example/http/server/stackless/Jamfile
new file mode 100644
index 000000000..f82934ff8
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/stackless/Jamfile
@@ -0,0 +1,15 @@
+#
+# 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
+#
+
+exe http-server-stackless :
+ http_server_stackless.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ ;
diff --git a/src/boost/libs/beast/example/http/server/stackless/http_server_stackless.cpp b/src/boost/libs/beast/example/http/server/stackless/http_server_stackless.cpp
new file mode 100644
index 000000000..2439c6894
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/stackless/http_server_stackless.cpp
@@ -0,0 +1,493 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: HTTP server, stackless coroutine
+//
+//------------------------------------------------------------------------------
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/http.hpp>
+#include <boost/beast/version.hpp>
+#include <boost/asio/coroutine.hpp>
+#include <boost/asio/dispatch.hpp>
+#include <boost/asio/strand.hpp>
+#include <boost/config.hpp>
+#include <algorithm>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <thread>
+#include <vector>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+// Return a reasonable mime type based on the extension of a file.
+beast::string_view
+mime_type(beast::string_view path)
+{
+ using beast::iequals;
+ auto const ext = [&path]
+ {
+ auto const pos = path.rfind(".");
+ if(pos == beast::string_view::npos)
+ return beast::string_view{};
+ return path.substr(pos);
+ }();
+ if(iequals(ext, ".htm")) return "text/html";
+ if(iequals(ext, ".html")) return "text/html";
+ if(iequals(ext, ".php")) return "text/html";
+ if(iequals(ext, ".css")) return "text/css";
+ if(iequals(ext, ".txt")) return "text/plain";
+ if(iequals(ext, ".js")) return "application/javascript";
+ if(iequals(ext, ".json")) return "application/json";
+ if(iequals(ext, ".xml")) return "application/xml";
+ if(iequals(ext, ".swf")) return "application/x-shockwave-flash";
+ if(iequals(ext, ".flv")) return "video/x-flv";
+ if(iequals(ext, ".png")) return "image/png";
+ if(iequals(ext, ".jpe")) return "image/jpeg";
+ if(iequals(ext, ".jpeg")) return "image/jpeg";
+ if(iequals(ext, ".jpg")) return "image/jpeg";
+ if(iequals(ext, ".gif")) return "image/gif";
+ if(iequals(ext, ".bmp")) return "image/bmp";
+ if(iequals(ext, ".ico")) return "image/vnd.microsoft.icon";
+ if(iequals(ext, ".tiff")) return "image/tiff";
+ if(iequals(ext, ".tif")) return "image/tiff";
+ if(iequals(ext, ".svg")) return "image/svg+xml";
+ if(iequals(ext, ".svgz")) return "image/svg+xml";
+ return "application/text";
+}
+
+// Append an HTTP rel-path to a local filesystem path.
+// The returned path is normalized for the platform.
+std::string
+path_cat(
+ beast::string_view base,
+ beast::string_view path)
+{
+ if(base.empty())
+ return std::string(path);
+ std::string result(base);
+#ifdef BOOST_MSVC
+ char constexpr path_separator = '\\';
+ if(result.back() == path_separator)
+ result.resize(result.size() - 1);
+ result.append(path.data(), path.size());
+ for(auto& c : result)
+ if(c == '/')
+ c = path_separator;
+#else
+ char constexpr path_separator = '/';
+ if(result.back() == path_separator)
+ result.resize(result.size() - 1);
+ result.append(path.data(), path.size());
+#endif
+ return result;
+}
+
+// This function produces an HTTP response for the given
+// request. The type of the response object depends on the
+// contents of the request, so the interface requires the
+// caller to pass a generic lambda for receiving the response.
+template<
+ class Body, class Allocator,
+ class Send>
+void
+handle_request(
+ beast::string_view doc_root,
+ http::request<Body, http::basic_fields<Allocator>>&& req,
+ Send&& send)
+{
+ // Returns a bad request response
+ auto const bad_request =
+ [&req](beast::string_view why)
+ {
+ http::response<http::string_body> res{http::status::bad_request, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = std::string(why);
+ res.prepare_payload();
+ return res;
+ };
+
+ // Returns a not found response
+ auto const not_found =
+ [&req](beast::string_view target)
+ {
+ http::response<http::string_body> res{http::status::not_found, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = "The resource '" + std::string(target) + "' was not found.";
+ res.prepare_payload();
+ return res;
+ };
+
+ // Returns a server error response
+ auto const server_error =
+ [&req](beast::string_view what)
+ {
+ http::response<http::string_body> res{http::status::internal_server_error, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = "An error occurred: '" + std::string(what) + "'";
+ res.prepare_payload();
+ return res;
+ };
+
+ // Make sure we can handle the method
+ if( req.method() != http::verb::get &&
+ req.method() != http::verb::head)
+ return send(bad_request("Unknown HTTP-method"));
+
+ // Request path must be absolute and not contain "..".
+ if( req.target().empty() ||
+ req.target()[0] != '/' ||
+ req.target().find("..") != beast::string_view::npos)
+ return send(bad_request("Illegal request-target"));
+
+ // Build the path to the requested file
+ std::string path = path_cat(doc_root, req.target());
+ if(req.target().back() == '/')
+ path.append("index.html");
+
+ // Attempt to open the file
+ beast::error_code ec;
+ http::file_body::value_type body;
+ body.open(path.c_str(), beast::file_mode::scan, ec);
+
+ // Handle the case where the file doesn't exist
+ if(ec == beast::errc::no_such_file_or_directory)
+ return send(not_found(req.target()));
+
+ // Handle an unknown error
+ if(ec)
+ return send(server_error(ec.message()));
+
+ // Cache the size since we need it after the move
+ auto const size = body.size();
+
+ // Respond to HEAD request
+ if(req.method() == http::verb::head)
+ {
+ http::response<http::empty_body> res{http::status::ok, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, mime_type(path));
+ res.content_length(size);
+ res.keep_alive(req.keep_alive());
+ return send(std::move(res));
+ }
+
+ // Respond to GET request
+ http::response<http::file_body> res{
+ std::piecewise_construct,
+ std::make_tuple(std::move(body)),
+ std::make_tuple(http::status::ok, req.version())};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, mime_type(path));
+ res.content_length(size);
+ res.keep_alive(req.keep_alive());
+ return send(std::move(res));
+}
+
+//------------------------------------------------------------------------------
+
+// Report a failure
+void
+fail(beast::error_code ec, char const* what)
+{
+ std::cerr << what << ": " << ec.message() << "\n";
+}
+
+// Handles an HTTP server connection
+class session
+ : public boost::asio::coroutine
+ , public std::enable_shared_from_this<session>
+{
+ // This is the C++11 equivalent of a generic lambda.
+ // The function object is used to send an HTTP message.
+ struct send_lambda
+ {
+ session& self_;
+ std::shared_ptr<void> res_;
+
+ explicit
+ send_lambda(session& self)
+ : self_(self)
+ {
+ }
+
+ template<bool isRequest, class Body, class Fields>
+ void
+ operator()(http::message<isRequest, Body, Fields>&& msg) const
+ {
+ // The lifetime of the message has to extend
+ // for the duration of the async operation so
+ // we use a shared_ptr to manage it.
+ auto sp = std::make_shared<
+ http::message<isRequest, Body, Fields>>(std::move(msg));
+
+ // Store a type-erased version of the shared
+ // pointer in the class to keep it alive.
+ self_.res_ = sp;
+
+ // Write the response
+ http::async_write(
+ self_.stream_,
+ *sp,
+ beast::bind_front_handler(
+ &session::loop,
+ self_.shared_from_this(),
+ sp->need_eof()));
+ }
+ };
+
+ beast::tcp_stream stream_;
+ beast::flat_buffer buffer_;
+ std::shared_ptr<std::string const> doc_root_;
+ http::request<http::string_body> req_;
+ std::shared_ptr<void> res_;
+ send_lambda lambda_;
+
+public:
+ // Take ownership of the socket
+ explicit
+ session(
+ tcp::socket&& socket,
+ std::shared_ptr<std::string const> const& doc_root)
+ : stream_(std::move(socket))
+ , doc_root_(doc_root)
+ , lambda_(*this)
+ {
+ }
+
+ // Start the asynchronous operation
+ void
+ run()
+ {
+ // We need to be executing within a strand to perform async operations
+ // on the I/O objects in this session. Although not strictly necessary
+ // for single-threaded contexts, this example code is written to be
+ // thread-safe by default.
+ net::dispatch(stream_.get_executor(),
+ beast::bind_front_handler(&session::loop,
+ shared_from_this(),
+ false,
+ beast::error_code{},
+ 0));
+ }
+
+ #include <boost/asio/yield.hpp>
+
+ void
+ loop(
+ bool close,
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+ reenter(*this)
+ {
+ for(;;)
+ {
+ // Make the request empty before reading,
+ // otherwise the operation behavior is undefined.
+ req_ = {};
+
+ // Set the timeout.
+ stream_.expires_after(std::chrono::seconds(30));
+
+ // Read a request
+ yield http::async_read(stream_, buffer_, req_,
+ beast::bind_front_handler(
+ &session::loop,
+ shared_from_this(),
+ false));
+ if(ec == http::error::end_of_stream)
+ {
+ // The remote host closed the connection
+ break;
+ }
+ if(ec)
+ return fail(ec, "read");
+
+ // Send the response
+ yield handle_request(*doc_root_, std::move(req_), lambda_);
+ if(ec)
+ return fail(ec, "write");
+ if(close)
+ {
+ // This means we should close the connection, usually because
+ // the response indicated the "Connection: close" semantic.
+ break;
+ }
+
+ // We're done with the response so delete it
+ res_ = nullptr;
+ }
+
+ // Send a TCP shutdown
+ stream_.socket().shutdown(tcp::socket::shutdown_send, ec);
+
+ // At this point the connection is closed gracefully
+ }
+ }
+
+ #include <boost/asio/unyield.hpp>
+};
+
+//------------------------------------------------------------------------------
+
+// Accepts incoming connections and launches the sessions
+class listener
+ : public boost::asio::coroutine
+ , public std::enable_shared_from_this<listener>
+{
+ net::io_context& ioc_;
+ tcp::acceptor acceptor_;
+ tcp::socket socket_;
+ std::shared_ptr<std::string const> doc_root_;
+
+public:
+ listener(
+ net::io_context& ioc,
+ tcp::endpoint endpoint,
+ std::shared_ptr<std::string const> const& doc_root)
+ : ioc_(ioc)
+ , acceptor_(net::make_strand(ioc))
+ , socket_(net::make_strand(ioc))
+ , doc_root_(doc_root)
+ {
+ beast::error_code ec;
+
+ // Open the acceptor
+ acceptor_.open(endpoint.protocol(), ec);
+ if(ec)
+ {
+ fail(ec, "open");
+ return;
+ }
+
+ // Allow address reuse
+ acceptor_.set_option(net::socket_base::reuse_address(true), ec);
+ if(ec)
+ {
+ fail(ec, "set_option");
+ return;
+ }
+
+ // Bind to the server address
+ acceptor_.bind(endpoint, ec);
+ if(ec)
+ {
+ fail(ec, "bind");
+ return;
+ }
+
+ // Start listening for connections
+ acceptor_.listen(net::socket_base::max_listen_connections, ec);
+ if(ec)
+ {
+ fail(ec, "listen");
+ return;
+ }
+ }
+
+ // Start accepting incoming connections
+ void
+ run()
+ {
+ loop();
+ }
+
+private:
+
+ #include <boost/asio/yield.hpp>
+
+ void
+ loop(beast::error_code ec = {})
+ {
+ reenter(*this)
+ {
+ for(;;)
+ {
+ yield acceptor_.async_accept(
+ socket_,
+ beast::bind_front_handler(
+ &listener::loop,
+ shared_from_this()));
+ if(ec)
+ {
+ fail(ec, "accept");
+ }
+ else
+ {
+ // Create the session and run it
+ std::make_shared<session>(
+ std::move(socket_),
+ doc_root_)->run();
+ }
+
+ // Make sure each session gets its own strand
+ socket_ = tcp::socket(net::make_strand(ioc_));
+ }
+ }
+ }
+
+ #include <boost/asio/unyield.hpp>
+};
+
+//------------------------------------------------------------------------------
+
+int main(int argc, char* argv[])
+{
+ // Check command line arguments.
+ if (argc != 5)
+ {
+ std::cerr <<
+ "Usage: http-server-stackless <address> <port> <doc_root> <threads>\n" <<
+ "Example:\n" <<
+ " http-server-stackless 0.0.0.0 8080 . 1\n";
+ return EXIT_FAILURE;
+ }
+ auto const address = net::ip::make_address(argv[1]);
+ auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
+ auto const doc_root = std::make_shared<std::string>(argv[3]);
+ auto const threads = std::max<int>(1, std::atoi(argv[4]));
+
+ // The io_context is required for all I/O
+ net::io_context ioc{threads};
+
+ // Create and launch a listening port
+ std::make_shared<listener>(
+ ioc,
+ tcp::endpoint{address, port},
+ doc_root)->run();
+
+ // Run the I/O service on the requested number of threads
+ std::vector<std::thread> v;
+ v.reserve(threads - 1);
+ for(auto i = threads - 1; i > 0; --i)
+ v.emplace_back(
+ [&ioc]
+ {
+ ioc.run();
+ });
+ ioc.run();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/http/server/sync-ssl/CMakeLists.txt b/src/boost/libs/beast/example/http/server/sync-ssl/CMakeLists.txt
new file mode 100644
index 000000000..4142e2c95
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/sync-ssl/CMakeLists.txt
@@ -0,0 +1,31 @@
+#
+# 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
+#
+
+if (OPENSSL_FOUND)
+ GroupSources(include/boost/beast beast)
+ GroupSources(example/common common)
+ GroupSources(example/http/server/sync-ssl "/")
+
+ add_executable (http-server-sync-ssl
+ ${BOOST_BEAST_FILES}
+ ${PROJECT_SOURCE_DIR}/example/common/server_certificate.hpp
+ Jamfile
+ http_server_sync_ssl.cpp
+ )
+
+ set_property(TARGET http-server-sync-ssl PROPERTY FOLDER "example-http-server")
+
+ target_link_libraries (http-server-sync-ssl
+ OpenSSL::SSL OpenSSL::Crypto
+ lib-asio
+ lib-asio-ssl
+ lib-beast
+ )
+
+endif()
diff --git a/src/boost/libs/beast/example/http/server/sync-ssl/Jamfile b/src/boost/libs/beast/example/http/server/sync-ssl/Jamfile
new file mode 100644
index 000000000..0ad5e57f5
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/sync-ssl/Jamfile
@@ -0,0 +1,22 @@
+#
+# 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
+#
+
+import ac ;
+
+project
+ : requirements
+ [ ac.check-library /boost/beast//lib-asio-ssl : <library>/boost/beast//lib-asio-ssl/<link>static : <build>no ]
+ ;
+
+exe http-server-sync-ssl :
+ http_server_sync_ssl.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ ;
diff --git a/src/boost/libs/beast/example/http/server/sync-ssl/http_server_sync_ssl.cpp b/src/boost/libs/beast/example/http/server/sync-ssl/http_server_sync_ssl.cpp
new file mode 100644
index 000000000..34b277530
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/sync-ssl/http_server_sync_ssl.cpp
@@ -0,0 +1,356 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: HTTP SSL server, synchronous
+//
+//------------------------------------------------------------------------------
+
+#include "example/common/server_certificate.hpp"
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/http.hpp>
+#include <boost/beast/ssl.hpp>
+#include <boost/beast/version.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/ssl/stream.hpp>
+#include <boost/config.hpp>
+#include <cstdlib>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <thread>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+// Return a reasonable mime type based on the extension of a file.
+beast::string_view
+mime_type(beast::string_view path)
+{
+ using beast::iequals;
+ auto const ext = [&path]
+ {
+ auto const pos = path.rfind(".");
+ if(pos == beast::string_view::npos)
+ return beast::string_view{};
+ return path.substr(pos);
+ }();
+ if(iequals(ext, ".htm")) return "text/html";
+ if(iequals(ext, ".html")) return "text/html";
+ if(iequals(ext, ".php")) return "text/html";
+ if(iequals(ext, ".css")) return "text/css";
+ if(iequals(ext, ".txt")) return "text/plain";
+ if(iequals(ext, ".js")) return "application/javascript";
+ if(iequals(ext, ".json")) return "application/json";
+ if(iequals(ext, ".xml")) return "application/xml";
+ if(iequals(ext, ".swf")) return "application/x-shockwave-flash";
+ if(iequals(ext, ".flv")) return "video/x-flv";
+ if(iequals(ext, ".png")) return "image/png";
+ if(iequals(ext, ".jpe")) return "image/jpeg";
+ if(iequals(ext, ".jpeg")) return "image/jpeg";
+ if(iequals(ext, ".jpg")) return "image/jpeg";
+ if(iequals(ext, ".gif")) return "image/gif";
+ if(iequals(ext, ".bmp")) return "image/bmp";
+ if(iequals(ext, ".ico")) return "image/vnd.microsoft.icon";
+ if(iequals(ext, ".tiff")) return "image/tiff";
+ if(iequals(ext, ".tif")) return "image/tiff";
+ if(iequals(ext, ".svg")) return "image/svg+xml";
+ if(iequals(ext, ".svgz")) return "image/svg+xml";
+ return "application/text";
+}
+
+// Append an HTTP rel-path to a local filesystem path.
+// The returned path is normalized for the platform.
+std::string
+path_cat(
+ beast::string_view base,
+ beast::string_view path)
+{
+ if(base.empty())
+ return std::string(path);
+ std::string result(base);
+#ifdef BOOST_MSVC
+ char constexpr path_separator = '\\';
+ if(result.back() == path_separator)
+ result.resize(result.size() - 1);
+ result.append(path.data(), path.size());
+ for(auto& c : result)
+ if(c == '/')
+ c = path_separator;
+#else
+ char constexpr path_separator = '/';
+ if(result.back() == path_separator)
+ result.resize(result.size() - 1);
+ result.append(path.data(), path.size());
+#endif
+ return result;
+}
+
+// This function produces an HTTP response for the given
+// request. The type of the response object depends on the
+// contents of the request, so the interface requires the
+// caller to pass a generic lambda for receiving the response.
+template<
+ class Body, class Allocator,
+ class Send>
+void
+handle_request(
+ beast::string_view doc_root,
+ http::request<Body, http::basic_fields<Allocator>>&& req,
+ Send&& send)
+{
+ // Returns a bad request response
+ auto const bad_request =
+ [&req](beast::string_view why)
+ {
+ http::response<http::string_body> res{http::status::bad_request, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = std::string(why);
+ res.prepare_payload();
+ return res;
+ };
+
+ // Returns a not found response
+ auto const not_found =
+ [&req](beast::string_view target)
+ {
+ http::response<http::string_body> res{http::status::not_found, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = "The resource '" + std::string(target) + "' was not found.";
+ res.prepare_payload();
+ return res;
+ };
+
+ // Returns a server error response
+ auto const server_error =
+ [&req](beast::string_view what)
+ {
+ http::response<http::string_body> res{http::status::internal_server_error, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = "An error occurred: '" + std::string(what) + "'";
+ res.prepare_payload();
+ return res;
+ };
+
+ // Make sure we can handle the method
+ if( req.method() != http::verb::get &&
+ req.method() != http::verb::head)
+ return send(bad_request("Unknown HTTP-method"));
+
+ // Request path must be absolute and not contain "..".
+ if( req.target().empty() ||
+ req.target()[0] != '/' ||
+ req.target().find("..") != beast::string_view::npos)
+ return send(bad_request("Illegal request-target"));
+
+ // Build the path to the requested file
+ std::string path = path_cat(doc_root, req.target());
+ if(req.target().back() == '/')
+ path.append("index.html");
+
+ // Attempt to open the file
+ beast::error_code ec;
+ http::file_body::value_type body;
+ body.open(path.c_str(), beast::file_mode::scan, ec);
+
+ // Handle the case where the file doesn't exist
+ if(ec == beast::errc::no_such_file_or_directory)
+ return send(not_found(req.target()));
+
+ // Handle an unknown error
+ if(ec)
+ return send(server_error(ec.message()));
+
+ // Cache the size since we need it after the move
+ auto const size = body.size();
+
+ // Respond to HEAD request
+ if(req.method() == http::verb::head)
+ {
+ http::response<http::empty_body> res{http::status::ok, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, mime_type(path));
+ res.content_length(size);
+ res.keep_alive(req.keep_alive());
+ return send(std::move(res));
+ }
+
+ // Respond to GET request
+ http::response<http::file_body> res{
+ std::piecewise_construct,
+ std::make_tuple(std::move(body)),
+ std::make_tuple(http::status::ok, req.version())};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, mime_type(path));
+ res.content_length(size);
+ res.keep_alive(req.keep_alive());
+ return send(std::move(res));
+}
+
+//------------------------------------------------------------------------------
+
+// Report a failure
+void
+fail(beast::error_code ec, char const* what)
+{
+ std::cerr << what << ": " << ec.message() << "\n";
+}
+
+// This is the C++11 equivalent of a generic lambda.
+// The function object is used to send an HTTP message.
+template<class Stream>
+struct send_lambda
+{
+ Stream& stream_;
+ bool& close_;
+ beast::error_code& ec_;
+
+ explicit
+ send_lambda(
+ Stream& stream,
+ bool& close,
+ beast::error_code& ec)
+ : stream_(stream)
+ , close_(close)
+ , ec_(ec)
+ {
+ }
+
+ template<bool isRequest, class Body, class Fields>
+ void
+ operator()(http::message<isRequest, Body, Fields>&& msg) const
+ {
+ // Determine if we should close the connection after
+ close_ = msg.need_eof();
+
+ // We need the serializer here because the serializer requires
+ // a non-const file_body, and the message oriented version of
+ // http::write only works with const messages.
+ http::serializer<isRequest, Body, Fields> sr{msg};
+ http::write(stream_, sr, ec_);
+ }
+};
+
+// Handles an HTTP server connection
+void
+do_session(
+ tcp::socket& socket,
+ ssl::context& ctx,
+ std::shared_ptr<std::string const> const& doc_root)
+{
+ bool close = false;
+ beast::error_code ec;
+
+ // Construct the stream around the socket
+ beast::ssl_stream<tcp::socket&> stream{socket, ctx};
+
+ // Perform the SSL handshake
+ stream.handshake(ssl::stream_base::server, ec);
+ if(ec)
+ return fail(ec, "handshake");
+
+ // This buffer is required to persist across reads
+ beast::flat_buffer buffer;
+
+ // This lambda is used to send messages
+ send_lambda<beast::ssl_stream<tcp::socket&>> lambda{stream, close, ec};
+
+ for(;;)
+ {
+ // Read a request
+ http::request<http::string_body> req;
+ http::read(stream, buffer, req, ec);
+ if(ec == http::error::end_of_stream)
+ break;
+ if(ec)
+ return fail(ec, "read");
+
+ // Send the response
+ handle_request(*doc_root, std::move(req), lambda);
+ if(ec)
+ return fail(ec, "write");
+ if(close)
+ {
+ // This means we should close the connection, usually because
+ // the response indicated the "Connection: close" semantic.
+ break;
+ }
+ }
+
+ // Perform the SSL shutdown
+ stream.shutdown(ec);
+ if(ec)
+ return fail(ec, "shutdown");
+
+ // At this point the connection is closed gracefully
+}
+
+//------------------------------------------------------------------------------
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ // Check command line arguments.
+ if (argc != 4)
+ {
+ std::cerr <<
+ "Usage: http-server-sync-ssl <address> <port> <doc_root>\n" <<
+ "Example:\n" <<
+ " http-server-sync-ssl 0.0.0.0 8080 .\n";
+ return EXIT_FAILURE;
+ }
+ auto const address = net::ip::make_address(argv[1]);
+ auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
+ auto const doc_root = std::make_shared<std::string>(argv[3]);
+
+ // The io_context is required for all I/O
+ net::io_context ioc{1};
+
+ // The SSL context is required, and holds certificates
+ ssl::context ctx{ssl::context::tlsv12};
+
+ // This holds the self-signed certificate used by the server
+ load_server_certificate(ctx);
+
+ // The acceptor receives incoming connections
+ tcp::acceptor acceptor{ioc, {address, port}};
+ for(;;)
+ {
+ // This will receive the new connection
+ tcp::socket socket{ioc};
+
+ // Block until we get a connection
+ acceptor.accept(socket);
+
+ // Launch the session, transferring ownership of the socket
+ std::thread{std::bind(
+ &do_session,
+ std::move(socket),
+ std::ref(ctx),
+ doc_root)}.detach();
+ }
+ }
+ catch (const std::exception& e)
+ {
+ std::cerr << "Error: " << e.what() << std::endl;
+ return EXIT_FAILURE;
+ }
+}
diff --git a/src/boost/libs/beast/example/http/server/sync/CMakeLists.txt b/src/boost/libs/beast/example/http/server/sync/CMakeLists.txt
new file mode 100644
index 000000000..250add773
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/sync/CMakeLists.txt
@@ -0,0 +1,24 @@
+#
+# 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
+#
+
+GroupSources(include/boost/beast beast)
+GroupSources(example/http/server/sync "/")
+
+add_executable (http-server-sync
+ ${BOOST_BEAST_FILES}
+ Jamfile
+ http_server_sync.cpp
+)
+
+target_link_libraries(http-server-sync
+ lib-asio
+ lib-asio-ssl
+ lib-beast)
+
+set_property(TARGET http-server-sync PROPERTY FOLDER "example-http-server")
diff --git a/src/boost/libs/beast/example/http/server/sync/Jamfile b/src/boost/libs/beast/example/http/server/sync/Jamfile
new file mode 100644
index 000000000..30e4f026b
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/sync/Jamfile
@@ -0,0 +1,15 @@
+#
+# 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
+#
+
+exe http-server-sync :
+ http_server_sync.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ ;
diff --git a/src/boost/libs/beast/example/http/server/sync/http_server_sync.cpp b/src/boost/libs/beast/example/http/server/sync/http_server_sync.cpp
new file mode 100644
index 000000000..2c5ca60fb
--- /dev/null
+++ b/src/boost/libs/beast/example/http/server/sync/http_server_sync.cpp
@@ -0,0 +1,335 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: HTTP server, synchronous
+//
+//------------------------------------------------------------------------------
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/http.hpp>
+#include <boost/beast/version.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/config.hpp>
+#include <cstdlib>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <thread>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+//------------------------------------------------------------------------------
+
+// Return a reasonable mime type based on the extension of a file.
+beast::string_view
+mime_type(beast::string_view path)
+{
+ using beast::iequals;
+ auto const ext = [&path]
+ {
+ auto const pos = path.rfind(".");
+ if(pos == beast::string_view::npos)
+ return beast::string_view{};
+ return path.substr(pos);
+ }();
+ if(iequals(ext, ".htm")) return "text/html";
+ if(iequals(ext, ".html")) return "text/html";
+ if(iequals(ext, ".php")) return "text/html";
+ if(iequals(ext, ".css")) return "text/css";
+ if(iequals(ext, ".txt")) return "text/plain";
+ if(iequals(ext, ".js")) return "application/javascript";
+ if(iequals(ext, ".json")) return "application/json";
+ if(iequals(ext, ".xml")) return "application/xml";
+ if(iequals(ext, ".swf")) return "application/x-shockwave-flash";
+ if(iequals(ext, ".flv")) return "video/x-flv";
+ if(iequals(ext, ".png")) return "image/png";
+ if(iequals(ext, ".jpe")) return "image/jpeg";
+ if(iequals(ext, ".jpeg")) return "image/jpeg";
+ if(iequals(ext, ".jpg")) return "image/jpeg";
+ if(iequals(ext, ".gif")) return "image/gif";
+ if(iequals(ext, ".bmp")) return "image/bmp";
+ if(iequals(ext, ".ico")) return "image/vnd.microsoft.icon";
+ if(iequals(ext, ".tiff")) return "image/tiff";
+ if(iequals(ext, ".tif")) return "image/tiff";
+ if(iequals(ext, ".svg")) return "image/svg+xml";
+ if(iequals(ext, ".svgz")) return "image/svg+xml";
+ return "application/text";
+}
+
+// Append an HTTP rel-path to a local filesystem path.
+// The returned path is normalized for the platform.
+std::string
+path_cat(
+ beast::string_view base,
+ beast::string_view path)
+{
+ if (base.empty())
+ return std::string(path);
+ std::string result(base);
+#ifdef BOOST_MSVC
+ char constexpr path_separator = '\\';
+ if(result.back() == path_separator)
+ result.resize(result.size() - 1);
+ result.append(path.data(), path.size());
+ for(auto& c : result)
+ if(c == '/')
+ c = path_separator;
+#else
+ char constexpr path_separator = '/';
+ if(result.back() == path_separator)
+ result.resize(result.size() - 1);
+ result.append(path.data(), path.size());
+#endif
+ return result;
+}
+
+// This function produces an HTTP response for the given
+// request. The type of the response object depends on the
+// contents of the request, so the interface requires the
+// caller to pass a generic lambda for receiving the response.
+template<
+ class Body, class Allocator,
+ class Send>
+void
+handle_request(
+ beast::string_view doc_root,
+ http::request<Body, http::basic_fields<Allocator>>&& req,
+ Send&& send)
+{
+ // Returns a bad request response
+ auto const bad_request =
+ [&req](beast::string_view why)
+ {
+ http::response<http::string_body> res{http::status::bad_request, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = std::string(why);
+ res.prepare_payload();
+ return res;
+ };
+
+ // Returns a not found response
+ auto const not_found =
+ [&req](beast::string_view target)
+ {
+ http::response<http::string_body> res{http::status::not_found, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = "The resource '" + std::string(target) + "' was not found.";
+ res.prepare_payload();
+ return res;
+ };
+
+ // Returns a server error response
+ auto const server_error =
+ [&req](beast::string_view what)
+ {
+ http::response<http::string_body> res{http::status::internal_server_error, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = "An error occurred: '" + std::string(what) + "'";
+ res.prepare_payload();
+ return res;
+ };
+
+ // Make sure we can handle the method
+ if( req.method() != http::verb::get &&
+ req.method() != http::verb::head)
+ return send(bad_request("Unknown HTTP-method"));
+
+ // Request path must be absolute and not contain "..".
+ if( req.target().empty() ||
+ req.target()[0] != '/' ||
+ req.target().find("..") != beast::string_view::npos)
+ return send(bad_request("Illegal request-target"));
+
+ // Build the path to the requested file
+ std::string path = path_cat(doc_root, req.target());
+ if(req.target().back() == '/')
+ path.append("index.html");
+
+ // Attempt to open the file
+ beast::error_code ec;
+ http::file_body::value_type body;
+ body.open(path.c_str(), beast::file_mode::scan, ec);
+
+ // Handle the case where the file doesn't exist
+ if(ec == beast::errc::no_such_file_or_directory)
+ return send(not_found(req.target()));
+
+ // Handle an unknown error
+ if(ec)
+ return send(server_error(ec.message()));
+
+ // Cache the size since we need it after the move
+ auto const size = body.size();
+
+ // Respond to HEAD request
+ if(req.method() == http::verb::head)
+ {
+ http::response<http::empty_body> res{http::status::ok, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, mime_type(path));
+ res.content_length(size);
+ res.keep_alive(req.keep_alive());
+ return send(std::move(res));
+ }
+
+ // Respond to GET request
+ http::response<http::file_body> res{
+ std::piecewise_construct,
+ std::make_tuple(std::move(body)),
+ std::make_tuple(http::status::ok, req.version())};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, mime_type(path));
+ res.content_length(size);
+ res.keep_alive(req.keep_alive());
+ return send(std::move(res));
+}
+
+//------------------------------------------------------------------------------
+
+// Report a failure
+void
+fail(beast::error_code ec, char const* what)
+{
+ std::cerr << what << ": " << ec.message() << "\n";
+}
+
+// This is the C++11 equivalent of a generic lambda.
+// The function object is used to send an HTTP message.
+template<class Stream>
+struct send_lambda
+{
+ Stream& stream_;
+ bool& close_;
+ beast::error_code& ec_;
+
+ explicit
+ send_lambda(
+ Stream& stream,
+ bool& close,
+ beast::error_code& ec)
+ : stream_(stream)
+ , close_(close)
+ , ec_(ec)
+ {
+ }
+
+ template<bool isRequest, class Body, class Fields>
+ void
+ operator()(http::message<isRequest, Body, Fields>&& msg) const
+ {
+ // Determine if we should close the connection after
+ close_ = msg.need_eof();
+
+ // We need the serializer here because the serializer requires
+ // a non-const file_body, and the message oriented version of
+ // http::write only works with const messages.
+ http::serializer<isRequest, Body, Fields> sr{msg};
+ http::write(stream_, sr, ec_);
+ }
+};
+
+// Handles an HTTP server connection
+void
+do_session(
+ tcp::socket& socket,
+ std::shared_ptr<std::string const> const& doc_root)
+{
+ bool close = false;
+ beast::error_code ec;
+
+ // This buffer is required to persist across reads
+ beast::flat_buffer buffer;
+
+ // This lambda is used to send messages
+ send_lambda<tcp::socket> lambda{socket, close, ec};
+
+ for(;;)
+ {
+ // Read a request
+ http::request<http::string_body> req;
+ http::read(socket, buffer, req, ec);
+ if(ec == http::error::end_of_stream)
+ break;
+ if(ec)
+ return fail(ec, "read");
+
+ // Send the response
+ handle_request(*doc_root, std::move(req), lambda);
+ if(ec)
+ return fail(ec, "write");
+ if(close)
+ {
+ // This means we should close the connection, usually because
+ // the response indicated the "Connection: close" semantic.
+ break;
+ }
+ }
+
+ // Send a TCP shutdown
+ socket.shutdown(tcp::socket::shutdown_send, ec);
+
+ // At this point the connection is closed gracefully
+}
+
+//------------------------------------------------------------------------------
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ // Check command line arguments.
+ if (argc != 4)
+ {
+ std::cerr <<
+ "Usage: http-server-sync <address> <port> <doc_root>\n" <<
+ "Example:\n" <<
+ " http-server-sync 0.0.0.0 8080 .\n";
+ return EXIT_FAILURE;
+ }
+ auto const address = net::ip::make_address(argv[1]);
+ auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
+ auto const doc_root = std::make_shared<std::string>(argv[3]);
+
+ // The io_context is required for all I/O
+ net::io_context ioc{1};
+
+ // The acceptor receives incoming connections
+ tcp::acceptor acceptor{ioc, {address, port}};
+ for(;;)
+ {
+ // This will receive the new connection
+ tcp::socket socket{ioc};
+
+ // Block until we get a connection
+ acceptor.accept(socket);
+
+ // Launch the session, transferring ownership of the socket
+ std::thread{std::bind(
+ &do_session,
+ std::move(socket),
+ doc_root)}.detach();
+ }
+ }
+ catch (const std::exception& e)
+ {
+ std::cerr << "Error: " << e.what() << std::endl;
+ return EXIT_FAILURE;
+ }
+}
diff --git a/src/boost/libs/beast/example/websocket/CMakeLists.txt b/src/boost/libs/beast/example/websocket/CMakeLists.txt
new file mode 100644
index 000000000..d38604dd0
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/CMakeLists.txt
@@ -0,0 +1,11 @@
+#
+# Copyright (c) 2013-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
+#
+
+add_subdirectory (client)
+add_subdirectory (server)
diff --git a/src/boost/libs/beast/example/websocket/Jamfile b/src/boost/libs/beast/example/websocket/Jamfile
new file mode 100644
index 000000000..32f2c5144
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/Jamfile
@@ -0,0 +1,11 @@
+#
+# Copyright (c) 2013-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
+#
+
+build-project client ;
+build-project server ;
diff --git a/src/boost/libs/beast/example/websocket/client/CMakeLists.txt b/src/boost/libs/beast/example/websocket/client/CMakeLists.txt
new file mode 100644
index 000000000..5d1300e2a
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/client/CMakeLists.txt
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2013-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
+#
+
+add_subdirectory (async)
+add_subdirectory (coro)
+add_subdirectory (sync)
+
+if (OPENSSL_FOUND)
+ add_subdirectory (async-ssl)
+ add_subdirectory (async-ssl-system-executor)
+ add_subdirectory (coro-ssl)
+ add_subdirectory (sync-ssl)
+endif()
diff --git a/src/boost/libs/beast/example/websocket/client/Jamfile b/src/boost/libs/beast/example/websocket/client/Jamfile
new file mode 100644
index 000000000..94a458110
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/client/Jamfile
@@ -0,0 +1,18 @@
+#
+# Copyright (c) 2013-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
+#
+
+build-project async ;
+build-project coro ;
+build-project sync ;
+
+# SSL
+build-project async-ssl ;
+build-project async-ssl-system-executor ;
+build-project coro-ssl ;
+build-project sync-ssl ;
diff --git a/src/boost/libs/beast/example/websocket/client/async-ssl-system-executor/CMakeLists.txt b/src/boost/libs/beast/example/websocket/client/async-ssl-system-executor/CMakeLists.txt
new file mode 100644
index 000000000..3a22aade8
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/client/async-ssl-system-executor/CMakeLists.txt
@@ -0,0 +1,31 @@
+#
+# 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
+#
+
+if (OPENSSL_FOUND)
+ GroupSources(include/boost/beast beast)
+ GroupSources(example/common common)
+ GroupSources(example/websocket/client/async-ssl-system-executor "/")
+
+ add_executable (websocket-client-async-ssl-system-executor
+ ${BOOST_BEAST_FILES}
+ ${PROJECT_SOURCE_DIR}/example/common/root_certificates.hpp
+ Jamfile
+ websocket_client_async_ssl_system_executor.cpp
+ )
+
+ set_property(TARGET websocket-client-async-ssl-system-executor PROPERTY FOLDER "example-websocket-client")
+
+ target_link_libraries (websocket-client-async-ssl-system-executor
+ OpenSSL::SSL OpenSSL::Crypto
+ lib-asio
+ lib-asio-ssl
+ lib-beast
+ )
+
+endif()
diff --git a/src/boost/libs/beast/example/websocket/client/async-ssl-system-executor/Jamfile b/src/boost/libs/beast/example/websocket/client/async-ssl-system-executor/Jamfile
new file mode 100644
index 000000000..770a93c7d
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/client/async-ssl-system-executor/Jamfile
@@ -0,0 +1,22 @@
+#
+# 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
+#
+
+import ac ;
+
+project
+ : requirements
+ [ ac.check-library /boost/beast//lib-asio-ssl : <library>/boost/beast//lib-asio-ssl/<link>static : <build>no ]
+ ;
+
+exe websocket-client-async-ssl-system-executor :
+ websocket_client_async_ssl_system_executor.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ ;
diff --git a/src/boost/libs/beast/example/websocket/client/async-ssl-system-executor/websocket_client_async_ssl_system_executor.cpp b/src/boost/libs/beast/example/websocket/client/async-ssl-system-executor/websocket_client_async_ssl_system_executor.cpp
new file mode 100644
index 000000000..40d19fd00
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/client/async-ssl-system-executor/websocket_client_async_ssl_system_executor.cpp
@@ -0,0 +1,259 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: WebSocket SSL client, asynchronous, using system_executor
+//
+//------------------------------------------------------------------------------
+
+#include "example/common/root_certificates.hpp"
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/ssl.hpp>
+#include <boost/beast/websocket.hpp>
+#include <boost/beast/websocket/ssl.hpp>
+#include <boost/asio/strand.hpp>
+#include <boost/asio/system_executor.hpp>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <string>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+//------------------------------------------------------------------------------
+
+// Report a failure
+void
+fail(beast::error_code ec, char const* what)
+{
+ std::cerr << what << ": " << ec.message() << "\n";
+}
+
+// Sends a WebSocket message and prints the response
+class session : public std::enable_shared_from_this<session>
+{
+ tcp::resolver resolver_;
+ websocket::stream<
+ beast::ssl_stream<beast::tcp_stream>> ws_;
+ beast::flat_buffer buffer_;
+ std::string host_;
+ std::string text_;
+
+ // Objects are constructed with a strand to
+ // ensure that handlers do not execute concurrently.
+ session(net::strand<net::system_executor> ex, ssl::context& ctx)
+ : resolver_(ex)
+ , ws_(ex, ctx)
+ {
+ }
+public:
+ // Delegate construction to a prive constructor to be able to use
+ // the same strand for both I/O objects.
+ explicit
+ session(ssl::context& ctx)
+ : session(net::make_strand(net::system_executor{}), ctx)
+ {
+ }
+
+ // Start the asynchronous operation
+ void
+ run(
+ char const* host,
+ char const* port,
+ char const* text)
+ {
+ // Save these for later
+ host_ = host;
+ text_ = text;
+
+ // Look up the domain name
+ resolver_.async_resolve(
+ host,
+ port,
+ beast::bind_front_handler(
+ &session::on_resolve,
+ shared_from_this()));
+ }
+
+ void
+ on_resolve(
+ beast::error_code ec,
+ tcp::resolver::results_type results)
+ {
+ if(ec)
+ return fail(ec, "resolve");
+
+ // Set a timeout on the operation
+ beast::get_lowest_layer(ws_).expires_after(std::chrono::seconds(30));
+
+ // Make the connection on the IP address we get from a lookup
+ beast::get_lowest_layer(ws_).async_connect(
+ results,
+ beast::bind_front_handler(
+ &session::on_connect,
+ shared_from_this()));
+ }
+
+ void
+ on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type ep)
+ {
+ if(ec)
+ return fail(ec, "connect");
+
+ // Update the host_ string. This will provide the value of the
+ // Host HTTP header during the WebSocket handshake.
+ // See https://tools.ietf.org/html/rfc7230#section-5.4
+ host_ += ':' + std::to_string(ep.port());
+
+ // Set a timeout on the operation
+ beast::get_lowest_layer(ws_).expires_after(std::chrono::seconds(30));
+
+ // Perform the SSL handshake
+ ws_.next_layer().async_handshake(
+ ssl::stream_base::client,
+ beast::bind_front_handler(
+ &session::on_ssl_handshake,
+ shared_from_this()));
+ }
+
+ void
+ on_ssl_handshake(beast::error_code ec)
+ {
+ if(ec)
+ return fail(ec, "ssl_handshake");
+
+ // Turn off the timeout on the tcp_stream, because
+ // the websocket stream has its own timeout system.
+ beast::get_lowest_layer(ws_).expires_never();
+
+ // Set suggested timeout settings for the websocket
+ ws_.set_option(
+ websocket::stream_base::timeout::suggested(
+ beast::role_type::client));
+
+ // Set a decorator to change the User-Agent of the handshake
+ ws_.set_option(websocket::stream_base::decorator(
+ [](websocket::request_type& req)
+ {
+ req.set(http::field::user_agent,
+ std::string(BOOST_BEAST_VERSION_STRING) +
+ " websocket-client-async-ssl");
+ }));
+
+ // Perform the websocket handshake
+ ws_.async_handshake(host_, "/",
+ beast::bind_front_handler(
+ &session::on_handshake,
+ shared_from_this()));
+ }
+
+ void
+ on_handshake(beast::error_code ec)
+ {
+ if(ec)
+ return fail(ec, "handshake");
+
+ // Send the message
+ ws_.async_write(
+ net::buffer(text_),
+ beast::bind_front_handler(
+ &session::on_write,
+ shared_from_this()));
+ }
+
+ void
+ on_write(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ if(ec)
+ return fail(ec, "write");
+
+ // Read a message into our buffer
+ ws_.async_read(
+ buffer_,
+ beast::bind_front_handler(
+ &session::on_read,
+ shared_from_this()));
+ }
+
+ void
+ on_read(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ if(ec)
+ return fail(ec, "read");
+
+ // Close the WebSocket connection
+ ws_.async_close(websocket::close_code::normal,
+ beast::bind_front_handler(
+ &session::on_close,
+ shared_from_this()));
+ }
+
+ void
+ on_close(beast::error_code ec)
+ {
+ if(ec)
+ return fail(ec, "close");
+
+ // If we get here then the connection is closed gracefully
+
+ // The make_printable() function helps print a ConstBufferSequence
+ std::cout << beast::make_printable(buffer_.data()) << std::endl;
+ }
+};
+
+//------------------------------------------------------------------------------
+
+int main(int argc, char** argv)
+{
+ // Check command line arguments.
+ if(argc != 4)
+ {
+ std::cerr <<
+ "Usage: websocket-client-async-ssl <host> <port> <text>\n" <<
+ "Example:\n" <<
+ " websocket-client-async-ssl echo.websocket.org 443 \"Hello, world!\"\n";
+ return EXIT_FAILURE;
+ }
+ auto const host = argv[1];
+ auto const port = argv[2];
+ auto const text = argv[3];
+
+
+ // The SSL context is required, and holds certificates
+ ssl::context ctx{ssl::context::tlsv12_client};
+
+ // This holds the root certificate used for verification
+ load_root_certificates(ctx);
+
+ // Launch the asynchronous operation
+ std::make_shared<session>(ctx)->run(host, port, text);
+
+ // The async operations will run on the system_executor.
+ // Because the main thread has nothing to do in this example, we just wait
+ // for the system_executor to run out of work.
+ net::system_executor().context().join();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/websocket/client/async-ssl/CMakeLists.txt b/src/boost/libs/beast/example/websocket/client/async-ssl/CMakeLists.txt
new file mode 100644
index 000000000..a21982806
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/client/async-ssl/CMakeLists.txt
@@ -0,0 +1,31 @@
+#
+# 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
+#
+
+if (OPENSSL_FOUND)
+ GroupSources(include/boost/beast beast)
+ GroupSources(example/common common)
+ GroupSources(example/websocket/client/async-ssl "/")
+
+ add_executable (websocket-client-async-ssl
+ ${BOOST_BEAST_FILES}
+ ${PROJECT_SOURCE_DIR}/example/common/root_certificates.hpp
+ Jamfile
+ websocket_client_async_ssl.cpp
+ )
+
+ set_property(TARGET websocket-client-async-ssl PROPERTY FOLDER "example-websocket-client")
+
+ target_link_libraries (websocket-client-async-ssl
+ OpenSSL::SSL OpenSSL::Crypto
+ lib-asio
+ lib-asio-ssl
+ lib-beast
+ )
+
+endif()
diff --git a/src/boost/libs/beast/example/websocket/client/async-ssl/Jamfile b/src/boost/libs/beast/example/websocket/client/async-ssl/Jamfile
new file mode 100644
index 000000000..1f46a94d9
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/client/async-ssl/Jamfile
@@ -0,0 +1,22 @@
+#
+# 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
+#
+
+import ac ;
+
+project
+ : requirements
+ [ ac.check-library /boost/beast//lib-asio-ssl : <library>/boost/beast//lib-asio-ssl/<link>static : <build>no ]
+ ;
+
+exe websocket-client-async-ssl :
+ websocket_client_async_ssl.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ ;
diff --git a/src/boost/libs/beast/example/websocket/client/async-ssl/websocket_client_async_ssl.cpp b/src/boost/libs/beast/example/websocket/client/async-ssl/websocket_client_async_ssl.cpp
new file mode 100644
index 000000000..4d413aa78
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/client/async-ssl/websocket_client_async_ssl.cpp
@@ -0,0 +1,252 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: WebSocket SSL client, asynchronous
+//
+//------------------------------------------------------------------------------
+
+#include "example/common/root_certificates.hpp"
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/ssl.hpp>
+#include <boost/beast/websocket.hpp>
+#include <boost/beast/websocket/ssl.hpp>
+#include <boost/asio/strand.hpp>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <string>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+//------------------------------------------------------------------------------
+
+// Report a failure
+void
+fail(beast::error_code ec, char const* what)
+{
+ std::cerr << what << ": " << ec.message() << "\n";
+}
+
+// Sends a WebSocket message and prints the response
+class session : public std::enable_shared_from_this<session>
+{
+ tcp::resolver resolver_;
+ websocket::stream<
+ beast::ssl_stream<beast::tcp_stream>> ws_;
+ beast::flat_buffer buffer_;
+ std::string host_;
+ std::string text_;
+
+public:
+ // Resolver and socket require an io_context
+ explicit
+ session(net::io_context& ioc, ssl::context& ctx)
+ : resolver_(net::make_strand(ioc))
+ , ws_(net::make_strand(ioc), ctx)
+ {
+ }
+
+ // Start the asynchronous operation
+ void
+ run(
+ char const* host,
+ char const* port,
+ char const* text)
+ {
+ // Save these for later
+ host_ = host;
+ text_ = text;
+
+ // Look up the domain name
+ resolver_.async_resolve(
+ host,
+ port,
+ beast::bind_front_handler(
+ &session::on_resolve,
+ shared_from_this()));
+ }
+
+ void
+ on_resolve(
+ beast::error_code ec,
+ tcp::resolver::results_type results)
+ {
+ if(ec)
+ return fail(ec, "resolve");
+
+ // Set a timeout on the operation
+ beast::get_lowest_layer(ws_).expires_after(std::chrono::seconds(30));
+
+ // Make the connection on the IP address we get from a lookup
+ beast::get_lowest_layer(ws_).async_connect(
+ results,
+ beast::bind_front_handler(
+ &session::on_connect,
+ shared_from_this()));
+ }
+
+ void
+ on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type ep)
+ {
+ if(ec)
+ return fail(ec, "connect");
+
+ // Update the host_ string. This will provide the value of the
+ // Host HTTP header during the WebSocket handshake.
+ // See https://tools.ietf.org/html/rfc7230#section-5.4
+ host_ += ':' + std::to_string(ep.port());
+
+ // Set a timeout on the operation
+ beast::get_lowest_layer(ws_).expires_after(std::chrono::seconds(30));
+
+ // Perform the SSL handshake
+ ws_.next_layer().async_handshake(
+ ssl::stream_base::client,
+ beast::bind_front_handler(
+ &session::on_ssl_handshake,
+ shared_from_this()));
+ }
+
+ void
+ on_ssl_handshake(beast::error_code ec)
+ {
+ if(ec)
+ return fail(ec, "ssl_handshake");
+
+ // Turn off the timeout on the tcp_stream, because
+ // the websocket stream has its own timeout system.
+ beast::get_lowest_layer(ws_).expires_never();
+
+ // Set suggested timeout settings for the websocket
+ ws_.set_option(
+ websocket::stream_base::timeout::suggested(
+ beast::role_type::client));
+
+ // Set a decorator to change the User-Agent of the handshake
+ ws_.set_option(websocket::stream_base::decorator(
+ [](websocket::request_type& req)
+ {
+ req.set(http::field::user_agent,
+ std::string(BOOST_BEAST_VERSION_STRING) +
+ " websocket-client-async-ssl");
+ }));
+
+ // Perform the websocket handshake
+ ws_.async_handshake(host_, "/",
+ beast::bind_front_handler(
+ &session::on_handshake,
+ shared_from_this()));
+ }
+
+ void
+ on_handshake(beast::error_code ec)
+ {
+ if(ec)
+ return fail(ec, "handshake");
+
+ // Send the message
+ ws_.async_write(
+ net::buffer(text_),
+ beast::bind_front_handler(
+ &session::on_write,
+ shared_from_this()));
+ }
+
+ void
+ on_write(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ if(ec)
+ return fail(ec, "write");
+
+ // Read a message into our buffer
+ ws_.async_read(
+ buffer_,
+ beast::bind_front_handler(
+ &session::on_read,
+ shared_from_this()));
+ }
+
+ void
+ on_read(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ if(ec)
+ return fail(ec, "read");
+
+ // Close the WebSocket connection
+ ws_.async_close(websocket::close_code::normal,
+ beast::bind_front_handler(
+ &session::on_close,
+ shared_from_this()));
+ }
+
+ void
+ on_close(beast::error_code ec)
+ {
+ if(ec)
+ return fail(ec, "close");
+
+ // If we get here then the connection is closed gracefully
+
+ // The make_printable() function helps print a ConstBufferSequence
+ std::cout << beast::make_printable(buffer_.data()) << std::endl;
+ }
+};
+
+//------------------------------------------------------------------------------
+
+int main(int argc, char** argv)
+{
+ // Check command line arguments.
+ if(argc != 4)
+ {
+ std::cerr <<
+ "Usage: websocket-client-async-ssl <host> <port> <text>\n" <<
+ "Example:\n" <<
+ " websocket-client-async-ssl echo.websocket.org 443 \"Hello, world!\"\n";
+ return EXIT_FAILURE;
+ }
+ auto const host = argv[1];
+ auto const port = argv[2];
+ auto const text = argv[3];
+
+ // The io_context is required for all I/O
+ net::io_context ioc;
+
+ // The SSL context is required, and holds certificates
+ ssl::context ctx{ssl::context::tlsv12_client};
+
+ // This holds the root certificate used for verification
+ load_root_certificates(ctx);
+
+ // Launch the asynchronous operation
+ std::make_shared<session>(ioc, ctx)->run(host, port, text);
+
+ // Run the I/O service. The call will return when
+ // the socket is closed.
+ ioc.run();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/websocket/client/async/CMakeLists.txt b/src/boost/libs/beast/example/websocket/client/async/CMakeLists.txt
new file mode 100644
index 000000000..cc6434071
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/client/async/CMakeLists.txt
@@ -0,0 +1,23 @@
+#
+# 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
+#
+
+GroupSources(include/boost/beast beast)
+GroupSources(example/websocket/client/async "/")
+
+add_executable (websocket-client-async
+ ${BOOST_BEAST_FILES}
+ Jamfile
+ websocket_client_async.cpp
+)
+
+target_link_libraries(websocket-client-async
+ lib-asio
+ lib-beast)
+
+set_property(TARGET websocket-client-async PROPERTY FOLDER "example-websocket-client")
diff --git a/src/boost/libs/beast/example/websocket/client/async/Jamfile b/src/boost/libs/beast/example/websocket/client/async/Jamfile
new file mode 100644
index 000000000..e5359db3b
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/client/async/Jamfile
@@ -0,0 +1,15 @@
+#
+# 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
+#
+
+exe websocket-client-async :
+ websocket_client_async.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ ;
diff --git a/src/boost/libs/beast/example/websocket/client/async/websocket_client_async.cpp b/src/boost/libs/beast/example/websocket/client/async/websocket_client_async.cpp
new file mode 100644
index 000000000..5fcf721b8
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/client/async/websocket_client_async.cpp
@@ -0,0 +1,223 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: WebSocket client, asynchronous
+//
+//------------------------------------------------------------------------------
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/websocket.hpp>
+#include <boost/asio/strand.hpp>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <string>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+//------------------------------------------------------------------------------
+
+// Report a failure
+void
+fail(beast::error_code ec, char const* what)
+{
+ std::cerr << what << ": " << ec.message() << "\n";
+}
+
+// Sends a WebSocket message and prints the response
+class session : public std::enable_shared_from_this<session>
+{
+ tcp::resolver resolver_;
+ websocket::stream<beast::tcp_stream> ws_;
+ beast::flat_buffer buffer_;
+ std::string host_;
+ std::string text_;
+
+public:
+ // Resolver and socket require an io_context
+ explicit
+ session(net::io_context& ioc)
+ : resolver_(net::make_strand(ioc))
+ , ws_(net::make_strand(ioc))
+ {
+ }
+
+ // Start the asynchronous operation
+ void
+ run(
+ char const* host,
+ char const* port,
+ char const* text)
+ {
+ // Save these for later
+ host_ = host;
+ text_ = text;
+
+ // Look up the domain name
+ resolver_.async_resolve(
+ host,
+ port,
+ beast::bind_front_handler(
+ &session::on_resolve,
+ shared_from_this()));
+ }
+
+ void
+ on_resolve(
+ beast::error_code ec,
+ tcp::resolver::results_type results)
+ {
+ if(ec)
+ return fail(ec, "resolve");
+
+ // Set the timeout for the operation
+ beast::get_lowest_layer(ws_).expires_after(std::chrono::seconds(30));
+
+ // Make the connection on the IP address we get from a lookup
+ beast::get_lowest_layer(ws_).async_connect(
+ results,
+ beast::bind_front_handler(
+ &session::on_connect,
+ shared_from_this()));
+ }
+
+ void
+ on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type ep)
+ {
+ if(ec)
+ return fail(ec, "connect");
+
+ // Turn off the timeout on the tcp_stream, because
+ // the websocket stream has its own timeout system.
+ beast::get_lowest_layer(ws_).expires_never();
+
+ // Set suggested timeout settings for the websocket
+ ws_.set_option(
+ websocket::stream_base::timeout::suggested(
+ beast::role_type::client));
+
+ // Set a decorator to change the User-Agent of the handshake
+ ws_.set_option(websocket::stream_base::decorator(
+ [](websocket::request_type& req)
+ {
+ req.set(http::field::user_agent,
+ std::string(BOOST_BEAST_VERSION_STRING) +
+ " websocket-client-async");
+ }));
+
+ // Update the host_ string. This will provide the value of the
+ // Host HTTP header during the WebSocket handshake.
+ // See https://tools.ietf.org/html/rfc7230#section-5.4
+ host_ += ':' + std::to_string(ep.port());
+
+ // Perform the websocket handshake
+ ws_.async_handshake(host_, "/",
+ beast::bind_front_handler(
+ &session::on_handshake,
+ shared_from_this()));
+ }
+
+ void
+ on_handshake(beast::error_code ec)
+ {
+ if(ec)
+ return fail(ec, "handshake");
+
+ // Send the message
+ ws_.async_write(
+ net::buffer(text_),
+ beast::bind_front_handler(
+ &session::on_write,
+ shared_from_this()));
+ }
+
+ void
+ on_write(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ if(ec)
+ return fail(ec, "write");
+
+ // Read a message into our buffer
+ ws_.async_read(
+ buffer_,
+ beast::bind_front_handler(
+ &session::on_read,
+ shared_from_this()));
+ }
+
+ void
+ on_read(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ if(ec)
+ return fail(ec, "read");
+
+ // Close the WebSocket connection
+ ws_.async_close(websocket::close_code::normal,
+ beast::bind_front_handler(
+ &session::on_close,
+ shared_from_this()));
+ }
+
+ void
+ on_close(beast::error_code ec)
+ {
+ if(ec)
+ return fail(ec, "close");
+
+ // If we get here then the connection is closed gracefully
+
+ // The make_printable() function helps print a ConstBufferSequence
+ std::cout << beast::make_printable(buffer_.data()) << std::endl;
+ }
+};
+
+//------------------------------------------------------------------------------
+
+int main(int argc, char** argv)
+{
+ // Check command line arguments.
+ if(argc != 4)
+ {
+ std::cerr <<
+ "Usage: websocket-client-async <host> <port> <text>\n" <<
+ "Example:\n" <<
+ " websocket-client-async echo.websocket.org 80 \"Hello, world!\"\n";
+ return EXIT_FAILURE;
+ }
+ auto const host = argv[1];
+ auto const port = argv[2];
+ auto const text = argv[3];
+
+ // The io_context is required for all I/O
+ net::io_context ioc;
+
+ // Launch the asynchronous operation
+ std::make_shared<session>(ioc)->run(host, port, text);
+
+ // Run the I/O service. The call will return when
+ // the socket is closed.
+ ioc.run();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/websocket/client/coro-ssl/CMakeLists.txt b/src/boost/libs/beast/example/websocket/client/coro-ssl/CMakeLists.txt
new file mode 100644
index 000000000..fe9db75c4
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/client/coro-ssl/CMakeLists.txt
@@ -0,0 +1,31 @@
+#
+# 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
+#
+
+if (OPENSSL_FOUND)
+ GroupSources(include/boost/beast beast)
+ GroupSources(example/common common)
+ GroupSources(example/websocket/client/coro-ssl "/")
+
+ add_executable (websocket-client-coro-ssl
+ ${BOOST_BEAST_FILES}
+ ${PROJECT_SOURCE_DIR}/example/common/root_certificates.hpp
+ Jamfile
+ websocket_client_coro_ssl.cpp
+ )
+
+ set_property(TARGET websocket-client-coro-ssl PROPERTY FOLDER "example-websocket-client")
+
+ target_link_libraries (websocket-client-coro-ssl
+ OpenSSL::SSL OpenSSL::Crypto
+ lib-asio
+ lib-asio-ssl
+ lib-beast
+ )
+
+endif()
diff --git a/src/boost/libs/beast/example/websocket/client/coro-ssl/Jamfile b/src/boost/libs/beast/example/websocket/client/coro-ssl/Jamfile
new file mode 100644
index 000000000..f6f1bb922
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/client/coro-ssl/Jamfile
@@ -0,0 +1,23 @@
+#
+# 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
+#
+
+import ac ;
+
+project
+ : requirements
+ [ ac.check-library /boost/beast//lib-asio-ssl : <library>/boost/beast//lib-asio-ssl/<link>static : <build>no ]
+ ;
+
+exe websocket-client-coro-ssl :
+ websocket_client_coro_ssl.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ <library>/boost/coroutine//boost_coroutine
+ ;
diff --git a/src/boost/libs/beast/example/websocket/client/coro-ssl/websocket_client_coro_ssl.cpp b/src/boost/libs/beast/example/websocket/client/coro-ssl/websocket_client_coro_ssl.cpp
new file mode 100644
index 000000000..5b4d9e9b4
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/client/coro-ssl/websocket_client_coro_ssl.cpp
@@ -0,0 +1,175 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: WebSocket SSL client, coroutine
+//
+//------------------------------------------------------------------------------
+
+#include "example/common/root_certificates.hpp"
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/ssl.hpp>
+#include <boost/beast/websocket.hpp>
+#include <boost/beast/websocket/ssl.hpp>
+#include <boost/asio/spawn.hpp>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <string>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+//------------------------------------------------------------------------------
+
+// Report a failure
+void
+fail(beast::error_code ec, char const* what)
+{
+ std::cerr << what << ": " << ec.message() << "\n";
+}
+
+// Sends a WebSocket message and prints the response
+void
+do_session(
+ std::string host,
+ std::string const& port,
+ std::string const& text,
+ net::io_context& ioc,
+ ssl::context& ctx,
+ net::yield_context yield)
+{
+ beast::error_code ec;
+
+ // These objects perform our I/O
+ tcp::resolver resolver(ioc);
+ websocket::stream<
+ beast::ssl_stream<beast::tcp_stream>> ws(ioc, ctx);
+
+ // Look up the domain name
+ auto const results = resolver.async_resolve(host, port, yield[ec]);
+ if(ec)
+ return fail(ec, "resolve");
+
+ // Set a timeout on the operation
+ beast::get_lowest_layer(ws).expires_after(std::chrono::seconds(30));
+
+ // Make the connection on the IP address we get from a lookup
+ auto ep = beast::get_lowest_layer(ws).async_connect(results, yield[ec]);
+ if(ec)
+ return fail(ec, "connect");
+
+ // Update the host_ string. This will provide the value of the
+ // Host HTTP header during the WebSocket handshake.
+ // See https://tools.ietf.org/html/rfc7230#section-5.4
+ host += ':' + std::to_string(ep.port());
+
+ // Set a timeout on the operation
+ beast::get_lowest_layer(ws).expires_after(std::chrono::seconds(30));
+
+ // Set a decorator to change the User-Agent of the handshake
+ ws.set_option(websocket::stream_base::decorator(
+ [](websocket::request_type& req)
+ {
+ req.set(http::field::user_agent,
+ std::string(BOOST_BEAST_VERSION_STRING) +
+ " websocket-client-coro");
+ }));
+
+ // Perform the SSL handshake
+ ws.next_layer().async_handshake(ssl::stream_base::client, yield[ec]);
+ if(ec)
+ return fail(ec, "ssl_handshake");
+
+ // Turn off the timeout on the tcp_stream, because
+ // the websocket stream has its own timeout system.
+ beast::get_lowest_layer(ws).expires_never();
+
+ // Set suggested timeout settings for the websocket
+ ws.set_option(
+ websocket::stream_base::timeout::suggested(
+ beast::role_type::client));
+
+ // Perform the websocket handshake
+ ws.async_handshake(host, "/", yield[ec]);
+ if(ec)
+ return fail(ec, "handshake");
+
+ // Send the message
+ ws.async_write(net::buffer(std::string(text)), yield[ec]);
+ if(ec)
+ return fail(ec, "write");
+
+ // This buffer will hold the incoming message
+ beast::flat_buffer buffer;
+
+ // Read a message into our buffer
+ ws.async_read(buffer, yield[ec]);
+ if(ec)
+ return fail(ec, "read");
+
+ // Close the WebSocket connection
+ ws.async_close(websocket::close_code::normal, yield[ec]);
+ if(ec)
+ return fail(ec, "close");
+
+ // If we get here then the connection is closed gracefully
+
+ // The make_printable() function helps print a ConstBufferSequence
+ std::cout << beast::make_printable(buffer.data()) << std::endl;
+}
+
+//------------------------------------------------------------------------------
+
+int main(int argc, char** argv)
+{
+ // Check command line arguments.
+ if(argc != 4)
+ {
+ std::cerr <<
+ "Usage: websocket-client-coro-ssl <host> <port> <text>\n" <<
+ "Example:\n" <<
+ " websocket-client-coro-ssl echo.websocket.org 443 \"Hello, world!\"\n";
+ return EXIT_FAILURE;
+ }
+ auto const host = argv[1];
+ auto const port = argv[2];
+ auto const text = argv[3];
+
+ // The io_context is required for all I/O
+ net::io_context ioc;
+
+ // The SSL context is required, and holds certificates
+ ssl::context ctx{ssl::context::tlsv12_client};
+
+ // This holds the root certificate used for verification
+ load_root_certificates(ctx);
+
+ // Launch the asynchronous operation
+ boost::asio::spawn(ioc, std::bind(
+ &do_session,
+ std::string(host),
+ std::string(port),
+ std::string(text),
+ std::ref(ioc),
+ std::ref(ctx),
+ std::placeholders::_1));
+
+ // Run the I/O service. The call will return when
+ // the socket is closed.
+ ioc.run();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/websocket/client/coro/CMakeLists.txt b/src/boost/libs/beast/example/websocket/client/coro/CMakeLists.txt
new file mode 100644
index 000000000..2bfeef282
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/client/coro/CMakeLists.txt
@@ -0,0 +1,23 @@
+#
+# 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
+#
+
+GroupSources(include/boost/beast beast)
+GroupSources(example/websocket/client/coro "/")
+
+add_executable (websocket-client-coro
+ ${BOOST_BEAST_FILES}
+ Jamfile
+ websocket_client_coro.cpp
+)
+
+target_link_libraries(websocket-client-coro
+ lib-asio
+ lib-beast)
+
+set_property(TARGET websocket-client-coro PROPERTY FOLDER "example-websocket-client")
diff --git a/src/boost/libs/beast/example/websocket/client/coro/Jamfile b/src/boost/libs/beast/example/websocket/client/coro/Jamfile
new file mode 100644
index 000000000..761dfe8ff
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/client/coro/Jamfile
@@ -0,0 +1,16 @@
+#
+# 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
+#
+
+exe websocket-client-coro :
+ websocket_client_coro.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ <library>/boost/coroutine//boost_coroutine
+ ;
diff --git a/src/boost/libs/beast/example/websocket/client/coro/websocket_client_coro.cpp b/src/boost/libs/beast/example/websocket/client/coro/websocket_client_coro.cpp
new file mode 100644
index 000000000..7a4b0616d
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/client/coro/websocket_client_coro.cpp
@@ -0,0 +1,153 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: WebSocket client, coroutine
+//
+//------------------------------------------------------------------------------
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/websocket.hpp>
+#include <boost/asio/spawn.hpp>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <string>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+//------------------------------------------------------------------------------
+
+// Report a failure
+void
+fail(beast::error_code ec, char const* what)
+{
+ std::cerr << what << ": " << ec.message() << "\n";
+}
+
+// Sends a WebSocket message and prints the response
+void
+do_session(
+ std::string host,
+ std::string const& port,
+ std::string const& text,
+ net::io_context& ioc,
+ net::yield_context yield)
+{
+ beast::error_code ec;
+
+ // These objects perform our I/O
+ tcp::resolver resolver(ioc);
+ websocket::stream<beast::tcp_stream> ws(ioc);
+
+ // Look up the domain name
+ auto const results = resolver.async_resolve(host, port, yield[ec]);
+ if(ec)
+ return fail(ec, "resolve");
+
+ // Set a timeout on the operation
+ beast::get_lowest_layer(ws).expires_after(std::chrono::seconds(30));
+
+ // Make the connection on the IP address we get from a lookup
+ auto ep = beast::get_lowest_layer(ws).async_connect(results, yield[ec]);
+ if(ec)
+ return fail(ec, "connect");
+
+ // Update the host_ string. This will provide the value of the
+ // Host HTTP header during the WebSocket handshake.
+ // See https://tools.ietf.org/html/rfc7230#section-5.4
+ host += ':' + std::to_string(ep.port());
+
+ // Turn off the timeout on the tcp_stream, because
+ // the websocket stream has its own timeout system.
+ beast::get_lowest_layer(ws).expires_never();
+
+ // Set suggested timeout settings for the websocket
+ ws.set_option(
+ websocket::stream_base::timeout::suggested(
+ beast::role_type::client));
+
+ // Set a decorator to change the User-Agent of the handshake
+ ws.set_option(websocket::stream_base::decorator(
+ [](websocket::request_type& req)
+ {
+ req.set(http::field::user_agent,
+ std::string(BOOST_BEAST_VERSION_STRING) +
+ " websocket-client-coro");
+ }));
+
+ // Perform the websocket handshake
+ ws.async_handshake(host, "/", yield[ec]);
+ if(ec)
+ return fail(ec, "handshake");
+
+ // Send the message
+ ws.async_write(net::buffer(std::string(text)), yield[ec]);
+ if(ec)
+ return fail(ec, "write");
+
+ // This buffer will hold the incoming message
+ beast::flat_buffer buffer;
+
+ // Read a message into our buffer
+ ws.async_read(buffer, yield[ec]);
+ if(ec)
+ return fail(ec, "read");
+
+ // Close the WebSocket connection
+ ws.async_close(websocket::close_code::normal, yield[ec]);
+ if(ec)
+ return fail(ec, "close");
+
+ // If we get here then the connection is closed gracefully
+
+ // The make_printable() function helps print a ConstBufferSequence
+ std::cout << beast::make_printable(buffer.data()) << std::endl;
+}
+
+//------------------------------------------------------------------------------
+
+int main(int argc, char** argv)
+{
+ // Check command line arguments.
+ if(argc != 4)
+ {
+ std::cerr <<
+ "Usage: websocket-client-coro <host> <port> <text>\n" <<
+ "Example:\n" <<
+ " websocket-client-coro echo.websocket.org 80 \"Hello, world!\"\n";
+ return EXIT_FAILURE;
+ }
+ auto const host = argv[1];
+ auto const port = argv[2];
+ auto const text = argv[3];
+
+ // The io_context is required for all I/O
+ net::io_context ioc;
+
+ // Launch the asynchronous operation
+ boost::asio::spawn(ioc, std::bind(
+ &do_session,
+ std::string(host),
+ std::string(port),
+ std::string(text),
+ std::ref(ioc),
+ std::placeholders::_1));
+
+ // Run the I/O service. The call will return when
+ // the socket is closed.
+ ioc.run();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/websocket/client/sync-ssl/CMakeLists.txt b/src/boost/libs/beast/example/websocket/client/sync-ssl/CMakeLists.txt
new file mode 100644
index 000000000..b84495702
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/client/sync-ssl/CMakeLists.txt
@@ -0,0 +1,31 @@
+#
+# 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
+#
+
+if (OPENSSL_FOUND)
+ GroupSources(include/boost/beast beast)
+ GroupSources(example/common common)
+ GroupSources(example/websocket/client/sync-ssl "/")
+
+ add_executable (websocket-client-sync-ssl
+ ${BOOST_BEAST_FILES}
+ ${PROJECT_SOURCE_DIR}/example/common/root_certificates.hpp
+ Jamfile
+ websocket_client_sync_ssl.cpp
+ )
+
+ set_property(TARGET websocket-client-sync-ssl PROPERTY FOLDER "example-websocket-client")
+
+ target_link_libraries (websocket-client-sync-ssl
+ OpenSSL::SSL OpenSSL::Crypto
+ lib-asio
+ lib-asio-ssl
+ lib-beast
+ )
+
+endif()
diff --git a/src/boost/libs/beast/example/websocket/client/sync-ssl/Jamfile b/src/boost/libs/beast/example/websocket/client/sync-ssl/Jamfile
new file mode 100644
index 000000000..0cfec0f68
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/client/sync-ssl/Jamfile
@@ -0,0 +1,22 @@
+#
+# 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
+#
+
+import ac ;
+
+project
+ : requirements
+ [ ac.check-library /boost/beast//lib-asio-ssl : <library>/boost/beast//lib-asio-ssl/<link>static : <build>no ]
+ ;
+
+exe websocket-client-sync-ssl :
+ websocket_client_sync_ssl.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ ;
diff --git a/src/boost/libs/beast/example/websocket/client/sync-ssl/websocket_client_sync_ssl.cpp b/src/boost/libs/beast/example/websocket/client/sync-ssl/websocket_client_sync_ssl.cpp
new file mode 100644
index 000000000..1a51f6b6b
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/client/sync-ssl/websocket_client_sync_ssl.cpp
@@ -0,0 +1,116 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: WebSocket SSL client, synchronous
+//
+//------------------------------------------------------------------------------
+
+#include "example/common/root_certificates.hpp"
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/ssl.hpp>
+#include <boost/beast/websocket.hpp>
+#include <boost/beast/websocket/ssl.hpp>
+#include <boost/asio/connect.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/ssl/stream.hpp>
+#include <cstdlib>
+#include <iostream>
+#include <string>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+// Sends a WebSocket message and prints the response
+int main(int argc, char** argv)
+{
+ try
+ {
+ // Check command line arguments.
+ if(argc != 4)
+ {
+ std::cerr <<
+ "Usage: websocket-client-sync-ssl <host> <port> <text>\n" <<
+ "Example:\n" <<
+ " websocket-client-sync-ssl echo.websocket.org 443 \"Hello, world!\"\n";
+ return EXIT_FAILURE;
+ }
+ std::string host = argv[1];
+ auto const port = argv[2];
+ auto const text = argv[3];
+
+ // The io_context is required for all I/O
+ net::io_context ioc;
+
+ // The SSL context is required, and holds certificates
+ ssl::context ctx{ssl::context::tlsv12_client};
+
+ // This holds the root certificate used for verification
+ load_root_certificates(ctx);
+
+ // These objects perform our I/O
+ tcp::resolver resolver{ioc};
+ websocket::stream<beast::ssl_stream<tcp::socket>> ws{ioc, ctx};
+
+ // Look up the domain name
+ auto const results = resolver.resolve(host, port);
+
+ // Make the connection on the IP address we get from a lookup
+ auto ep = net::connect(get_lowest_layer(ws), results);
+
+ // Update the host_ string. This will provide the value of the
+ // Host HTTP header during the WebSocket handshake.
+ // See https://tools.ietf.org/html/rfc7230#section-5.4
+ host += ':' + std::to_string(ep.port());
+
+ // Perform the SSL handshake
+ ws.next_layer().handshake(ssl::stream_base::client);
+
+ // Set a decorator to change the User-Agent of the handshake
+ ws.set_option(websocket::stream_base::decorator(
+ [](websocket::request_type& req)
+ {
+ req.set(http::field::user_agent,
+ std::string(BOOST_BEAST_VERSION_STRING) +
+ " websocket-client-coro");
+ }));
+
+ // Perform the websocket handshake
+ ws.handshake(host, "/");
+
+ // Send the message
+ ws.write(net::buffer(std::string(text)));
+
+ // This buffer will hold the incoming message
+ beast::flat_buffer buffer;
+
+ // Read a message into our buffer
+ ws.read(buffer);
+
+ // Close the WebSocket connection
+ ws.close(websocket::close_code::normal);
+
+ // If we get here then the connection is closed gracefully
+
+ // The make_printable() function helps print a ConstBufferSequence
+ std::cout << beast::make_printable(buffer.data()) << std::endl;
+ }
+ catch(std::exception const& e)
+ {
+ std::cerr << "Error: " << e.what() << std::endl;
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/websocket/client/sync/CMakeLists.txt b/src/boost/libs/beast/example/websocket/client/sync/CMakeLists.txt
new file mode 100644
index 000000000..d8606ab55
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/client/sync/CMakeLists.txt
@@ -0,0 +1,23 @@
+#
+# 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
+#
+
+GroupSources(include/boost/beast beast)
+GroupSources(example/websocket/client/sync "/")
+
+add_executable (websocket-client-sync
+ ${BOOST_BEAST_FILES}
+ Jamfile
+ websocket_client_sync.cpp
+)
+
+target_link_libraries(websocket-client-sync
+ lib-asio
+ lib-beast)
+
+set_property(TARGET websocket-client-sync PROPERTY FOLDER "example-websocket-client")
diff --git a/src/boost/libs/beast/example/websocket/client/sync/Jamfile b/src/boost/libs/beast/example/websocket/client/sync/Jamfile
new file mode 100644
index 000000000..ea71a0ce6
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/client/sync/Jamfile
@@ -0,0 +1,15 @@
+#
+# 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
+#
+
+exe websocket-client-sync :
+ websocket_client_sync.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ ;
diff --git a/src/boost/libs/beast/example/websocket/client/sync/websocket_client_sync.cpp b/src/boost/libs/beast/example/websocket/client/sync/websocket_client_sync.cpp
new file mode 100644
index 000000000..07409b70e
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/client/sync/websocket_client_sync.cpp
@@ -0,0 +1,105 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: WebSocket client, synchronous
+//
+//------------------------------------------------------------------------------
+
+//[example_websocket_client
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/websocket.hpp>
+#include <boost/asio/connect.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <cstdlib>
+#include <iostream>
+#include <string>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+// Sends a WebSocket message and prints the response
+int main(int argc, char** argv)
+{
+ try
+ {
+ // Check command line arguments.
+ if(argc != 4)
+ {
+ std::cerr <<
+ "Usage: websocket-client-sync <host> <port> <text>\n" <<
+ "Example:\n" <<
+ " websocket-client-sync echo.websocket.org 80 \"Hello, world!\"\n";
+ return EXIT_FAILURE;
+ }
+ std::string host = argv[1];
+ auto const port = argv[2];
+ auto const text = argv[3];
+
+ // The io_context is required for all I/O
+ net::io_context ioc;
+
+ // These objects perform our I/O
+ tcp::resolver resolver{ioc};
+ websocket::stream<tcp::socket> ws{ioc};
+
+ // Look up the domain name
+ auto const results = resolver.resolve(host, port);
+
+ // Make the connection on the IP address we get from a lookup
+ auto ep = net::connect(ws.next_layer(), results);
+
+ // Update the host_ string. This will provide the value of the
+ // Host HTTP header during the WebSocket handshake.
+ // See https://tools.ietf.org/html/rfc7230#section-5.4
+ host += ':' + std::to_string(ep.port());
+
+ // Set a decorator to change the User-Agent of the handshake
+ ws.set_option(websocket::stream_base::decorator(
+ [](websocket::request_type& req)
+ {
+ req.set(http::field::user_agent,
+ std::string(BOOST_BEAST_VERSION_STRING) +
+ " websocket-client-coro");
+ }));
+
+ // Perform the websocket handshake
+ ws.handshake(host, "/");
+
+ // Send the message
+ ws.write(net::buffer(std::string(text)));
+
+ // This buffer will hold the incoming message
+ beast::flat_buffer buffer;
+
+ // Read a message into our buffer
+ ws.read(buffer);
+
+ // Close the WebSocket connection
+ ws.close(websocket::close_code::normal);
+
+ // If we get here then the connection is closed gracefully
+
+ // The make_printable() function helps print a ConstBufferSequence
+ std::cout << beast::make_printable(buffer.data()) << std::endl;
+ }
+ catch(std::exception const& e)
+ {
+ std::cerr << "Error: " << e.what() << std::endl;
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
+}
+
+//]
diff --git a/src/boost/libs/beast/example/websocket/server/CMakeLists.txt b/src/boost/libs/beast/example/websocket/server/CMakeLists.txt
new file mode 100644
index 000000000..c5b8da5d6
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/CMakeLists.txt
@@ -0,0 +1,22 @@
+#
+# Copyright (c) 2013-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
+#
+
+add_subdirectory (async)
+add_subdirectory (chat-multi)
+add_subdirectory (coro)
+add_subdirectory (fast)
+add_subdirectory (stackless)
+add_subdirectory (sync)
+
+if (OPENSSL_FOUND)
+ add_subdirectory (async-ssl)
+ add_subdirectory (coro-ssl)
+ add_subdirectory (stackless-ssl)
+ add_subdirectory (sync-ssl)
+endif()
diff --git a/src/boost/libs/beast/example/websocket/server/Jamfile b/src/boost/libs/beast/example/websocket/server/Jamfile
new file mode 100644
index 000000000..ccfd63fa4
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/Jamfile
@@ -0,0 +1,21 @@
+#
+# Copyright (c) 2013-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
+#
+
+build-project async ;
+build-project chat-multi ;
+build-project coro ;
+build-project fast ;
+build-project stackless ;
+build-project sync ;
+
+# SSL
+build-project async-ssl ;
+build-project coro-ssl ;
+build-project stackless-ssl ;
+build-project sync-ssl ;
diff --git a/src/boost/libs/beast/example/websocket/server/async-ssl/CMakeLists.txt b/src/boost/libs/beast/example/websocket/server/async-ssl/CMakeLists.txt
new file mode 100644
index 000000000..8f1055d2f
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/async-ssl/CMakeLists.txt
@@ -0,0 +1,31 @@
+#
+# 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
+#
+
+if (OPENSSL_FOUND)
+ GroupSources(include/boost/beast beast)
+ GroupSources(example/common common)
+ GroupSources(example/websocket/server/async-ssl "/")
+
+ add_executable (websocket-server-async-ssl
+ ${BOOST_BEAST_FILES}
+ ${PROJECT_SOURCE_DIR}/example/common/server_certificate.hpp
+ Jamfile
+ websocket_server_async_ssl.cpp
+ )
+
+ set_property(TARGET websocket-server-async-ssl PROPERTY FOLDER "example-websocket-server")
+
+ target_link_libraries (websocket-server-async-ssl
+ OpenSSL::SSL OpenSSL::Crypto
+ lib-asio
+ lib-asio-ssl
+ lib-beast
+ )
+
+endif()
diff --git a/src/boost/libs/beast/example/websocket/server/async-ssl/Jamfile b/src/boost/libs/beast/example/websocket/server/async-ssl/Jamfile
new file mode 100644
index 000000000..f9b253a0c
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/async-ssl/Jamfile
@@ -0,0 +1,22 @@
+#
+# 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
+#
+
+import ac ;
+
+project
+ : requirements
+ [ ac.check-library /boost/beast//lib-asio-ssl : <library>/boost/beast//lib-asio-ssl/<link>static : <build>no ]
+ ;
+
+exe websocket-server-async-ssl :
+ websocket_server_async_ssl.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ ;
diff --git a/src/boost/libs/beast/example/websocket/server/async-ssl/websocket_server_async_ssl.cpp b/src/boost/libs/beast/example/websocket/server/async-ssl/websocket_server_async_ssl.cpp
new file mode 100644
index 000000000..b79abbbfb
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/async-ssl/websocket_server_async_ssl.cpp
@@ -0,0 +1,317 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: WebSocket SSL server, asynchronous
+//
+//------------------------------------------------------------------------------
+
+#include "example/common/server_certificate.hpp"
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/ssl.hpp>
+#include <boost/beast/websocket.hpp>
+#include <boost/beast/websocket/ssl.hpp>
+#include <boost/asio/strand.hpp>
+#include <boost/asio/dispatch.hpp>
+#include <algorithm>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <thread>
+#include <vector>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+//------------------------------------------------------------------------------
+
+// Report a failure
+void
+fail(beast::error_code ec, char const* what)
+{
+ std::cerr << what << ": " << ec.message() << "\n";
+}
+
+// Echoes back all received WebSocket messages
+class session : public std::enable_shared_from_this<session>
+{
+ websocket::stream<
+ beast::ssl_stream<beast::tcp_stream>> ws_;
+ beast::flat_buffer buffer_;
+
+public:
+ // Take ownership of the socket
+ session(tcp::socket&& socket, ssl::context& ctx)
+ : ws_(std::move(socket), ctx)
+ {
+ }
+
+ // Get on the correct executor
+ void
+ run()
+ {
+ // We need to be executing within a strand to perform async operations
+ // on the I/O objects in this session. Although not strictly necessary
+ // for single-threaded contexts, this example code is written to be
+ // thread-safe by default.
+ net::dispatch(ws_.get_executor(),
+ beast::bind_front_handler(
+ &session::on_run,
+ shared_from_this()));
+ }
+
+ // Start the asynchronous operation
+ void
+ on_run()
+ {
+ // Set the timeout.
+ beast::get_lowest_layer(ws_).expires_after(std::chrono::seconds(30));
+
+ // Perform the SSL handshake
+ ws_.next_layer().async_handshake(
+ ssl::stream_base::server,
+ beast::bind_front_handler(
+ &session::on_handshake,
+ shared_from_this()));
+ }
+
+ void
+ on_handshake(beast::error_code ec)
+ {
+ if(ec)
+ return fail(ec, "handshake");
+
+ // Turn off the timeout on the tcp_stream, because
+ // the websocket stream has its own timeout system.
+ beast::get_lowest_layer(ws_).expires_never();
+
+ // Set suggested timeout settings for the websocket
+ ws_.set_option(
+ websocket::stream_base::timeout::suggested(
+ beast::role_type::server));
+
+ // Set a decorator to change the Server of the handshake
+ ws_.set_option(websocket::stream_base::decorator(
+ [](websocket::response_type& res)
+ {
+ res.set(http::field::server,
+ std::string(BOOST_BEAST_VERSION_STRING) +
+ " websocket-server-async-ssl");
+ }));
+
+ // Accept the websocket handshake
+ ws_.async_accept(
+ beast::bind_front_handler(
+ &session::on_accept,
+ shared_from_this()));
+ }
+
+ void
+ on_accept(beast::error_code ec)
+ {
+ if(ec)
+ return fail(ec, "accept");
+
+ // Read a message
+ do_read();
+ }
+
+ void
+ do_read()
+ {
+ // Read a message into our buffer
+ ws_.async_read(
+ buffer_,
+ beast::bind_front_handler(
+ &session::on_read,
+ shared_from_this()));
+ }
+
+ void
+ on_read(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ // This indicates that the session was closed
+ if(ec == websocket::error::closed)
+ return;
+
+ if(ec)
+ fail(ec, "read");
+
+ // Echo the message
+ ws_.text(ws_.got_text());
+ ws_.async_write(
+ buffer_.data(),
+ beast::bind_front_handler(
+ &session::on_write,
+ shared_from_this()));
+ }
+
+ void
+ on_write(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ if(ec)
+ return fail(ec, "write");
+
+ // Clear the buffer
+ buffer_.consume(buffer_.size());
+
+ // Do another read
+ do_read();
+ }
+};
+
+//------------------------------------------------------------------------------
+
+// Accepts incoming connections and launches the sessions
+class listener : public std::enable_shared_from_this<listener>
+{
+ net::io_context& ioc_;
+ ssl::context& ctx_;
+ tcp::acceptor acceptor_;
+
+public:
+ listener(
+ net::io_context& ioc,
+ ssl::context& ctx,
+ tcp::endpoint endpoint)
+ : ioc_(ioc)
+ , ctx_(ctx)
+ , acceptor_(net::make_strand(ioc))
+ {
+ beast::error_code ec;
+
+ // Open the acceptor
+ acceptor_.open(endpoint.protocol(), ec);
+ if(ec)
+ {
+ fail(ec, "open");
+ return;
+ }
+
+ // Allow address reuse
+ acceptor_.set_option(net::socket_base::reuse_address(true), ec);
+ if(ec)
+ {
+ fail(ec, "set_option");
+ return;
+ }
+
+ // Bind to the server address
+ acceptor_.bind(endpoint, ec);
+ if(ec)
+ {
+ fail(ec, "bind");
+ return;
+ }
+
+ // Start listening for connections
+ acceptor_.listen(
+ net::socket_base::max_listen_connections, ec);
+ if(ec)
+ {
+ fail(ec, "listen");
+ return;
+ }
+ }
+
+ // Start accepting incoming connections
+ void
+ run()
+ {
+ do_accept();
+ }
+
+private:
+ void
+ do_accept()
+ {
+ // The new connection gets its own strand
+ acceptor_.async_accept(
+ net::make_strand(ioc_),
+ beast::bind_front_handler(
+ &listener::on_accept,
+ shared_from_this()));
+ }
+
+ void
+ on_accept(beast::error_code ec, tcp::socket socket)
+ {
+ if(ec)
+ {
+ fail(ec, "accept");
+ }
+ else
+ {
+ // Create the session and run it
+ std::make_shared<session>(std::move(socket), ctx_)->run();
+ }
+
+ // Accept another connection
+ do_accept();
+ }
+};
+
+//------------------------------------------------------------------------------
+
+int main(int argc, char* argv[])
+{
+ // Check command line arguments.
+ if (argc != 4)
+ {
+ std::cerr <<
+ "Usage: websocket-server-async-ssl <address> <port> <threads>\n" <<
+ "Example:\n" <<
+ " websocket-server-async-ssl 0.0.0.0 8080 1\n";
+ return EXIT_FAILURE;
+ }
+ auto const address = net::ip::make_address(argv[1]);
+ auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
+ auto const threads = std::max<int>(1, std::atoi(argv[3]));
+
+ // The io_context is required for all I/O
+ net::io_context ioc{threads};
+
+ // The SSL context is required, and holds certificates
+ ssl::context ctx{ssl::context::tlsv12};
+
+ // This holds the self-signed certificate used by the server
+ load_server_certificate(ctx);
+
+ // Create and launch a listening port
+ std::make_shared<listener>(ioc, ctx, tcp::endpoint{address, port})->run();
+
+ // Run the I/O service on the requested number of threads
+ std::vector<std::thread> v;
+ v.reserve(threads - 1);
+ for(auto i = threads - 1; i > 0; --i)
+ v.emplace_back(
+ [&ioc]
+ {
+ ioc.run();
+ });
+ ioc.run();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/websocket/server/async/CMakeLists.txt b/src/boost/libs/beast/example/websocket/server/async/CMakeLists.txt
new file mode 100644
index 000000000..0e1ceb8b6
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/async/CMakeLists.txt
@@ -0,0 +1,23 @@
+#
+# 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
+#
+
+GroupSources(include/boost/beast beast)
+GroupSources(example/websocket/server/async "/")
+
+add_executable (websocket-server-async
+ ${BOOST_BEAST_FILES}
+ Jamfile
+ websocket_server_async.cpp
+)
+
+target_link_libraries(websocket-server-async
+ lib-asio
+ lib-beast)
+
+set_property(TARGET websocket-server-async PROPERTY FOLDER "example-websocket-server")
diff --git a/src/boost/libs/beast/example/websocket/server/async/Jamfile b/src/boost/libs/beast/example/websocket/server/async/Jamfile
new file mode 100644
index 000000000..e1e63e14d
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/async/Jamfile
@@ -0,0 +1,15 @@
+#
+# 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
+#
+
+exe websocket-server-async :
+ websocket_server_async.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ ;
diff --git a/src/boost/libs/beast/example/websocket/server/async/websocket_server_async.cpp b/src/boost/libs/beast/example/websocket/server/async/websocket_server_async.cpp
new file mode 100644
index 000000000..4b9570868
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/async/websocket_server_async.cpp
@@ -0,0 +1,281 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: WebSocket server, asynchronous
+//
+//------------------------------------------------------------------------------
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/websocket.hpp>
+#include <boost/asio/dispatch.hpp>
+#include <boost/asio/strand.hpp>
+#include <algorithm>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <thread>
+#include <vector>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+//------------------------------------------------------------------------------
+
+// Report a failure
+void
+fail(beast::error_code ec, char const* what)
+{
+ std::cerr << what << ": " << ec.message() << "\n";
+}
+
+// Echoes back all received WebSocket messages
+class session : public std::enable_shared_from_this<session>
+{
+ websocket::stream<beast::tcp_stream> ws_;
+ beast::flat_buffer buffer_;
+
+public:
+ // Take ownership of the socket
+ explicit
+ session(tcp::socket&& socket)
+ : ws_(std::move(socket))
+ {
+ }
+
+ // Get on the correct executor
+ void
+ run()
+ {
+ // We need to be executing within a strand to perform async operations
+ // on the I/O objects in this session. Although not strictly necessary
+ // for single-threaded contexts, this example code is written to be
+ // thread-safe by default.
+ net::dispatch(ws_.get_executor(),
+ beast::bind_front_handler(
+ &session::on_run,
+ shared_from_this()));
+ }
+
+ // Start the asynchronous operation
+ void
+ on_run()
+ {
+ // Set suggested timeout settings for the websocket
+ ws_.set_option(
+ websocket::stream_base::timeout::suggested(
+ beast::role_type::server));
+
+ // Set a decorator to change the Server of the handshake
+ ws_.set_option(websocket::stream_base::decorator(
+ [](websocket::response_type& res)
+ {
+ res.set(http::field::server,
+ std::string(BOOST_BEAST_VERSION_STRING) +
+ " websocket-server-async");
+ }));
+ // Accept the websocket handshake
+ ws_.async_accept(
+ beast::bind_front_handler(
+ &session::on_accept,
+ shared_from_this()));
+ }
+
+ void
+ on_accept(beast::error_code ec)
+ {
+ if(ec)
+ return fail(ec, "accept");
+
+ // Read a message
+ do_read();
+ }
+
+ void
+ do_read()
+ {
+ // Read a message into our buffer
+ ws_.async_read(
+ buffer_,
+ beast::bind_front_handler(
+ &session::on_read,
+ shared_from_this()));
+ }
+
+ void
+ on_read(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ // This indicates that the session was closed
+ if(ec == websocket::error::closed)
+ return;
+
+ if(ec)
+ fail(ec, "read");
+
+ // Echo the message
+ ws_.text(ws_.got_text());
+ ws_.async_write(
+ buffer_.data(),
+ beast::bind_front_handler(
+ &session::on_write,
+ shared_from_this()));
+ }
+
+ void
+ on_write(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ if(ec)
+ return fail(ec, "write");
+
+ // Clear the buffer
+ buffer_.consume(buffer_.size());
+
+ // Do another read
+ do_read();
+ }
+};
+
+//------------------------------------------------------------------------------
+
+// Accepts incoming connections and launches the sessions
+class listener : public std::enable_shared_from_this<listener>
+{
+ net::io_context& ioc_;
+ tcp::acceptor acceptor_;
+
+public:
+ listener(
+ net::io_context& ioc,
+ tcp::endpoint endpoint)
+ : ioc_(ioc)
+ , acceptor_(ioc)
+ {
+ beast::error_code ec;
+
+ // Open the acceptor
+ acceptor_.open(endpoint.protocol(), ec);
+ if(ec)
+ {
+ fail(ec, "open");
+ return;
+ }
+
+ // Allow address reuse
+ acceptor_.set_option(net::socket_base::reuse_address(true), ec);
+ if(ec)
+ {
+ fail(ec, "set_option");
+ return;
+ }
+
+ // Bind to the server address
+ acceptor_.bind(endpoint, ec);
+ if(ec)
+ {
+ fail(ec, "bind");
+ return;
+ }
+
+ // Start listening for connections
+ acceptor_.listen(
+ net::socket_base::max_listen_connections, ec);
+ if(ec)
+ {
+ fail(ec, "listen");
+ return;
+ }
+ }
+
+ // Start accepting incoming connections
+ void
+ run()
+ {
+ do_accept();
+ }
+
+private:
+ void
+ do_accept()
+ {
+ // The new connection gets its own strand
+ acceptor_.async_accept(
+ net::make_strand(ioc_),
+ beast::bind_front_handler(
+ &listener::on_accept,
+ shared_from_this()));
+ }
+
+ void
+ on_accept(beast::error_code ec, tcp::socket socket)
+ {
+ if(ec)
+ {
+ fail(ec, "accept");
+ }
+ else
+ {
+ // Create the session and run it
+ std::make_shared<session>(std::move(socket))->run();
+ }
+
+ // Accept another connection
+ do_accept();
+ }
+};
+
+//------------------------------------------------------------------------------
+
+int main(int argc, char* argv[])
+{
+ // Check command line arguments.
+ if (argc != 4)
+ {
+ std::cerr <<
+ "Usage: websocket-server-async <address> <port> <threads>\n" <<
+ "Example:\n" <<
+ " websocket-server-async 0.0.0.0 8080 1\n";
+ return EXIT_FAILURE;
+ }
+ auto const address = net::ip::make_address(argv[1]);
+ auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
+ auto const threads = std::max<int>(1, std::atoi(argv[3]));
+
+ // The io_context is required for all I/O
+ net::io_context ioc{threads};
+
+ // Create and launch a listening port
+ std::make_shared<listener>(ioc, tcp::endpoint{address, port})->run();
+
+ // Run the I/O service on the requested number of threads
+ std::vector<std::thread> v;
+ v.reserve(threads - 1);
+ for(auto i = threads - 1; i > 0; --i)
+ v.emplace_back(
+ [&ioc]
+ {
+ ioc.run();
+ });
+ ioc.run();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/websocket/server/chat-multi/CMakeLists.txt b/src/boost/libs/beast/example/websocket/server/chat-multi/CMakeLists.txt
new file mode 100644
index 000000000..a256b000f
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/chat-multi/CMakeLists.txt
@@ -0,0 +1,41 @@
+#
+# 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
+#
+
+GroupSources(include/boost/beast beast)
+GroupSources(example/websocket/server/chat-multi "/")
+
+file (GLOB APP_FILES
+ beast.hpp
+ http_session.cpp
+ http_session.hpp
+ Jamfile
+ listener.cpp
+ listener.hpp
+ main.cpp
+ net.hpp
+ shared_state.cpp
+ shared_state.hpp
+ websocket_session.cpp
+ websocket_session.hpp
+ chat_client.html
+ README.md
+)
+
+source_group ("" FILES ${APP_FILES})
+
+add_executable (websocket-chat-multi
+ ${APP_FILES}
+ ${BOOST_BEAST_FILES}
+)
+
+target_link_libraries(websocket-chat-multi
+ lib-asio
+ lib-beast)
+
+set_property(TARGET websocket-chat-multi PROPERTY FOLDER "example-websocket-server")
diff --git a/src/boost/libs/beast/example/websocket/server/chat-multi/Jamfile b/src/boost/libs/beast/example/websocket/server/chat-multi/Jamfile
new file mode 100644
index 000000000..a8d49bfdd
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/chat-multi/Jamfile
@@ -0,0 +1,19 @@
+#
+# 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
+#
+
+exe websocket-chat-multi :
+ http_session.cpp
+ listener.cpp
+ main.cpp
+ shared_state.cpp
+ websocket_session.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ ;
diff --git a/src/boost/libs/beast/example/websocket/server/chat-multi/beast.hpp b/src/boost/libs/beast/example/websocket/server/chat-multi/beast.hpp
new file mode 100644
index 000000000..0b7a9c61a
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/chat-multi/beast.hpp
@@ -0,0 +1,19 @@
+//
+// Copyright (c) 2016-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/vinniefalco/CppCon2018
+//
+
+#ifndef BOOST_BEAST_EXAMPLE_WEBSOCKET_CHAT_MULTI_BEAST_HPP
+#define BOOST_BEAST_EXAMPLE_WEBSOCKET_CHAT_MULTI_BEAST_HPP
+
+#include <boost/beast.hpp>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
+
+#endif
diff --git a/src/boost/libs/beast/example/websocket/server/chat-multi/chat_client.html b/src/boost/libs/beast/example/websocket/server/chat-multi/chat_client.html
new file mode 100644
index 000000000..2be69cdf0
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/chat-multi/chat_client.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>Boost.Beast WebSocket Chat Client</title>
+</head>
+<body>
+ <h1>Boost.Beast WebSocket Chat Client</h1>
+ <p>
+ <a href="http://www.boost.org/libs/beast">Boost.Beast</a>
+ <a href="http://www.boost.org/libs/beast/example/websocket/server/chat-multi">Source Code</a>
+ </p>
+ Server URI: <input class="draw-border" id="uri" size="47" value="ws://localhost:8080" style="margin-bottom: 5px;">
+ <button class="echo-button" id="connect">Connect</button>
+ <button class="echo-button" id="disconnect">Disconnect</button><br>
+ Your Name: <input class="draw-border" id="userName" size=47 style="margin-bottom: 5px;"><br>
+ <pre id="messages" style="width: 600px; height: 400px; white-space: normal; overflow: auto; border: solid 1px #cccccc; margin-bottom: 5px;"></pre>
+ <div style="margin-bottom: 5px;">
+ Message<br>
+ <input class="draw-border" id="sendMessage" size="74" value="">
+ <button class="echo-button" id="send">Send</button>
+ </div>
+ <script>
+ var ws = null;
+ function showMessage(msg) {
+ messages.innerText += msg + "\n";
+ messages.scrollTop = messages.scrollHeight - messages.clientHeight;
+ };
+ connect.onclick = function() {
+ ws = new WebSocket(uri.value);
+ ws.onopen = function(ev) {
+ showMessage("[connection opened]");
+ };
+ ws.onclose = function(ev) {
+ showMessage("[connection closed]");
+ };
+ ws.onmessage = function(ev) {
+ showMessage(ev.data);
+ };
+ ws.onerror = function(ev) {
+ showMessage("[error]");
+ console.log(ev);
+ };
+ };
+ disconnect.onclick = function() {
+ ws.close();
+ };
+ send.onclick = function() {
+ ws.send(userName.value + ": " + sendMessage.value);
+ sendMessage.value = "";
+ };
+ sendMessage.onkeyup = function(ev) {
+ ev.preventDefault();
+ if (ev.keyCode === 13) {
+ send.click();
+ }
+ }
+ </script>
+</body>
+</html>
diff --git a/src/boost/libs/beast/example/websocket/server/chat-multi/http_session.cpp b/src/boost/libs/beast/example/websocket/server/chat-multi/http_session.cpp
new file mode 100644
index 000000000..9d4dee871
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/chat-multi/http_session.cpp
@@ -0,0 +1,371 @@
+//
+// Copyright (c) 2016-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/vinniefalco/CppCon2018
+//
+
+#include "http_session.hpp"
+#include "websocket_session.hpp"
+#include <boost/config.hpp>
+#include <iostream>
+
+#define BOOST_NO_CXX14_GENERIC_LAMBDAS
+
+//------------------------------------------------------------------------------
+
+// Return a reasonable mime type based on the extension of a file.
+beast::string_view
+mime_type(beast::string_view path)
+{
+ using beast::iequals;
+ auto const ext = [&path]
+ {
+ auto const pos = path.rfind(".");
+ if(pos == beast::string_view::npos)
+ return beast::string_view{};
+ return path.substr(pos);
+ }();
+ if(iequals(ext, ".htm")) return "text/html";
+ if(iequals(ext, ".html")) return "text/html";
+ if(iequals(ext, ".php")) return "text/html";
+ if(iequals(ext, ".css")) return "text/css";
+ if(iequals(ext, ".txt")) return "text/plain";
+ if(iequals(ext, ".js")) return "application/javascript";
+ if(iequals(ext, ".json")) return "application/json";
+ if(iequals(ext, ".xml")) return "application/xml";
+ if(iequals(ext, ".swf")) return "application/x-shockwave-flash";
+ if(iequals(ext, ".flv")) return "video/x-flv";
+ if(iequals(ext, ".png")) return "image/png";
+ if(iequals(ext, ".jpe")) return "image/jpeg";
+ if(iequals(ext, ".jpeg")) return "image/jpeg";
+ if(iequals(ext, ".jpg")) return "image/jpeg";
+ if(iequals(ext, ".gif")) return "image/gif";
+ if(iequals(ext, ".bmp")) return "image/bmp";
+ if(iequals(ext, ".ico")) return "image/vnd.microsoft.icon";
+ if(iequals(ext, ".tiff")) return "image/tiff";
+ if(iequals(ext, ".tif")) return "image/tiff";
+ if(iequals(ext, ".svg")) return "image/svg+xml";
+ if(iequals(ext, ".svgz")) return "image/svg+xml";
+ return "application/text";
+}
+
+// Append an HTTP rel-path to a local filesystem path.
+// The returned path is normalized for the platform.
+std::string
+path_cat(
+ beast::string_view base,
+ beast::string_view path)
+{
+ if(base.empty())
+ return std::string(path);
+ std::string result(base);
+#ifdef BOOST_MSVC
+ char constexpr path_separator = '\\';
+ if(result.back() == path_separator)
+ result.resize(result.size() - 1);
+ result.append(path.data(), path.size());
+ for(auto& c : result)
+ if(c == '/')
+ c = path_separator;
+#else
+ char constexpr path_separator = '/';
+ if(result.back() == path_separator)
+ result.resize(result.size() - 1);
+ result.append(path.data(), path.size());
+#endif
+ return result;
+}
+
+// This function produces an HTTP response for the given
+// request. The type of the response object depends on the
+// contents of the request, so the interface requires the
+// caller to pass a generic lambda for receiving the response.
+template<
+ class Body, class Allocator,
+ class Send>
+void
+handle_request(
+ beast::string_view doc_root,
+ http::request<Body, http::basic_fields<Allocator>>&& req,
+ Send&& send)
+{
+ // Returns a bad request response
+ auto const bad_request =
+ [&req](beast::string_view why)
+ {
+ http::response<http::string_body> res{http::status::bad_request, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = std::string(why);
+ res.prepare_payload();
+ return res;
+ };
+
+ // Returns a not found response
+ auto const not_found =
+ [&req](beast::string_view target)
+ {
+ http::response<http::string_body> res{http::status::not_found, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = "The resource '" + std::string(target) + "' was not found.";
+ res.prepare_payload();
+ return res;
+ };
+
+ // Returns a server error response
+ auto const server_error =
+ [&req](beast::string_view what)
+ {
+ http::response<http::string_body> res{http::status::internal_server_error, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, "text/html");
+ res.keep_alive(req.keep_alive());
+ res.body() = "An error occurred: '" + std::string(what) + "'";
+ res.prepare_payload();
+ return res;
+ };
+
+ // Make sure we can handle the method
+ if( req.method() != http::verb::get &&
+ req.method() != http::verb::head)
+ return send(bad_request("Unknown HTTP-method"));
+
+ // Request path must be absolute and not contain "..".
+ if( req.target().empty() ||
+ req.target()[0] != '/' ||
+ req.target().find("..") != beast::string_view::npos)
+ return send(bad_request("Illegal request-target"));
+
+ // Build the path to the requested file
+ std::string path = path_cat(doc_root, req.target());
+ if(req.target().back() == '/')
+ path.append("index.html");
+
+ // Attempt to open the file
+ beast::error_code ec;
+ http::file_body::value_type body;
+ body.open(path.c_str(), beast::file_mode::scan, ec);
+
+ // Handle the case where the file doesn't exist
+ if(ec == boost::system::errc::no_such_file_or_directory)
+ return send(not_found(req.target()));
+
+ // Handle an unknown error
+ if(ec)
+ return send(server_error(ec.message()));
+
+ // Cache the size since we need it after the move
+ auto const size = body.size();
+
+ // Respond to HEAD request
+ if(req.method() == http::verb::head)
+ {
+ http::response<http::empty_body> res{http::status::ok, req.version()};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, mime_type(path));
+ res.content_length(size);
+ res.keep_alive(req.keep_alive());
+ return send(std::move(res));
+ }
+
+ // Respond to GET request
+ http::response<http::file_body> res{
+ std::piecewise_construct,
+ std::make_tuple(std::move(body)),
+ std::make_tuple(http::status::ok, req.version())};
+ res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
+ res.set(http::field::content_type, mime_type(path));
+ res.content_length(size);
+ res.keep_alive(req.keep_alive());
+ return send(std::move(res));
+}
+
+//------------------------------------------------------------------------------
+
+struct http_session::send_lambda
+{
+ http_session& self_;
+
+ explicit
+ send_lambda(http_session& self)
+ : self_(self)
+ {
+ }
+
+ template<bool isRequest, class Body, class Fields>
+ void
+ operator()(http::message<isRequest, Body, Fields>&& msg) const
+ {
+ // The lifetime of the message has to extend
+ // for the duration of the async operation so
+ // we use a shared_ptr to manage it.
+ auto sp = boost::make_shared<
+ http::message<isRequest, Body, Fields>>(std::move(msg));
+
+ // Write the response
+ auto self = self_.shared_from_this();
+ http::async_write(
+ self_.stream_,
+ *sp,
+ [self, sp](beast::error_code ec, std::size_t bytes)
+ {
+ self->on_write(ec, bytes, sp->need_eof());
+ });
+ }
+};
+
+//------------------------------------------------------------------------------
+
+http_session::
+http_session(
+ tcp::socket&& socket,
+ boost::shared_ptr<shared_state> const& state)
+ : stream_(std::move(socket))
+ , state_(state)
+{
+}
+
+void
+http_session::
+run()
+{
+ do_read();
+}
+
+// Report a failure
+void
+http_session::
+fail(beast::error_code ec, char const* what)
+{
+ // Don't report on canceled operations
+ if(ec == net::error::operation_aborted)
+ return;
+
+ std::cerr << what << ": " << ec.message() << "\n";
+}
+
+void
+http_session::
+do_read()
+{
+ // Construct a new parser for each message
+ parser_.emplace();
+
+ // Apply a reasonable limit to the allowed size
+ // of the body in bytes to prevent abuse.
+ parser_->body_limit(10000);
+
+ // Set the timeout.
+ stream_.expires_after(std::chrono::seconds(30));
+
+ // Read a request
+ http::async_read(
+ stream_,
+ buffer_,
+ parser_->get(),
+ beast::bind_front_handler(
+ &http_session::on_read,
+ shared_from_this()));
+}
+
+void
+http_session::
+on_read(beast::error_code ec, std::size_t)
+{
+ // This means they closed the connection
+ if(ec == http::error::end_of_stream)
+ {
+ stream_.socket().shutdown(tcp::socket::shutdown_send, ec);
+ return;
+ }
+
+ // Handle the error, if any
+ if(ec)
+ return fail(ec, "read");
+
+ // See if it is a WebSocket Upgrade
+ if(websocket::is_upgrade(parser_->get()))
+ {
+ // Create a websocket session, transferring ownership
+ // of both the socket and the HTTP request.
+ boost::make_shared<websocket_session>(
+ stream_.release_socket(),
+ state_)->run(parser_->release());
+ return;
+ }
+
+ // Send the response
+#ifndef BOOST_NO_CXX14_GENERIC_LAMBDAS
+ //
+ // The following code requires generic
+ // lambdas, available in C++14 and later.
+ //
+ handle_request(
+ state_->doc_root(),
+ std::move(req_),
+ [this](auto&& response)
+ {
+ // The lifetime of the message has to extend
+ // for the duration of the async operation so
+ // we use a shared_ptr to manage it.
+ using response_type = typename std::decay<decltype(response)>::type;
+ auto sp = boost::make_shared<response_type>(std::forward<decltype(response)>(response));
+
+ #if 0
+ // NOTE This causes an ICE in gcc 7.3
+ // Write the response
+ http::async_write(this->stream_, *sp,
+ [self = shared_from_this(), sp](
+ beast::error_code ec, std::size_t bytes)
+ {
+ self->on_write(ec, bytes, sp->need_eof());
+ });
+ #else
+ // Write the response
+ auto self = shared_from_this();
+ http::async_write(stream_, *sp,
+ [self, sp](
+ beast::error_code ec, std::size_t bytes)
+ {
+ self->on_write(ec, bytes, sp->need_eof());
+ });
+ #endif
+ });
+#else
+ //
+ // This code uses the function object type send_lambda in
+ // place of a generic lambda which is not available in C++11
+ //
+ handle_request(
+ state_->doc_root(),
+ parser_->release(),
+ send_lambda(*this));
+
+#endif
+}
+
+void
+http_session::
+on_write(beast::error_code ec, std::size_t, bool close)
+{
+ // Handle the error, if any
+ if(ec)
+ return fail(ec, "write");
+
+ if(close)
+ {
+ // This means we should close the connection, usually because
+ // the response indicated the "Connection: close" semantic.
+ stream_.socket().shutdown(tcp::socket::shutdown_send, ec);
+ return;
+ }
+
+ // Read another request
+ do_read();
+}
diff --git a/src/boost/libs/beast/example/websocket/server/chat-multi/http_session.hpp b/src/boost/libs/beast/example/websocket/server/chat-multi/http_session.hpp
new file mode 100644
index 000000000..637a5d898
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/chat-multi/http_session.hpp
@@ -0,0 +1,48 @@
+//
+// Copyright (c) 2016-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/vinniefalco/CppCon2018
+//
+
+#ifndef BOOST_BEAST_EXAMPLE_WEBSOCKET_CHAT_MULTI_HTTP_SESSION_HPP
+#define BOOST_BEAST_EXAMPLE_WEBSOCKET_CHAT_MULTI_HTTP_SESSION_HPP
+
+#include "net.hpp"
+#include "beast.hpp"
+#include "shared_state.hpp"
+#include <boost/optional.hpp>
+#include <boost/smart_ptr.hpp>
+#include <cstdlib>
+#include <memory>
+
+/** Represents an established HTTP connection
+*/
+class http_session : public boost::enable_shared_from_this<http_session>
+{
+ beast::tcp_stream stream_;
+ beast::flat_buffer buffer_;
+ boost::shared_ptr<shared_state> state_;
+
+ // The parser is stored in an optional container so we can
+ // construct it from scratch it at the beginning of each new message.
+ boost::optional<http::request_parser<http::string_body>> parser_;
+
+ struct send_lambda;
+
+ void fail(beast::error_code ec, char const* what);
+ void do_read();
+ void on_read(beast::error_code ec, std::size_t);
+ void on_write(beast::error_code ec, std::size_t, bool close);
+
+public:
+ http_session(
+ tcp::socket&& socket,
+ boost::shared_ptr<shared_state> const& state);
+
+ void run();
+};
+
+#endif
diff --git a/src/boost/libs/beast/example/websocket/server/chat-multi/listener.cpp b/src/boost/libs/beast/example/websocket/server/chat-multi/listener.cpp
new file mode 100644
index 000000000..8bbecb49b
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/chat-multi/listener.cpp
@@ -0,0 +1,101 @@
+//
+// Copyright (c) 2016-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/vinniefalco/CppCon2018
+//
+
+#include "listener.hpp"
+#include "http_session.hpp"
+#include <iostream>
+
+listener::
+listener(
+ net::io_context& ioc,
+ tcp::endpoint endpoint,
+ boost::shared_ptr<shared_state> const& state)
+ : ioc_(ioc)
+ , acceptor_(ioc)
+ , state_(state)
+{
+ beast::error_code ec;
+
+ // Open the acceptor
+ acceptor_.open(endpoint.protocol(), ec);
+ if(ec)
+ {
+ fail(ec, "open");
+ return;
+ }
+
+ // Allow address reuse
+ acceptor_.set_option(net::socket_base::reuse_address(true), ec);
+ if(ec)
+ {
+ fail(ec, "set_option");
+ return;
+ }
+
+ // Bind to the server address
+ acceptor_.bind(endpoint, ec);
+ if(ec)
+ {
+ fail(ec, "bind");
+ return;
+ }
+
+ // Start listening for connections
+ acceptor_.listen(
+ net::socket_base::max_listen_connections, ec);
+ if(ec)
+ {
+ fail(ec, "listen");
+ return;
+ }
+}
+
+void
+listener::
+run()
+{
+ // The new connection gets its own strand
+ acceptor_.async_accept(
+ net::make_strand(ioc_),
+ beast::bind_front_handler(
+ &listener::on_accept,
+ shared_from_this()));
+}
+
+// Report a failure
+void
+listener::
+fail(beast::error_code ec, char const* what)
+{
+ // Don't report on canceled operations
+ if(ec == net::error::operation_aborted)
+ return;
+ std::cerr << what << ": " << ec.message() << "\n";
+}
+
+// Handle a connection
+void
+listener::
+on_accept(beast::error_code ec, tcp::socket socket)
+{
+ if(ec)
+ return fail(ec, "accept");
+ else
+ // Launch a new session for this connection
+ boost::make_shared<http_session>(
+ std::move(socket),
+ state_)->run();
+
+ // The new connection gets its own strand
+ acceptor_.async_accept(
+ net::make_strand(ioc_),
+ beast::bind_front_handler(
+ &listener::on_accept,
+ shared_from_this()));
+}
diff --git a/src/boost/libs/beast/example/websocket/server/chat-multi/listener.hpp b/src/boost/libs/beast/example/websocket/server/chat-multi/listener.hpp
new file mode 100644
index 000000000..a0c536e2e
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/chat-multi/listener.hpp
@@ -0,0 +1,42 @@
+//
+// Copyright (c) 2016-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/vinniefalco/CppCon2018
+//
+
+#ifndef BOOST_BEAST_EXAMPLE_WEBSOCKET_CHAT_MULTI_LISTENER_HPP
+#define BOOST_BEAST_EXAMPLE_WEBSOCKET_CHAT_MULTI_LISTENER_HPP
+
+#include "beast.hpp"
+#include "net.hpp"
+#include <boost/smart_ptr.hpp>
+#include <memory>
+#include <string>
+
+// Forward declaration
+class shared_state;
+
+// Accepts incoming connections and launches the sessions
+class listener : public boost::enable_shared_from_this<listener>
+{
+ net::io_context& ioc_;
+ tcp::acceptor acceptor_;
+ boost::shared_ptr<shared_state> state_;
+
+ void fail(beast::error_code ec, char const* what);
+ void on_accept(beast::error_code ec, tcp::socket socket);
+
+public:
+ listener(
+ net::io_context& ioc,
+ tcp::endpoint endpoint,
+ boost::shared_ptr<shared_state> const& state);
+
+ // Start accepting incoming connections
+ void run();
+};
+
+#endif
diff --git a/src/boost/libs/beast/example/websocket/server/chat-multi/main.cpp b/src/boost/libs/beast/example/websocket/server/chat-multi/main.cpp
new file mode 100644
index 000000000..8645f1ded
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/chat-multi/main.cpp
@@ -0,0 +1,84 @@
+//
+// Copyright (c) 2016-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/vinniefalco/CppCon2018
+//
+
+//------------------------------------------------------------------------------
+/*
+ WebSocket chat server, multi-threaded
+
+ This implements a multi-user chat room using WebSocket. The
+ `io_context` runs on any number of threads, specified at
+ the command line.
+
+*/
+//------------------------------------------------------------------------------
+
+#include "listener.hpp"
+#include "shared_state.hpp"
+
+#include <boost/asio/signal_set.hpp>
+#include <boost/smart_ptr.hpp>
+#include <iostream>
+#include <vector>
+
+int
+main(int argc, char* argv[])
+{
+ // Check command line arguments.
+ if (argc != 5)
+ {
+ std::cerr <<
+ "Usage: websocket-chat-multi <address> <port> <doc_root> <threads>\n" <<
+ "Example:\n" <<
+ " websocket-chat-server 0.0.0.0 8080 . 5\n";
+ return EXIT_FAILURE;
+ }
+ auto address = net::ip::make_address(argv[1]);
+ auto port = static_cast<unsigned short>(std::atoi(argv[2]));
+ auto doc_root = argv[3];
+ auto const threads = std::max<int>(1, std::atoi(argv[4]));
+
+ // The io_context is required for all I/O
+ net::io_context ioc;
+
+ // Create and launch a listening port
+ boost::make_shared<listener>(
+ ioc,
+ tcp::endpoint{address, port},
+ boost::make_shared<shared_state>(doc_root))->run();
+
+ // Capture SIGINT and SIGTERM to perform a clean shutdown
+ net::signal_set signals(ioc, SIGINT, SIGTERM);
+ signals.async_wait(
+ [&ioc](boost::system::error_code const&, int)
+ {
+ // Stop the io_context. This will cause run()
+ // to return immediately, eventually destroying the
+ // io_context and any remaining handlers in it.
+ ioc.stop();
+ });
+
+ // Run the I/O service on the requested number of threads
+ std::vector<std::thread> v;
+ v.reserve(threads - 1);
+ for(auto i = threads - 1; i > 0; --i)
+ v.emplace_back(
+ [&ioc]
+ {
+ ioc.run();
+ });
+ ioc.run();
+
+ // (If we get here, it means we got a SIGINT or SIGTERM)
+
+ // Block until all the threads exit
+ for(auto& t : v)
+ t.join();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/websocket/server/chat-multi/net.hpp b/src/boost/libs/beast/example/websocket/server/chat-multi/net.hpp
new file mode 100644
index 000000000..48a215355
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/chat-multi/net.hpp
@@ -0,0 +1,18 @@
+//
+// Copyright (c) 2016-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/vinniefalco/CppCon2018
+//
+
+#ifndef BOOST_BEAST_EXAMPLE_WEBSOCKET_CHAT_MULTI_NET_HPP
+#define BOOST_BEAST_EXAMPLE_WEBSOCKET_CHAT_MULTI_NET_HPP
+
+#include <boost/asio.hpp>
+
+namespace net = boost::asio; // from <boost/asio.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+#endif
diff --git a/src/boost/libs/beast/example/websocket/server/chat-multi/shared_state.cpp b/src/boost/libs/beast/example/websocket/server/chat-multi/shared_state.cpp
new file mode 100644
index 000000000..9fceecc5d
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/chat-multi/shared_state.cpp
@@ -0,0 +1,59 @@
+//
+// Copyright (c) 2016-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/vinniefalco/CppCon2018
+//
+
+#include "shared_state.hpp"
+#include "websocket_session.hpp"
+
+shared_state::
+shared_state(std::string doc_root)
+ : doc_root_(std::move(doc_root))
+{
+}
+
+void
+shared_state::
+join(websocket_session* session)
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+ sessions_.insert(session);
+}
+
+void
+shared_state::
+leave(websocket_session* session)
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+ sessions_.erase(session);
+}
+
+// Broadcast a message to all websocket client sessions
+void
+shared_state::
+send(std::string message)
+{
+ // Put the message in a shared pointer so we can re-use it for each client
+ auto const ss = boost::make_shared<std::string const>(std::move(message));
+
+ // Make a local list of all the weak pointers representing
+ // the sessions, so we can do the actual sending without
+ // holding the mutex:
+ std::vector<boost::weak_ptr<websocket_session>> v;
+ {
+ std::lock_guard<std::mutex> lock(mutex_);
+ v.reserve(sessions_.size());
+ for(auto p : sessions_)
+ v.emplace_back(p->weak_from_this());
+ }
+
+ // For each session in our local list, try to acquire a strong
+ // pointer. If successful, then send the message on that session.
+ for(auto const& wp : v)
+ if(auto sp = wp.lock())
+ sp->send(ss);
+}
diff --git a/src/boost/libs/beast/example/websocket/server/chat-multi/shared_state.hpp b/src/boost/libs/beast/example/websocket/server/chat-multi/shared_state.hpp
new file mode 100644
index 000000000..08f4b2d34
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/chat-multi/shared_state.hpp
@@ -0,0 +1,48 @@
+//
+// Copyright (c) 2016-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/vinniefalco/CppCon2018
+//
+
+#ifndef BOOST_BEAST_EXAMPLE_WEBSOCKET_CHAT_MULTI_SHARED_STATE_HPP
+#define BOOST_BEAST_EXAMPLE_WEBSOCKET_CHAT_MULTI_SHARED_STATE_HPP
+
+#include <boost/smart_ptr.hpp>
+#include <memory>
+#include <mutex>
+#include <string>
+#include <unordered_set>
+
+// Forward declaration
+class websocket_session;
+
+// Represents the shared server state
+class shared_state
+{
+ std::string const doc_root_;
+
+ // This mutex synchronizes all access to sessions_
+ std::mutex mutex_;
+
+ // Keep a list of all the connected clients
+ std::unordered_set<websocket_session*> sessions_;
+
+public:
+ explicit
+ shared_state(std::string doc_root);
+
+ std::string const&
+ doc_root() const noexcept
+ {
+ return doc_root_;
+ }
+
+ void join (websocket_session* session);
+ void leave (websocket_session* session);
+ void send (std::string message);
+};
+
+#endif
diff --git a/src/boost/libs/beast/example/websocket/server/chat-multi/websocket_session.cpp b/src/boost/libs/beast/example/websocket/server/chat-multi/websocket_session.cpp
new file mode 100644
index 000000000..4807a5f1e
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/chat-multi/websocket_session.cpp
@@ -0,0 +1,135 @@
+//
+// Copyright (c) 2016-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/vinniefalco/CppCon2018
+//
+
+#include "websocket_session.hpp"
+#include <iostream>
+
+websocket_session::
+websocket_session(
+ tcp::socket&& socket,
+ boost::shared_ptr<shared_state> const& state)
+ : ws_(std::move(socket))
+ , state_(state)
+{
+}
+
+websocket_session::
+~websocket_session()
+{
+ // Remove this session from the list of active sessions
+ state_->leave(this);
+}
+
+void
+websocket_session::
+fail(beast::error_code ec, char const* what)
+{
+ // Don't report these
+ if( ec == net::error::operation_aborted ||
+ ec == websocket::error::closed)
+ return;
+
+ std::cerr << what << ": " << ec.message() << "\n";
+}
+
+void
+websocket_session::
+on_accept(beast::error_code ec)
+{
+ // Handle the error, if any
+ if(ec)
+ return fail(ec, "accept");
+
+ // Add this session to the list of active sessions
+ state_->join(this);
+
+ // Read a message
+ ws_.async_read(
+ buffer_,
+ beast::bind_front_handler(
+ &websocket_session::on_read,
+ shared_from_this()));
+}
+
+void
+websocket_session::
+on_read(beast::error_code ec, std::size_t)
+{
+ // Handle the error, if any
+ if(ec)
+ return fail(ec, "read");
+
+ // Send to all connections
+ state_->send(beast::buffers_to_string(buffer_.data()));
+
+ // Clear the buffer
+ buffer_.consume(buffer_.size());
+
+ // Read another message
+ ws_.async_read(
+ buffer_,
+ beast::bind_front_handler(
+ &websocket_session::on_read,
+ shared_from_this()));
+}
+
+void
+websocket_session::
+send(boost::shared_ptr<std::string const> const& ss)
+{
+ // Post our work to the strand, this ensures
+ // that the members of `this` will not be
+ // accessed concurrently.
+
+ net::post(
+ ws_.get_executor(),
+ beast::bind_front_handler(
+ &websocket_session::on_send,
+ shared_from_this(),
+ ss));
+}
+
+void
+websocket_session::
+on_send(boost::shared_ptr<std::string const> const& ss)
+{
+ // Always add to queue
+ queue_.push_back(ss);
+
+ // Are we already writing?
+ if(queue_.size() > 1)
+ return;
+
+ // We are not currently writing, so send this immediately
+ ws_.async_write(
+ net::buffer(*queue_.front()),
+ beast::bind_front_handler(
+ &websocket_session::on_write,
+ shared_from_this()));
+}
+
+void
+websocket_session::
+on_write(beast::error_code ec, std::size_t)
+{
+ // Handle the error, if any
+ if(ec)
+ return fail(ec, "write");
+
+ // Remove the string from the queue
+ queue_.erase(queue_.begin());
+
+ // Send the next message if any
+ if(! queue_.empty())
+ ws_.async_write(
+ net::buffer(*queue_.front()),
+ beast::bind_front_handler(
+ &websocket_session::on_write,
+ shared_from_this()));
+}
diff --git a/src/boost/libs/beast/example/websocket/server/chat-multi/websocket_session.hpp b/src/boost/libs/beast/example/websocket/server/chat-multi/websocket_session.hpp
new file mode 100644
index 000000000..c47d48ac9
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/chat-multi/websocket_session.hpp
@@ -0,0 +1,86 @@
+//
+// Copyright (c) 2016-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/vinniefalco/CppCon2018
+//
+
+#ifndef BOOST_BEAST_EXAMPLE_WEBSOCKET_CHAT_MULTI_WEBSOCKET_SESSION_HPP
+#define BOOST_BEAST_EXAMPLE_WEBSOCKET_CHAT_MULTI_WEBSOCKET_SESSION_HPP
+
+#include "net.hpp"
+#include "beast.hpp"
+#include "shared_state.hpp"
+
+#include <cstdlib>
+#include <memory>
+#include <string>
+#include <vector>
+
+// Forward declaration
+class shared_state;
+
+/** Represents an active WebSocket connection to the server
+*/
+class websocket_session : public boost::enable_shared_from_this<websocket_session>
+{
+ beast::flat_buffer buffer_;
+ websocket::stream<beast::tcp_stream> ws_;
+ boost::shared_ptr<shared_state> state_;
+ std::vector<boost::shared_ptr<std::string const>> queue_;
+
+ void fail(beast::error_code ec, char const* what);
+ void on_accept(beast::error_code ec);
+ void on_read(beast::error_code ec, std::size_t bytes_transferred);
+ void on_write(beast::error_code ec, std::size_t bytes_transferred);
+
+public:
+ websocket_session(
+ tcp::socket&& socket,
+ boost::shared_ptr<shared_state> const& state);
+
+ ~websocket_session();
+
+ template<class Body, class Allocator>
+ void
+ run(http::request<Body, http::basic_fields<Allocator>> req);
+
+ // Send a message
+ void
+ send(boost::shared_ptr<std::string const> const& ss);
+
+private:
+ void
+ on_send(boost::shared_ptr<std::string const> const& ss);
+};
+
+template<class Body, class Allocator>
+void
+websocket_session::
+run(http::request<Body, http::basic_fields<Allocator>> req)
+{
+ // Set suggested timeout settings for the websocket
+ ws_.set_option(
+ websocket::stream_base::timeout::suggested(
+ beast::role_type::server));
+
+ // Set a decorator to change the Server of the handshake
+ ws_.set_option(websocket::stream_base::decorator(
+ [](websocket::response_type& res)
+ {
+ res.set(http::field::server,
+ std::string(BOOST_BEAST_VERSION_STRING) +
+ " websocket-chat-multi");
+ }));
+
+ // Accept the websocket handshake
+ ws_.async_accept(
+ req,
+ beast::bind_front_handler(
+ &websocket_session::on_accept,
+ shared_from_this()));
+}
+
+#endif
diff --git a/src/boost/libs/beast/example/websocket/server/coro-ssl/CMakeLists.txt b/src/boost/libs/beast/example/websocket/server/coro-ssl/CMakeLists.txt
new file mode 100644
index 000000000..a302a2f56
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/coro-ssl/CMakeLists.txt
@@ -0,0 +1,31 @@
+#
+# 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
+#
+
+if (OPENSSL_FOUND)
+ GroupSources(include/boost/beast beast)
+ GroupSources(example/common common)
+ GroupSources(example/websocket/server/coro-ssl "/")
+
+ add_executable (websocket-server-coro-ssl
+ ${BOOST_BEAST_FILES}
+ ${PROJECT_SOURCE_DIR}/example/common/server_certificate.hpp
+ Jamfile
+ websocket_server_coro_ssl.cpp
+ )
+
+ set_property(TARGET websocket-server-coro-ssl PROPERTY FOLDER "example-websocket-server")
+
+ target_link_libraries (websocket-server-coro-ssl
+ OpenSSL::SSL OpenSSL::Crypto
+ lib-asio
+ lib-asio-ssl
+ lib-beast
+ )
+
+endif()
diff --git a/src/boost/libs/beast/example/websocket/server/coro-ssl/Jamfile b/src/boost/libs/beast/example/websocket/server/coro-ssl/Jamfile
new file mode 100644
index 000000000..621b0ce58
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/coro-ssl/Jamfile
@@ -0,0 +1,23 @@
+#
+# 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
+#
+
+import ac ;
+
+project
+ : requirements
+ [ ac.check-library /boost/beast//lib-asio-ssl : <library>/boost/beast//lib-asio-ssl/<link>static : <build>no ]
+ ;
+
+exe websocket-server-coro-ssl :
+ websocket_server_coro_ssl.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ <library>/boost/coroutine//boost_coroutine
+ ;
diff --git a/src/boost/libs/beast/example/websocket/server/coro-ssl/websocket_server_coro_ssl.cpp b/src/boost/libs/beast/example/websocket/server/coro-ssl/websocket_server_coro_ssl.cpp
new file mode 100644
index 000000000..3e1785f00
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/coro-ssl/websocket_server_coro_ssl.cpp
@@ -0,0 +1,206 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: WebSocket SSL server, coroutine
+//
+//------------------------------------------------------------------------------
+
+#include "example/common/server_certificate.hpp"
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/ssl.hpp>
+#include <boost/beast/websocket.hpp>
+#include <boost/beast/websocket/ssl.hpp>
+#include <boost/asio/spawn.hpp>
+#include <algorithm>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <thread>
+#include <vector>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+//------------------------------------------------------------------------------
+
+// Report a failure
+void
+fail(beast::error_code ec, char const* what)
+{
+ std::cerr << what << ": " << ec.message() << "\n";
+}
+
+// Echoes back all received WebSocket messages
+void
+do_session(
+ websocket::stream<
+ beast::ssl_stream<beast::tcp_stream>>& ws,
+ net::yield_context yield)
+{
+ beast::error_code ec;
+
+ // Set the timeout.
+ beast::get_lowest_layer(ws).expires_after(std::chrono::seconds(30));
+
+ // Perform the SSL handshake
+ ws.next_layer().async_handshake(ssl::stream_base::server, yield[ec]);
+ if(ec)
+ return fail(ec, "handshake");
+
+ // Turn off the timeout on the tcp_stream, because
+ // the websocket stream has its own timeout system.
+ beast::get_lowest_layer(ws).expires_never();
+
+ // Set suggested timeout settings for the websocket
+ ws.set_option(
+ websocket::stream_base::timeout::suggested(
+ beast::role_type::server));
+
+ // Set a decorator to change the Server of the handshake
+ ws.set_option(websocket::stream_base::decorator(
+ [](websocket::response_type& res)
+ {
+ res.set(http::field::server,
+ std::string(BOOST_BEAST_VERSION_STRING) +
+ " websocket-server-coro-ssl");
+ }));
+
+ // Accept the websocket handshake
+ ws.async_accept(yield[ec]);
+ if(ec)
+ return fail(ec, "accept");
+
+ for(;;)
+ {
+ // This buffer will hold the incoming message
+ beast::flat_buffer buffer;
+
+ // Read a message
+ ws.async_read(buffer, yield[ec]);
+
+ // This indicates that the session was closed
+ if(ec == websocket::error::closed)
+ break;
+
+ if(ec)
+ return fail(ec, "read");
+
+ // Echo the message back
+ ws.text(ws.got_text());
+ ws.async_write(buffer.data(), yield[ec]);
+ if(ec)
+ return fail(ec, "write");
+ }
+}
+
+//------------------------------------------------------------------------------
+
+// Accepts incoming connections and launches the sessions
+void
+do_listen(
+ net::io_context& ioc,
+ ssl::context& ctx,
+ tcp::endpoint endpoint,
+ net::yield_context yield)
+{
+ beast::error_code ec;
+
+ // Open the acceptor
+ tcp::acceptor acceptor(ioc);
+ acceptor.open(endpoint.protocol(), ec);
+ if(ec)
+ return fail(ec, "open");
+
+ // Allow address reuse
+ acceptor.set_option(net::socket_base::reuse_address(true), ec);
+ if(ec)
+ return fail(ec, "set_option");
+
+ // Bind to the server address
+ acceptor.bind(endpoint, ec);
+ if(ec)
+ return fail(ec, "bind");
+
+ // Start listening for connections
+ acceptor.listen(net::socket_base::max_listen_connections, ec);
+ if(ec)
+ return fail(ec, "listen");
+
+ for(;;)
+ {
+ tcp::socket socket(ioc);
+ acceptor.async_accept(socket, yield[ec]);
+ if(ec)
+ fail(ec, "accept");
+ else
+ boost::asio::spawn(
+ acceptor.get_executor(),
+ std::bind(
+ &do_session,
+ websocket::stream<beast::ssl_stream<
+ beast::tcp_stream>>(std::move(socket), ctx),
+ std::placeholders::_1));
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ // Check command line arguments.
+ if (argc != 4)
+ {
+ std::cerr <<
+ "Usage: websocket-server-coro-ssl <address> <port> <threads>\n" <<
+ "Example:\n" <<
+ " websocket-server-coro-ssl 0.0.0.0 8080 1\n";
+ return EXIT_FAILURE;
+ }
+ auto const address = net::ip::make_address(argv[1]);
+ auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
+ auto const threads = std::max<int>(1, std::atoi(argv[3]));
+
+ // The io_context is required for all I/O
+ net::io_context ioc{threads};
+
+ // The SSL context is required, and holds certificates
+ ssl::context ctx{ssl::context::tlsv12};
+
+ // This holds the self-signed certificate used by the server
+ load_server_certificate(ctx);
+
+ // Spawn a listening port
+ boost::asio::spawn(ioc,
+ std::bind(
+ &do_listen,
+ std::ref(ioc),
+ std::ref(ctx),
+ tcp::endpoint{address, port},
+ std::placeholders::_1));
+
+ // Run the I/O service on the requested number of threads
+ std::vector<std::thread> v;
+ v.reserve(threads - 1);
+ for(auto i = threads - 1; i > 0; --i)
+ v.emplace_back(
+ [&ioc]
+ {
+ ioc.run();
+ });
+ ioc.run();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/websocket/server/coro/CMakeLists.txt b/src/boost/libs/beast/example/websocket/server/coro/CMakeLists.txt
new file mode 100644
index 000000000..c8e408d1c
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/coro/CMakeLists.txt
@@ -0,0 +1,23 @@
+#
+# 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
+#
+
+GroupSources(include/boost/beast beast)
+GroupSources(example/websocket/server/coro "/")
+
+add_executable (websocket-server-coro
+ ${BOOST_BEAST_FILES}
+ Jamfile
+ websocket_server_coro.cpp
+)
+
+target_link_libraries(websocket-server-coro
+ lib-asio
+ lib-beast)
+
+set_property(TARGET websocket-server-coro PROPERTY FOLDER "example-websocket-server")
diff --git a/src/boost/libs/beast/example/websocket/server/coro/Jamfile b/src/boost/libs/beast/example/websocket/server/coro/Jamfile
new file mode 100644
index 000000000..5e8cbf948
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/coro/Jamfile
@@ -0,0 +1,16 @@
+#
+# 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
+#
+
+exe websocket-server-coro :
+ websocket_server_coro.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ <library>/boost/coroutine//boost_coroutine
+ ;
diff --git a/src/boost/libs/beast/example/websocket/server/coro/websocket_server_coro.cpp b/src/boost/libs/beast/example/websocket/server/coro/websocket_server_coro.cpp
new file mode 100644
index 000000000..e15b01079
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/coro/websocket_server_coro.cpp
@@ -0,0 +1,180 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: WebSocket server, coroutine
+//
+//------------------------------------------------------------------------------
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/websocket.hpp>
+#include <boost/asio/spawn.hpp>
+#include <algorithm>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <thread>
+#include <vector>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+//------------------------------------------------------------------------------
+
+// Report a failure
+void
+fail(beast::error_code ec, char const* what)
+{
+ std::cerr << what << ": " << ec.message() << "\n";
+}
+
+// Echoes back all received WebSocket messages
+void
+do_session(
+ websocket::stream<beast::tcp_stream>& ws,
+ net::yield_context yield)
+{
+ beast::error_code ec;
+
+ // Set suggested timeout settings for the websocket
+ ws.set_option(
+ websocket::stream_base::timeout::suggested(
+ beast::role_type::server));
+
+ // Set a decorator to change the Server of the handshake
+ ws.set_option(websocket::stream_base::decorator(
+ [](websocket::response_type& res)
+ {
+ res.set(http::field::server,
+ std::string(BOOST_BEAST_VERSION_STRING) +
+ " websocket-server-coro");
+ }));
+
+ // Accept the websocket handshake
+ ws.async_accept(yield[ec]);
+ if(ec)
+ return fail(ec, "accept");
+
+ for(;;)
+ {
+ // This buffer will hold the incoming message
+ beast::flat_buffer buffer;
+
+ // Read a message
+ ws.async_read(buffer, yield[ec]);
+
+ // This indicates that the session was closed
+ if(ec == websocket::error::closed)
+ break;
+
+ if(ec)
+ return fail(ec, "read");
+
+ // Echo the message back
+ ws.text(ws.got_text());
+ ws.async_write(buffer.data(), yield[ec]);
+ if(ec)
+ return fail(ec, "write");
+ }
+}
+
+//------------------------------------------------------------------------------
+
+// Accepts incoming connections and launches the sessions
+void
+do_listen(
+ net::io_context& ioc,
+ tcp::endpoint endpoint,
+ net::yield_context yield)
+{
+ beast::error_code ec;
+
+ // Open the acceptor
+ tcp::acceptor acceptor(ioc);
+ acceptor.open(endpoint.protocol(), ec);
+ if(ec)
+ return fail(ec, "open");
+
+ // Allow address reuse
+ acceptor.set_option(net::socket_base::reuse_address(true), ec);
+ if(ec)
+ return fail(ec, "set_option");
+
+ // Bind to the server address
+ acceptor.bind(endpoint, ec);
+ if(ec)
+ return fail(ec, "bind");
+
+ // Start listening for connections
+ acceptor.listen(net::socket_base::max_listen_connections, ec);
+ if(ec)
+ return fail(ec, "listen");
+
+ for(;;)
+ {
+ tcp::socket socket(ioc);
+ acceptor.async_accept(socket, yield[ec]);
+ if(ec)
+ fail(ec, "accept");
+ else
+ boost::asio::spawn(
+ acceptor.get_executor(),
+ std::bind(
+ &do_session,
+ websocket::stream<
+ beast::tcp_stream>(std::move(socket)),
+ std::placeholders::_1));
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ // Check command line arguments.
+ if (argc != 4)
+ {
+ std::cerr <<
+ "Usage: websocket-server-coro <address> <port> <threads>\n" <<
+ "Example:\n" <<
+ " websocket-server-coro 0.0.0.0 8080 1\n";
+ return EXIT_FAILURE;
+ }
+ auto const address = net::ip::make_address(argv[1]);
+ auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
+ auto const threads = std::max<int>(1, std::atoi(argv[3]));
+
+ // The io_context is required for all I/O
+ net::io_context ioc(threads);
+
+ // Spawn a listening port
+ boost::asio::spawn(ioc,
+ std::bind(
+ &do_listen,
+ std::ref(ioc),
+ tcp::endpoint{address, port},
+ std::placeholders::_1));
+
+ // Run the I/O service on the requested number of threads
+ std::vector<std::thread> v;
+ v.reserve(threads - 1);
+ for(auto i = threads - 1; i > 0; --i)
+ v.emplace_back(
+ [&ioc]
+ {
+ ioc.run();
+ });
+ ioc.run();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/websocket/server/fast/CMakeLists.txt b/src/boost/libs/beast/example/websocket/server/fast/CMakeLists.txt
new file mode 100644
index 000000000..93d469e91
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/fast/CMakeLists.txt
@@ -0,0 +1,23 @@
+#
+# 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
+#
+
+GroupSources(include/boost/beast beast)
+GroupSources(example/websocket/server/fast "/")
+
+add_executable (websocket-server-fast
+ ${BOOST_BEAST_FILES}
+ Jamfile
+ websocket_server_fast.cpp
+)
+
+target_link_libraries(websocket-server-fast
+ lib-asio
+ lib-beast)
+
+set_property(TARGET websocket-server-fast PROPERTY FOLDER "example-websocket-server")
diff --git a/src/boost/libs/beast/example/websocket/server/fast/Jamfile b/src/boost/libs/beast/example/websocket/server/fast/Jamfile
new file mode 100644
index 000000000..3e6cbf5b0
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/fast/Jamfile
@@ -0,0 +1,16 @@
+#
+# 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
+#
+
+exe websocket-server-fast :
+ websocket_server_fast.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ <library>/boost/coroutine//boost_coroutine
+ ;
diff --git a/src/boost/libs/beast/example/websocket/server/fast/websocket_server_fast.cpp b/src/boost/libs/beast/example/websocket/server/fast/websocket_server_fast.cpp
new file mode 100644
index 000000000..7f2a5e3cb
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/fast/websocket_server_fast.cpp
@@ -0,0 +1,480 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: WebSocket server, fast
+//
+//------------------------------------------------------------------------------
+
+/* This server contains the following ports:
+
+ Synchronous <base port + 0>
+ Asynchronous <base port + 1>
+ Coroutine <base port + 2>
+
+ This program is optimized for the Autobahn|Testsuite
+ benchmarking and WebSocket compliants testing program.
+
+ See:
+ https://github.com/crossbario/autobahn-testsuite
+*/
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/http.hpp>
+#include <boost/beast/version.hpp>
+#include <boost/beast/websocket.hpp>
+#include <boost/asio/spawn.hpp>
+#include <boost/asio/strand.hpp>
+#include <algorithm>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <thread>
+#include <vector>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+//------------------------------------------------------------------------------
+
+// Report a failure
+void
+fail(beast::error_code ec, char const* what)
+{
+ std::cerr << (std::string(what) + ": " + ec.message() + "\n");
+}
+
+// Adjust settings on the stream
+template<class NextLayer>
+void
+setup_stream(websocket::stream<NextLayer>& ws)
+{
+ // These values are tuned for Autobahn|Testsuite, and
+ // should also be generally helpful for increased performance.
+
+ websocket::permessage_deflate pmd;
+ pmd.client_enable = true;
+ pmd.server_enable = true;
+ pmd.compLevel = 3;
+ ws.set_option(pmd);
+
+ ws.auto_fragment(false);
+
+ // Autobahn|Testsuite needs this
+ ws.read_message_max(64 * 1024 * 1024);
+}
+
+//------------------------------------------------------------------------------
+
+void
+do_sync_session(websocket::stream<beast::tcp_stream>& ws)
+{
+ beast::error_code ec;
+
+ setup_stream(ws);
+
+ // Set a decorator to change the Server of the handshake
+ ws.set_option(websocket::stream_base::decorator(
+ [](websocket::response_type& res)
+ {
+ res.set(http::field::server, std::string(
+ BOOST_BEAST_VERSION_STRING) + "-Sync");
+ }));
+
+ ws.accept(ec);
+ if(ec)
+ return fail(ec, "accept");
+
+ for(;;)
+ {
+ beast::flat_buffer buffer;
+
+ ws.read(buffer, ec);
+ if(ec == websocket::error::closed)
+ break;
+ if(ec)
+ return fail(ec, "read");
+ ws.text(ws.got_text());
+ ws.write(buffer.data(), ec);
+ if(ec)
+ return fail(ec, "write");
+ }
+}
+
+void
+do_sync_listen(
+ net::io_context& ioc,
+ tcp::endpoint endpoint)
+{
+ beast::error_code ec;
+ tcp::acceptor acceptor{ioc, endpoint};
+ for(;;)
+ {
+ tcp::socket socket{ioc};
+
+ acceptor.accept(socket, ec);
+ if(ec)
+ return fail(ec, "accept");
+
+ std::thread(std::bind(
+ &do_sync_session,
+ websocket::stream<beast::tcp_stream>(
+ std::move(socket)))).detach();
+ }
+}
+
+//------------------------------------------------------------------------------
+
+// Echoes back all received WebSocket messages
+class async_session : public std::enable_shared_from_this<async_session>
+{
+ websocket::stream<beast::tcp_stream> ws_;
+ beast::flat_buffer buffer_;
+
+public:
+ // Take ownership of the socket
+ explicit
+ async_session(tcp::socket&& socket)
+ : ws_(std::move(socket))
+ {
+ setup_stream(ws_);
+ }
+
+ // Start the asynchronous operation
+ void
+ run()
+ {
+ // Set suggested timeout settings for the websocket
+ ws_.set_option(
+ websocket::stream_base::timeout::suggested(
+ beast::role_type::server));
+
+ // Set a decorator to change the Server of the handshake
+ ws_.set_option(websocket::stream_base::decorator(
+ [](websocket::response_type& res)
+ {
+ res.set(http::field::server, std::string(
+ BOOST_BEAST_VERSION_STRING) + "-Async");
+ }));
+
+ // Accept the websocket handshake
+ ws_.async_accept(
+ beast::bind_front_handler(
+ &async_session::on_accept,
+ shared_from_this()));
+ }
+
+ void
+ on_accept(beast::error_code ec)
+ {
+ if(ec)
+ return fail(ec, "accept");
+
+ // Read a message
+ do_read();
+ }
+
+ void
+ do_read()
+ {
+ // Read a message into our buffer
+ ws_.async_read(
+ buffer_,
+ beast::bind_front_handler(
+ &async_session::on_read,
+ shared_from_this()));
+ }
+
+ void
+ on_read(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ // This indicates that the async_session was closed
+ if(ec == websocket::error::closed)
+ return;
+
+ if(ec)
+ fail(ec, "read");
+
+ // Echo the message
+ ws_.text(ws_.got_text());
+ ws_.async_write(
+ buffer_.data(),
+ beast::bind_front_handler(
+ &async_session::on_write,
+ shared_from_this()));
+ }
+
+ void
+ on_write(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ if(ec)
+ return fail(ec, "write");
+
+ // Clear the buffer
+ buffer_.consume(buffer_.size());
+
+ // Do another read
+ do_read();
+ }
+};
+
+// Accepts incoming connections and launches the sessions
+class async_listener : public std::enable_shared_from_this<async_listener>
+{
+ net::io_context& ioc_;
+ tcp::acceptor acceptor_;
+
+public:
+ async_listener(
+ net::io_context& ioc,
+ tcp::endpoint endpoint)
+ : ioc_(ioc)
+ , acceptor_(net::make_strand(ioc))
+ {
+ beast::error_code ec;
+
+ // Open the acceptor
+ acceptor_.open(endpoint.protocol(), ec);
+ if(ec)
+ {
+ fail(ec, "open");
+ return;
+ }
+
+ // Allow address reuse
+ acceptor_.set_option(net::socket_base::reuse_address(true), ec);
+ if(ec)
+ {
+ fail(ec, "set_option");
+ return;
+ }
+
+ // Bind to the server address
+ acceptor_.bind(endpoint, ec);
+ if(ec)
+ {
+ fail(ec, "bind");
+ return;
+ }
+
+ // Start listening for connections
+ acceptor_.listen(
+ net::socket_base::max_listen_connections, ec);
+ if(ec)
+ {
+ fail(ec, "listen");
+ return;
+ }
+ }
+
+ // Start accepting incoming connections
+ void
+ run()
+ {
+ do_accept();
+ }
+
+private:
+ void
+ do_accept()
+ {
+ // The new connection gets its own strand
+ acceptor_.async_accept(
+ net::make_strand(ioc_),
+ beast::bind_front_handler(
+ &async_listener::on_accept,
+ shared_from_this()));
+ }
+
+ void
+ on_accept(beast::error_code ec, tcp::socket socket)
+ {
+ if(ec)
+ {
+ fail(ec, "accept");
+ }
+ else
+ {
+ // Create the async_session and run it
+ std::make_shared<async_session>(std::move(socket))->run();
+ }
+
+ // Accept another connection
+ do_accept();
+ }
+};
+
+//------------------------------------------------------------------------------
+
+void
+do_coro_session(
+ websocket::stream<beast::tcp_stream>& ws,
+ net::yield_context yield)
+{
+ beast::error_code ec;
+
+ setup_stream(ws);
+
+ // Set suggested timeout settings for the websocket
+ ws.set_option(
+ websocket::stream_base::timeout::suggested(
+ beast::role_type::server));
+
+ // Set a decorator to change the Server of the handshake
+ ws.set_option(websocket::stream_base::decorator(
+ [](websocket::response_type& res)
+ {
+ res.set(http::field::server, std::string(
+ BOOST_BEAST_VERSION_STRING) + "-Fiber");
+ }));
+
+ ws.async_accept(yield[ec]);
+ if(ec)
+ return fail(ec, "accept");
+
+ for(;;)
+ {
+ beast::flat_buffer buffer;
+
+ ws.async_read(buffer, yield[ec]);
+ if(ec == websocket::error::closed)
+ break;
+ if(ec)
+ return fail(ec, "read");
+
+ ws.text(ws.got_text());
+ ws.async_write(buffer.data(), yield[ec]);
+ if(ec)
+ return fail(ec, "write");
+ }
+}
+
+void
+do_coro_listen(
+ net::io_context& ioc,
+ tcp::endpoint endpoint,
+ net::yield_context yield)
+{
+ beast::error_code ec;
+
+ tcp::acceptor acceptor(ioc);
+ acceptor.open(endpoint.protocol(), ec);
+ if(ec)
+ return fail(ec, "open");
+
+ acceptor.set_option(net::socket_base::reuse_address(true), ec);
+ if(ec)
+ return fail(ec, "set_option");
+
+ acceptor.bind(endpoint, ec);
+ if(ec)
+ return fail(ec, "bind");
+
+ acceptor.listen(net::socket_base::max_listen_connections, ec);
+ if(ec)
+ return fail(ec, "listen");
+
+ for(;;)
+ {
+ tcp::socket socket(ioc);
+
+ acceptor.async_accept(socket, yield[ec]);
+ if(ec)
+ {
+ fail(ec, "accept");
+ continue;
+ }
+
+ boost::asio::spawn(
+ acceptor.get_executor(),
+ std::bind(
+ &do_coro_session,
+ websocket::stream<
+ beast::tcp_stream>(std::move(socket)),
+ std::placeholders::_1));
+ }
+}
+
+//------------------------------------------------------------------------------
+
+int main(int argc, char* argv[])
+{
+ // Check command line arguments.
+ if (argc != 4)
+ {
+ std::cerr <<
+ "Usage: websocket-server-fast <address> <starting-port> <threads>\n" <<
+ "Example:\n"
+ " websocket-server-fast 0.0.0.0 8080 1\n"
+ " Connect to:\n"
+ " starting-port+0 for synchronous,\n"
+ " starting-port+1 for asynchronous,\n"
+ " starting-port+2 for coroutine.\n";
+ return EXIT_FAILURE;
+ }
+ auto const address = net::ip::make_address(argv[1]);
+ auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
+ auto const threads = std::max<int>(1, std::atoi(argv[3]));
+
+ // The io_context is required for all I/O
+ net::io_context ioc{threads};
+
+ // Create sync port
+ std::thread(beast::bind_front_handler(
+ &do_sync_listen,
+ std::ref(ioc),
+ tcp::endpoint{
+ address,
+ static_cast<unsigned short>(port + 0u)}
+ )).detach();
+
+ // Create async port
+ std::make_shared<async_listener>(
+ ioc,
+ tcp::endpoint{
+ address,
+ static_cast<unsigned short>(port + 1u)})->run();
+
+ // Create coro port
+ boost::asio::spawn(ioc,
+ std::bind(
+ &do_coro_listen,
+ std::ref(ioc),
+ tcp::endpoint{
+ address,
+ static_cast<unsigned short>(port + 2u)},
+ std::placeholders::_1));
+
+ // Run the I/O service on the requested number of threads
+ std::vector<std::thread> v;
+ v.reserve(threads - 1);
+ for(auto i = threads - 1; i > 0; --i)
+ v.emplace_back(
+ [&ioc]
+ {
+ ioc.run();
+ });
+ ioc.run();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/websocket/server/stackless-ssl/CMakeLists.txt b/src/boost/libs/beast/example/websocket/server/stackless-ssl/CMakeLists.txt
new file mode 100644
index 000000000..7ae66a07b
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/stackless-ssl/CMakeLists.txt
@@ -0,0 +1,31 @@
+#
+# 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
+#
+
+if (OPENSSL_FOUND)
+ GroupSources(include/boost/beast beast)
+ GroupSources(example/common common)
+ GroupSources(example/websocket/server/stackless-ssl "/")
+
+ add_executable (websocket-server-stackless-ssl
+ ${BOOST_BEAST_FILES}
+ ${PROJECT_SOURCE_DIR}/example/common/server_certificate.hpp
+ Jamfile
+ websocket_server_stackless_ssl.cpp
+ )
+
+ set_property(TARGET websocket-server-stackless-ssl PROPERTY FOLDER "example-websocket-server")
+
+ target_link_libraries (websocket-server-stackless-ssl
+ OpenSSL::SSL OpenSSL::Crypto
+ lib-asio
+ lib-asio-ssl
+ lib-beast
+ )
+
+endif()
diff --git a/src/boost/libs/beast/example/websocket/server/stackless-ssl/Jamfile b/src/boost/libs/beast/example/websocket/server/stackless-ssl/Jamfile
new file mode 100644
index 000000000..b0eaa4aa2
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/stackless-ssl/Jamfile
@@ -0,0 +1,22 @@
+#
+# 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
+#
+
+import ac ;
+
+project
+ : requirements
+ [ ac.check-library /boost/beast//lib-asio-ssl : <library>/boost/beast//lib-asio-ssl/<link>static : <build>no ]
+ ;
+
+exe websocket-server-stackless-ssl :
+ websocket_server_stackless_ssl.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ ;
diff --git a/src/boost/libs/beast/example/websocket/server/stackless-ssl/websocket_server_stackless_ssl.cpp b/src/boost/libs/beast/example/websocket/server/stackless-ssl/websocket_server_stackless_ssl.cpp
new file mode 100644
index 000000000..c6eaec60c
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/stackless-ssl/websocket_server_stackless_ssl.cpp
@@ -0,0 +1,314 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: WebSocket SSL server, stackless coroutine
+//
+//------------------------------------------------------------------------------
+
+#include "example/common/server_certificate.hpp"
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/ssl.hpp>
+#include <boost/beast/websocket.hpp>
+#include <boost/beast/websocket/ssl.hpp>
+#include <boost/asio/coroutine.hpp>
+#include <boost/asio/strand.hpp>
+#include <boost/asio/dispatch.hpp>
+#include <algorithm>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <thread>
+#include <vector>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+//------------------------------------------------------------------------------
+
+// Report a failure
+void
+fail(beast::error_code ec, char const* what)
+{
+ std::cerr << what << ": " << ec.message() << "\n";
+}
+
+// Echoes back all received WebSocket messages
+class session
+ : public boost::asio::coroutine
+ , public std::enable_shared_from_this<session>
+{
+ websocket::stream<beast::ssl_stream<beast::tcp_stream>> ws_;
+ beast::flat_buffer buffer_;
+
+public:
+ // Take ownership of the socket
+ session(tcp::socket&& socket, ssl::context& ctx)
+ : ws_(std::move(socket), ctx)
+ {
+ }
+
+ // Start the asynchronous operation
+ void
+ run()
+ {
+ // We need to be executing within a strand to perform async operations
+ // on the I/O objects in this session. Although not strictly necessary
+ // for single-threaded contexts, this example code is written to be
+ // thread-safe by default.
+ net::dispatch(ws_.get_executor(),
+ beast::bind_front_handler(&session::loop,
+ shared_from_this(),
+ beast::error_code{},
+ 0));
+ }
+
+ #include <boost/asio/yield.hpp>
+
+ void
+ loop(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+
+ reenter(*this)
+ {
+ // Set the timeout.
+ beast::get_lowest_layer(ws_).expires_after(std::chrono::seconds(30));
+
+ // Perform the SSL handshake
+ yield ws_.next_layer().async_handshake(
+ ssl::stream_base::server,
+ std::bind(
+ &session::loop,
+ shared_from_this(),
+ std::placeholders::_1,
+ 0));
+ if(ec)
+ return fail(ec, "handshake");
+
+ // Turn off the timeout on the tcp_stream, because
+ // the websocket stream has its own timeout system.
+ beast::get_lowest_layer(ws_).expires_never();
+
+ // Set suggested timeout settings for the websocket
+ ws_.set_option(
+ websocket::stream_base::timeout::suggested(
+ beast::role_type::server));
+
+ // Set a decorator to change the Server of the handshake
+ ws_.set_option(websocket::stream_base::decorator(
+ [](websocket::response_type& res)
+ {
+ res.set(http::field::server,
+ std::string(BOOST_BEAST_VERSION_STRING) +
+ " websocket-server-stackless-ssl");
+ }));
+
+ // Accept the websocket handshake
+ yield ws_.async_accept(
+ std::bind(
+ &session::loop,
+ shared_from_this(),
+ std::placeholders::_1,
+ 0));
+ if(ec)
+ return fail(ec, "accept");
+
+ for(;;)
+ {
+ // Read a message into our buffer
+ yield ws_.async_read(
+ buffer_,
+ std::bind(
+ &session::loop,
+ shared_from_this(),
+ std::placeholders::_1,
+ std::placeholders::_2));
+ if(ec == websocket::error::closed)
+ {
+ // This indicates that the session was closed
+ return;
+ }
+ if(ec)
+ fail(ec, "read");
+
+ // Echo the message
+ ws_.text(ws_.got_text());
+ yield ws_.async_write(
+ buffer_.data(),
+ std::bind(
+ &session::loop,
+ shared_from_this(),
+ std::placeholders::_1,
+ std::placeholders::_2));
+ if(ec)
+ return fail(ec, "write");
+
+ // Clear the buffer
+ buffer_.consume(buffer_.size());
+ }
+ }
+ }
+
+ #include <boost/asio/unyield.hpp>
+};
+
+//------------------------------------------------------------------------------
+
+// Accepts incoming connections and launches the sessions
+class listener
+ : public boost::asio::coroutine
+ , public std::enable_shared_from_this<listener>
+{
+ net::io_context& ioc_;
+ ssl::context& ctx_;
+ tcp::acceptor acceptor_;
+ tcp::socket socket_;
+
+public:
+ listener(
+ net::io_context& ioc,
+ ssl::context& ctx,
+ tcp::endpoint endpoint)
+ : ioc_(ioc)
+ , ctx_(ctx)
+ , acceptor_(ioc)
+ , socket_(ioc)
+ {
+ beast::error_code ec;
+
+ // Open the acceptor
+ acceptor_.open(endpoint.protocol(), ec);
+ if(ec)
+ {
+ fail(ec, "open");
+ return;
+ }
+
+ // Allow address reuse
+ acceptor_.set_option(net::socket_base::reuse_address(true), ec);
+ if(ec)
+ {
+ fail(ec, "set_option");
+ return;
+ }
+
+ // Bind to the server address
+ acceptor_.bind(endpoint, ec);
+ if(ec)
+ {
+ fail(ec, "bind");
+ return;
+ }
+
+ // Start listening for connections
+ acceptor_.listen(
+ net::socket_base::max_listen_connections, ec);
+ if(ec)
+ {
+ fail(ec, "listen");
+ return;
+ }
+ }
+
+ // Start accepting incoming connections
+ void
+ run()
+ {
+ loop();
+ }
+
+private:
+
+ #include <boost/asio/yield.hpp>
+
+ void
+ loop(beast::error_code ec = {})
+ {
+ reenter(*this)
+ {
+ for(;;)
+ {
+ yield acceptor_.async_accept(
+ socket_,
+ std::bind(
+ &listener::loop,
+ shared_from_this(),
+ std::placeholders::_1));
+ if(ec)
+ {
+ fail(ec, "accept");
+ }
+ else
+ {
+ // Create the session and run it
+ std::make_shared<session>(std::move(socket_), ctx_)->run();
+ }
+
+ // Make sure each session gets its own strand
+ socket_ = tcp::socket(net::make_strand(ioc_));
+ }
+ }
+ }
+
+ #include <boost/asio/unyield.hpp>
+};
+
+//------------------------------------------------------------------------------
+
+int main(int argc, char* argv[])
+{
+ // Check command line arguments.
+ if (argc != 4)
+ {
+ std::cerr <<
+ "Usage: websocket-server-async-ssl <address> <port> <threads>\n" <<
+ "Example:\n" <<
+ " websocket-server-async-ssl 0.0.0.0 8080 1\n";
+ return EXIT_FAILURE;
+ }
+ auto const address = net::ip::make_address(argv[1]);
+ auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
+ auto const threads = std::max<int>(1, std::atoi(argv[3]));
+
+ // The io_context is required for all I/O
+ net::io_context ioc{threads};
+
+ // The SSL context is required, and holds certificates
+ ssl::context ctx{ssl::context::tlsv12};
+
+ // This holds the self-signed certificate used by the server
+ load_server_certificate(ctx);
+
+ // Create and launch a listening port
+ std::make_shared<listener>(ioc, ctx, tcp::endpoint{address, port})->run();
+
+ // Run the I/O service on the requested number of threads
+ std::vector<std::thread> v;
+ v.reserve(threads - 1);
+ for(auto i = threads - 1; i > 0; --i)
+ v.emplace_back(
+ [&ioc]
+ {
+ ioc.run();
+ });
+ ioc.run();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/websocket/server/stackless/CMakeLists.txt b/src/boost/libs/beast/example/websocket/server/stackless/CMakeLists.txt
new file mode 100644
index 000000000..b260ca48b
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/stackless/CMakeLists.txt
@@ -0,0 +1,23 @@
+#
+# 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
+#
+
+GroupSources(include/boost/beast beast)
+GroupSources(example/websocket/server/stackless "/")
+
+add_executable (websocket-server-stackless
+ ${BOOST_BEAST_FILES}
+ Jamfile
+ websocket_server_stackless.cpp
+)
+
+target_link_libraries(websocket-server-stackless
+ lib-asio
+ lib-beast)
+
+set_property(TARGET websocket-server-stackless PROPERTY FOLDER "example-websocket-server")
diff --git a/src/boost/libs/beast/example/websocket/server/stackless/Jamfile b/src/boost/libs/beast/example/websocket/server/stackless/Jamfile
new file mode 100644
index 000000000..ce9ab8987
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/stackless/Jamfile
@@ -0,0 +1,15 @@
+#
+# 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
+#
+
+exe websocket-server-stackless :
+ websocket_server_stackless.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ ;
diff --git a/src/boost/libs/beast/example/websocket/server/stackless/websocket_server_stackless.cpp b/src/boost/libs/beast/example/websocket/server/stackless/websocket_server_stackless.cpp
new file mode 100644
index 000000000..c57fe2899
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/stackless/websocket_server_stackless.cpp
@@ -0,0 +1,282 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: WebSocket server, stackless coroutine
+//
+//------------------------------------------------------------------------------
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/websocket.hpp>
+#include <boost/asio/coroutine.hpp>
+#include <boost/asio/strand.hpp>
+#include <boost/asio/dispatch.hpp>
+#include <algorithm>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <thread>
+#include <vector>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+//------------------------------------------------------------------------------
+
+// Report a failure
+void
+fail(beast::error_code ec, char const* what)
+{
+ std::cerr << what << ": " << ec.message() << "\n";
+}
+
+// Echoes back all received WebSocket messages
+class session
+ : public boost::asio::coroutine
+ , public std::enable_shared_from_this<session>
+{
+ websocket::stream<beast::tcp_stream> ws_;
+ beast::flat_buffer buffer_;
+
+public:
+ // Take ownership of the socket
+ explicit
+ session(tcp::socket socket)
+ : ws_(std::move(socket))
+ {
+ }
+
+ // Start the asynchronous operation
+ void
+ run()
+ {
+ // We need to be executing within a strand to perform async operations
+ // on the I/O objects in this session. Although not strictly necessary
+ // for single-threaded contexts, this example code is written to be
+ // thread-safe by default.
+ net::dispatch(ws_.get_executor(),
+ beast::bind_front_handler(&session::loop,
+ shared_from_this(),
+ beast::error_code{},
+ 0));
+ }
+
+ #include <boost/asio/yield.hpp>
+
+ void
+ loop(
+ beast::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ boost::ignore_unused(bytes_transferred);
+ reenter(*this)
+ {
+ // Set suggested timeout settings for the websocket
+ ws_.set_option(
+ websocket::stream_base::timeout::suggested(
+ beast::role_type::server));
+
+ // Set a decorator to change the Server of the handshake
+ ws_.set_option(websocket::stream_base::decorator(
+ [](websocket::response_type& res)
+ {
+ res.set(http::field::server,
+ std::string(BOOST_BEAST_VERSION_STRING) +
+ " websocket-server-stackless");
+ }));
+
+ // Accept the websocket handshake
+ yield ws_.async_accept(
+ std::bind(
+ &session::loop,
+ shared_from_this(),
+ std::placeholders::_1,
+ 0));
+ if(ec)
+ return fail(ec, "accept");
+
+ for(;;)
+ {
+ // Read a message into our buffer
+ yield ws_.async_read(
+ buffer_,
+ std::bind(
+ &session::loop,
+ shared_from_this(),
+ std::placeholders::_1,
+ std::placeholders::_2));
+ if(ec == websocket::error::closed)
+ {
+ // This indicates that the session was closed
+ return;
+ }
+ if(ec)
+ fail(ec, "read");
+
+ // Echo the message
+ ws_.text(ws_.got_text());
+ yield ws_.async_write(
+ buffer_.data(),
+ std::bind(
+ &session::loop,
+ shared_from_this(),
+ std::placeholders::_1,
+ std::placeholders::_2));
+ if(ec)
+ return fail(ec, "write");
+
+ // Clear the buffer
+ buffer_.consume(buffer_.size());
+ }
+ }
+ }
+
+ #include <boost/asio/unyield.hpp>
+};
+
+//------------------------------------------------------------------------------
+
+// Accepts incoming connections and launches the sessions
+class listener
+ : public boost::asio::coroutine
+ , public std::enable_shared_from_this<listener>
+{
+ net::io_context& ioc_;
+ tcp::acceptor acceptor_;
+ tcp::socket socket_;
+
+public:
+ listener(
+ net::io_context& ioc,
+ tcp::endpoint endpoint)
+ : ioc_(ioc)
+ , acceptor_(net::make_strand(ioc))
+ , socket_(net::make_strand(ioc))
+ {
+ beast::error_code ec;
+
+ // Open the acceptor
+ acceptor_.open(endpoint.protocol(), ec);
+ if(ec)
+ {
+ fail(ec, "open");
+ return;
+ }
+
+ // Allow address reuse
+ acceptor_.set_option(net::socket_base::reuse_address(true), ec);
+ if(ec)
+ {
+ fail(ec, "set_option");
+ return;
+ }
+
+ // Bind to the server address
+ acceptor_.bind(endpoint, ec);
+ if(ec)
+ {
+ fail(ec, "bind");
+ return;
+ }
+
+ // Start listening for connections
+ acceptor_.listen(
+ net::socket_base::max_listen_connections, ec);
+ if(ec)
+ {
+ fail(ec, "listen");
+ return;
+ }
+ }
+
+ // Start accepting incoming connections
+ void
+ run()
+ {
+ loop();
+ }
+
+private:
+
+ #include <boost/asio/yield.hpp>
+
+ void
+ loop(beast::error_code ec = {})
+ {
+ reenter(*this)
+ {
+ for(;;)
+ {
+ yield acceptor_.async_accept(
+ socket_,
+ std::bind(
+ &listener::loop,
+ shared_from_this(),
+ std::placeholders::_1));
+ if(ec)
+ {
+ fail(ec, "accept");
+ }
+ else
+ {
+ // Create the session and run it
+ std::make_shared<session>(std::move(socket_))->run();
+ }
+
+ // Make sure each session gets its own strand
+ socket_ = tcp::socket(net::make_strand(ioc_));
+ }
+ }
+ }
+
+ #include <boost/asio/unyield.hpp>
+};
+
+//------------------------------------------------------------------------------
+
+int main(int argc, char* argv[])
+{
+ // Check command line arguments.
+ if (argc != 4)
+ {
+ std::cerr <<
+ "Usage: websocket-server-stackless <address> <port> <threads>\n" <<
+ "Example:\n" <<
+ " websocket-server-stackless 0.0.0.0 8080 1\n";
+ return EXIT_FAILURE;
+ }
+ auto const address = net::ip::make_address(argv[1]);
+ auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
+ auto const threads = std::max<int>(1, std::atoi(argv[3]));
+
+ // The io_context is required for all I/O
+ net::io_context ioc{threads};
+
+ // Create and launch a listening port
+ std::make_shared<listener>(ioc, tcp::endpoint{address, port})->run();
+
+ // Run the I/O service on the requested number of threads
+ std::vector<std::thread> v;
+ v.reserve(threads - 1);
+ for(auto i = threads - 1; i > 0; --i)
+ v.emplace_back(
+ [&ioc]
+ {
+ ioc.run();
+ });
+ ioc.run();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/boost/libs/beast/example/websocket/server/sync-ssl/CMakeLists.txt b/src/boost/libs/beast/example/websocket/server/sync-ssl/CMakeLists.txt
new file mode 100644
index 000000000..0ad254ce5
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/sync-ssl/CMakeLists.txt
@@ -0,0 +1,31 @@
+#
+# 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
+#
+
+if (OPENSSL_FOUND)
+ GroupSources(include/boost/beast beast)
+ GroupSources(example/common common)
+ GroupSources(example/websocket/server/sync-ssl "/")
+
+ add_executable (websocket-server-sync-ssl
+ ${BOOST_BEAST_FILES}
+ ${PROJECT_SOURCE_DIR}/example/common/server_certificate.hpp
+ Jamfile
+ websocket_server_sync_ssl.cpp
+ )
+
+ set_property(TARGET websocket-server-sync-ssl PROPERTY FOLDER "example-websocket-server")
+
+ target_link_libraries (websocket-server-sync-ssl
+ OpenSSL::SSL OpenSSL::Crypto
+ lib-asio
+ lib-asio-ssl
+ lib-beast
+ )
+
+endif()
diff --git a/src/boost/libs/beast/example/websocket/server/sync-ssl/Jamfile b/src/boost/libs/beast/example/websocket/server/sync-ssl/Jamfile
new file mode 100644
index 000000000..55ac35b84
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/sync-ssl/Jamfile
@@ -0,0 +1,22 @@
+#
+# 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
+#
+
+import ac ;
+
+project
+ : requirements
+ [ ac.check-library /boost/beast//lib-asio-ssl : <library>/boost/beast//lib-asio-ssl/<link>static : <build>no ]
+ ;
+
+exe websocket-server-sync-ssl :
+ websocket_server_sync_ssl.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ ;
diff --git a/src/boost/libs/beast/example/websocket/server/sync-ssl/websocket_server_sync_ssl.cpp b/src/boost/libs/beast/example/websocket/server/sync-ssl/websocket_server_sync_ssl.cpp
new file mode 100644
index 000000000..5a7b4dc06
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/sync-ssl/websocket_server_sync_ssl.cpp
@@ -0,0 +1,137 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: WebSocket SSL server, synchronous
+//
+//------------------------------------------------------------------------------
+
+#include "example/common/server_certificate.hpp"
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/ssl.hpp>
+#include <boost/beast/websocket.hpp>
+#include <boost/beast/websocket/ssl.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/ssl/stream.hpp>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <string>
+#include <thread>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+//------------------------------------------------------------------------------
+
+// Echoes back all received WebSocket messages
+void
+do_session(tcp::socket& socket, ssl::context& ctx)
+{
+ try
+ {
+ // Construct the websocket stream around the socket
+ websocket::stream<beast::ssl_stream<tcp::socket&>> ws{socket, ctx};
+
+ // Perform the SSL handshake
+ ws.next_layer().handshake(ssl::stream_base::server);
+
+ // Set a decorator to change the Server of the handshake
+ ws.set_option(websocket::stream_base::decorator(
+ [](websocket::response_type& res)
+ {
+ res.set(http::field::server,
+ std::string(BOOST_BEAST_VERSION_STRING) +
+ " websocket-server-sync-ssl");
+ }));
+
+ // Accept the websocket handshake
+ ws.accept();
+
+ for(;;)
+ {
+ // This buffer will hold the incoming message
+ beast::flat_buffer buffer;
+
+ // Read a message
+ ws.read(buffer);
+
+ // Echo the message back
+ ws.text(ws.got_text());
+ ws.write(buffer.data());
+ }
+ }
+ catch(beast::system_error const& se)
+ {
+ // This indicates that the session was closed
+ if(se.code() != websocket::error::closed)
+ std::cerr << "Error: " << se.code().message() << std::endl;
+ }
+ catch(std::exception const& e)
+ {
+ std::cerr << "Error: " << e.what() << std::endl;
+ }
+}
+
+//------------------------------------------------------------------------------
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ // Check command line arguments.
+ if (argc != 3)
+ {
+ std::cerr <<
+ "Usage: websocket-server-sync-ssl <address> <port>\n" <<
+ "Example:\n" <<
+ " websocket-server-sync-ssl 0.0.0.0 8080\n";
+ return EXIT_FAILURE;
+ }
+ auto const address = net::ip::make_address(argv[1]);
+ auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
+
+ // The io_context is required for all I/O
+ net::io_context ioc{1};
+
+ // The SSL context is required, and holds certificates
+ ssl::context ctx{ssl::context::tlsv12};
+
+ // This holds the self-signed certificate used by the server
+ load_server_certificate(ctx);
+
+ // The acceptor receives incoming connections
+ tcp::acceptor acceptor{ioc, {address, port}};
+ for(;;)
+ {
+ // This will receive the new connection
+ tcp::socket socket{ioc};
+
+ // Block until we get a connection
+ acceptor.accept(socket);
+
+ // Launch the session, transferring ownership of the socket
+ std::thread{std::bind(
+ &do_session,
+ std::move(socket),
+ std::ref(ctx))}.detach();
+ }
+ }
+ catch (const std::exception& e)
+ {
+ std::cerr << "Error: " << e.what() << std::endl;
+ return EXIT_FAILURE;
+ }
+}
diff --git a/src/boost/libs/beast/example/websocket/server/sync/CMakeLists.txt b/src/boost/libs/beast/example/websocket/server/sync/CMakeLists.txt
new file mode 100644
index 000000000..486998615
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/sync/CMakeLists.txt
@@ -0,0 +1,23 @@
+#
+# 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
+#
+
+GroupSources(include/boost/beast beast)
+GroupSources(example/websocket/server/sync "/")
+
+add_executable (websocket-server-sync
+ ${BOOST_BEAST_FILES}
+ Jamfile
+ websocket_server_sync.cpp
+)
+
+target_link_libraries(websocket-server-sync
+ lib-asio
+ lib-beast)
+
+set_property(TARGET websocket-server-sync PROPERTY FOLDER "example-websocket-server")
diff --git a/src/boost/libs/beast/example/websocket/server/sync/Jamfile b/src/boost/libs/beast/example/websocket/server/sync/Jamfile
new file mode 100644
index 000000000..7fd14ce4a
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/sync/Jamfile
@@ -0,0 +1,15 @@
+#
+# 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
+#
+
+exe websocket-server-sync :
+ websocket_server_sync.cpp
+ :
+ <variant>coverage:<build>no
+ <variant>ubasan:<build>no
+ ;
diff --git a/src/boost/libs/beast/example/websocket/server/sync/websocket_server_sync.cpp b/src/boost/libs/beast/example/websocket/server/sync/websocket_server_sync.cpp
new file mode 100644
index 000000000..2f75c468e
--- /dev/null
+++ b/src/boost/libs/beast/example/websocket/server/sync/websocket_server_sync.cpp
@@ -0,0 +1,121 @@
+//
+// Copyright (c) 2016-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
+//
+
+//------------------------------------------------------------------------------
+//
+// Example: WebSocket server, synchronous
+//
+//------------------------------------------------------------------------------
+
+#include <boost/beast/core.hpp>
+#include <boost/beast/websocket.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <string>
+#include <thread>
+
+namespace beast = boost::beast; // from <boost/beast.hpp>
+namespace http = beast::http; // from <boost/beast/http.hpp>
+namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
+namespace net = boost::asio; // from <boost/asio.hpp>
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+
+//------------------------------------------------------------------------------
+
+// Echoes back all received WebSocket messages
+void
+do_session(tcp::socket& socket)
+{
+ try
+ {
+ // Construct the stream by moving in the socket
+ websocket::stream<tcp::socket> ws{std::move(socket)};
+
+ // Set a decorator to change the Server of the handshake
+ ws.set_option(websocket::stream_base::decorator(
+ [](websocket::response_type& res)
+ {
+ res.set(http::field::server,
+ std::string(BOOST_BEAST_VERSION_STRING) +
+ " websocket-server-sync");
+ }));
+
+ // Accept the websocket handshake
+ ws.accept();
+
+ for(;;)
+ {
+ // This buffer will hold the incoming message
+ beast::flat_buffer buffer;
+
+ // Read a message
+ ws.read(buffer);
+
+ // Echo the message back
+ ws.text(ws.got_text());
+ ws.write(buffer.data());
+ }
+ }
+ catch(beast::system_error const& se)
+ {
+ // This indicates that the session was closed
+ if(se.code() != websocket::error::closed)
+ std::cerr << "Error: " << se.code().message() << std::endl;
+ }
+ catch(std::exception const& e)
+ {
+ std::cerr << "Error: " << e.what() << std::endl;
+ }
+}
+
+//------------------------------------------------------------------------------
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ // Check command line arguments.
+ if (argc != 3)
+ {
+ std::cerr <<
+ "Usage: websocket-server-sync <address> <port>\n" <<
+ "Example:\n" <<
+ " websocket-server-sync 0.0.0.0 8080\n";
+ return EXIT_FAILURE;
+ }
+ auto const address = net::ip::make_address(argv[1]);
+ auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
+
+ // The io_context is required for all I/O
+ net::io_context ioc{1};
+
+ // The acceptor receives incoming connections
+ tcp::acceptor acceptor{ioc, {address, port}};
+ for(;;)
+ {
+ // This will receive the new connection
+ tcp::socket socket{ioc};
+
+ // Block until we get a connection
+ acceptor.accept(socket);
+
+ // Launch the session, transferring ownership of the socket
+ std::thread{std::bind(
+ &do_session,
+ std::move(socket))}.detach();
+ }
+ }
+ catch (const std::exception& e)
+ {
+ std::cerr << "Error: " << e.what() << std::endl;
+ return EXIT_FAILURE;
+ }
+}