Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/marian-nmt/Simple-WebSocket-Server.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml4
-rw-r--r--CMakeLists.txt2
-rw-r--r--asio_compatibility.hpp4
-rw-r--r--client_ws.hpp62
-rw-r--r--client_wss.hpp18
-rw-r--r--crypto.hpp157
-rw-r--r--server_ws.hpp29
-rw-r--r--server_wss.hpp15
-rw-r--r--tests/parse_test.cpp102
-rw-r--r--utility.hpp10
10 files changed, 223 insertions, 180 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index e9e8b82..9591259 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -17,10 +17,6 @@ buster:
image: "registry.gitlab.com/eidheim/docker-images:buster"
<<: *compile_and_test
-jessie:
- image: "registry.gitlab.com/eidheim/docker-images:jessie"
- <<: *compile_and_test
-
stretch:
image: "registry.gitlab.com/eidheim/docker-images:stretch"
<<: *compile_and_test
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 11e11f1..5c83068 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -19,7 +19,7 @@ target_link_libraries(simple-websocket-server INTERFACE ${CMAKE_THREAD_LIBS_INIT
# TODO 2020 when Debian Jessie LTS ends:
# Remove Boost system, thread, regex components; use Boost::<component> aliases; remove Boost target_include_directories
if(USE_STANDALONE_ASIO)
- target_compile_definitions(simple-websocket-server INTERFACE USE_STANDALONE_ASIO)
+ target_compile_definitions(simple-websocket-server INTERFACE ASIO_STANDALONE)
find_path(ASIO_PATH asio.hpp)
if(NOT ASIO_PATH)
message(FATAL_ERROR "Standalone Asio not found")
diff --git a/asio_compatibility.hpp b/asio_compatibility.hpp
index c2e0b66..5a7007d 100644
--- a/asio_compatibility.hpp
+++ b/asio_compatibility.hpp
@@ -3,7 +3,7 @@
#include <memory>
-#ifdef USE_STANDALONE_ASIO
+#ifdef ASIO_STANDALONE
#include <asio.hpp>
#include <asio/steady_timer.hpp>
namespace SimpleWeb {
@@ -27,7 +27,7 @@ namespace SimpleWeb {
#endif
namespace SimpleWeb {
-#if(USE_STANDALONE_ASIO && ASIO_VERSION >= 101300) || BOOST_ASIO_VERSION >= 101300
+#if(ASIO_STANDALONE && ASIO_VERSION >= 101300) || BOOST_ASIO_VERSION >= 101300
using io_context = asio::io_context;
using resolver_results = asio::ip::tcp::resolver::results_type;
using async_connect_endpoint = asio::ip::tcp::endpoint;
diff --git a/client_ws.hpp b/client_ws.hpp
index e4a26f6..4b1d4e9 100644
--- a/client_ws.hpp
+++ b/client_ws.hpp
@@ -70,8 +70,8 @@ namespace SimpleWeb {
private:
template <typename... Args>
- Connection(std::shared_ptr<ScopeRunner> handler_runner_, long timeout_idle, Args &&... args) noexcept
- : handler_runner(std::move(handler_runner_)), socket(new socket_type(std::forward<Args>(args)...)), timeout_idle(timeout_idle), closed(false) {}
+ Connection(std::shared_ptr<ScopeRunner> handler_runner_, long timeout_idle, Args &&...args) noexcept
+ : handler_runner(std::move(handler_runner_)), socket(new socket_type(std::forward<Args>(args)...)), timeout_idle(timeout_idle), close_sent(false) {}
std::shared_ptr<ScopeRunner> handler_runner;
@@ -84,16 +84,10 @@ namespace SimpleWeb {
Mutex timer_mutex;
std::unique_ptr<asio::steady_timer> timer GUARDED_BY(timer_mutex);
- std::atomic<bool> closed;
+ std::atomic<bool> close_sent;
asio::ip::tcp::endpoint endpoint; // The endpoint is read in SocketClient::upgrade and must be stored so that it can be read reliably in all handlers, including on_error
- void close() noexcept {
- error_code ec;
- socket->lowest_layer().shutdown(asio::ip::tcp::socket::shutdown_both, ec);
- socket->lowest_layer().cancel(ec);
- }
-
void set_timeout(long seconds = -1) noexcept {
bool use_timeout_idle = false;
if(seconds == -1) {
@@ -113,8 +107,12 @@ namespace SimpleWeb {
timer->async_wait([connection_weak, use_timeout_idle](const error_code &ec) {
if(!ec) {
if(auto connection = connection_weak.lock()) {
- if(use_timeout_idle)
- connection->send_close(1000, "idle timeout"); // 1000=normal closure
+ if(use_timeout_idle) {
+ if(connection->close_sent)
+ connection->close();
+ else
+ connection->send_close(1000, "idle timeout"); // 1000=normal closure
+ }
else
connection->close();
}
@@ -240,9 +238,9 @@ namespace SimpleWeb {
void send_close(int status, const std::string &reason = "", std::function<void(const error_code &)> callback = nullptr) {
// Send close only once (in case close is initiated by client)
- if(closed)
+ if(close_sent)
return;
- closed = true;
+ close_sent = true;
auto out_message = std::make_shared<OutMessage>();
@@ -255,6 +253,13 @@ namespace SimpleWeb {
send(out_message, std::move(callback), 136);
}
+ /// Force close connection. Use `send_close()` instead for standard compliant connection close.
+ void close() noexcept {
+ error_code ec;
+ socket->lowest_layer().shutdown(asio::ip::tcp::socket::shutdown_both, ec);
+ socket->lowest_layer().cancel(ec);
+ }
+
const asio::ip::tcp::endpoint &remote_endpoint() const noexcept {
return endpoint;
}
@@ -279,6 +284,8 @@ namespace SimpleWeb {
CaseInsensitiveMultimap header;
/// Set proxy server (server:port)
std::string proxy_server;
+ /// Set proxy authorization (username:password)
+ std::string proxy_auth;
};
/// Set before calling start().
Config config;
@@ -365,22 +372,33 @@ namespace SimpleWeb {
}
std::pair<std::string, unsigned short> parse_host_port(const std::string &host_port, unsigned short default_port) const noexcept {
- std::pair<std::string, unsigned short> parsed_host_port;
- std::size_t host_end = host_port.find(':');
- if(host_end == std::string::npos) {
- parsed_host_port.first = host_port;
- parsed_host_port.second = default_port;
+ std::string host, port;
+ host.reserve(host_port.size());
+ bool parse_port = false;
+ int square_count = 0; // To parse IPv6 addresses
+ for(auto chr : host_port) {
+ if(chr == '[')
+ ++square_count;
+ else if(chr == ']')
+ --square_count;
+ else if(square_count == 0 && chr == ':')
+ parse_port = true;
+ else if(!parse_port)
+ host += chr;
+ else
+ port += chr;
}
+
+ if(port.empty())
+ return {std::move(host), default_port};
else {
- parsed_host_port.first = host_port.substr(0, host_end);
try {
- parsed_host_port.second = static_cast<unsigned short>(stoul(host_port.substr(host_end + 1)));
+ return {std::move(host), static_cast<unsigned short>(std::stoul(port))};
}
catch(...) {
- parsed_host_port.second = default_port;
+ return {std::move(host), default_port};
}
}
- return parsed_host_port;
}
virtual void connect() = 0;
diff --git a/client_wss.hpp b/client_wss.hpp
index 55ee929..0d19fc9 100644
--- a/client_wss.hpp
+++ b/client_wss.hpp
@@ -3,7 +3,7 @@
#include "client_ws.hpp"
-#ifdef USE_STANDALONE_ASIO
+#ifdef ASIO_STANDALONE
#include <asio/ssl.hpp>
#else
#include <boost/asio/ssl.hpp>
@@ -27,7 +27,16 @@ namespace SimpleWeb {
SocketClient(const std::string &server_port_path, bool verify_certificate = true,
const std::string &certification_file = std::string(), const std::string &private_key_file = std::string(),
const std::string &verify_file = std::string())
- : SocketClientBase<WSS>::SocketClientBase(server_port_path, 443), context(asio::ssl::context::tlsv12) {
+ : SocketClientBase<WSS>::SocketClientBase(server_port_path, 443),
+#if(ASIO_STANDALONE && ASIO_VERSION >= 101300) || BOOST_ASIO_VERSION >= 101300
+ context(asio::ssl::context::tls_client) {
+ // Disabling TLS 1.0 and 1.1 (see RFC 8996)
+ context.set_options(asio::ssl::context::no_tlsv1);
+ context.set_options(asio::ssl::context::no_tlsv1_1);
+#else
+ context(asio::ssl::context::tlsv12) {
+#endif
+
if(certification_file.size() > 0 && private_key_file.size() > 0) {
context.use_certificate_chain_file(certification_file);
context.use_private_key_file(private_key_file, asio::ssl::context::pem);
@@ -87,7 +96,10 @@ namespace SimpleWeb {
std::ostream ostream(streambuf.get());
auto host_port = this->host + ':' + std::to_string(this->port);
ostream << "CONNECT " + host_port + " HTTP/1.1\r\n"
- << "Host: " << host_port << "\r\n\r\n";
+ << "Host: " << host_port << "\r\n";
+ if(!this->config.proxy_auth.empty())
+ ostream << "Proxy-Authorization: Basic " << Crypto::Base64::encode(this->config.proxy_auth) << "\r\n";
+ ostream << "\r\n";
connection->set_timeout(this->config.timeout_request);
asio::async_write(connection->socket->next_layer(), *streambuf, [this, connection, streambuf](const error_code &ec, std::size_t /*bytes_transferred*/) {
connection->cancel_timeout();
diff --git a/crypto.hpp b/crypto.hpp
index 994862d..0d3adbe 100644
--- a/crypto.hpp
+++ b/crypto.hpp
@@ -32,7 +32,7 @@ namespace SimpleWeb {
std::string base64;
BIO *bio, *b64;
- BUF_MEM *bptr = BUF_MEM_new();
+ auto bptr = BUF_MEM_new();
b64 = BIO_new(BIO_f_base64());
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
@@ -62,10 +62,8 @@ namespace SimpleWeb {
/// Returns Base64 decoded string from base64 input.
static std::string decode(const std::string &base64) noexcept {
- std::string ascii;
+ std::string ascii((6 * base64.size()) / 8, '\0'); // The size is a up to two bytes too large.
- // Resize ascii, however, the size is a up to two bytes too large.
- ascii.resize((6 * base64.size()) / 8);
BIO *b64, *bio;
b64 = BIO_new(BIO_f_base64());
@@ -99,133 +97,109 @@ namespace SimpleWeb {
return hex_stream.str();
}
- /// Returns md5 hash value from input string.
- static std::string md5(const std::string &input, std::size_t iterations = 1) noexcept {
- std::string hash;
+ /// Return hash value using specific EVP_MD from input string.
+ static std::string message_digest(const std::string &str, const EVP_MD *evp_md, std::size_t digest_length) noexcept {
+ std::string md(digest_length, '\0');
+
+ auto ctx = EVP_MD_CTX_create();
+ EVP_MD_CTX_init(ctx);
+ EVP_DigestInit_ex(ctx, evp_md, nullptr);
+ EVP_DigestUpdate(ctx, str.data(), str.size());
+ EVP_DigestFinal_ex(ctx, reinterpret_cast<unsigned char *>(&md[0]), nullptr);
+ EVP_MD_CTX_destroy(ctx);
+
+ return md;
+ }
+
+ /// Return hash value using specific EVP_MD from input stream.
+ static std::string stream_digest(std::istream &stream, const EVP_MD *evp_md, std::size_t digest_length) noexcept {
+ std::string md(digest_length, '\0');
+ std::unique_ptr<char[]> buffer(new char[buffer_size]);
+ std::streamsize read_length;
- hash.resize(128 / 8);
- MD5(reinterpret_cast<const unsigned char *>(&input[0]), input.size(), reinterpret_cast<unsigned char *>(&hash[0]));
+ auto ctx = EVP_MD_CTX_create();
+ EVP_MD_CTX_init(ctx);
+ EVP_DigestInit_ex(ctx, evp_md, nullptr);
+ while((read_length = stream.read(buffer.get(), buffer_size).gcount()) > 0)
+ EVP_DigestUpdate(ctx, buffer.get(), static_cast<std::size_t>(read_length));
+ EVP_DigestFinal_ex(ctx, reinterpret_cast<unsigned char *>(&md[0]), nullptr);
+ EVP_MD_CTX_destroy(ctx);
- for(std::size_t c = 1; c < iterations; ++c)
- MD5(reinterpret_cast<const unsigned char *>(&hash[0]), hash.size(), reinterpret_cast<unsigned char *>(&hash[0]));
+ return md;
+ }
+ /// Returns md5 hash value from input string.
+ static std::string md5(const std::string &input, std::size_t iterations = 1) noexcept {
+ auto evp_md = EVP_md5();
+ auto hash = message_digest(input, evp_md, MD5_DIGEST_LENGTH);
+ for(std::size_t i = 1; i < iterations; ++i)
+ hash = message_digest(hash, evp_md, MD5_DIGEST_LENGTH);
return hash;
}
/// Returns md5 hash value from input stream.
static std::string md5(std::istream &stream, std::size_t iterations = 1) noexcept {
- MD5_CTX context;
- MD5_Init(&context);
- std::streamsize read_length;
- std::vector<char> buffer(buffer_size);
- while((read_length = stream.read(&buffer[0], buffer_size).gcount()) > 0)
- MD5_Update(&context, buffer.data(), static_cast<std::size_t>(read_length));
- std::string hash;
- hash.resize(128 / 8);
- MD5_Final(reinterpret_cast<unsigned char *>(&hash[0]), &context);
-
- for(std::size_t c = 1; c < iterations; ++c)
- MD5(reinterpret_cast<const unsigned char *>(&hash[0]), hash.size(), reinterpret_cast<unsigned char *>(&hash[0]));
-
+ auto evp_md = EVP_md5();
+ auto hash = stream_digest(stream, evp_md, MD5_DIGEST_LENGTH);
+ for(std::size_t i = 1; i < iterations; ++i)
+ hash = message_digest(hash, evp_md, MD5_DIGEST_LENGTH);
return hash;
}
/// Returns sha1 hash value from input string.
static std::string sha1(const std::string &input, std::size_t iterations = 1) noexcept {
- std::string hash;
-
- hash.resize(160 / 8);
- SHA1(reinterpret_cast<const unsigned char *>(&input[0]), input.size(), reinterpret_cast<unsigned char *>(&hash[0]));
-
- for(std::size_t c = 1; c < iterations; ++c)
- SHA1(reinterpret_cast<const unsigned char *>(&hash[0]), hash.size(), reinterpret_cast<unsigned char *>(&hash[0]));
-
+ auto evp_md = EVP_sha1();
+ auto hash = message_digest(input, evp_md, SHA_DIGEST_LENGTH);
+ for(std::size_t i = 1; i < iterations; ++i)
+ hash = message_digest(hash, evp_md, SHA_DIGEST_LENGTH);
return hash;
}
/// Returns sha1 hash value from input stream.
static std::string sha1(std::istream &stream, std::size_t iterations = 1) noexcept {
- SHA_CTX context;
- SHA1_Init(&context);
- std::streamsize read_length;
- std::vector<char> buffer(buffer_size);
- while((read_length = stream.read(&buffer[0], buffer_size).gcount()) > 0)
- SHA1_Update(&context, buffer.data(), static_cast<std::size_t>(read_length));
- std::string hash;
- hash.resize(160 / 8);
- SHA1_Final(reinterpret_cast<unsigned char *>(&hash[0]), &context);
-
- for(std::size_t c = 1; c < iterations; ++c)
- SHA1(reinterpret_cast<const unsigned char *>(&hash[0]), hash.size(), reinterpret_cast<unsigned char *>(&hash[0]));
-
+ auto evp_md = EVP_sha1();
+ auto hash = stream_digest(stream, evp_md, SHA_DIGEST_LENGTH);
+ for(std::size_t i = 1; i < iterations; ++i)
+ hash = message_digest(hash, evp_md, SHA_DIGEST_LENGTH);
return hash;
}
/// Returns sha256 hash value from input string.
static std::string sha256(const std::string &input, std::size_t iterations = 1) noexcept {
- std::string hash;
-
- hash.resize(256 / 8);
- SHA256(reinterpret_cast<const unsigned char *>(&input[0]), input.size(), reinterpret_cast<unsigned char *>(&hash[0]));
-
- for(std::size_t c = 1; c < iterations; ++c)
- SHA256(reinterpret_cast<const unsigned char *>(&hash[0]), hash.size(), reinterpret_cast<unsigned char *>(&hash[0]));
-
+ auto evp_md = EVP_sha256();
+ auto hash = message_digest(input, evp_md, SHA256_DIGEST_LENGTH);
+ for(std::size_t i = 1; i < iterations; ++i)
+ hash = message_digest(hash, evp_md, SHA256_DIGEST_LENGTH);
return hash;
}
/// Returns sha256 hash value from input stream.
static std::string sha256(std::istream &stream, std::size_t iterations = 1) noexcept {
- SHA256_CTX context;
- SHA256_Init(&context);
- std::streamsize read_length;
- std::vector<char> buffer(buffer_size);
- while((read_length = stream.read(&buffer[0], buffer_size).gcount()) > 0)
- SHA256_Update(&context, buffer.data(), static_cast<std::size_t>(read_length));
- std::string hash;
- hash.resize(256 / 8);
- SHA256_Final(reinterpret_cast<unsigned char *>(&hash[0]), &context);
-
- for(std::size_t c = 1; c < iterations; ++c)
- SHA256(reinterpret_cast<const unsigned char *>(&hash[0]), hash.size(), reinterpret_cast<unsigned char *>(&hash[0]));
-
+ auto evp_md = EVP_sha256();
+ auto hash = stream_digest(stream, evp_md, SHA256_DIGEST_LENGTH);
+ for(std::size_t i = 1; i < iterations; ++i)
+ hash = message_digest(hash, evp_md, SHA256_DIGEST_LENGTH);
return hash;
}
/// Returns sha512 hash value from input string.
static std::string sha512(const std::string &input, std::size_t iterations = 1) noexcept {
- std::string hash;
-
- hash.resize(512 / 8);
- SHA512(reinterpret_cast<const unsigned char *>(&input[0]), input.size(), reinterpret_cast<unsigned char *>(&hash[0]));
-
- for(std::size_t c = 1; c < iterations; ++c)
- SHA512(reinterpret_cast<const unsigned char *>(&hash[0]), hash.size(), reinterpret_cast<unsigned char *>(&hash[0]));
-
+ auto evp_md = EVP_sha512();
+ auto hash = message_digest(input, evp_md, SHA512_DIGEST_LENGTH);
+ for(std::size_t i = 1; i < iterations; ++i)
+ hash = message_digest(hash, evp_md, SHA512_DIGEST_LENGTH);
return hash;
}
/// Returns sha512 hash value from input stream.
static std::string sha512(std::istream &stream, std::size_t iterations = 1) noexcept {
- SHA512_CTX context;
- SHA512_Init(&context);
- std::streamsize read_length;
- std::vector<char> buffer(buffer_size);
- while((read_length = stream.read(&buffer[0], buffer_size).gcount()) > 0)
- SHA512_Update(&context, buffer.data(), static_cast<std::size_t>(read_length));
- std::string hash;
- hash.resize(512 / 8);
- SHA512_Final(reinterpret_cast<unsigned char *>(&hash[0]), &context);
-
- for(std::size_t c = 1; c < iterations; ++c)
- SHA512(reinterpret_cast<const unsigned char *>(&hash[0]), hash.size(), reinterpret_cast<unsigned char *>(&hash[0]));
-
+ auto evp_md = EVP_sha512();
+ auto hash = stream_digest(stream, evp_md, SHA512_DIGEST_LENGTH);
+ for(std::size_t i = 1; i < iterations; ++i)
+ hash = message_digest(hash, evp_md, SHA512_DIGEST_LENGTH);
return hash;
}
- /// Returns PBKDF2 hash value from the given password
- /// Input parameter key_size number of bytes of the returned key.
-
/**
* Returns PBKDF2 derived key from the given password.
*
@@ -237,8 +211,7 @@ namespace SimpleWeb {
* @return The PBKDF2 derived key.
*/
static std::string pbkdf2(const std::string &password, const std::string &salt, int iterations, int key_size) noexcept {
- std::string key;
- key.resize(static_cast<std::size_t>(key_size));
+ std::string key(static_cast<std::size_t>(key_size), '\0');
PKCS5_PBKDF2_HMAC_SHA1(password.c_str(), password.size(),
reinterpret_cast<const unsigned char *>(salt.c_str()), salt.size(), iterations,
key_size, reinterpret_cast<unsigned char *>(&key[0]));
diff --git a/server_ws.hpp b/server_ws.hpp
index 2256d55..339d65b 100644
--- a/server_ws.hpp
+++ b/server_ws.hpp
@@ -79,7 +79,7 @@ namespace SimpleWeb {
friend class SocketServer<socket_type>;
public:
- Connection(std::unique_ptr<socket_type> &&socket_) noexcept : socket(std::move(socket_)), timeout_idle(0), closed(false) {}
+ Connection(std::unique_ptr<socket_type> &&socket_) noexcept : socket(std::move(socket_)), timeout_idle(0), close_sent(false) {}
std::string method, path, query_string, http_version;
@@ -90,8 +90,8 @@ namespace SimpleWeb {
private:
/// Used to call SocketServer::upgrade.
template <typename... Args>
- Connection(std::shared_ptr<ScopeRunner> handler_runner_, long timeout_idle, Args &&... args) noexcept
- : handler_runner(std::move(handler_runner_)), socket(new socket_type(std::forward<Args>(args)...)), timeout_idle(timeout_idle), closed(false) {}
+ Connection(std::shared_ptr<ScopeRunner> handler_runner_, long timeout_idle, Args &&...args) noexcept
+ : handler_runner(std::move(handler_runner_)), socket(new socket_type(std::forward<Args>(args)...)), timeout_idle(timeout_idle), close_sent(false) {}
std::shared_ptr<ScopeRunner> handler_runner;
@@ -105,16 +105,10 @@ namespace SimpleWeb {
Mutex timer_mutex;
std::unique_ptr<asio::steady_timer> timer GUARDED_BY(timer_mutex);
- std::atomic<bool> closed;
+ std::atomic<bool> close_sent;
asio::ip::tcp::endpoint endpoint; // The endpoint is read in SocketServer::write_handshake and must be stored so that it can be read reliably in all handlers, including on_error
- void close() noexcept {
- error_code ec;
- socket->lowest_layer().shutdown(asio::ip::tcp::socket::shutdown_both, ec);
- socket->lowest_layer().cancel(ec);
- }
-
void set_timeout(long seconds = -1) noexcept {
if(seconds == -1)
seconds = timeout_idle;
@@ -244,9 +238,9 @@ namespace SimpleWeb {
void send_close(int status, const std::string &reason = "", std::function<void(const error_code &)> callback = nullptr) {
// Send close only once (in case close is initiated by server)
- if(closed)
+ if(close_sent)
return;
- closed = true;
+ close_sent = true;
auto send_stream = std::make_shared<OutMessage>();
@@ -259,6 +253,13 @@ namespace SimpleWeb {
send(std::move(send_stream), std::move(callback), 136);
}
+ /// Force close connection. Use `send_close()` instead for standard compliant connection close.
+ void close() noexcept {
+ error_code ec;
+ socket->lowest_layer().shutdown(asio::ip::tcp::socket::shutdown_both, ec);
+ socket->lowest_layer().cancel(ec);
+ }
+
const asio::ip::tcp::endpoint &remote_endpoint() const noexcept {
return endpoint;
}
@@ -274,7 +275,7 @@ namespace SimpleWeb {
}
/// Deprecated, please use remote_endpoint().address().to_string() instead.
- DEPRECATED std::string remote_endpoint_address() const noexcept {
+ SW_DEPRECATED std::string remote_endpoint_address() const noexcept {
try {
return endpoint.address().to_string();
}
@@ -284,7 +285,7 @@ namespace SimpleWeb {
}
/// Deprecated, please use remote_endpoint().port() instead.
- DEPRECATED unsigned short remote_endpoint_port() const noexcept {
+ SW_DEPRECATED unsigned short remote_endpoint_port() const noexcept {
try {
return endpoint.port();
}
diff --git a/server_wss.hpp b/server_wss.hpp
index 05afd85..42d8133 100644
--- a/server_wss.hpp
+++ b/server_wss.hpp
@@ -5,7 +5,7 @@
#include <algorithm>
#include <openssl/ssl.h>
-#ifdef USE_STANDALONE_ASIO
+#ifdef ASIO_STANDALONE
#include <asio/ssl.hpp>
#else
#include <boost/asio/ssl.hpp>
@@ -23,12 +23,21 @@ namespace SimpleWeb {
/**
* Constructs a server object.
*
- * @param certification_file If non-empty, sends the given certification file to client.
+ * @param certification_file Sends the given certification file to client.
* @param private_key_file Specifies the file containing the private key for certification_file.
* @param verify_file If non-empty, use this certificate authority file to perform verification of client's certificate and hostname according to RFC 2818.
*/
SocketServer(const std::string &certification_file, const std::string &private_key_file, const std::string &verify_file = std::string())
- : SocketServerBase<WSS>(443), context(asio::ssl::context::tlsv12) {
+ : SocketServerBase<WSS>(443),
+#if(ASIO_STANDALONE && ASIO_VERSION >= 101300) || BOOST_ASIO_VERSION >= 101300
+ context(asio::ssl::context::tls_server) {
+ // Disabling TLS 1.0 and 1.1 (see RFC 8996)
+ context.set_options(asio::ssl::context::no_tlsv1);
+ context.set_options(asio::ssl::context::no_tlsv1_1);
+#else
+ context(asio::ssl::context::tlsv12) {
+#endif
+
context.use_certificate_chain_file(certification_file);
context.use_private_key_file(private_key_file, asio::ssl::context::pem);
diff --git a/tests/parse_test.cpp b/tests/parse_test.cpp
index 45f5476..58b8962 100644
--- a/tests/parse_test.cpp
+++ b/tests/parse_test.cpp
@@ -57,30 +57,6 @@ public:
void connect() {}
- void constructor_parse_test1() {
- ASSERT(path == "/test");
- ASSERT(host == "test.org");
- ASSERT(port == 8080);
- }
-
- void constructor_parse_test2() {
- ASSERT(path == "/test");
- ASSERT(host == "test.org");
- ASSERT(port == 80);
- }
-
- void constructor_parse_test3() {
- ASSERT(path == "/");
- ASSERT(host == "test.org");
- ASSERT(port == 80);
- }
-
- void constructor_parse_test4() {
- ASSERT(path == "/");
- ASSERT(host == "test.org");
- ASSERT(port == 8080);
- }
-
void parse_response_header_test() {
auto connection = std::shared_ptr<Connection>(new Connection(handler_runner, config.timeout_idle, *io_service));
connection->in_message = std::shared_ptr<InMessage>(new InMessage());
@@ -136,18 +112,76 @@ int main() {
serverTest.parse_request_test();
- SocketClientTest clientTest("test.org:8080/test");
- clientTest.constructor_parse_test1();
+ {
+ SocketClientTest clientTest("test.org:8080/test");
+ ASSERT(clientTest.path == "/test");
+ ASSERT(clientTest.host == "test.org");
+ ASSERT(clientTest.port == 8080);
+ }
+
+ {
+ SocketClientTest clientTest("test.org/test");
+ ASSERT(clientTest.path == "/test");
+ ASSERT(clientTest.host == "test.org");
+ ASSERT(clientTest.port == 80);
+ }
+
+ {
+ SocketClientTest clientTest("test.org");
+ ASSERT(clientTest.path == "/");
+ ASSERT(clientTest.host == "test.org");
+ ASSERT(clientTest.port == 80);
+ }
+
+ {
+ SocketClientTest clientTest("test.org:test");
+ ASSERT(clientTest.path == "/");
+ ASSERT(clientTest.host == "test.org");
+ ASSERT(clientTest.port == 80);
+ }
+
+ {
+ SocketClientTest clientTest("[::1]");
+ ASSERT(clientTest.path == "/");
+ ASSERT(clientTest.host == "::1");
+ ASSERT(clientTest.port == 80);
+ }
+
+ {
+ SocketClientTest clientTest("[::1]/test");
+ ASSERT(clientTest.path == "/test");
+ ASSERT(clientTest.host == "::1");
+ ASSERT(clientTest.port == 80);
+ }
+
+ {
+ SocketClientTest clientTest("[::1]:8080");
+ ASSERT(clientTest.path == "/");
+ ASSERT(clientTest.host == "::1");
+ ASSERT(clientTest.port == 8080);
+ }
- SocketClientTest clientTest2("test.org/test");
- clientTest2.constructor_parse_test2();
+ {
+ SocketClientTest clientTest("[::1]:8080/test");
+ ASSERT(clientTest.path == "/test");
+ ASSERT(clientTest.host == "::1");
+ ASSERT(clientTest.port == 8080);
+ }
- SocketClientTest clientTest3("test.org");
- clientTest3.constructor_parse_test3();
+ {
+ SocketClientTest clientTest("[::1]:test/test");
+ ASSERT(clientTest.path == "/test");
+ ASSERT(clientTest.host == "::1");
+ ASSERT(clientTest.port == 80);
+ }
- SocketClientTest clientTest4("test.org:8080");
- clientTest4.io_service = std::make_shared<io_context>();
- clientTest4.constructor_parse_test4();
+ {
+ SocketClientTest clientTest("test.org:8080");
+ clientTest.io_service = std::make_shared<io_context>();
+ ASSERT(clientTest.path == "/");
+ ASSERT(clientTest.host == "test.org");
+ ASSERT(clientTest.port == 8080);
- clientTest4.parse_response_header_test();
+ clientTest.parse_response_header_test();
+ }
}
diff --git a/utility.hpp b/utility.hpp
index 3b41ff3..cac7dfa 100644
--- a/utility.hpp
+++ b/utility.hpp
@@ -12,13 +12,13 @@
#include <string>
#include <unordered_map>
-#ifndef DEPRECATED
+#ifndef SW_DEPRECATED
#if defined(__GNUC__) || defined(__clang__)
-#define DEPRECATED __attribute__((deprecated))
+#define SW_DEPRECATED __attribute__((deprecated))
#elif defined(_MSC_VER)
-#define DEPRECATED __declspec(deprecated)
+#define SW_DEPRECATED __declspec(deprecated)
#else
-#define DEPRECATED
+#define SW_DEPRECATED
#endif
#endif
@@ -27,7 +27,7 @@
namespace SimpleWeb {
using string_view = std::string_view;
}
-#elif !defined(USE_STANDALONE_ASIO)
+#elif !defined(ASIO_STANDALONE)
#include <boost/utility/string_ref.hpp>
namespace SimpleWeb {
using string_view = boost::string_ref;