diff options
author | Roman Grundkiewicz <rgrundkiewicz@gmail.com> | 2021-02-10 17:19:16 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-10 17:19:16 +0300 |
commit | 1d7e84aeb3f1ebdc78f6965d79ad3ca3003789fe (patch) | |
tree | 632919470254d78cb9a0c20e39f75a75d40c8407 | |
parent | 257439f5bd0a15f315c1c2733ea8a4fb0e32c1db (diff) | |
parent | 92cbb95fe06378a0f0cac0f7cf90a829aa85ea4a (diff) |
Merge pull request #1 from rihardsk/upstream-master
Merge upstream master
-rw-r--r-- | .clang-format | 1 | ||||
-rw-r--r-- | .gitignore | 6 | ||||
-rw-r--r-- | CMakeLists.txt | 12 | ||||
-rw-r--r-- | asio_compatibility.hpp | 12 | ||||
-rw-r--r-- | client_ws.hpp | 14 | ||||
-rw-r--r-- | server_ws.hpp | 74 | ||||
-rw-r--r-- | tests/CMakeLists.txt | 18 | ||||
-rw-r--r-- | utility.hpp | 6 | ||||
-rw-r--r-- | ws_examples.cpp | 3 | ||||
-rw-r--r-- | wss_examples.cpp | 3 |
10 files changed, 83 insertions, 66 deletions
diff --git a/.clang-format b/.clang-format index 50f9423..740ccf7 100644 --- a/.clang-format +++ b/.clang-format @@ -7,3 +7,4 @@ SpaceBeforeParens: Never BreakBeforeBraces: Custom BraceWrapping: {BeforeElse: true, BeforeCatch: true} NamespaceIndentation: All +AllowShortCaseLabelsOnASingleLine: true @@ -17,6 +17,6 @@ compile_commands.json # executables ws_examples wss_examples -crypto_test -io_test -parse_test +swss_crypto_test +swss_io_test +swss_parse_test diff --git a/CMakeLists.txt b/CMakeLists.txt index 9d2d4f7..11e11f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,13 @@ -cmake_minimum_required (VERSION 3.0) +cmake_minimum_required(VERSION 3.0) -project (Simple-WebSocket-Server) +project(Simple-WebSocket-Server) option(USE_STANDALONE_ASIO "set ON to use standalone Asio instead of Boost.Asio" OFF) -option(BUILD_TESTING "set ON to build library tests" OFF) +if(CMAKE_SOURCE_DIR STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") + option(BUILD_TESTING "set ON to build library tests" ON) +else() + option(BUILD_TESTING "set ON to build library tests" OFF) +endif() add_library(simple-websocket-server INTERFACE) @@ -60,8 +64,6 @@ if(CMAKE_SOURCE_DIR STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") add_executable(wss_examples wss_examples.cpp) target_link_libraries(wss_examples simple-websocket-server) - set(BUILD_TESTING ON) - install(FILES asio_compatibility.hpp server_ws.hpp client_ws.hpp server_wss.hpp client_wss.hpp crypto.hpp utility.hpp status_code.hpp mutex.hpp DESTINATION include/simple-websocket-server) endif() diff --git a/asio_compatibility.hpp b/asio_compatibility.hpp index a9abd7c..c2e0b66 100644 --- a/asio_compatibility.hpp +++ b/asio_compatibility.hpp @@ -42,9 +42,9 @@ namespace SimpleWeb { inline asio::ip::address make_address(const std::string &str) noexcept { return asio::ip::make_address(str); } - template <typename socket_type> - asio::executor get_socket_executor(socket_type &socket) { - return socket.get_executor(); + template <typename socket_type, typename duration_type> + std::unique_ptr<asio::steady_timer> make_steady_timer(socket_type &socket, std::chrono::duration<duration_type> duration) { + return std::unique_ptr<asio::steady_timer>(new asio::steady_timer(socket.get_executor(), duration)); } template <typename handler_type> void async_resolve(asio::ip::tcp::resolver &resolver, const std::pair<std::string, std::string> &host_port, handler_type &&handler) { @@ -68,9 +68,9 @@ namespace SimpleWeb { inline asio::ip::address make_address(const std::string &str) noexcept { return asio::ip::address::from_string(str); } - template <typename socket_type> - io_context &get_socket_executor(socket_type &socket) { - return socket.get_io_service(); + template <typename socket_type, typename duration_type> + std::unique_ptr<asio::steady_timer> make_steady_timer(socket_type &socket, std::chrono::duration<duration_type> duration) { + return std::unique_ptr<asio::steady_timer>(new asio::steady_timer(socket.get_io_service(), duration)); } template <typename handler_type> void async_resolve(asio::ip::tcp::resolver &resolver, const std::pair<std::string, std::string> &host_port, handler_type &&handler) { diff --git a/client_ws.hpp b/client_ws.hpp index b5ce2d7..e4a26f6 100644 --- a/client_ws.hpp +++ b/client_ws.hpp @@ -86,6 +86,8 @@ namespace SimpleWeb { std::atomic<bool> closed; + 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); @@ -106,7 +108,7 @@ namespace SimpleWeb { return; } - timer = std::unique_ptr<asio::steady_timer>(new asio::steady_timer(get_socket_executor(*socket), std::chrono::seconds(seconds))); + timer = make_steady_timer(*socket, std::chrono::seconds(seconds)); std::weak_ptr<Connection> connection_weak(this->shared_from_this()); // To avoid keeping Connection instance alive longer than needed timer->async_wait([connection_weak, use_timeout_idle](const error_code &ec) { if(!ec) { @@ -252,6 +254,10 @@ namespace SimpleWeb { // fin_rsv_opcode=136: message close send(out_message, std::move(callback), 136); } + + const asio::ip::tcp::endpoint &remote_endpoint() const noexcept { + return endpoint; + } }; class Config { @@ -409,6 +415,12 @@ namespace SimpleWeb { ostream << header_field.first << ": " << header_field.second << "\r\n"; ostream << "\r\n"; + try { + connection->endpoint = connection->socket->lowest_layer().remote_endpoint(); + } + catch(...) { + } + connection->in_message = std::shared_ptr<InMessage>(new InMessage()); connection->set_timeout(config.timeout_request); diff --git a/server_ws.hpp b/server_ws.hpp index 158813d..2256d55 100644 --- a/server_ws.hpp +++ b/server_ws.hpp @@ -87,42 +87,8 @@ namespace SimpleWeb { regex::smatch path_match; - const asio::ip::tcp::endpoint &remote_endpoint() const noexcept { - return endpoint; - } - - asio::ip::tcp::endpoint local_endpoint() const noexcept { - try { - if(auto connection = this->connection.lock()) - return connection->socket->lowest_layer().local_endpoint(); - } - catch(...) { - } - return asio::ip::tcp::endpoint(); - } - - /// Deprecated, please use remote_endpoint().address().to_string() instead. - DEPRECATED std::string remote_endpoint_address() const noexcept { - try { - return endpoint.address().to_string(); - } - catch(...) { - } - return std::string(); - } - - /// Deprecated, please use remote_endpoint().port() instead. - DEPRECATED unsigned short remote_endpoint_port() const noexcept { - try { - return endpoint.port(); - } - catch(...) { - } - return 0; - } - private: - /// Used to call Server::upgrade. + /// 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) {} @@ -141,7 +107,7 @@ namespace SimpleWeb { std::atomic<bool> closed; - asio::ip::tcp::endpoint endpoint; // The endpoint is read in Server::write_handshake and must be stored so that it can be read reliably in all handlers, including on_error + 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; @@ -160,7 +126,7 @@ namespace SimpleWeb { return; } - timer = std::unique_ptr<asio::steady_timer>(new asio::steady_timer(get_socket_executor(*socket), std::chrono::seconds(seconds))); + timer = make_steady_timer(*socket, std::chrono::seconds(seconds)); std::weak_ptr<Connection> connection_weak(this->shared_from_this()); // To avoid keeping Connection instance alive longer than needed timer->async_wait([connection_weak](const error_code &ec) { if(!ec) { @@ -292,6 +258,40 @@ namespace SimpleWeb { // fin_rsv_opcode=136: message close send(std::move(send_stream), std::move(callback), 136); } + + const asio::ip::tcp::endpoint &remote_endpoint() const noexcept { + return endpoint; + } + + asio::ip::tcp::endpoint local_endpoint() const noexcept { + try { + if(auto connection = this->connection.lock()) + return connection->socket->lowest_layer().local_endpoint(); + } + catch(...) { + } + return asio::ip::tcp::endpoint(); + } + + /// Deprecated, please use remote_endpoint().address().to_string() instead. + DEPRECATED std::string remote_endpoint_address() const noexcept { + try { + return endpoint.address().to_string(); + } + catch(...) { + } + return std::string(); + } + + /// Deprecated, please use remote_endpoint().port() instead. + DEPRECATED unsigned short remote_endpoint_port() const noexcept { + try { + return endpoint.port(); + } + catch(...) { + } + return 0; + } }; class Endpoint { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f5b1526..9d50bdd 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -4,15 +4,15 @@ if(NOT MSVC) add_compile_options(-Wno-thread-safety) endif() - add_executable(parse_test parse_test.cpp) - target_link_libraries(parse_test simple-websocket-server) - add_test(parse_test parse_test) + add_executable(swss_parse_test parse_test.cpp) + target_link_libraries(swss_parse_test simple-websocket-server) + add_test(swss_parse_test swss_parse_test) endif() -add_executable(crypto_test crypto_test.cpp) -target_link_libraries(crypto_test simple-websocket-server) -add_test(crypto_test crypto_test) +add_executable(swss_crypto_test crypto_test.cpp) +target_link_libraries(swss_crypto_test simple-websocket-server) +add_test(swss_crypto_test swss_crypto_test) -add_executable(io_test io_test.cpp) -target_link_libraries(io_test simple-websocket-server) -add_test(io_test io_test) +add_executable(swss_io_test io_test.cpp) +target_link_libraries(swss_io_test simple-websocket-server) +add_test(swss_io_test swss_io_test) diff --git a/utility.hpp b/utility.hpp index 2c0e7cf..3b41ff3 100644 --- a/utility.hpp +++ b/utility.hpp @@ -145,13 +145,13 @@ namespace SimpleWeb { name_end_pos = std::string::npos; value_pos = std::string::npos; } - else if(query_string[c] == '=') { + else if(query_string[c] == '=' && name_end_pos == std::string::npos) { name_end_pos = c; value_pos = c + 1; } } if(name_pos < query_string.size()) { - auto name = query_string.substr(name_pos, name_end_pos - name_pos); + auto name = query_string.substr(name_pos, (name_end_pos == std::string::npos ? std::string::npos : name_end_pos - name_pos)); if(!name.empty()) { auto value = value_pos >= query_string.size() ? std::string() : query_string.substr(value_pos); result.emplace(std::move(name), Percent::decode(value)); @@ -260,7 +260,7 @@ namespace SimpleWeb { std::size_t query_start = std::string::npos; std::size_t path_and_query_string_end = std::string::npos; for(std::size_t i = method_end + 1; i < line.size(); ++i) { - if(line[i] == '?' && (i + 1) < line.size()) + if(line[i] == '?' && (i + 1) < line.size() && query_start == std::string::npos) query_start = i + 1; else if(line[i] == ' ') { path_and_query_string_end = i; diff --git a/ws_examples.cpp b/ws_examples.cpp index 36798cd..ce516ff 100644 --- a/ws_examples.cpp +++ b/ws_examples.cpp @@ -103,7 +103,8 @@ int main() { server_port.set_value(port); }); }); - cout << "Server listening on port " << server_port.get_future().get() << endl << endl; + cout << "Server listening on port " << server_port.get_future().get() << endl + << endl; // Example 4: Client communication with server // Possible output: diff --git a/wss_examples.cpp b/wss_examples.cpp index d5a2527..74e4a84 100644 --- a/wss_examples.cpp +++ b/wss_examples.cpp @@ -103,7 +103,8 @@ int main() { server_port.set_value(port); }); }); - cout << "Server listening on port " << server_port.get_future().get() << endl << endl; + cout << "Server listening on port " << server_port.get_future().get() << endl + << endl; // Example 4: Client communication with server // Possible output: |