From 7dd2d2108a4a21e4f9d61323e128ecddbef39e3a Mon Sep 17 00:00:00 2001 From: eidheim Date: Sat, 22 Jul 2017 12:50:40 +0200 Subject: [PATCH] Added noexcept --- client_http.hpp | 69 ++++++++++++++++++++------------------ client_https.hpp | 8 ++--- crypto.hpp | 26 +++++++-------- server_http.hpp | 79 +++++++++++++++++++++++--------------------- server_https.hpp | 6 ++-- status_code.hpp | 6 ++-- tests/parse_test.cpp | 6 ++-- utility.hpp | 34 +++++++++---------- 8 files changed, 122 insertions(+), 112 deletions(-) diff --git a/client_http.hpp b/client_http.hpp index ed6838a..47accb1 100644 --- a/client_http.hpp +++ b/client_http.hpp @@ -40,19 +40,24 @@ namespace SimpleWeb { friend class ClientBase; public: - size_t size() { + size_t size() noexcept { return streambuf.size(); } /// Convenience function to return std::string. Note that the stream buffer is emptied when this functions is used. - std::string string() { - std::stringstream ss; - ss << rdbuf(); - return ss.str(); + std::string string() noexcept { + try { + std::stringstream ss; + ss << rdbuf(); + return ss.str(); + } + catch(...) { + return std::string(); + } } private: asio::streambuf &streambuf; - Content(asio::streambuf &streambuf) : std::istream(&streambuf), streambuf(streambuf) {} + Content(asio::streambuf &streambuf) noexcept : std::istream(&streambuf), streambuf(streambuf) {} }; class Response { @@ -69,14 +74,14 @@ namespace SimpleWeb { private: asio::streambuf content_buffer; - Response() : content(content_buffer) {} + Response() noexcept : content(content_buffer) {} }; class Config { friend class ClientBase; private: - Config() {} + Config() noexcept {} public: /// Set timeout on requests in seconds. Default value: 0 (no timeout). @@ -91,7 +96,7 @@ namespace SimpleWeb { class Connection : public std::enable_shared_from_this { public: template - Connection(std::shared_ptr handler_runner, long timeout, Args &&... args) + Connection(std::shared_ptr handler_runner, long timeout, Args &&... args) noexcept : handler_runner(std::move(handler_runner)), timeout(timeout), socket(new socket_type(std::forward(args)...)) {} std::shared_ptr handler_runner; @@ -103,7 +108,7 @@ namespace SimpleWeb { std::unique_ptr timer; - void set_timeout(long seconds = 0) { + void set_timeout(long seconds = 0) noexcept { if(seconds == 0) seconds = timeout; if(seconds == 0) { @@ -121,7 +126,7 @@ namespace SimpleWeb { }); } - void cancel_timeout() { + void cancel_timeout() noexcept { if(timer) timer->cancel(); } @@ -129,7 +134,7 @@ namespace SimpleWeb { class Session { public: - Session(std::shared_ptr connection, std::unique_ptr request_buffer) + Session(std::shared_ptr connection, std::unique_ptr request_buffer) noexcept : connection(std::move(connection)), request_buffer(std::move(request_buffer)), response(new Response()) {} std::shared_ptr connection; @@ -209,7 +214,7 @@ namespace SimpleWeb { /// Asynchronous request where setting and/or running Client's io_service is required. /// Do not use concurrently with the synchronous request functions. void request(const std::string &method, const std::string &path, string_view content, const CaseInsensitiveMultimap &header, - std::function, const error_code &)> &&request_callback_) { + std::function, const error_code &)> &&request_callback_) noexcept { auto session = std::make_shared(get_connection(), create_request_header(method, path, header)); auto response = session->response; auto request_callback = std::make_shared, const error_code &)>>(std::move(request_callback_)); @@ -251,24 +256,24 @@ namespace SimpleWeb { /// Asynchronous request where setting and/or running Client's io_service is required. /// Do not use concurrently with the synchronous request functions. void request(const std::string &method, const std::string &path, string_view content, - std::function, const error_code &)> &&request_callback) { + std::function, const error_code &)> &&request_callback) noexcept { request(method, path, content, CaseInsensitiveMultimap(), std::move(request_callback)); } /// Asynchronous request where setting and/or running Client's io_service is required. void request(const std::string &method, const std::string &path, - std::function, const error_code &)> &&request_callback) { + std::function, const error_code &)> &&request_callback) noexcept { request(method, path, std::string(), CaseInsensitiveMultimap(), std::move(request_callback)); } /// Asynchronous request where setting and/or running Client's io_service is required. - void request(const std::string &method, std::function, const error_code &)> &&request_callback) { + void request(const std::string &method, std::function, const error_code &)> &&request_callback) noexcept { request(method, std::string("/"), std::string(), CaseInsensitiveMultimap(), std::move(request_callback)); } /// Asynchronous request where setting and/or running Client's io_service is required. void request(const std::string &method, const std::string &path, std::istream &content, const CaseInsensitiveMultimap &header, - std::function, const error_code &)> &&request_callback_) { + std::function, const error_code &)> &&request_callback_) noexcept { auto session = std::make_shared(get_connection(), create_request_header(method, path, header)); auto response = session->response; auto request_callback = std::make_shared, const error_code &)>>(std::move(request_callback_)); @@ -313,12 +318,12 @@ namespace SimpleWeb { /// Asynchronous request where setting and/or running Client's io_service is required. void request(const std::string &method, const std::string &path, std::istream &content, - std::function, const error_code &)> &&request_callback) { + std::function, const error_code &)> &&request_callback) noexcept { request(method, path, content, CaseInsensitiveMultimap(), std::move(request_callback)); } /// Close connections - void stop() { + void stop() noexcept { std::unique_lock lock(connections_mutex); for(auto it = connections.begin(); it != connections.end();) { error_code ec; @@ -327,7 +332,7 @@ namespace SimpleWeb { } } - virtual ~ClientBase() { + virtual ~ClientBase() noexcept { handler_runner->stop(); stop(); } @@ -348,13 +353,13 @@ namespace SimpleWeb { size_t concurrent_synchronous_requests = 0; std::mutex concurrent_synchronous_requests_mutex; - ClientBase(const std::string &host_port, unsigned short default_port) : handler_runner(new ScopeRunner()) { + ClientBase(const std::string &host_port, unsigned short default_port) noexcept : handler_runner(new ScopeRunner()) { auto parsed_host_port = parse_host_port(host_port, default_port); host = parsed_host_port.first; port = parsed_host_port.second; } - std::shared_ptr get_connection() { + std::shared_ptr get_connection() noexcept { std::shared_ptr connection; std::unique_lock lock(connections_mutex); @@ -388,10 +393,10 @@ namespace SimpleWeb { return connection; } - virtual std::shared_ptr create_connection() = 0; - virtual void connect(const std::shared_ptr &) = 0; + virtual std::shared_ptr create_connection() noexcept = 0; + virtual void connect(const std::shared_ptr &) noexcept = 0; - std::unique_ptr create_request_header(const std::string &method, const std::string &path, const CaseInsensitiveMultimap &header) const { + std::unique_ptr create_request_header(const std::string &method, const std::string &path, const CaseInsensitiveMultimap &header) const noexcept { auto corrected_path = path; if(corrected_path == "") corrected_path = "/"; @@ -407,7 +412,7 @@ namespace SimpleWeb { return request_buffer; } - std::pair parse_host_port(const std::string &host_port, unsigned short default_port) const { + std::pair parse_host_port(const std::string &host_port, unsigned short default_port) const noexcept { std::pair parsed_host_port; size_t host_end = host_port.find(':'); if(host_end == std::string::npos) { @@ -421,7 +426,7 @@ namespace SimpleWeb { return parsed_host_port; } - void write(const std::shared_ptr &session) { + void write(const std::shared_ptr &session) noexcept { session->connection->set_timeout(); asio::async_write(*session->connection->socket, session->request_buffer->data(), [this, session](const error_code &ec, size_t /*bytes_transferred*/) { session->connection->cancel_timeout(); @@ -435,7 +440,7 @@ namespace SimpleWeb { }); } - void read(const std::shared_ptr &session) { + void read(const std::shared_ptr &session) noexcept { session->connection->set_timeout(); asio::async_read_until(*session->connection->socket, session->response->content_buffer, "\r\n\r\n", [this, session](const error_code &ec, size_t bytes_transferred) { session->connection->cancel_timeout(); @@ -515,7 +520,7 @@ namespace SimpleWeb { }); } - void read_chunked(const std::shared_ptr &session, const std::shared_ptr &tmp_streambuf) { + void read_chunked(const std::shared_ptr &session, const std::shared_ptr &tmp_streambuf) noexcept { session->connection->set_timeout(); asio::async_read_until(*session->connection->socket, session->response->content_buffer, "\r\n", [this, session, tmp_streambuf](const error_code &ec, size_t bytes_transferred) { session->connection->cancel_timeout(); @@ -583,14 +588,14 @@ namespace SimpleWeb { template <> class Client : public ClientBase { public: - Client(const std::string &server_port_path) : ClientBase::ClientBase(server_port_path, 80) {} + Client(const std::string &server_port_path) noexcept : ClientBase::ClientBase(server_port_path, 80) {} protected: - std::shared_ptr create_connection() override { + std::shared_ptr create_connection() noexcept override { return std::make_shared(handler_runner, config.timeout, *io_service); } - void connect(const std::shared_ptr &session) override { + void connect(const std::shared_ptr &session) noexcept override { if(!session->connection->socket->lowest_layer().is_open()) { auto resolver = std::make_shared(*io_service); session->connection->set_timeout(config.timeout_connect); diff --git a/client_https.hpp b/client_https.hpp index 1e45441..3b24b70 100644 --- a/client_https.hpp +++ b/client_https.hpp @@ -16,7 +16,7 @@ namespace SimpleWeb { class Client : public ClientBase { public: Client(const std::string &server_port_path, bool verify_certificate = true, const std::string &cert_file = std::string(), - const std::string &private_key_file = std::string(), const std::string &verify_file = std::string()) + const std::string &private_key_file = std::string(), const std::string &verify_file = std::string()) noexcept : ClientBase::ClientBase(server_port_path, 443), context(asio::ssl::context::tlsv12) { if(cert_file.size() > 0 && private_key_file.size() > 0) { context.use_certificate_chain_file(cert_file); @@ -40,11 +40,11 @@ namespace SimpleWeb { protected: asio::ssl::context context; - std::shared_ptr create_connection() override { + std::shared_ptr create_connection() noexcept override { return std::make_shared(handler_runner, config.timeout, *io_service, context); } - void connect(const std::shared_ptr &session) override { + void connect(const std::shared_ptr &session) noexcept override { if(!session->connection->socket->lowest_layer().is_open()) { auto resolver = std::make_shared(*io_service); resolver->async_resolve(*query, [this, session, resolver](const error_code &ec, asio::ip::tcp::resolver::iterator it) { @@ -116,7 +116,7 @@ namespace SimpleWeb { write(session); } - void handshake(const std::shared_ptr &session) { + void handshake(const std::shared_ptr &session) noexcept { session->connection->set_timeout(this->config.timeout_connect); session->connection->socket->async_handshake(asio::ssl::stream_base::client, [this, session](const error_code &ec) { session->connection->cancel_timeout(); diff --git a/crypto.hpp b/crypto.hpp index 6b8512a..c57d2c8 100644 --- a/crypto.hpp +++ b/crypto.hpp @@ -16,7 +16,7 @@ namespace SimpleWeb { // TODO 2017: remove workaround for MSVS 2012 #if _MSC_VER == 1700 // MSVS 2012 has no definition for round() - inline double round(double x) { // Custom definition of round() for positive numbers + inline double round(double x) noexcept { // Custom definition of round() for positive numbers return floor(x + 0.5); } #endif @@ -27,7 +27,7 @@ namespace SimpleWeb { public: class Base64 { public: - static std::string encode(const std::string &ascii) { + static std::string encode(const std::string &ascii) noexcept { std::string base64; BIO *bio, *b64; @@ -59,7 +59,7 @@ namespace SimpleWeb { return base64; } - static std::string decode(const std::string &base64) { + static std::string decode(const std::string &base64) noexcept { std::string ascii; // Resize ascii, however, the size is a up to two bytes too large. @@ -84,7 +84,7 @@ namespace SimpleWeb { }; /// Return hex string from bytes in input string. - static std::string to_hex_string(const std::string &input) { + static std::string to_hex_string(const std::string &input) noexcept { std::stringstream hex_stream; hex_stream << std::hex << std::internal << std::setfill('0'); for(auto &byte : input) @@ -92,7 +92,7 @@ namespace SimpleWeb { return hex_stream.str(); } - static std::string md5(const std::string &input, size_t iterations = 1) { + static std::string md5(const std::string &input, size_t iterations = 1) noexcept { std::string hash; hash.resize(128 / 8); @@ -104,7 +104,7 @@ namespace SimpleWeb { return hash; } - static std::string md5(std::istream &stream, size_t iterations = 1) { + static std::string md5(std::istream &stream, size_t iterations = 1) noexcept { MD5_CTX context; MD5_Init(&context); std::streamsize read_length; @@ -121,7 +121,7 @@ namespace SimpleWeb { return hash; } - static std::string sha1(const std::string &input, size_t iterations = 1) { + static std::string sha1(const std::string &input, size_t iterations = 1) noexcept { std::string hash; hash.resize(160 / 8); @@ -133,7 +133,7 @@ namespace SimpleWeb { return hash; } - static std::string sha1(std::istream &stream, size_t iterations = 1) { + static std::string sha1(std::istream &stream, size_t iterations = 1) noexcept { SHA_CTX context; SHA1_Init(&context); std::streamsize read_length; @@ -150,7 +150,7 @@ namespace SimpleWeb { return hash; } - static std::string sha256(const std::string &input, size_t iterations = 1) { + static std::string sha256(const std::string &input, size_t iterations = 1) noexcept { std::string hash; hash.resize(256 / 8); @@ -162,7 +162,7 @@ namespace SimpleWeb { return hash; } - static std::string sha256(std::istream &stream, size_t iterations = 1) { + static std::string sha256(std::istream &stream, size_t iterations = 1) noexcept { SHA256_CTX context; SHA256_Init(&context); std::streamsize read_length; @@ -179,7 +179,7 @@ namespace SimpleWeb { return hash; } - static std::string sha512(const std::string &input, size_t iterations = 1) { + static std::string sha512(const std::string &input, size_t iterations = 1) noexcept { std::string hash; hash.resize(512 / 8); @@ -191,7 +191,7 @@ namespace SimpleWeb { return hash; } - static std::string sha512(std::istream &stream, size_t iterations = 1) { + static std::string sha512(std::istream &stream, size_t iterations = 1) noexcept { SHA512_CTX context; SHA512_Init(&context); std::streamsize read_length; @@ -209,7 +209,7 @@ namespace SimpleWeb { } /// key_size is number of bytes of the returned key. - static std::string pbkdf2(const std::string &password, const std::string &salt, int iterations, int key_size) { + static std::string pbkdf2(const std::string &password, const std::string &salt, int iterations, int key_size) noexcept { std::string key; key.resize(key_size); PKCS5_PBKDF2_HMAC_SHA1(password.c_str(), password.size(), diff --git a/server_http.hpp b/server_http.hpp index 01cb5a2..6efe9ff 100644 --- a/server_http.hpp +++ b/server_http.hpp @@ -59,10 +59,10 @@ namespace SimpleWeb { std::shared_ptr session; long timeout_content; - Response(std::shared_ptr session, long timeout_content) : std::ostream(&streambuf), session(std::move(session)), timeout_content(timeout_content) {} + Response(std::shared_ptr session, long timeout_content) noexcept : std::ostream(&streambuf), session(std::move(session)), timeout_content(timeout_content) {} template - void write_header(const CaseInsensitiveMultimap &header, size_type size) { + void write_header(const CaseInsensitiveMultimap &header, size_type size) noexcept { bool content_length_written = false; bool chunked_transfer_encoding = false; for(auto &field : header) { @@ -80,12 +80,12 @@ namespace SimpleWeb { } public: - size_t size() { + size_t size() noexcept { return streambuf.size(); } /// Use this function if you need to recursively send parts of a longer message - void send(const std::function &callback = nullptr) { + void send(const std::function &callback = nullptr) noexcept { session->connection->set_timeout(timeout_content); auto self = this->shared_from_this(); // Keep Response instance alive through the following async_write asio::async_write(*session->connection->socket, streambuf, [self, callback](const error_code &ec, size_t /*bytes_transferred*/) { @@ -99,18 +99,18 @@ namespace SimpleWeb { } /// Write directly to stream buffer using std::ostream::write - void write(const char_type *ptr, std::streamsize n) { + void write(const char_type *ptr, std::streamsize n) noexcept { std::ostream::write(ptr, n); } /// Convenience function for writing status line, potential header fields, and empty content - void write(StatusCode status_code = StatusCode::success_ok, const CaseInsensitiveMultimap &header = CaseInsensitiveMultimap()) { + void write(StatusCode status_code = StatusCode::success_ok, const CaseInsensitiveMultimap &header = CaseInsensitiveMultimap()) noexcept { *this << "HTTP/1.1 " << SimpleWeb::status_code(status_code) << "\r\n"; write_header(header, 0); } /// Convenience function for writing status line, header fields, and content - void write(StatusCode status_code, const std::string &content, const CaseInsensitiveMultimap &header = CaseInsensitiveMultimap()) { + void write(StatusCode status_code, const std::string &content, const CaseInsensitiveMultimap &header = CaseInsensitiveMultimap()) noexcept { *this << "HTTP/1.1 " << SimpleWeb::status_code(status_code) << "\r\n"; write_header(header, content.size()); if(!content.empty()) @@ -118,7 +118,7 @@ namespace SimpleWeb { } /// Convenience function for writing status line, header fields, and content - void write(StatusCode status_code, std::istream &content, const CaseInsensitiveMultimap &header = CaseInsensitiveMultimap()) { + void write(StatusCode status_code, std::istream &content, const CaseInsensitiveMultimap &header = CaseInsensitiveMultimap()) noexcept { *this << "HTTP/1.1 " << SimpleWeb::status_code(status_code) << "\r\n"; content.seekg(0, std::ios::end); auto size = content.tellg(); @@ -129,17 +129,17 @@ namespace SimpleWeb { } /// Convenience function for writing success status line, header fields, and content - void write(const std::string &content, const CaseInsensitiveMultimap &header = CaseInsensitiveMultimap()) { + void write(const std::string &content, const CaseInsensitiveMultimap &header = CaseInsensitiveMultimap()) noexcept { write(StatusCode::success_ok, content, header); } /// Convenience function for writing success status line, header fields, and content - void write(std::istream &content, const CaseInsensitiveMultimap &header = CaseInsensitiveMultimap()) { + void write(std::istream &content, const CaseInsensitiveMultimap &header = CaseInsensitiveMultimap()) noexcept { write(StatusCode::success_ok, content, header); } /// Convenience function for writing success status line, and header fields - void write(const CaseInsensitiveMultimap &header) { + void write(const CaseInsensitiveMultimap &header) noexcept { write(StatusCode::success_ok, std::string(), header); } @@ -154,19 +154,24 @@ namespace SimpleWeb { friend class ServerBase; public: - size_t size() { + size_t size() noexcept { return streambuf.size(); } /// Convenience function to return std::string. Note that the stream buffer is emptied when this functions is used. - std::string string() { - std::stringstream ss; - ss << rdbuf(); - return ss.str(); + std::string string() noexcept { + try { + std::stringstream ss; + ss << rdbuf(); + return ss.str(); + } + catch(...) { + return std::string(); + } } private: asio::streambuf &streambuf; - Content(asio::streambuf &streambuf) : std::istream(&streambuf), streambuf(streambuf) {} + Content(asio::streambuf &streambuf) noexcept : std::istream(&streambuf), streambuf(streambuf) {} }; class Request { @@ -187,14 +192,14 @@ namespace SimpleWeb { unsigned short remote_endpoint_port; /// Returns query keys with percent-decoded values. - CaseInsensitiveMultimap parse_query_string() { + CaseInsensitiveMultimap parse_query_string() noexcept { return SimpleWeb::QueryString::parse(query_string); } private: asio::streambuf streambuf; - Request(const std::string &remote_endpoint_address = std::string(), unsigned short remote_endpoint_port = 0) + Request(const std::string &remote_endpoint_address = std::string(), unsigned short remote_endpoint_port = 0) noexcept : content(streambuf), remote_endpoint_address(remote_endpoint_address), remote_endpoint_port(remote_endpoint_port) {} }; @@ -202,7 +207,7 @@ namespace SimpleWeb { class Connection : public std::enable_shared_from_this { public: template - Connection(std::shared_ptr handler_runner, Args &&... args) : handler_runner(std::move(handler_runner)), socket(new socket_type(std::forward(args)...)) {} + Connection(std::shared_ptr handler_runner, Args &&... args) noexcept : handler_runner(std::move(handler_runner)), socket(new socket_type(std::forward(args)...)) {} std::shared_ptr handler_runner; @@ -211,14 +216,14 @@ namespace SimpleWeb { std::unique_ptr timer; - void close() { + void close() noexcept { error_code ec; std::unique_lock lock(socket_close_mutex); // The following operations seems to be needed to run sequentially socket->lowest_layer().shutdown(asio::ip::tcp::socket::shutdown_both, ec); socket->lowest_layer().close(ec); } - void set_timeout(long seconds) { + void set_timeout(long seconds) noexcept { if(seconds == 0) { timer = nullptr; return; @@ -233,7 +238,7 @@ namespace SimpleWeb { }); } - void cancel_timeout() { + void cancel_timeout() noexcept { if(timer) timer->cancel(); } @@ -241,7 +246,7 @@ namespace SimpleWeb { class Session { public: - Session(std::shared_ptr connection) : connection(std::move(connection)) { + Session(std::shared_ptr connection) noexcept : connection(std::move(connection)) { try { auto remote_endpoint = this->connection->socket->lowest_layer().remote_endpoint(); request = std::shared_ptr(new Request(remote_endpoint.address().to_string(), remote_endpoint.port())); @@ -259,7 +264,7 @@ namespace SimpleWeb { class Config { friend class ServerBase; - Config(unsigned short port) : port(port) {} + Config(unsigned short port) noexcept : port(port) {} public: /// Port number to use. Defaults to 80 for HTTP and 443 for HTTPS. @@ -287,7 +292,7 @@ namespace SimpleWeb { public: regex_orderable(const char *regex_cstr) : regex::regex(regex_cstr), str(regex_cstr) {} regex_orderable(std::string regex_str) : regex::regex(regex_str), str(std::move(regex_str)) {} - bool operator<(const regex_orderable &rhs) const { + bool operator<(const regex_orderable &rhs) const noexcept { return str < rhs.str; } }; @@ -305,7 +310,7 @@ namespace SimpleWeb { /// If you have your own asio::io_service, store its pointer here before running start(). std::shared_ptr io_service; - virtual void start() { + virtual void start() noexcept { if(!io_service) { io_service = std::make_shared(); internal_io_service = true; @@ -349,7 +354,7 @@ namespace SimpleWeb { } /// Stop accepting new requests, and close current connections. - void stop() { + void stop() noexcept { if(acceptor) { error_code ec; acceptor->close(ec); @@ -366,7 +371,7 @@ namespace SimpleWeb { } } - virtual ~ServerBase() { + virtual ~ServerBase() noexcept { handler_runner->stop(); stop(); } @@ -382,12 +387,12 @@ namespace SimpleWeb { std::shared_ptr handler_runner; - ServerBase(unsigned short port) : config(port), connections(new std::unordered_set()), connections_mutex(new std::mutex()), handler_runner(new ScopeRunner()) {} + ServerBase(unsigned short port) noexcept : config(port), connections(new std::unordered_set()), connections_mutex(new std::mutex()), handler_runner(new ScopeRunner()) {} - virtual void accept() = 0; + virtual void accept() noexcept = 0; template - std::shared_ptr create_connection(Args &&... args) { + std::shared_ptr create_connection(Args &&... args) noexcept { auto connections = this->connections; auto connections_mutex = this->connections_mutex; auto connection = std::shared_ptr(new Connection(handler_runner, std::forward(args)...), [connections, connections_mutex](Connection *connection) { @@ -406,7 +411,7 @@ namespace SimpleWeb { return connection; } - void read_request_and_content(const std::shared_ptr &session) { + void read_request_and_content(const std::shared_ptr &session) noexcept { session->connection->set_timeout(config.timeout_request); asio::async_read_until(*session->connection->socket, session->request->streambuf, "\r\n\r\n", [this, session](const error_code &ec, size_t bytes_transferred) { session->connection->cancel_timeout(); @@ -463,7 +468,7 @@ namespace SimpleWeb { }); } - void find_resource(const std::shared_ptr &session) { + void find_resource(const std::shared_ptr &session) noexcept { // Upgrade connection if(on_upgrade) { auto it = session->request->header.find("Upgrade"); @@ -498,7 +503,7 @@ namespace SimpleWeb { } void write_response(const std::shared_ptr &session, - std::function::Response>, std::shared_ptr::Request>)> &resource_function) { + std::function::Response>, std::shared_ptr::Request>)> &resource_function) noexcept { session->connection->set_timeout(config.timeout_content); auto response = std::shared_ptr(new Response(session, config.timeout_content), [this](Response *response_ptr) { auto response = std::shared_ptr(response_ptr); @@ -547,10 +552,10 @@ namespace SimpleWeb { template <> class Server : public ServerBase { public: - Server() : ServerBase::ServerBase(80) {} + Server() noexcept : ServerBase::ServerBase(80) {} protected: - void accept() override { + void accept() noexcept override { auto session = std::make_shared(create_connection(*io_service)); acceptor->async_accept(*session->connection->socket, [this, session](const error_code &ec) { diff --git a/server_https.hpp b/server_https.hpp index 51e3b62..2143601 100644 --- a/server_https.hpp +++ b/server_https.hpp @@ -21,7 +21,7 @@ namespace SimpleWeb { bool set_session_id_context = false; public: - Server(const std::string &cert_file, const std::string &private_key_file, const std::string &verify_file = std::string()) + Server(const std::string &cert_file, const std::string &private_key_file, const std::string &verify_file = std::string()) noexcept : ServerBase::ServerBase(443), context(asio::ssl::context::tlsv12) { context.use_certificate_chain_file(cert_file); context.use_private_key_file(private_key_file, asio::ssl::context::pem); @@ -33,7 +33,7 @@ namespace SimpleWeb { } } - void start() override { + void start() noexcept override { if(set_session_id_context) { // Creating session_id_context from address:port but reversed due to small SSL_MAX_SSL_SESSION_ID_LENGTH session_id_context = std::to_string(config.port) + ':'; @@ -47,7 +47,7 @@ namespace SimpleWeb { protected: asio::ssl::context context; - void accept() override { + void accept() noexcept override { auto session = std::make_shared(create_connection(*io_service, context)); acceptor->async_accept(session->connection->socket->lowest_layer(), [this, session](const error_code &ec) { diff --git a/status_code.hpp b/status_code.hpp index 747512b..267a621 100644 --- a/status_code.hpp +++ b/status_code.hpp @@ -70,7 +70,7 @@ namespace SimpleWeb { server_error_network_authentication_required }; - const static std::vector> &status_codes() { + const static std::vector> &status_codes() noexcept { const static std::vector> status_codes = { {StatusCode::unknown, ""}, {StatusCode::information_continue, "100 Continue"}, @@ -137,7 +137,7 @@ namespace SimpleWeb { return status_codes; } - inline StatusCode status_code(const std::string &status_code_str) { + inline StatusCode status_code(const std::string &status_code_str) noexcept { for(auto &status_code : status_codes()) { if(status_code.second == status_code_str) return status_code.first; @@ -145,7 +145,7 @@ namespace SimpleWeb { return StatusCode::unknown; } - inline const std::string &status_code(StatusCode status_code_enum) { + inline const std::string &status_code(StatusCode status_code_enum) noexcept { for(auto &status_code : status_codes()) { if(status_code.first == status_code_enum) return status_code.second; diff --git a/tests/parse_test.cpp b/tests/parse_test.cpp index 7887aed..19297f0 100644 --- a/tests/parse_test.cpp +++ b/tests/parse_test.cpp @@ -10,7 +10,7 @@ class ServerTest : public ServerBase { public: ServerTest() : ServerBase::ServerBase(8080) {} - void accept() override {} + void accept() noexcept override {} void parse_request_test() { auto session = std::make_shared(create_connection(*io_service)); @@ -55,11 +55,11 @@ class ClientTest : public ClientBase { public: ClientTest(const std::string &server_port_path) : ClientBase::ClientBase(server_port_path, 80) {} - std::shared_ptr create_connection() override { + std::shared_ptr create_connection() noexcept override { return nullptr; } - void connect(const std::shared_ptr &) override {} + void connect(const std::shared_ptr &) noexcept override {} void constructor_parse_test1() { assert(host == "test.org"); diff --git a/utility.hpp b/utility.hpp index 6f733f9..280ae82 100644 --- a/utility.hpp +++ b/utility.hpp @@ -9,7 +9,7 @@ #include namespace SimpleWeb { - inline bool case_insensitive_equal(const std::string &str1, const std::string &str2) { + inline bool case_insensitive_equal(const std::string &str1, const std::string &str2) noexcept { return str1.size() == str2.size() && std::equal(str1.begin(), str1.end(), str2.begin(), [](char a, char b) { return tolower(a) == tolower(b); @@ -17,14 +17,14 @@ namespace SimpleWeb { } class CaseInsensitiveEqual { public: - bool operator()(const std::string &str1, const std::string &str2) const { + bool operator()(const std::string &str1, const std::string &str2) const noexcept { return case_insensitive_equal(str1, str2); } }; // Based on https://stackoverflow.com/questions/2590677/how-do-i-combine-hash-values-in-c0x/2595226#2595226 class CaseInsensitiveHash { public: - size_t operator()(const std::string &str) const { + size_t operator()(const std::string &str) const noexcept { size_t h = 0; std::hash hash; for(auto c : str) @@ -39,7 +39,7 @@ namespace SimpleWeb { class Percent { public: /// Returns percent-encoded string - static std::string encode(const std::string &value) { + static std::string encode(const std::string &value) noexcept { static auto hex_chars = "0123456789ABCDEF"; std::string result; @@ -58,7 +58,7 @@ namespace SimpleWeb { } /// Returns percent-decoded string - static std::string decode(const std::string &value) { + static std::string decode(const std::string &value) noexcept { std::string result; result.reserve(value.size() / 3 + (value.size() % 3)); // Minimum size of result @@ -84,7 +84,7 @@ namespace SimpleWeb { class QueryString { public: /// Returns query string created from given field names and values - static std::string create(const CaseInsensitiveMultimap &fields) { + static std::string create(const CaseInsensitiveMultimap &fields) noexcept { std::string result; bool first = true; @@ -97,7 +97,7 @@ namespace SimpleWeb { } /// Returns query keys with percent-decoded values. - static CaseInsensitiveMultimap parse(const std::string &query_string) { + static CaseInsensitiveMultimap parse(const std::string &query_string) noexcept { CaseInsensitiveMultimap result; if(query_string.empty()) @@ -137,7 +137,7 @@ namespace SimpleWeb { class RequestMessage { public: /// Parse request line and header fields - static bool parse(std::istream &stream, std::string &method, std::string &path, std::string &query_string, std::string &version, CaseInsensitiveMultimap &header) { + static bool parse(std::istream &stream, std::string &method, std::string &path, std::string &query_string, std::string &version, CaseInsensitiveMultimap &header) noexcept { header.clear(); std::string line; getline(stream, line); @@ -198,7 +198,7 @@ namespace SimpleWeb { class ResponseMessage { public: /// Parse status line and header fields - static bool parse(std::istream &stream, std::string &version, std::string &status_code, CaseInsensitiveMultimap &header) { + static bool parse(std::istream &stream, std::string &version, std::string &status_code, CaseInsensitiveMultimap &header) noexcept { header.clear(); std::string line; getline(stream, line); @@ -237,17 +237,17 @@ namespace SimpleWeb { #ifdef __SSE2__ #include namespace SimpleWeb { - inline void spin_loop_pause() { _mm_pause(); } + inline void spin_loop_pause() noexcept { _mm_pause(); } } // namespace SimpleWeb // TODO: need verification that the following checks are correct: #elif defined(_MSC_VER) && _MSC_VER >= 1800 && (defined(_M_X64) || defined(_M_IX86)) #include namespace SimpleWeb { - inline void spin_loop_pause() { _mm_pause(); } + inline void spin_loop_pause() noexcept { _mm_pause(); } } // namespace SimpleWeb #else namespace SimpleWeb { - inline void spin_loop_pause() {} + inline void spin_loop_pause() noexcept {} } // namespace SimpleWeb #endif @@ -261,20 +261,20 @@ namespace SimpleWeb { class SharedLock { friend class ScopeRunner; std::atomic &count; - SharedLock(std::atomic &count) : count(count) {} + SharedLock(std::atomic &count) noexcept : count(count) {} SharedLock &operator=(const SharedLock &) = delete; SharedLock(const SharedLock &) = delete; public: - ~SharedLock() { + ~SharedLock() noexcept { count.fetch_sub(1); } }; - ScopeRunner() : count(0) {} + ScopeRunner() noexcept : count(0) {} /// Returns nullptr if scope should be exited, or a shared lock otherwise - std::unique_ptr continue_lock() { + std::unique_ptr continue_lock() noexcept { long expected = count; while(expected >= 0 && !count.compare_exchange_weak(expected, expected + 1)) spin_loop_pause(); @@ -286,7 +286,7 @@ namespace SimpleWeb { } //// Blocks until all shared locks are released, then prevents future shared locks - void stop() { + void stop() noexcept { long expected = 0; while(!count.compare_exchange_weak(expected, -1)) { if(expected < 0)