From bc42770efcd6b0ce821c78ac3ddcb42f8707389e Mon Sep 17 00:00:00 2001 From: sztomi Date: Fri, 27 Oct 2017 00:28:55 +0200 Subject: [PATCH 01/54] README: fix link for waffle --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 394a5224..d20ad3c6 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # rpclib ![MIT](https://img.shields.io/badge/license-MIT-blue.svg) [![Build Status](https://travis-ci.org/rpclib/rpclib.svg?branch=master)](https://travis-ci.org/rpclib/rpclib) [![Build status](https://ci.appveyor.com/api/projects/status/9lft2tlamcox8epq?svg=true)](https://ci.appveyor.com/project/sztomi/callme) [![Coverage Status](https://img.shields.io/codecov/c/github/rpclib/rpclib/dev.svg)](https://img.shields.io/codecov/c/github/rpclib/rpclib/dev.svg) ![Coverity](https://scan.coverity.com/projects/7259/badge.svg?flat=1) [![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg?maxAge=2592000)](https://gitter.im/rpclib/Lobby) -![waffle](https://badge.waffle.io/rpclib/rpclib.svg?columns=In%20Progress,Waiting%20For%20Release) +[![waffle](https://badge.waffle.io/rpclib/rpclib.svg?columns=In%20Progress,Waiting%20For%20Release)](https://waffle.io/rpclib/rpclib) `rpclib` is a RPC library for C++, providing both a client and server implementation. It is built using modern C++14, and as such, requires a recent compiler. Main highlights: From e5c8c3cb6a0cd722fc855f1712a614aa78e847bb Mon Sep 17 00:00:00 2001 From: sztomi Date: Fri, 27 Oct 2017 00:29:34 +0200 Subject: [PATCH 02/54] ci: disabled VS2017 --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 4d9969a6..b502f4fd 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -14,7 +14,7 @@ configuration: environment: matrix: - CMAKE_PLATFORM: "Visual Studio 14 2015" - - CMAKE_PLATFORM: "Visual Studio 15 2017" + #- CMAKE_PLATFORM: "Visual Studio 15 2017" install: true From def9b2dc3bb67b7149755f903ebb443afdca494f Mon Sep 17 00:00:00 2001 From: sztomi Date: Fri, 27 Oct 2017 17:02:40 +0200 Subject: [PATCH 03/54] client: fixed early deallocation of error object --- include/rpc/rpc_error.h | 6 +++--- lib/rpc/client.cc | 3 +-- lib/rpc/rpc_error.cc | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/include/rpc/rpc_error.h b/include/rpc/rpc_error.h index 558e8297..7efd6ab7 100644 --- a/include/rpc/rpc_error.h +++ b/include/rpc/rpc_error.h @@ -23,16 +23,16 @@ class rpc_error : public std::runtime_error { //! \brief Returns the error object that the server //! provided. - virtual RPCLIB_MSGPACK::object_handle& get_error(); + virtual RPCLIB_MSGPACK::object_handle &get_error(); private: friend class client; rpc_error(std::string const &what_arg, std::string const &function_name, - RPCLIB_MSGPACK::object_handle o); + std::shared_ptr o); private: std::string func_name_; - RPCLIB_MSGPACK::object_handle ob_h_; + std::shared_ptr ob_h_; }; //! \brief This exception is thrown by the client when either the connection diff --git a/lib/rpc/client.cc b/lib/rpc/client.cc index dca0f830..13f57021 100644 --- a/lib/rpc/client.cc +++ b/lib/rpc/client.cc @@ -80,8 +80,7 @@ struct client::impl { if (r.get_error()) { throw rpc_error("rpc::rpc_error during call", std::get<0>(current_call), - RPCLIB_MSGPACK::clone( - r.get_error()->get())); + r.get_error()); } std::get<1>(current_call) .set_value(std::move(*r.get_result())); diff --git a/lib/rpc/rpc_error.cc b/lib/rpc/rpc_error.cc index 8af70060..47e76e6b 100644 --- a/lib/rpc/rpc_error.cc +++ b/lib/rpc/rpc_error.cc @@ -5,14 +5,14 @@ namespace rpc { rpc_error::rpc_error(std::string const &what_arg, std::string const &function_name, - RPCLIB_MSGPACK::object_handle o) + std::shared_ptr o) : std::runtime_error(what_arg), func_name_(function_name), ob_h_(std::move(o)) {} std::string rpc_error::get_function_name() const { return func_name_; } -RPCLIB_MSGPACK::object_handle &rpc_error::get_error() { return ob_h_; } +RPCLIB_MSGPACK::object_handle &rpc_error::get_error() { return *ob_h_; } timeout::timeout(std::string const &what_arg) : std::runtime_error(what_arg) { formatted = From 6082003f267a3856a854c01e6f93874988514364 Mon Sep 17 00:00:00 2001 From: sztomi Date: Fri, 27 Oct 2017 17:03:08 +0200 Subject: [PATCH 04/54] server_session_test: do a lot less of connection tests. Windows is slow, yo --- tests/rpc/server_session_test.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/rpc/server_session_test.cc b/tests/rpc/server_session_test.cc index 40a08759..283d20b1 100644 --- a/tests/rpc/server_session_test.cc +++ b/tests/rpc/server_session_test.cc @@ -39,7 +39,12 @@ TEST_F(server_session_test, consume_big_param) { } TEST_F(server_session_test, connection_closed_properly) { - for (unsigned counter = 0; counter < 1000; ++counter) { +#ifdef RPCLIB_WIN32 + const unsigned max_tries = 10; +#else + const unsigned max_tries = 1000; +#endif + for (unsigned counter = 0; counter < max_tries; ++counter) { rpc::client client("localhost", rpc::constants::DEFAULT_PORT); auto response = client.call("func"); } From b3bb3b74adce6302d9463ce133b3eae04d4d6c64 Mon Sep 17 00:00:00 2001 From: sztomi Date: Sat, 28 Oct 2017 11:26:33 +0200 Subject: [PATCH 05/54] Updated changedlog --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7ef91a5..cf99269f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +### 2.2.1 + +This release fixed a crash on Windows. + +*Fixes*: + + * Fixed client crashing when `suppress_exceptions` was on + and the server threw an exception. + ### 2.2.0 This release fixed a number of long-standing issues. From 3b00c4ccf480b9f9569b1d064e7a3b43585b8dfd Mon Sep 17 00:00:00 2001 From: sztomi Date: Sat, 28 Oct 2017 11:26:47 +0200 Subject: [PATCH 06/54] cmake: bumped version to 2.2.1 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 58e7827d..58456348 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.9.0) -project(rpc VERSION 2.2.0) +project(rpc VERSION 2.2.1) set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") From d1146b7915b375fde5fc70c1c90823f3b2b1d496 Mon Sep 17 00:00:00 2001 From: Klemen Forstneric Date: Sat, 18 Nov 2017 09:50:48 +0100 Subject: [PATCH 07/54] Added self to lambda capture lists to prevent this from being destroyed --- lib/rpc/detail/server_session.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/rpc/detail/server_session.cc b/lib/rpc/detail/server_session.cc index d6f89177..a4575843 100644 --- a/lib/rpc/detail/server_session.cc +++ b/lib/rpc/detail/server_session.cc @@ -60,7 +60,7 @@ void server_session::do_read() { // any worker thread can take this call auto z = std::shared_ptr( result.zone().release()); - io_->post([this, msg, z]() { + io_->post([this, self, msg, z]() { this_handler().clear(); this_session().clear(); this_session().set_id(reinterpret_cast(this)); @@ -96,7 +96,7 @@ void server_session::do_read() { [=]() { write(resp.get_data()); }); #else write_strand_.post( - [this, resp, z]() { write(resp.get_data()); }); + [this, self, resp, z]() { write(resp.get_data()); }); #endif } From ab748217da75c72480c0a88d8ab007b63492c833 Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Tue, 26 Dec 2017 18:21:55 +0900 Subject: [PATCH 08/54] Use cmake's find_package(Thread) to find a theread library on a system. --- CMakeLists.txt | 3 ++- examples/calculator/CMakeLists.txt | 4 ++-- examples/echo/CMakeLists.txt | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 58456348..ae07a454 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -121,7 +121,7 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") list(APPEND RPCLIB_BUILD_FLAGS -Wall -pedantic -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-padded -Wno-missing-prototypes - -Wno-undef -pthread) + -Wno-undef) set(UNUSED_LAMBDA_CAPTURE_WARN_SUPPORTED) check_warning_flag("unused-lambda-capture" UNUSED_LAMBDA_CAPTURE_WARN_SUPPORTED) @@ -197,6 +197,7 @@ endif() # Example programs # if(RPCLIB_BUILD_EXAMPLES) + find_package(Threads) set(RPCLIB_ROOT_DIR "${PROJECT_SOURCE_DIR}") set(RPCLIB_PROJECT_NAME "${CMAKE_PROJECT_NAME}") set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/localbuild") diff --git a/examples/calculator/CMakeLists.txt b/examples/calculator/CMakeLists.txt index 9e08a4ef..d53e26de 100644 --- a/examples/calculator/CMakeLists.txt +++ b/examples/calculator/CMakeLists.txt @@ -6,7 +6,7 @@ find_package(rpclib REQUIRED) include_directories(${RPCLIB_INCLUDE_DIR}) add_executable(calculator_server calculator_server.cc) -target_link_libraries(calculator_server ${RPCLIB_LIBS}) +target_link_libraries(calculator_server ${RPCLIB_LIBS} ${CMAKE_THREAD_LIBS_INIT}) set_target_properties( calculator_server PROPERTIES @@ -15,7 +15,7 @@ set_target_properties( target_compile_definitions(calculator_server PUBLIC ${RPCLIB_COMPILE_DEFINITIONS}) add_executable(calculator_client calculator_client.cc) -target_link_libraries(calculator_client ${RPCLIB_LIBS}) +target_link_libraries(calculator_client ${RPCLIB_LIBS} ${CMAKE_THREAD_LIBS_INIT}) set_target_properties( calculator_client PROPERTIES diff --git a/examples/echo/CMakeLists.txt b/examples/echo/CMakeLists.txt index a84839ef..2dcea5ce 100644 --- a/examples/echo/CMakeLists.txt +++ b/examples/echo/CMakeLists.txt @@ -6,7 +6,7 @@ find_package(rpclib REQUIRED) include_directories(${RPCLIB_INCLUDE_DIR}) add_executable(echo_server echo_server.cc) -target_link_libraries(echo_server ${RPCLIB_LIBS}) +target_link_libraries(echo_server ${RPCLIB_LIBS} ${CMAKE_THREAD_LIBS_INIT}) set_target_properties( echo_server PROPERTIES @@ -15,7 +15,7 @@ set_target_properties( target_compile_definitions(echo_server PUBLIC ${RPCLIB_COMPILE_DEFINITIONS}) add_executable(echo_client echo_client.cc) -target_link_libraries(echo_client ${RPCLIB_LIBS}) +target_link_libraries(echo_client ${RPCLIB_LIBS} ${CMAKE_THREAD_LIBS_INIT}) set_target_properties( echo_client PROPERTIES From 250919aafd464d9d6a300fd3e6373f72ff9bc9a1 Mon Sep 17 00:00:00 2001 From: sztomi Date: Sat, 28 Oct 2017 11:26:33 +0200 Subject: [PATCH 09/54] Updated changedlog --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7ef91a5..cf99269f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +### 2.2.1 + +This release fixed a crash on Windows. + +*Fixes*: + + * Fixed client crashing when `suppress_exceptions` was on + and the server threw an exception. + ### 2.2.0 This release fixed a number of long-standing issues. From 69bd06de1bb0355a52ec14d24d10e31ab8a9c25e Mon Sep 17 00:00:00 2001 From: sztomi Date: Sat, 28 Oct 2017 11:26:47 +0200 Subject: [PATCH 10/54] cmake: bumped version to 2.2.1 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 58e7827d..58456348 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.9.0) -project(rpc VERSION 2.2.0) +project(rpc VERSION 2.2.1) set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") From fc53b2ee0dbfdddf7238f9e2e331f98ac5c24c03 Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Tue, 26 Dec 2017 18:21:55 +0900 Subject: [PATCH 11/54] Use cmake's find_package(Thread) to find a theread library on a system. --- CMakeLists.txt | 3 ++- examples/calculator/CMakeLists.txt | 4 ++-- examples/echo/CMakeLists.txt | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 58456348..ae07a454 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -121,7 +121,7 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") list(APPEND RPCLIB_BUILD_FLAGS -Wall -pedantic -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-padded -Wno-missing-prototypes - -Wno-undef -pthread) + -Wno-undef) set(UNUSED_LAMBDA_CAPTURE_WARN_SUPPORTED) check_warning_flag("unused-lambda-capture" UNUSED_LAMBDA_CAPTURE_WARN_SUPPORTED) @@ -197,6 +197,7 @@ endif() # Example programs # if(RPCLIB_BUILD_EXAMPLES) + find_package(Threads) set(RPCLIB_ROOT_DIR "${PROJECT_SOURCE_DIR}") set(RPCLIB_PROJECT_NAME "${CMAKE_PROJECT_NAME}") set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/localbuild") diff --git a/examples/calculator/CMakeLists.txt b/examples/calculator/CMakeLists.txt index 9e08a4ef..d53e26de 100644 --- a/examples/calculator/CMakeLists.txt +++ b/examples/calculator/CMakeLists.txt @@ -6,7 +6,7 @@ find_package(rpclib REQUIRED) include_directories(${RPCLIB_INCLUDE_DIR}) add_executable(calculator_server calculator_server.cc) -target_link_libraries(calculator_server ${RPCLIB_LIBS}) +target_link_libraries(calculator_server ${RPCLIB_LIBS} ${CMAKE_THREAD_LIBS_INIT}) set_target_properties( calculator_server PROPERTIES @@ -15,7 +15,7 @@ set_target_properties( target_compile_definitions(calculator_server PUBLIC ${RPCLIB_COMPILE_DEFINITIONS}) add_executable(calculator_client calculator_client.cc) -target_link_libraries(calculator_client ${RPCLIB_LIBS}) +target_link_libraries(calculator_client ${RPCLIB_LIBS} ${CMAKE_THREAD_LIBS_INIT}) set_target_properties( calculator_client PROPERTIES diff --git a/examples/echo/CMakeLists.txt b/examples/echo/CMakeLists.txt index a84839ef..2dcea5ce 100644 --- a/examples/echo/CMakeLists.txt +++ b/examples/echo/CMakeLists.txt @@ -6,7 +6,7 @@ find_package(rpclib REQUIRED) include_directories(${RPCLIB_INCLUDE_DIR}) add_executable(echo_server echo_server.cc) -target_link_libraries(echo_server ${RPCLIB_LIBS}) +target_link_libraries(echo_server ${RPCLIB_LIBS} ${CMAKE_THREAD_LIBS_INIT}) set_target_properties( echo_server PROPERTIES @@ -15,7 +15,7 @@ set_target_properties( target_compile_definitions(echo_server PUBLIC ${RPCLIB_COMPILE_DEFINITIONS}) add_executable(echo_client echo_client.cc) -target_link_libraries(echo_client ${RPCLIB_LIBS}) +target_link_libraries(echo_client ${RPCLIB_LIBS} ${CMAKE_THREAD_LIBS_INIT}) set_target_properties( echo_client PROPERTIES From 15af9d14925c37e8a28f45f782d8cfb0e7ef2977 Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Mon, 29 Jan 2018 14:00:13 +0900 Subject: [PATCH 12/54] Remove redundant `no` from `no-no-unused-lambda-capture` --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 58e7827d..1140a59c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -126,7 +126,7 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") set(UNUSED_LAMBDA_CAPTURE_WARN_SUPPORTED) check_warning_flag("unused-lambda-capture" UNUSED_LAMBDA_CAPTURE_WARN_SUPPORTED) if(${UNUSED_LAMBDA_CAPTURE_WARN_SUPPORTED}) - list(APPEND RPCLIB_BUILD_FLAGS -Wno-no-unused-lambda-capture) + list(APPEND RPCLIB_BUILD_FLAGS -Wno-unused-lambda-capture) endif() check_warning_flag("zero-as-null-pointer-constant" ZERO_AS_NULL_POINTER_CONSTANT_WARN_SUPPORTED) From 13860e03e3bf553bcba981e4d41b0c7ace47b041 Mon Sep 17 00:00:00 2001 From: Emanuele Ruffaldi Date: Mon, 19 Feb 2018 09:49:38 +0100 Subject: [PATCH 13/54] server reuseaddress and random port --- doc/pages/versions.md | 2 +- examples/echo/echo_server.cc | 2 ++ include/rpc/server.h | 4 ++++ include/rpc/version.h | 2 +- lib/rpc/server.cc | 27 ++++++++++++++++++++++----- 5 files changed, 30 insertions(+), 7 deletions(-) diff --git a/doc/pages/versions.md b/doc/pages/versions.md index cde88106..f2874691 100644 --- a/doc/pages/versions.md +++ b/doc/pages/versions.md @@ -1,4 +1,4 @@ -You are reading the documentation of 2.2.0. +You are reading the documentation of 2.2.1. If, for some reason you need the documentation of older versions, you can download them from this page. * [1.0.0](/archive/rpclib_docs_1.0.0.zip) diff --git a/examples/echo/echo_server.cc b/examples/echo/echo_server.cc index 6988bbdc..3c59e155 100644 --- a/examples/echo/echo_server.cc +++ b/examples/echo/echo_server.cc @@ -1,7 +1,9 @@ #include "rpc/server.h" +#include int main() { rpc::server srv(rpc::constants::DEFAULT_PORT); + std::cout << "registered on port " << srv.port() << std::endl; srv.bind("echo", [](std::string const& s) { return s; diff --git a/include/rpc/server.h b/include/rpc/server.h index f240acf1..64e6fe1e 100644 --- a/include/rpc/server.h +++ b/include/rpc/server.h @@ -104,6 +104,10 @@ class server { //! \note This should not be called from worker threads. void stop(); + //! \brief Returns port + //! \note The port + unsigned short port() const; + //! \brief Closes all sessions gracefully. void close_sessions(); diff --git a/include/rpc/version.h b/include/rpc/version.h index 206c7c64..805dec1e 100644 --- a/include/rpc/version.h +++ b/include/rpc/version.h @@ -7,7 +7,7 @@ namespace rpc { static constexpr unsigned VERSION_MAJOR = 2; static constexpr unsigned VERSION_MINOR = 2; -static constexpr unsigned VERSION_PATCH = 0; +static constexpr unsigned VERSION_PATCH = 1; } /* rpc */ diff --git a/lib/rpc/server.cc b/lib/rpc/server.cc index 1012c6d9..419ea332 100644 --- a/lib/rpc/server.cc +++ b/lib/rpc/server.cc @@ -25,17 +25,28 @@ struct server::impl { impl(server *parent, std::string const &address, uint16_t port) : parent_(parent), io_(), - acceptor_(io_, - tcp::endpoint(ip::address::from_string(address), port)), + acceptor_(io_), socket_(io_), - suppress_exceptions_(false) {} + suppress_exceptions_(false) { + auto ep = tcp::endpoint(ip::address::from_string(address), port); + acceptor_.open(ep.protocol()); + acceptor_.set_option(tcp::acceptor::reuse_address(true)); + acceptor_.bind(ep); + acceptor_.listen(); + } impl(server *parent, uint16_t port) : parent_(parent), io_(), - acceptor_(io_, tcp::endpoint(tcp::v4(), port)), + acceptor_(io_), socket_(io_), - suppress_exceptions_(false) {} + suppress_exceptions_(false) { + auto ep = tcp::endpoint(tcp::v4(), port); + acceptor_.open(ep.protocol()); + acceptor_.set_option(tcp::acceptor::reuse_address(true)); + acceptor_.bind(ep); + acceptor_.listen(); + } void start_accept() { acceptor_.async_accept(socket_, [this](std::error_code ec) { @@ -66,6 +77,10 @@ struct server::impl { loop_workers_.join_all(); } + unsigned short port() const { + return acceptor_.local_endpoint().port(); + } + server *parent_; io_service io_; ip::tcp::acceptor acceptor_; @@ -126,6 +141,8 @@ void server::async_run(std::size_t worker_threads) { void server::stop() { pimpl->stop(); } +unsigned short server::port() const { return pimpl->port(); } + void server::close_sessions() { pimpl->close_sessions(); } void server::close_session(std::shared_ptr const &s) { From b38d1570b8a79198c787ff6429caed37fb3c829a Mon Sep 17 00:00:00 2001 From: Robert Rudi Date: Wed, 4 Jul 2018 10:30:23 +0200 Subject: [PATCH 14/54] Fixes #190. Race condition when reading on rpc --- lib/rpc/client.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/rpc/client.cc b/lib/rpc/client.cc index 13f57021..2bb993fe 100644 --- a/lib/rpc/client.cc +++ b/lib/rpc/client.cc @@ -192,8 +192,7 @@ void client::wait_conn() { } int client::get_next_call_idx() { - ++(pimpl->call_idx_); - return pimpl->call_idx_; + return ++(pimpl->call_idx_); } void client::post(std::shared_ptr buffer, int idx, From c6475ae8105cb1404e6e072a5e5f8911fa2b0ca6 Mon Sep 17 00:00:00 2001 From: Yosi Zelensky Date: Wed, 5 Sep 2018 10:48:11 +0300 Subject: [PATCH 15/54] Update cookbook.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed `Storing per-session data` section to have a capturing lambda so the example will work 😄 --- doc/pages/cookbook.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/pages/cookbook.md b/doc/pages/cookbook.md index 8de2879a..df0c7374 100644 --- a/doc/pages/cookbook.md +++ b/doc/pages/cookbook.md @@ -281,7 +281,7 @@ int main() { rpc::server srv(8080); // listen on TCP port 8080 std::unordered_map data; - srv.bind("store_me_maybe", [](std::string const& value) { + srv.bind("store_me_maybe", [&](std::string const& value) { auto id = rpc::this_session().id(); data[id] = value; }); From 074e7632d251f83eedfd6f9717f4eb2ae42c9374 Mon Sep 17 00:00:00 2001 From: Zhishan Zhang Date: Wed, 14 Nov 2018 14:46:44 +0800 Subject: [PATCH 16/54] check if it is assignment to self --- lib/rpc/server.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/rpc/server.cc b/lib/rpc/server.cc index 1012c6d9..ff27d8a2 100644 --- a/lib/rpc/server.cc +++ b/lib/rpc/server.cc @@ -102,10 +102,12 @@ server::~server() { } server& server::operator=(server &&other) { - pimpl = std::move(other.pimpl); - other.pimpl = nullptr; - disp_ = std::move(other.disp_); - other.disp_ = nullptr; + if (this != &other) { + pimpl = std::move(other.pimpl); + other.pimpl = nullptr; + disp_ = std::move(other.disp_); + other.disp_ = nullptr; + } return *this; } From 9742f8e167ea7e7ce512eebaa6d58a742afa4af9 Mon Sep 17 00:00:00 2001 From: Quentin Chateau Date: Mon, 10 Dec 2018 16:54:11 +0100 Subject: [PATCH 17/54] Added test for issue #175 --- tests/rpc/server_session_test.cc | 33 +++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/tests/rpc/server_session_test.cc b/tests/rpc/server_session_test.cc index 283d20b1..276d46f5 100644 --- a/tests/rpc/server_session_test.cc +++ b/tests/rpc/server_session_test.cc @@ -1,5 +1,6 @@ #include #include +#include #include "gtest/gtest.h" @@ -68,7 +69,7 @@ TEST(server_session_test_bug153, bug_153_crash_on_client_timeout) { auto client = std::unique_ptr(new rpc::client("localhost", rpc::constants::DEFAULT_PORT)); client->set_timeout(5); - + try { client->call("bug_153"); } catch(rpc::timeout& ) { @@ -77,3 +78,33 @@ TEST(server_session_test_bug153, bug_153_crash_on_client_timeout) { std::this_thread::sleep_for(std::chrono::milliseconds(20)); // no crash is enough } + + +TEST(server_session_test_bug175, bug_175_multhread_crash) { + const int nr_threads = 4; + const int nr_calls_per_thread = 100; + + rpc::server s("127.0.0.1", rpc::constants::DEFAULT_PORT); + s.bind("bug_175", [&](int idx, int i) { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + return 0; + }); + s.async_run(nr_threads); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + auto spam_call = [&](int idx, int nr_calls) { + for (int i=0; i(new rpc::client("localhost", rpc::constants::DEFAULT_PORT)); + client->call("bug_175", idx, i); + } + }; + + std::vector> futures; + for (int i=0; i Date: Mon, 10 Dec 2018 19:44:29 +0100 Subject: [PATCH 18/54] Thread safety in session management --- lib/rpc/server.cc | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/rpc/server.cc b/lib/rpc/server.cc index 1012c6d9..cd371d03 100644 --- a/lib/rpc/server.cc +++ b/lib/rpc/server.cc @@ -19,6 +19,7 @@ using namespace rpc::detail; using RPCLIB_ASIO::ip::tcp; using namespace RPCLIB_ASIO; + namespace rpc { struct server::impl { @@ -45,6 +46,7 @@ struct server::impl { parent_, &io_, std::move(socket_), parent_->disp_, suppress_exceptions_); s->start(); + std::unique_lock lock(sessions_mutex_); sessions_.push_back(s); } else { LOG_ERROR("Error while accepting connection: {}", ec); @@ -55,10 +57,15 @@ struct server::impl { } void close_sessions() { - for (auto &session : sessions_) { + std::unique_lock lock(sessions_mutex_); + auto sessions_copy = sessions_; + sessions_.clear(); + lock.unlock(); + + // release shared pointers outside of the mutex + for (auto &session : sessions_copy) { session->close(); } - sessions_.clear(); } void stop() { @@ -74,6 +81,7 @@ struct server::impl { std::vector> sessions_; std::atomic_bool suppress_exceptions_; RPCLIB_CREATE_LOG_CHANNEL(server) + std::mutex sessions_mutex_; }; RPCLIB_CREATE_LOG_CHANNEL(server) @@ -129,10 +137,15 @@ void server::stop() { pimpl->stop(); } void server::close_sessions() { pimpl->close_sessions(); } void server::close_session(std::shared_ptr const &s) { + std::unique_lock lock(pimpl->sessions_mutex_); auto it = std::find(begin(pimpl->sessions_), end(pimpl->sessions_), s); + std::shared_ptr session; if (it != end(pimpl->sessions_)) { + session = *it; pimpl->sessions_.erase(it); } + lock.unlock(); + // session shared pointer is released outside of the mutex } } /* rpc */ From d41cf13a0b6fa788443c35a4fa61ca822307dc23 Mon Sep 17 00:00:00 2001 From: Quentin Chateau Date: Mon, 10 Dec 2018 19:45:40 +0100 Subject: [PATCH 19/54] Prevent segfault --- lib/rpc/detail/server_session.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/rpc/detail/server_session.cc b/lib/rpc/detail/server_session.cc index d6f89177..9287ac81 100644 --- a/lib/rpc/detail/server_session.cc +++ b/lib/rpc/detail/server_session.cc @@ -34,9 +34,11 @@ void server_session::start() { do_read(); } void server_session::close() { LOG_INFO("Closing session."); exit_ = true; - write_strand_.post([this]() { + auto self(shared_from_base()); + + write_strand_.post([this, self]() { socket_.close(); - parent_->close_session(shared_from_base()); + parent_->close_session(self); }); } From 613c70b73fb51343676bec9bc09ce73c4959db6c Mon Sep 17 00:00:00 2001 From: Quentin Chateau Date: Mon, 10 Dec 2018 23:39:13 +0100 Subject: [PATCH 20/54] Fixed double close --- lib/rpc/detail/server_session.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/rpc/detail/server_session.cc b/lib/rpc/detail/server_session.cc index 9287ac81..063537cc 100644 --- a/lib/rpc/detail/server_session.cc +++ b/lib/rpc/detail/server_session.cc @@ -139,9 +139,6 @@ void server_session::do_read() { LOG_ERROR("Unhandled error code: {} | '{}'", ec, ec.message()); } })); - if (exit_) { - socket_.close(); - } } } /* detail */ From f1af237563c5eeb72381fd6f719223587822b2f1 Mon Sep 17 00:00:00 2001 From: Quentin Chateau Date: Wed, 12 Dec 2018 00:02:43 +0100 Subject: [PATCH 21/54] Detect failed connect, fix CV spurious wakeup --- include/rpc/rpc_error.h | 7 +++++++ lib/rpc/client.cc | 15 +++++++++++++-- tests/rpc/client_test.cc | 22 +++++++++++++++++++++- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/include/rpc/rpc_error.h b/include/rpc/rpc_error.h index 7efd6ab7..abd74914 100644 --- a/include/rpc/rpc_error.h +++ b/include/rpc/rpc_error.h @@ -49,6 +49,13 @@ class timeout : public std::runtime_error { std::string formatted; }; +//! \brief This exception is throw by the client when the connection or call +//! causes a system error +class system_error : public std::system_error { +public: + using std::system_error::system_error; +}; + } /* rpc */ diff --git a/lib/rpc/client.cc b/lib/rpc/client.cc index 13f57021..a51fc64a 100644 --- a/lib/rpc/client.cc +++ b/lib/rpc/client.cc @@ -37,12 +37,14 @@ struct client::impl { state_(client::connection_state::initial), writer_(std::make_shared( &io_, RPCLIB_ASIO::ip::tcp::socket(io_))), - timeout_(nonstd::nullopt) { + timeout_(nonstd::nullopt), + connection_ec_(nonstd::nullopt) { pac_.reserve_buffer(default_buffer_size); } void do_connect(tcp::resolver::iterator endpoint_iterator) { LOG_INFO("Initiating connection."); + connection_ec_ = nonstd::nullopt; RPCLIB_ASIO::async_connect( writer_->socket_, endpoint_iterator, [this](std::error_code ec, tcp::resolver::iterator) { @@ -54,7 +56,11 @@ struct client::impl { conn_finished_.notify_all(); do_read(); } else { + std::unique_lock lock(mut_connection_finished_); LOG_ERROR("Error during connection: {}", ec); + state_ = client::connection_state::disconnected; + connection_ec_ = ec; + conn_finished_.notify_all(); } }); } @@ -157,6 +163,7 @@ struct client::impl { std::atomic state_; std::shared_ptr writer_; nonstd::optional timeout_; + nonstd::optional connection_ec_; RPCLIB_CREATE_LOG_CHANNEL(client) }; @@ -176,7 +183,11 @@ client::client(std::string const &addr, uint16_t port) void client::wait_conn() { std::unique_lock lock(pimpl->mut_connection_finished_); - if (!pimpl->is_connected_) { + while (!pimpl->is_connected_) { + if (auto ec = pimpl->connection_ec_) { + throw rpc::system_error(ec.value()); + } + if (auto timeout = pimpl->timeout_) { auto result = pimpl->conn_finished_.wait_for( lock, std::chrono::milliseconds(*timeout)); diff --git a/tests/rpc/client_test.cc b/tests/rpc/client_test.cc index c6bee33f..a3b56f6b 100644 --- a/tests/rpc/client_test.cc +++ b/tests/rpc/client_test.cc @@ -106,9 +106,29 @@ TEST_F(client_test, timeout_clear) { EXPECT_FALSE(client.get_timeout()); } +// Only enable this test on linux +// It seems like the connection error is not detected on windows +TEST_F(client_test, bad_ip) { + rpc::client client("127.0.0.2", test_port); + client.set_timeout(1000); +#ifdef __linux__ + EXPECT_THROW(client.call("dummy_void_zeroarg"), rpc::system_error); + // We expect a connection refused, not a timeout +#else + EXPECT_ANY_THROW(client.call("dummy_void_zeroarg")); + // throw is enough for windows +#endif +} + TEST(client_test2, timeout_while_connection) { rpc::client client("localhost", rpc::constants::DEFAULT_PORT); client.set_timeout(50); +#ifdef __linux__ // this client never connects, so this tests the timout in wait_conn() - EXPECT_THROW(client.call("whatev"), rpc::timeout); + // We expect a connection refused, not a timeout + EXPECT_THROW(client.call("whatev"), rpc::system_error); +#else + EXPECT_ANY_THROW(client.call("dummy_void_zeroarg")); + // throw is enough for windows +#endif } From 780e5001f6cd7d1b13ff106f83cd1c5fbe053343 Mon Sep 17 00:00:00 2001 From: Quentin Chateau Date: Sun, 16 Dec 2018 17:36:31 +0100 Subject: [PATCH 22/54] Updated readme --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d20ad3c6..fe4f2c5f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,11 @@ -# rpclib ![MIT](https://img.shields.io/badge/license-MIT-blue.svg) [![Build Status](https://travis-ci.org/rpclib/rpclib.svg?branch=master)](https://travis-ci.org/rpclib/rpclib) [![Build status](https://ci.appveyor.com/api/projects/status/9lft2tlamcox8epq?svg=true)](https://ci.appveyor.com/project/sztomi/callme) [![Coverage Status](https://img.shields.io/codecov/c/github/rpclib/rpclib/dev.svg)](https://img.shields.io/codecov/c/github/rpclib/rpclib/dev.svg) ![Coverity](https://scan.coverity.com/projects/7259/badge.svg?flat=1) [![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg?maxAge=2592000)](https://gitter.im/rpclib/Lobby) +# rpclib ![MIT](https://img.shields.io/badge/license-MIT-blue.svg) [![Build Status](https://travis-ci.org/Tytan/rpclib.svg?branch=master)](https://travis-ci.org/Tytan/rpclib) [![Build status](https://ci.appveyor.com/api/projects/status/hlpej63bpxks141j?svg=true)](https://ci.appveyor.com/project/Tytan/rpclib) [![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg?maxAge=2592000)](https://gitter.im/rpclib/Lobby) -[![waffle](https://badge.waffle.io/rpclib/rpclib.svg?columns=In%20Progress,Waiting%20For%20Release)](https://waffle.io/rpclib/rpclib) +# Fork + +The original repository is at [rpclib/rpclib](https://github.com/rpclib/rpclib). Due to the lack of maintenance, I picked up the project. Currently the goal is mainly to merge pull requests submitted to the main repository. + +# rpclib `rpclib` is a RPC library for C++, providing both a client and server implementation. It is built using modern C++14, and as such, requires a recent compiler. Main highlights: From fa16c9a31459a65281fe22816d8a9c3150cabdca Mon Sep 17 00:00:00 2001 From: Quentin Chateau Date: Wed, 19 Dec 2018 23:07:58 +0100 Subject: [PATCH 23/54] Fixed clang7 warnings about weak vtables and deprecation --- include/rpc/nonstd/optional.hpp | 2 +- include/rpc/rpc_error.h | 1 + lib/rpc/nonstd/optional.cc | 4 +++- lib/rpc/rpc_error.cc | 2 ++ 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/include/rpc/nonstd/optional.hpp b/include/rpc/nonstd/optional.hpp index d9888cf4..e6d941d5 100644 --- a/include/rpc/nonstd/optional.hpp +++ b/include/rpc/nonstd/optional.hpp @@ -564,7 +564,7 @@ class bad_optional_access : public std::logic_error public: explicit bad_optional_access() : logic_error( "bad optional access" ) {} - ~bad_optional_access(); + const char* what() const noexcept; }; /// optional diff --git a/include/rpc/rpc_error.h b/include/rpc/rpc_error.h index abd74914..22a36099 100644 --- a/include/rpc/rpc_error.h +++ b/include/rpc/rpc_error.h @@ -54,6 +54,7 @@ class timeout : public std::runtime_error { class system_error : public std::system_error { public: using std::system_error::system_error; + const char* what() const noexcept; }; } /* rpc */ diff --git a/lib/rpc/nonstd/optional.cc b/lib/rpc/nonstd/optional.cc index f80c9319..ac89d298 100644 --- a/lib/rpc/nonstd/optional.cc +++ b/lib/rpc/nonstd/optional.cc @@ -3,4 +3,6 @@ // This is no-op; the reason it exists is to avoid // the weak vtables problem. For more info, see // https://stackoverflow.com/a/23749273/140367 -nonstd::bad_optional_access::~bad_optional_access() {} +const char* nonstd::bad_optional_access::what() const noexcept { + return std::logic_error::what(); +} diff --git a/lib/rpc/rpc_error.cc b/lib/rpc/rpc_error.cc index 47e76e6b..57df4244 100644 --- a/lib/rpc/rpc_error.cc +++ b/lib/rpc/rpc_error.cc @@ -21,4 +21,6 @@ timeout::timeout(std::string const &what_arg) : std::runtime_error(what_arg) { const char *timeout::what() const noexcept { return formatted.data(); } +const char* system_error::what() const noexcept { return std::system_error::what(); } + } /* rpc */ From 38b02e1b123c9494622f4dcc3ae2f904f774eec6 Mon Sep 17 00:00:00 2001 From: Quentin Chateau Date: Sun, 23 Dec 2018 13:16:34 +0100 Subject: [PATCH 24/54] Removed unused attributes --- include/rpc/detail/async_writer.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/rpc/detail/async_writer.h b/include/rpc/detail/async_writer.h index 66488ff6..7c8a01ee 100644 --- a/include/rpc/detail/async_writer.h +++ b/include/rpc/detail/async_writer.h @@ -84,9 +84,6 @@ class async_writer : public std::enable_shared_from_this { RPCLIB_ASIO::ip::tcp::socket socket_; RPCLIB_ASIO::strand write_strand_; std::atomic_bool exit_{false}; - bool exited_ = false; - std::mutex m_exit_; - std::condition_variable cv_exit_; private: std::deque write_queue_; From 96733317187e6e91f982f9790cc9f3e1b0544132 Mon Sep 17 00:00:00 2001 From: Quentin Chateau Date: Sun, 23 Dec 2018 13:26:26 +0100 Subject: [PATCH 25/54] Hide exit_ flag --- include/rpc/detail/async_writer.h | 10 +++++++++- lib/rpc/detail/server_session.cc | 10 +++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/include/rpc/detail/async_writer.h b/include/rpc/detail/async_writer.h index 7c8a01ee..c1941774 100644 --- a/include/rpc/detail/async_writer.h +++ b/include/rpc/detail/async_writer.h @@ -23,6 +23,14 @@ class async_writer : public std::enable_shared_from_this { RPCLIB_ASIO::ip::tcp::socket socket) : socket_(std::move(socket)), write_strand_(*io), exit_(false) {} + void close() { + exit_ = true; + } + + bool is_closed() const { + return exit_.load(); + } + void do_write() { if (exit_) { return; @@ -83,9 +91,9 @@ class async_writer : public std::enable_shared_from_this { protected: RPCLIB_ASIO::ip::tcp::socket socket_; RPCLIB_ASIO::strand write_strand_; - std::atomic_bool exit_{false}; private: + std::atomic_bool exit_{false}; std::deque write_queue_; RPCLIB_CREATE_LOG_CHANNEL(async_writer) }; diff --git a/lib/rpc/detail/server_session.cc b/lib/rpc/detail/server_session.cc index a39bd5bb..e18215e9 100644 --- a/lib/rpc/detail/server_session.cc +++ b/lib/rpc/detail/server_session.cc @@ -33,7 +33,7 @@ void server_session::start() { do_read(); } void server_session::close() { LOG_INFO("Closing session."); - exit_ = true; + async_writer::close(); auto self(shared_from_base()); write_strand_.post([this, self]() { @@ -51,11 +51,11 @@ void server_session::do_read() { // (since it's constexpr), but MSVC insists. read_strand_.wrap([this, self, max_read_bytes](std::error_code ec, std::size_t length) { - if (exit_) { return; } + if (is_closed()) { return; } if (!ec) { pac_.buffer_consumed(length); RPCLIB_MSGPACK::unpacked result; - while (pac_.next(result) && !exit_) { + while (pac_.next(result) && !is_closed()) { auto msg = result.get(); output_buf_.clear(); @@ -106,7 +106,7 @@ void server_session::do_read() { LOG_WARN("Session exit requested from a handler."); // posting through the strand so this comes after // the previous write - write_strand_.post([this]() { exit_ = true; }); + write_strand_.post([this]() { close(); }); } if (this_server().stopping_) { @@ -119,7 +119,7 @@ void server_session::do_read() { }); } - if (!exit_) { + if (!is_closed()) { // resizing strategy: if the remaining buffer size is // less than the maximum bytes requested from asio, // then request max_read_bytes. This prompts the unpacker From ac059e5fa9a8f7dc177d62c03a053d6aa62d65f6 Mon Sep 17 00:00:00 2001 From: Quentin Chateau Date: Sun, 23 Dec 2018 13:39:57 +0100 Subject: [PATCH 26/54] Made protected attributes private. Reorganised server close --- include/rpc/detail/async_writer.h | 41 ++++++++++++++++++------------- lib/rpc/detail/server_session.cc | 15 ++++++----- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/include/rpc/detail/async_writer.h b/include/rpc/detail/async_writer.h index c1941774..67a71e54 100644 --- a/include/rpc/detail/async_writer.h +++ b/include/rpc/detail/async_writer.h @@ -25,6 +25,21 @@ class async_writer : public std::enable_shared_from_this { void close() { exit_ = true; + + auto self = shared_from_this(); + write_strand_.post([this, self]() { + LOG_INFO("Closing socket"); + try { + socket_.shutdown( + RPCLIB_ASIO::ip::tcp::socket::shutdown_both); + } + catch (std::system_error &e) { + (void)e; + LOG_WARN("std::system_error during socket shutdown. " + "Code: {}. Message: {}", e.code(), e.what()); + } + socket_.close(); + }); } bool is_closed() const { @@ -54,20 +69,6 @@ class async_writer : public std::enable_shared_from_this { } else { LOG_ERROR("Error while writing to socket: {}", ec); } - - if (exit_) { - LOG_INFO("Closing socket"); - try { - socket_.shutdown( - RPCLIB_ASIO::ip::tcp::socket::shutdown_both); - } - catch (std::system_error &e) { - (void)e; - LOG_WARN("std::system_error during socket shutdown. " - "Code: {}. Message: {}", e.code(), e.what()); - } - socket_.close(); - } })); } @@ -88,11 +89,17 @@ class async_writer : public std::enable_shared_from_this { return std::static_pointer_cast(shared_from_this()); } -protected: - RPCLIB_ASIO::ip::tcp::socket socket_; - RPCLIB_ASIO::strand write_strand_; + RPCLIB_ASIO::ip::tcp::socket& socket() { + return socket_; + } + + RPCLIB_ASIO::strand& write_strand() { + return write_strand_; + } private: + RPCLIB_ASIO::ip::tcp::socket socket_; + RPCLIB_ASIO::strand write_strand_; std::atomic_bool exit_{false}; std::deque write_queue_; RPCLIB_CREATE_LOG_CHANNEL(async_writer) diff --git a/lib/rpc/detail/server_session.cc b/lib/rpc/detail/server_session.cc index e18215e9..3e987185 100644 --- a/lib/rpc/detail/server_session.cc +++ b/lib/rpc/detail/server_session.cc @@ -34,10 +34,9 @@ void server_session::start() { do_read(); } void server_session::close() { LOG_INFO("Closing session."); async_writer::close(); - auto self(shared_from_base()); - write_strand_.post([this, self]() { - socket_.close(); + auto self(shared_from_base()); + write_strand().post([this, self]() { parent_->close_session(self); }); } @@ -45,7 +44,7 @@ void server_session::close() { void server_session::do_read() { auto self(shared_from_base()); constexpr std::size_t max_read_bytes = default_buffer_size; - socket_.async_read_some( + socket().async_read_some( RPCLIB_ASIO::buffer(pac_.buffer(), default_buffer_size), // I don't think max_read_bytes needs to be captured explicitly // (since it's constexpr), but MSVC insists. @@ -94,10 +93,10 @@ void server_session::do_read() { if (!resp.is_empty()) { #ifdef _MSC_VER // doesn't compile otherwise. - write_strand_.post( + write_strand().post( [=]() { write(resp.get_data()); }); #else - write_strand_.post( + write_strand().post( [this, self, resp, z]() { write(resp.get_data()); }); #endif } @@ -106,14 +105,14 @@ void server_session::do_read() { LOG_WARN("Session exit requested from a handler."); // posting through the strand so this comes after // the previous write - write_strand_.post([this]() { close(); }); + write_strand().post([this]() { close(); }); } if (this_server().stopping_) { LOG_WARN("Server exit requested from a handler."); // posting through the strand so this comes after // the previous write - write_strand_.post( + write_strand().post( [this]() { parent_->close_sessions(); }); } }); From 8dcfa73edd36964f2fc9e3abd2382dbe8a57c430 Mon Sep 17 00:00:00 2001 From: Quentin Chateau Date: Sun, 23 Dec 2018 15:23:02 +0100 Subject: [PATCH 27/54] Removed friendship asyncwriter/client --- include/rpc/detail/async_writer.h | 8 +++----- lib/rpc/client.cc | 4 ++-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/include/rpc/detail/async_writer.h b/include/rpc/detail/async_writer.h index 67a71e54..e390572c 100644 --- a/include/rpc/detail/async_writer.h +++ b/include/rpc/detail/async_writer.h @@ -81,7 +81,9 @@ class async_writer : public std::enable_shared_from_this { do_write(); } - friend class rpc::client; + RPCLIB_ASIO::ip::tcp::socket& socket() { + return socket_; + } protected: template @@ -89,10 +91,6 @@ class async_writer : public std::enable_shared_from_this { return std::static_pointer_cast(shared_from_this()); } - RPCLIB_ASIO::ip::tcp::socket& socket() { - return socket_; - } - RPCLIB_ASIO::strand& write_strand() { return write_strand_; } diff --git a/lib/rpc/client.cc b/lib/rpc/client.cc index f8314719..eb1f8928 100644 --- a/lib/rpc/client.cc +++ b/lib/rpc/client.cc @@ -46,7 +46,7 @@ struct client::impl { LOG_INFO("Initiating connection."); connection_ec_ = nonstd::nullopt; RPCLIB_ASIO::async_connect( - writer_->socket_, endpoint_iterator, + writer_->socket(), endpoint_iterator, [this](std::error_code ec, tcp::resolver::iterator) { if (!ec) { std::unique_lock lock(mut_connection_finished_); @@ -68,7 +68,7 @@ struct client::impl { void do_read() { LOG_TRACE("do_read"); constexpr std::size_t max_read_bytes = default_buffer_size; - writer_->socket_.async_read_some( + writer_->socket().async_read_some( RPCLIB_ASIO::buffer(pac_.buffer(), max_read_bytes), // I don't think max_read_bytes needs to be captured explicitly // (since it's constexpr), but MSVC insists. From 28e306c8470df122ef6b3a69f886fd82d368ae28 Mon Sep 17 00:00:00 2001 From: Quentin Chateau Date: Sun, 23 Dec 2018 15:24:52 +0100 Subject: [PATCH 28/54] Made exception constructors public --- include/rpc/rpc_error.h | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/include/rpc/rpc_error.h b/include/rpc/rpc_error.h index 22a36099..8f6eed6c 100644 --- a/include/rpc/rpc_error.h +++ b/include/rpc/rpc_error.h @@ -17,6 +17,9 @@ namespace rpc { //! throw it, hence its constructor is private. class rpc_error : public std::runtime_error { public: + rpc_error(std::string const &what_arg, std::string const &function_name, + std::shared_ptr o); + //! \brief Returns the name of the function that was //! called on the server while the error occurred. std::string get_function_name() const; @@ -25,11 +28,6 @@ class rpc_error : public std::runtime_error { //! provided. virtual RPCLIB_MSGPACK::object_handle &get_error(); -private: - friend class client; - rpc_error(std::string const &what_arg, std::string const &function_name, - std::shared_ptr o); - private: std::string func_name_; std::shared_ptr ob_h_; @@ -40,12 +38,12 @@ class rpc_error : public std::runtime_error { //! \note There isn't necessarily a timeout set, it is an optional value. class timeout : public std::runtime_error { public: + explicit timeout(std::string const &what_arg); + //! \brief Describes the exception. const char *what() const noexcept override; private: - friend class client; - explicit timeout(std::string const &what_arg); std::string formatted; }; From c02d25b604584e4217384510dab0c785d1e0ceac Mon Sep 17 00:00:00 2001 From: Quentin Chateau Date: Sun, 23 Dec 2018 15:26:49 +0100 Subject: [PATCH 29/54] Removed server/server_session friendship --- include/rpc/server.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/rpc/server.h b/include/rpc/server.h index 64e6fe1e..60c6b86a 100644 --- a/include/rpc/server.h +++ b/include/rpc/server.h @@ -111,9 +111,6 @@ class server { //! \brief Closes all sessions gracefully. void close_sessions(); - friend class detail::server_session; - -private: //! \brief Closes a specific session. void close_session(std::shared_ptr const& s); From 043da6bf01d21771fcbc4e59d14794075471e115 Mon Sep 17 00:00:00 2001 From: Quentin Chateau Date: Sun, 23 Dec 2018 15:31:34 +0100 Subject: [PATCH 30/54] Removed this_server/server_session friendship --- include/rpc/this_server.h | 3 ++- lib/rpc/detail/server_session.cc | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/rpc/this_server.h b/include/rpc/this_server.h index 7e8826b6..d1954e4a 100644 --- a/include/rpc/this_server.h +++ b/include/rpc/this_server.h @@ -19,7 +19,8 @@ class this_server_t { //! \brief Cancels a requested stop operation. void cancel_stop(); - friend class rpc::detail::server_session; + //! Check if a stop is requested + bool stopping() const { return stopping_; } private: bool stopping_; diff --git a/lib/rpc/detail/server_session.cc b/lib/rpc/detail/server_session.cc index 3e987185..dec9d3b2 100644 --- a/lib/rpc/detail/server_session.cc +++ b/lib/rpc/detail/server_session.cc @@ -108,7 +108,7 @@ void server_session::do_read() { write_strand().post([this]() { close(); }); } - if (this_server().stopping_) { + if (this_server().stopping()) { LOG_WARN("Server exit requested from a handler."); // posting through the strand so this comes after // the previous write From 89bee5822a01975d827ef0c9ec4d97d362f17625 Mon Sep 17 00:00:00 2001 From: liufengshan Date: Mon, 31 Dec 2018 20:33:38 +0800 Subject: [PATCH 31/54] Fixed some typo --- include/rpc/client.h | 2 +- include/rpc/client.inl | 2 +- lib/rpc/client.cc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/rpc/client.h b/include/rpc/client.h index 837e85c9..fcd16ebe 100644 --- a/include/rpc/client.h +++ b/include/rpc/client.h @@ -88,7 +88,7 @@ class client { //! //! \param func_name The name of the notification to call. //! \param args The arguments to pass to the function. - //! \tparam Args THe types of the arguments. + //! \tparam Args The types of the arguments. //! //! \note This function returns immediately (possibly before the //! notification is written to the socket). diff --git a/include/rpc/client.inl b/include/rpc/client.inl index 04dc825b..f980f069 100644 --- a/include/rpc/client.inl +++ b/include/rpc/client.inl @@ -47,7 +47,7 @@ client::async_call(std::string const &func_name, Args... args) { //! \param args The arguments to pass to the function. //! \note This function returns when the notification is written to the //! socket. -//! \tparam Args THe types of the arguments. +//! \tparam Args The types of the arguments. template void client::send(std::string const &func_name, Args... args) { RPCLIB_CREATE_LOG_CHANNEL(client) diff --git a/lib/rpc/client.cc b/lib/rpc/client.cc index 13f57021..e7593ce0 100644 --- a/lib/rpc/client.cc +++ b/lib/rpc/client.cc @@ -122,7 +122,7 @@ struct client::impl { client::connection_state get_connection_state() const { return state_; } //! \brief Waits for the write queue and writes any buffers to the network - //! connection. Should be executed throught strand_. + //! connection. Should be executed through strand_. void write(RPCLIB_MSGPACK::sbuffer item) { writer_->write(std::move(item)); } From 985ea56e75dcc2464afcd1ddd709b8fed3d66b5a Mon Sep 17 00:00:00 2001 From: Alexander Overvoorde Date: Fri, 11 Jan 2019 01:59:55 +0100 Subject: [PATCH 32/54] Update included asio to handle glibc strerror_r better --- dependencies/include/asio/impl/error_code.ipp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/dependencies/include/asio/impl/error_code.ipp b/dependencies/include/asio/impl/error_code.ipp index 68674f71..c256bb53 100644 --- a/dependencies/include/asio/impl/error_code.ipp +++ b/dependencies/include/asio/impl/error_code.ipp @@ -97,20 +97,18 @@ public: #if defined(__sun) || defined(__QNX__) || defined(__SYMBIAN32__) using namespace std; return strerror(value); -#elif defined(__MACH__) && defined(__APPLE__) \ - || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) \ - || defined(_AIX) || defined(__hpux) || defined(__osf__) \ - || defined(__ANDROID__) - char buf[256] = ""; - using namespace std; - strerror_r(value, buf, sizeof(buf)); - return buf; #else char buf[256] = ""; - return strerror_r(value, buf, sizeof(buf)); + using namespace std; + return strerror_result(strerror_r(value, buf, sizeof(buf)), buf); #endif #endif // defined(ASIO_WINDOWS) } + +private: + // Helper function to adapt the result from glibc's variant of strerror_r. + static const char* strerror_result(int, const char* s) { return s; } + static const char* strerror_result(const char* s, const char*) { return s; } }; } // namespace detail From d20ba38c59503d6b63be3302b5d826c8cad80df1 Mon Sep 17 00:00:00 2001 From: Punit Agrawal Date: Tue, 29 Jan 2019 16:37:18 +0900 Subject: [PATCH 33/54] examples: Add pthread link time dependency Compiling the calculator and echo examples fail on a Linux system due to missing pthread library during linking. Add this dependency. --- examples/calculator/CMakeLists.txt | 5 +++-- examples/echo/CMakeLists.txt | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/examples/calculator/CMakeLists.txt b/examples/calculator/CMakeLists.txt index 9e08a4ef..b56e391b 100644 --- a/examples/calculator/CMakeLists.txt +++ b/examples/calculator/CMakeLists.txt @@ -2,11 +2,12 @@ cmake_minimum_required(VERSION 3.0.0) project(calculator) find_package(rpclib REQUIRED) +find_package(Threads REQUIRED) include_directories(${RPCLIB_INCLUDE_DIR}) add_executable(calculator_server calculator_server.cc) -target_link_libraries(calculator_server ${RPCLIB_LIBS}) +target_link_libraries(calculator_server ${RPCLIB_LIBS} ${CMAKE_THREAD_LIBS_INIT}) set_target_properties( calculator_server PROPERTIES @@ -15,7 +16,7 @@ set_target_properties( target_compile_definitions(calculator_server PUBLIC ${RPCLIB_COMPILE_DEFINITIONS}) add_executable(calculator_client calculator_client.cc) -target_link_libraries(calculator_client ${RPCLIB_LIBS}) +target_link_libraries(calculator_client ${RPCLIB_LIBS} ${CMAKE_THREAD_LIBS_INIT}) set_target_properties( calculator_client PROPERTIES diff --git a/examples/echo/CMakeLists.txt b/examples/echo/CMakeLists.txt index a84839ef..987c5055 100644 --- a/examples/echo/CMakeLists.txt +++ b/examples/echo/CMakeLists.txt @@ -2,11 +2,12 @@ cmake_minimum_required(VERSION 3.0.0) project(echo) find_package(rpclib REQUIRED) +find_package(Threads REQUIRED) include_directories(${RPCLIB_INCLUDE_DIR}) add_executable(echo_server echo_server.cc) -target_link_libraries(echo_server ${RPCLIB_LIBS}) +target_link_libraries(echo_server ${RPCLIB_LIBS} ${CMAKE_THREAD_LIBS_INIT}) set_target_properties( echo_server PROPERTIES @@ -15,7 +16,7 @@ set_target_properties( target_compile_definitions(echo_server PUBLIC ${RPCLIB_COMPILE_DEFINITIONS}) add_executable(echo_client echo_client.cc) -target_link_libraries(echo_client ${RPCLIB_LIBS}) +target_link_libraries(echo_client ${RPCLIB_LIBS} ${CMAKE_THREAD_LIBS_INIT}) set_target_properties( echo_client PROPERTIES From d638ae33cf0faf7de935a18ead626ff021951f16 Mon Sep 17 00:00:00 2001 From: Quentin Chateau Date: Sat, 16 Mar 2019 12:38:03 +0100 Subject: [PATCH 34/54] Use error code instead of exception in socket shutdown By: nsubiron --- include/rpc/detail/async_writer.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/include/rpc/detail/async_writer.h b/include/rpc/detail/async_writer.h index e390572c..7c3d3ff4 100644 --- a/include/rpc/detail/async_writer.h +++ b/include/rpc/detail/async_writer.h @@ -29,12 +29,10 @@ class async_writer : public std::enable_shared_from_this { auto self = shared_from_this(); write_strand_.post([this, self]() { LOG_INFO("Closing socket"); - try { - socket_.shutdown( - RPCLIB_ASIO::ip::tcp::socket::shutdown_both); - } - catch (std::system_error &e) { - (void)e; + std::error_code e; + socket_.shutdown( + RPCLIB_ASIO::ip::tcp::socket::shutdown_both, e); + if (e) { LOG_WARN("std::system_error during socket shutdown. " "Code: {}. Message: {}", e.code(), e.what()); } From dcf5fbb6370fe4be7c6b27181da6fba1956c9d46 Mon Sep 17 00:00:00 2001 From: Quentin Chateau Date: Mon, 18 Mar 2019 23:07:46 +0100 Subject: [PATCH 35/54] Require cmake 3.5.1 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b65cf3be..8ae2874a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.9.0) +cmake_minimum_required(VERSION 3.5.1) project(rpc VERSION 2.2.1) set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") From 55ef948f0c1c01866bb4e1c05edbdb88e23e8109 Mon Sep 17 00:00:00 2001 From: Quentin Chateau Date: Mon, 18 Mar 2019 23:35:17 +0100 Subject: [PATCH 36/54] Fix error code regression d638ae33cf0faf7de935a18ead626ff021951f16 --- include/rpc/detail/async_writer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/rpc/detail/async_writer.h b/include/rpc/detail/async_writer.h index 7c3d3ff4..508500a7 100644 --- a/include/rpc/detail/async_writer.h +++ b/include/rpc/detail/async_writer.h @@ -34,7 +34,7 @@ class async_writer : public std::enable_shared_from_this { RPCLIB_ASIO::ip::tcp::socket::shutdown_both, e); if (e) { LOG_WARN("std::system_error during socket shutdown. " - "Code: {}. Message: {}", e.code(), e.what()); + "Code: {}. Message: {}", e.value(), e.message()); } socket_.close(); }); From c707e7587268645e6d693eacf4617a99bea7bdf7 Mon Sep 17 00:00:00 2001 From: Quentin Chateau Date: Mon, 18 Mar 2019 23:26:42 +0100 Subject: [PATCH 37/54] Reproduce #187 --- tests/rpc/this_server_test.cc | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/tests/rpc/this_server_test.cc b/tests/rpc/this_server_test.cc index 995347a3..dfaf9d2c 100644 --- a/tests/rpc/this_server_test.cc +++ b/tests/rpc/this_server_test.cc @@ -1,5 +1,7 @@ #include "gtest/gtest.h" +#include + #include "rpc/client.h" #include "rpc/server.h" #include "rpc/this_server.h" @@ -24,7 +26,7 @@ class this_server_test : public testing::Test { rpc::client c2; }; -TEST_F(this_server_test, stop) { +TEST_F(this_server_test, stop_async) { s.bind("stop_server", []() { rpc::this_server().stop(); }); s.async_run(); c1.call("stop_server"); @@ -35,3 +37,21 @@ TEST_F(this_server_test, stop) { EXPECT_EQ(c2.get_connection_state(), client::connection_state::disconnected); } + +TEST_F(this_server_test, stop_sync) { + s.bind("stop_server", []() { rpc::this_server().stop(); }); + + auto handle = std::async(std::launch::async, [this]() { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + c1.call("stop_server"); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + }); + + s.run(); + handle.get(); + + EXPECT_EQ(c1.get_connection_state(), + client::connection_state::disconnected); + EXPECT_EQ(c2.get_connection_state(), + client::connection_state::disconnected); +} From eaba3606dce6e4ed608356c504fc5c0fc4ff6778 Mon Sep 17 00:00:00 2001 From: Quentin Chateau Date: Tue, 19 Mar 2019 22:43:34 +0100 Subject: [PATCH 38/54] Fix this_server stop --- lib/rpc/server.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/rpc/server.cc b/lib/rpc/server.cc index da143667..6a84b408 100644 --- a/lib/rpc/server.cc +++ b/lib/rpc/server.cc @@ -9,6 +9,7 @@ #include "asio.hpp" #include "format.h" +#include "rpc/this_server.h" #include "rpc/detail/dev_utils.h" #include "rpc/detail/log.h" #include "rpc/detail/log.h" @@ -62,7 +63,8 @@ struct server::impl { } else { LOG_ERROR("Error while accepting connection: {}", ec); } - start_accept(); + if (!this_server().stopping()) + start_accept(); // TODO: allow graceful exit [sztomi 2016-01-13] }); } @@ -77,6 +79,9 @@ struct server::impl { for (auto &session : sessions_copy) { session->close(); } + + if (this_server().stopping()) + acceptor_.cancel(); } void stop() { From 38315c08fb2344123e64419a326bbb164b92e605 Mon Sep 17 00:00:00 2001 From: Yue Tan Date: Tue, 7 May 2019 12:06:06 -0400 Subject: [PATCH 39/54] patch for gcc version < 5 std::put_time unavailable --- include/rpc/detail/log.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/include/rpc/detail/log.h b/include/rpc/detail/log.h index 0d5e51c6..09db735a 100644 --- a/include/rpc/detail/log.h +++ b/include/rpc/detail/log.h @@ -83,11 +83,19 @@ class logger { std::stringstream ss; timespec now_t = {}; clock_gettime(CLOCK_REALTIME, &now_t); +#if __GNUC__ >= 5 ss << std::put_time( std::localtime(reinterpret_cast(&now_t.tv_sec)), "%F %T") - << RPCLIB_FMT::format( +#else + char mltime[128]; + strftime(mltime, sizeof(mltime), "%c %Z", + std::localtime(reinterpret_cast(&now_t.tv_sec))); + ss << mltime +#endif + << RPCLIB_FMT::format( ".{:03}", round(static_cast(now_t.tv_nsec) / 1.0e6)); + return ss.str(); } #endif From aafe60943813f164fb01acd96182855b344e1ba7 Mon Sep 17 00:00:00 2001 From: Zoltan Dezsi Date: Sun, 29 Nov 2020 20:55:47 +0100 Subject: [PATCH 40/54] fix compile error for gcc 4.9 --- include/rpc/rpc_error.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/rpc/rpc_error.h b/include/rpc/rpc_error.h index 8f6eed6c..63cc1d85 100644 --- a/include/rpc/rpc_error.h +++ b/include/rpc/rpc_error.h @@ -4,6 +4,7 @@ #define RPC_ERROR_H_NEOOSTKY #include +#include #include "rpc/msgpack.hpp" From 10d8c85ba455a44dc53eb3bd70cabdd1fb2cb7d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20Szelei?= <240594+sztomi@users.noreply.github.com> Date: Mon, 26 Apr 2021 19:11:51 +0200 Subject: [PATCH 41/54] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index d20ad3c6..467ddb8c 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +**[rpclib is looking for maintainers](https://github.com/rpclib/rpclib/issues/273)** + # rpclib ![MIT](https://img.shields.io/badge/license-MIT-blue.svg) [![Build Status](https://travis-ci.org/rpclib/rpclib.svg?branch=master)](https://travis-ci.org/rpclib/rpclib) [![Build status](https://ci.appveyor.com/api/projects/status/9lft2tlamcox8epq?svg=true)](https://ci.appveyor.com/project/sztomi/callme) [![Coverage Status](https://img.shields.io/codecov/c/github/rpclib/rpclib/dev.svg)](https://img.shields.io/codecov/c/github/rpclib/rpclib/dev.svg) ![Coverity](https://scan.coverity.com/projects/7259/badge.svg?flat=1) [![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg?maxAge=2592000)](https://gitter.im/rpclib/Lobby) From 03cdc8fe941a7035dfc22e1c2f4a849185dcfc88 Mon Sep 17 00:00:00 2001 From: Quentin Chateau Date: Mon, 26 Apr 2021 22:45:11 +0200 Subject: [PATCH 42/54] update travis CI --- .travis.yml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 85433623..2dabe462 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: c++ -os: linux -dist: trusty +os: linux +dist: focal sudo: required matrix: @@ -15,14 +15,10 @@ matrix: env: RPCLIB_CXX_STANDARD=14 BUILD_TYPE=Release COVERAGE="OFF" before_install: - - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test - sudo apt-get update -qq install: - - sudo apt-get install -qq g++-5 - - sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-5 90 - - wget https://cmake.org/files/v3.9/cmake-3.9.2-Linux-x86_64.sh - - sudo sh cmake-3.9.2-Linux-x86_64.sh -- --skip-license --prefix=/usr + - sudo apt-get install -qq g++ cmake script: - mkdir build ; cd build From c24e0760c8bd049d183768fe195d493bf1c1c78c Mon Sep 17 00:00:00 2001 From: Quentin Chateau Date: Mon, 26 Apr 2021 23:44:54 +0200 Subject: [PATCH 43/54] Fix readme --- README.md | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/README.md b/README.md index c8559df3..f6017b82 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,6 @@ **[rpclib is looking for maintainers](https://github.com/rpclib/rpclib/issues/273)** - -# rpclib ![MIT](https://img.shields.io/badge/license-MIT-blue.svg) [![Build Status](https://travis-ci.org/Tytan/rpclib.svg?branch=master)](https://travis-ci.org/Tytan/rpclib) [![Build status](https://ci.appveyor.com/api/projects/status/hlpej63bpxks141j?svg=true)](https://ci.appveyor.com/project/Tytan/rpclib) [![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg?maxAge=2592000)](https://gitter.im/rpclib/Lobby) - -# Fork - -The original repository is at [rpclib/rpclib](https://github.com/rpclib/rpclib). Due to the lack of maintenance, I picked up the project. Currently the goal is mainly to merge pull requests submitted to the main repository. - -# rpclib +# rpclib ![MIT](https://img.shields.io/badge/license-MIT-blue.svg) [![Build Status](https://travis-ci.org/rpclib/rpclib.svg?branch=master)](https://travis-ci.org/rpclib/rpclib) [![Build status](https://ci.appveyor.com/api/projects/status/9lft2tlamcox8epq?svg=true)](https://ci.appveyor.com/project/sztomi/callme) [![Coverage Status](https://img.shields.io/codecov/c/github/rpclib/rpclib/dev.svg)](https://img.shields.io/codecov/c/github/rpclib/rpclib/dev.svg) ![Coverity](https://scan.coverity.com/projects/7259/badge.svg?flat=1) [![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg?maxAge=2592000)](https://gitter.im/rpclib/Lobby) `rpclib` is a RPC library for C++, providing both a client and server implementation. It is built using modern C++14, and as such, requires a recent compiler. Main highlights: From 7e7130221c0aeb60f41c367db8e4fd05ad3b6002 Mon Sep 17 00:00:00 2001 From: Ewout ter Hoeven Date: Tue, 27 Apr 2021 11:01:42 +0200 Subject: [PATCH 44/54] CI: Refactor AppVeyor - Updates to Visual Studio 2019 image (which runs on Windows Server 2019) - Use msbuild with the build/rpc.sln project instead of CMake --build - Restructure script into before_build, build and test_script parts - Clean up unused variables --- appveyor.yml | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index b502f4fd..0679387a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,29 +1,20 @@ -version: 1.0.{build} -os: Visual Studio 2015 -clone_folder: C:\projects\rpc -test: off +image: Visual Studio 2019 +configuration: Release branches: only: - master - dev -configuration: - - Release - -environment: - matrix: - - CMAKE_PLATFORM: "Visual Studio 14 2015" - #- CMAKE_PLATFORM: "Visual Studio 15 2017" - -install: true - -build_script: - - cd c:\projects\rpc +before_build: - git submodule init - git submodule update --init --recursive - md build - cd build - - cmake -DRPCLIB_BUILD_TESTS=ON -G "%CMAKE_PLATFORM%" .. - - cmake --build . --config %CONFIGURATION% + - cmake .. -DRPCLIB_BUILD_TESTS=ON + +build: + project: build/rpc.sln + +test_script: - .\tests\Release\rpc_test.exe From a663a1598a4b419123b2e13c0ae6a39c91dcf5b8 Mon Sep 17 00:00:00 2001 From: Quentin Chateau Date: Tue, 27 Apr 2021 22:38:55 +0200 Subject: [PATCH 45/54] cmake: bump version to 2.3.0 --- CHANGELOG.md | 20 ++++++++++++++++++++ CMakeLists.txt | 2 +- doc/pages/versions.md | 2 +- include/rpc/version.h | 4 ++-- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf99269f..c9c57a1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,25 @@ # Changelog +### 2.3.0 + +This release fixes various issues. + +*Fixes* + + * Fix compile error on gcc 4.9 + * Fix warnings in clang 7 + * Fix self-assignment + * Fix early destruction of server sessions + * Fix crashes in multithreaded environment (#175) + +*Additions* + + * Support calling `rpc::this_server().stop()` from a server procedure (#187) + * Make rpclib compatible with codebases that do not use exceptions + * Add `server::port()` to query the port used by the server + * Set `reuseaddress` option on the server + + ### 2.2.1 This release fixed a crash on Windows. diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ae2874a..8f40bdfb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.5.1) -project(rpc VERSION 2.2.1) +project(rpc VERSION 2.3.0) set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") diff --git a/doc/pages/versions.md b/doc/pages/versions.md index f2874691..b56c57bc 100644 --- a/doc/pages/versions.md +++ b/doc/pages/versions.md @@ -1,4 +1,4 @@ -You are reading the documentation of 2.2.1. +You are reading the documentation of 2.3.0. If, for some reason you need the documentation of older versions, you can download them from this page. * [1.0.0](/archive/rpclib_docs_1.0.0.zip) diff --git a/include/rpc/version.h b/include/rpc/version.h index 805dec1e..47e19e92 100644 --- a/include/rpc/version.h +++ b/include/rpc/version.h @@ -6,8 +6,8 @@ namespace rpc { static constexpr unsigned VERSION_MAJOR = 2; -static constexpr unsigned VERSION_MINOR = 2; -static constexpr unsigned VERSION_PATCH = 1; +static constexpr unsigned VERSION_MINOR = 3; +static constexpr unsigned VERSION_PATCH = 0; } /* rpc */ From db5eb39b2ada15ea07e645b65156f9406aa7ff9c Mon Sep 17 00:00:00 2001 From: Admin Date: Wed, 16 Jun 2021 19:19:05 +0300 Subject: [PATCH 46/54] disable SO_REUSEADDR on windows due to it causing undefined behaviour when binding to the same existing server port --- lib/rpc/server.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/rpc/server.cc b/lib/rpc/server.cc index 6a84b408..4ee68c5d 100644 --- a/lib/rpc/server.cc +++ b/lib/rpc/server.cc @@ -32,7 +32,9 @@ struct server::impl { suppress_exceptions_(false) { auto ep = tcp::endpoint(ip::address::from_string(address), port); acceptor_.open(ep.protocol()); +#ifndef _WIN32 acceptor_.set_option(tcp::acceptor::reuse_address(true)); +#endif // !_WIN32 acceptor_.bind(ep); acceptor_.listen(); } @@ -45,7 +47,9 @@ struct server::impl { suppress_exceptions_(false) { auto ep = tcp::endpoint(tcp::v4(), port); acceptor_.open(ep.protocol()); +#ifndef _WIN32 acceptor_.set_option(tcp::acceptor::reuse_address(true)); +#endif // !_WIN32 acceptor_.bind(ep); acceptor_.listen(); } From 4bcff714cf547775bc47e5785d67b58980d0cdd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20R=C3=B6ll?= Date: Fri, 30 Jul 2021 09:13:06 +0200 Subject: [PATCH 47/54] Updated Document generation and requirements File --- doc/mkdocs.yml | 3 +- doc/pages/reference.md | 66 +++++++++++++++++++++--------------------- doc/reference.md.mako | 2 +- doc/requirements.txt | 20 ++++++++++++- 4 files changed, 55 insertions(+), 36 deletions(-) diff --git a/doc/mkdocs.yml b/doc/mkdocs.yml index 9c58a5dc..6353760f 100644 --- a/doc/mkdocs.yml +++ b/doc/mkdocs.yml @@ -1,7 +1,7 @@ docs_dir: pages site_name: rpclib -pages: +nav: - 'Home': 'index.md' - 'Guides': - 'Getting started': 'gettingstarted.md' @@ -23,6 +23,7 @@ markdown_extensions: - toc: permalink: False baselevel: 2 + toc_depth: 5 - admonition - attr_list - codehilite diff --git a/doc/pages/reference.md b/doc/pages/reference.md index 130d1da6..ae8d0ca7 100644 --- a/doc/pages/reference.md +++ b/doc/pages/reference.md @@ -40,7 +40,7 @@ Use this class to connect to msgpack-rpc servers and call their exposed function | void | [wait_all_responses](#classrpc_1_1client_1ac37437bc05b70588c079079b957eb15f)() -

rpc::client::client

+#### rpc::client::client ```cpp rpc::client::client(std::string const &addr, uint16_t port); ``` @@ -56,7 +56,7 @@ Constructs a client. When a client is constructed, it initiates a connection asynchronically. This means that it will not block while the connection is established. However, when the first call is performed, it *might* block if the connection was not already established. -

rpc::client::~client

+#### rpc::client::~client ```cpp rpc::client::~client(); ``` @@ -67,7 +67,7 @@ Destructor. During destruction, the connection to the server is gracefully closed. This means that any outstanding reads and writes are completed first. -

rpc::client::call

+#### rpc::client::call ```cpp RPCLIB_MSGPACK::object_handle rpc::client::call(std::string const &func_name, Args... args); ``` @@ -86,7 +86,7 @@ Calls a function with the given name and arguments (if any). A RPCLIB_MSGPACK::object containing the result of the function (if any). To obtain a typed value, use the msgpack API. -

rpc::client::async_call

+#### rpc::client::async_call ```cpp std::future< RPCLIB_MSGPACK::object_handle > rpc::client::async_call(std::string const &func_name, Args... args); ``` @@ -108,7 +108,7 @@ A call is performed asynchronously in the context of the client, i.e. this is no A std::future, possibly holding a future result (which is a RPCLIB_MSGPACK::object). -

rpc::client::send

+#### rpc::client::send ```cpp void rpc::client::send(std::string const &func_name, Args... args); ``` @@ -129,7 +129,7 @@ Notifications are a special kind of calls. They can be used to notify the server !!! warn This function returns immediately (possibly before the notification is written to the socket). -

rpc::client::get_timeout

+#### rpc::client::get_timeout ```cpp nonstd::optional< int64_t > rpc::client::get_timeout() const; ``` @@ -142,7 +142,7 @@ The timeout is applied to synchronous calls. If the timeout expires without rece !!! warn The timeout has no effect on async calls. For those, the preferred timeout mechanism remains using std::future. -

rpc::client::set_timeout

+#### rpc::client::set_timeout ```cpp void rpc::client::set_timeout(int64_t value); ``` @@ -150,7 +150,7 @@ void rpc::client::set_timeout(int64_t value); Sets the timeout for synchronous calls. For more information, see -

rpc::client::clear_timeout

+#### rpc::client::clear_timeout ```cpp void rpc::client::clear_timeout(); ``` @@ -158,7 +158,7 @@ void rpc::client::clear_timeout(); Clears the timeout for synchronous calls. For more information, see -

rpc::client::get_connection_state

+#### rpc::client::get_connection_state ```cpp connection_state rpc::client::get_connection_state() const; ``` @@ -166,7 +166,7 @@ connection_state rpc::client::get_connection_state() const; Returns the current connection state. -

rpc::client::wait_all_responses

+#### rpc::client::wait_all_responses ```cpp void rpc::client::wait_all_responses(); ``` @@ -194,7 +194,7 @@ This type allows clients to handle arbitrary error objects as the msgpack-rpc sp | RPCLIB_MSGPACK::object_handle & | [get_error](#classrpc_1_1rpc__error_1a88ab8f211393ae62813042a797c08663)() -

rpc::rpc_error::get_function_name

+#### rpc::rpc_error::get_function_name ```cpp std::string rpc::rpc_error::get_function_name() const; ``` @@ -202,7 +202,7 @@ std::string rpc::rpc_error::get_function_name() const; Returns the name of the function that was called on the server while the error occurred. -

rpc::rpc_error::get_error

+#### rpc::rpc_error::get_error ```cpp RPCLIB_MSGPACK::object_handle & rpc::rpc_error::get_error(); ``` @@ -239,7 +239,7 @@ The server maintains a registry of function bindings that it uses to dispatch ca | void | [close_sessions](#classrpc_1_1server_1abf6bebbbeea52451aef2126d29240094)() -

rpc::server::server

+#### rpc::server::server ```cpp rpc::server::server(uint16_t port); ``` @@ -250,7 +250,7 @@ Constructs a server that listens on the localhost on the specified port. `port` The port number to listen on. -

rpc::server::server

+#### rpc::server::server ```cpp rpc::server::server(server &&other) noexcept; ``` @@ -261,7 +261,7 @@ Move constructor. This is implemented by calling the move assignment operator. `other` The other instance to move from. -

rpc::server::server

+#### rpc::server::server ```cpp rpc::server::server(std::string const &address, uint16_t port); ``` @@ -274,7 +274,7 @@ Constructs a server that listens on the specified address on the specified port. `port` The port number to listen on. -

rpc::server::~server

+#### rpc::server::~server ```cpp rpc::server::~server(); ``` @@ -285,7 +285,7 @@ Destructor. When the server is destroyed, all ongoin sessions are closed gracefully. -

rpc::server::operator=

+#### rpc::server::operator= ```cpp server rpc::server::operator=(server &&other); ``` @@ -299,7 +299,7 @@ Move assignment operator. The result of the assignment. -

rpc::server::run

+#### rpc::server::run ```cpp void rpc::server::run(); ``` @@ -310,7 +310,7 @@ Starts the server loop. This is a blocking call. First and foremost, running the event loop causes the server to start listening on the specified port. Also, as connections are established and calls are made by clients, the server executes the calls as part of this call. This means that the handlers are executed on the thread that calls `run`. Reads and writes are initiated by this function internally as well. -

rpc::server::async_run

+#### rpc::server::async_run ```cpp void rpc::server::async_run(std::size_t worker_threads=1); ``` @@ -324,7 +324,7 @@ Starts the server loop on one or more threads. This is a non-blocking call. This function behaves similarly to `run`, except the event loop is optionally started on different threads. Effectively this sets up a worker thread pool for the server. Handlers will be executed on one of the threads. -

rpc::server::bind

+#### rpc::server::bind ```cpp void rpc::server::bind(std::string const &name, F func); ``` @@ -343,7 +343,7 @@ Binds a functor to a name so it becomes callable via RPC. This function template accepts a wide range of callables. The arguments and return types of these callables should be serializable by msgpack. `bind` effectively generates a suitable, light-weight compile-time wrapper for the functor. -

rpc::server::suppress_exceptions

+#### rpc::server::suppress_exceptions ```cpp void rpc::server::suppress_exceptions(bool suppress); ``` @@ -353,7 +353,7 @@ Sets the exception behavior in handlers. By default, handlers throwing will cras !!! warn Setting this flag only affects subsequent connections. -

rpc::server::stop

+#### rpc::server::stop ```cpp void rpc::server::stop(); ``` @@ -363,7 +363,7 @@ Stops the server. !!! warn This should not be called from worker threads. -

rpc::server::close_sessions

+#### rpc::server::close_sessions ```cpp void rpc::server::close_sessions(); ``` @@ -394,7 +394,7 @@ Encapsulates information about the currently executing handler. This is the inte | void | [clear](#classrpc_1_1this__handler__t_1a0a53e27b4d8d5b542790b218029d26f4)() -

rpc::this_handler_t::respond_error

+#### rpc::this_handler_t::respond_error ```cpp void rpc::this_handler_t::respond_error(T &&err_obj); ``` @@ -408,7 +408,7 @@ Sets an arbitrary object to be sent back as an error response to the client. `err_obj` The error object. This can be anything that is possible to encode with messagepack (even custom structures). -

rpc::this_handler_t::respond

+#### rpc::this_handler_t::respond ```cpp void rpc::this_handler_t::respond(T &&resp_obj); ``` @@ -424,7 +424,7 @@ Sets an arbitrary object to be sent back as the response to the call. !!! warn The normal return value of the function (if any) will be ignored if a special response is set. -

rpc::this_handler_t::disable_response

+#### rpc::this_handler_t::disable_response ```cpp void rpc::this_handler_t::disable_response(); ``` @@ -434,7 +434,7 @@ Instructs the server to not send a response to the client (ignoring any errors a !!! warn It is unusual to not send a response to requests, and doing so might cause problems in the client (depending on its implementation). -

rpc::this_handler_t::enable_response

+#### rpc::this_handler_t::enable_response ```cpp void rpc::this_handler_t::enable_response(); ``` @@ -442,7 +442,7 @@ void rpc::this_handler_t::enable_response(); Enables sending a response to the call. Sending the response is by default enabled. Enabling the response multiple times have no effect. -

rpc::this_handler_t::clear

+#### rpc::this_handler_t::clear ```cpp void rpc::this_handler_t::clear(); ``` @@ -470,7 +470,7 @@ Allows controlling the server instance from the currently executing handler. | void | [cancel_stop](#classrpc_1_1this__server__t_1a127035c6f2281a5a1bfadf19f4dfe451)() -

rpc::this_server_t::stop

+#### rpc::this_server_t::stop ```cpp void rpc::this_server_t::stop(); ``` @@ -478,7 +478,7 @@ void rpc::this_server_t::stop(); Gracefully stops the server. -

rpc::this_server_t::cancel_stop

+#### rpc::this_server_t::cancel_stop ```cpp void rpc::this_server_t::cancel_stop(); ``` @@ -506,7 +506,7 @@ Encapsulates information about the server session/connection this handler is run | session_id_t | [id](#classrpc_1_1this__session__t_1aada2250ec9dd3d88781ca16eb4352047)() const -

rpc::this_session_t::post_exit

+#### rpc::this_session_t::post_exit ```cpp void rpc::this_session_t::post_exit(); ``` @@ -516,7 +516,7 @@ Gracefully exits the session (i.e. ongoing writes and reads are completed; queue !!! warn Use this function if you need to close the connection from a handler. -

rpc::this_session_t::id

+#### rpc::this_session_t::id ```cpp session_id_t rpc::this_session_t::id() const; ``` @@ -545,7 +545,7 @@ This exception is thrown by the client when either the connection or a call take | const char * | [what](#classrpc_1_1timeout_1ad782f083798c650188b5927a226c3b04)() const noexcept override -

rpc::timeout::what

+#### rpc::timeout::what ```cpp const char * rpc::timeout::what() const noexcept override; ``` diff --git a/doc/reference.md.mako b/doc/reference.md.mako index 49c62b5f..07c4806d 100644 --- a/doc/reference.md.mako +++ b/doc/reference.md.mako @@ -41,7 +41,7 @@ ${"### Public functions"} % for f in c.functions: -

${c.name}::${f.name}

+${"#### "}${c.name}::${f.name} ```cpp ${opt(f.type)} ${c.name}::${f.name}${f.argsstr}; ``` diff --git a/doc/requirements.txt b/doc/requirements.txt index 2767e397..472c5dd8 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -1,4 +1,22 @@ lxml>=3.6.4 Mako>=1.0.4 -mkdocs +mkdocs>=1.0.0 pygments +xsltproc +docker + + +# Manage Docker as non-root user +https://docs.docker.com/engine/install/linux-postinstall/ + +$ sudo groupadd docker +$ sudo usermod -aG docker $USER + +# log out and in to reevaluate user groups or +$ newgrp docker + +# Verify that you can run docker commands without sudo. +$ docker run hello-world + +# If mkdocs serve is used, this is required as well +mkdocs-material From e42d85ba7bf073e61ce5ecbe9fe59988738d95a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20R=C3=B6ll?= Date: Fri, 30 Jul 2021 09:35:13 +0200 Subject: [PATCH 48/54] Use clang-format on server.cc and client.cc --- lib/rpc/client.cc | 31 ++++++++--------------- lib/rpc/server.cc | 63 ++++++++++++++++++++++------------------------- 2 files changed, 39 insertions(+), 55 deletions(-) diff --git a/lib/rpc/client.cc b/lib/rpc/client.cc index bea9df7e..6ab2c56c 100644 --- a/lib/rpc/client.cc +++ b/lib/rpc/client.cc @@ -23,7 +23,8 @@ using namespace rpc::detail; namespace rpc { -static constexpr uint32_t default_buffer_size = rpc::constants::DEFAULT_BUFFER_SIZE; +static constexpr uint32_t default_buffer_size = + rpc::constants::DEFAULT_BUFFER_SIZE; struct client::impl { impl(client *parent, std::string const &addr, uint16_t port) @@ -133,17 +134,11 @@ struct client::impl { writer_->write(std::move(item)); } - nonstd::optional get_timeout() { - return timeout_; - } + nonstd::optional get_timeout() { return timeout_; } - void set_timeout(int64_t value) { - timeout_ = value; - } + void set_timeout(int64_t value) { timeout_ = value; } - void clear_timeout() { - timeout_ = nonstd::nullopt; - } + void clear_timeout() { timeout_ = nonstd::nullopt; } using call_t = std::pair>; @@ -202,9 +197,7 @@ void client::wait_conn() { } } -int client::get_next_call_idx() { - return ++(pimpl->call_idx_); -} +int client::get_next_call_idx() { return ++(pimpl->call_idx_); } void client::post(std::shared_ptr buffer, int idx, std::string const &func_name, @@ -231,13 +224,9 @@ nonstd::optional client::get_timeout() const { return pimpl->get_timeout(); } -void client::set_timeout(int64_t value) { - pimpl->set_timeout(value); -} +void client::set_timeout(int64_t value) { pimpl->set_timeout(value); } -void client::clear_timeout() { - pimpl->clear_timeout(); -} +void client::clear_timeout() { pimpl->clear_timeout(); } void client::wait_all_responses() { for (auto &c : pimpl->ongoing_calls_) { @@ -245,7 +234,7 @@ void client::wait_all_responses() { } } -RPCLIB_NORETURN void client::throw_timeout(std::string const& func_name) { +RPCLIB_NORETURN void client::throw_timeout(std::string const &func_name) { throw rpc::timeout( RPCLIB_FMT::format("Timeout of {}ms while calling RPC function '{}'", *get_timeout(), func_name)); @@ -256,4 +245,4 @@ client::~client() { pimpl->io_thread_.join(); } -} +} // namespace rpc diff --git a/lib/rpc/server.cc b/lib/rpc/server.cc index 4ee68c5d..4f01ab1b 100644 --- a/lib/rpc/server.cc +++ b/lib/rpc/server.cc @@ -9,18 +9,16 @@ #include "asio.hpp" #include "format.h" -#include "rpc/this_server.h" #include "rpc/detail/dev_utils.h" #include "rpc/detail/log.h" -#include "rpc/detail/log.h" #include "rpc/detail/server_session.h" #include "rpc/detail/thread_group.h" +#include "rpc/this_server.h" using namespace rpc::detail; using RPCLIB_ASIO::ip::tcp; using namespace RPCLIB_ASIO; - namespace rpc { struct server::impl { @@ -30,14 +28,14 @@ struct server::impl { acceptor_(io_), socket_(io_), suppress_exceptions_(false) { - auto ep = tcp::endpoint(ip::address::from_string(address), port); - acceptor_.open(ep.protocol()); + auto ep = tcp::endpoint(ip::address::from_string(address), port); + acceptor_.open(ep.protocol()); #ifndef _WIN32 - acceptor_.set_option(tcp::acceptor::reuse_address(true)); + acceptor_.set_option(tcp::acceptor::reuse_address(true)); #endif // !_WIN32 - acceptor_.bind(ep); - acceptor_.listen(); - } + acceptor_.bind(ep); + acceptor_.listen(); + } impl(server *parent, uint16_t port) : parent_(parent), @@ -45,14 +43,14 @@ struct server::impl { acceptor_(io_), socket_(io_), suppress_exceptions_(false) { - auto ep = tcp::endpoint(tcp::v4(), port); - acceptor_.open(ep.protocol()); + auto ep = tcp::endpoint(tcp::v4(), port); + acceptor_.open(ep.protocol()); #ifndef _WIN32 - acceptor_.set_option(tcp::acceptor::reuse_address(true)); + acceptor_.set_option(tcp::acceptor::reuse_address(true)); #endif // !_WIN32 - acceptor_.bind(ep); - acceptor_.listen(); - } + acceptor_.bind(ep); + acceptor_.listen(); + } void start_accept() { acceptor_.async_accept(socket_, [this](std::error_code ec) { @@ -93,9 +91,7 @@ struct server::impl { loop_workers_.join_all(); } - unsigned short port() const { - return acceptor_.local_endpoint().port(); - } + unsigned short port() const { return acceptor_.local_endpoint().port(); } server *parent_; io_service io_; @@ -111,18 +107,17 @@ struct server::impl { RPCLIB_CREATE_LOG_CHANNEL(server) server::server(uint16_t port) - : pimpl(new server::impl(this, port)), disp_(std::make_shared()) { + : pimpl(new server::impl(this, port)), + disp_(std::make_shared()) { LOG_INFO("Created server on localhost:{}", port); pimpl->start_accept(); } -server::server(server&& other) noexcept { - *this = std::move(other); -} +server::server(server &&other) noexcept { *this = std::move(other); } server::server(std::string const &address, uint16_t port) : pimpl(new server::impl(this, address, port)), - disp_(std::make_shared()) { + disp_(std::make_shared()) { LOG_INFO("Created server on address {}:{}", address, port); pimpl->start_accept(); } @@ -133,7 +128,7 @@ server::~server() { } } -server& server::operator=(server &&other) { +server &server::operator=(server &&other) { if (this != &other) { pimpl = std::move(other.pimpl); other.pimpl = nullptr; @@ -165,15 +160,15 @@ unsigned short server::port() const { return pimpl->port(); } void server::close_sessions() { pimpl->close_sessions(); } void server::close_session(std::shared_ptr const &s) { - std::unique_lock lock(pimpl->sessions_mutex_); - auto it = std::find(begin(pimpl->sessions_), end(pimpl->sessions_), s); - std::shared_ptr session; - if (it != end(pimpl->sessions_)) { - session = *it; - pimpl->sessions_.erase(it); - } - lock.unlock(); - // session shared pointer is released outside of the mutex + std::unique_lock lock(pimpl->sessions_mutex_); + auto it = std::find(begin(pimpl->sessions_), end(pimpl->sessions_), s); + std::shared_ptr session; + if (it != end(pimpl->sessions_)) { + session = *it; + pimpl->sessions_.erase(it); + } + lock.unlock(); + // session shared pointer is released outside of the mutex } -} /* rpc */ +} // namespace rpc From 9cdcd2d065c5680cfcf3ff6597e88743914f6a49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20R=C3=B6ll?= Date: Tue, 3 Aug 2021 09:48:19 +0200 Subject: [PATCH 49/54] Issue #267: Enable Logging of connected clients ip address and port on log level info --- lib/rpc/server.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/rpc/server.cc b/lib/rpc/server.cc index 4f01ab1b..a591ab32 100644 --- a/lib/rpc/server.cc +++ b/lib/rpc/server.cc @@ -56,6 +56,8 @@ struct server::impl { acceptor_.async_accept(socket_, [this](std::error_code ec) { if (!ec) { LOG_INFO("Accepted connection."); + auto ep = socket_.remote_endpoint(); + LOG_INFO("Connected client: {}:{}", ep.address(), ep.port()); auto s = std::make_shared( parent_, &io_, std::move(socket_), parent_->disp_, suppress_exceptions_); From 0560232cd995d94dce2df6ebeeabcd1ddbcfdf14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20R=C3=B6ll?= Date: Thu, 5 Aug 2021 09:21:00 +0200 Subject: [PATCH 50/54] Issue #267: Merge accepted connection and client info log message --- lib/rpc/server.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/rpc/server.cc b/lib/rpc/server.cc index a591ab32..1565b2b4 100644 --- a/lib/rpc/server.cc +++ b/lib/rpc/server.cc @@ -55,9 +55,9 @@ struct server::impl { void start_accept() { acceptor_.async_accept(socket_, [this](std::error_code ec) { if (!ec) { - LOG_INFO("Accepted connection."); auto ep = socket_.remote_endpoint(); - LOG_INFO("Connected client: {}:{}", ep.address(), ep.port()); + LOG_INFO("Accepted connection from {}:{}", ep.address(), + ep.port()); auto s = std::make_shared( parent_, &io_, std::move(socket_), parent_->disp_, suppress_exceptions_); From 9f5269cf5e3f8eb586c1471b19261319aac9f56c Mon Sep 17 00:00:00 2001 From: Brandon Ros Date: Mon, 11 Oct 2021 21:53:21 -0400 Subject: [PATCH 51/54] link against windows winsock libraries --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f40bdfb..721b0931 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -167,6 +167,9 @@ if(RPCLIB_COMPILE_DEFINITIONS) endif() target_link_libraries(${PROJECT_NAME} ${RPCLIB_DEP_LIBRARIES}) +if (WIN32) + target_link_libraries(${PROJECT_NAME} wsock32 ws2_32) +endif() target_include_directories( ${PROJECT_NAME} PUBLIC $ From 4b9ea2f5680ebfdec627cdf097613e4963b4d64e Mon Sep 17 00:00:00 2001 From: jaafari <36949083+jaafari@users.noreply.github.com> Date: Sat, 14 May 2022 10:20:36 +0430 Subject: [PATCH 52/54] add unbind to enable runtime binding/unbinding adding unbind function to remove a binding in runtime (if wanted) and names function to list all binded functors (usable for debugging etc.) --- include/rpc/dispatcher.h | 13 +++++++++++++ include/rpc/server.h | 18 ++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/include/rpc/dispatcher.h b/include/rpc/dispatcher.h index 8044d4cb..5e298854 100644 --- a/include/rpc/dispatcher.h +++ b/include/rpc/dispatcher.h @@ -60,6 +60,19 @@ class dispatcher { detail::tags::nonvoid_result const &, detail::tags::nonzero_arg const &); + //! \brief removes a functor with given name from callable functors. + void remove(std::string const &name) { + funcs_.erase(name); + } + + //! \brief returns a list name of all functors binded + std::vector names() { + std::vector names; + for(auto it = funcs_.begin(); it != funcs_.end(); ++it) + names.push_back(it->first); + return names; + } + //! @} //! \brief Processes a message that contains a call according to diff --git a/include/rpc/server.h b/include/rpc/server.h index 60c6b86a..b5628042 100644 --- a/include/rpc/server.h +++ b/include/rpc/server.h @@ -93,6 +93,24 @@ class server { disp_->bind(name, func); } + //! \brief Unbinds a functor binded to a name. + //! + //! This function removes already binded function from RPC Ccallable functions + //! + //! \param name The name of the functor. + void unbind(std::string const &name) { + disp_->remove(name); + } + + //! \brief Returns all binded names + //! + //! This function returns a list of all names which functors are binded to + //! + //! \param name The name of the functor. + std::vector names() { + return disp_->names(); + } + //! \brief Sets the exception behavior in handlers. By default, //! handlers throwing will crash the server. If suppressing is on, //! the server will try to gather textual data and return it to From 391df59975cd287870b5c3ecb107f85877ea86e4 Mon Sep 17 00:00:00 2001 From: jaafari <36949083+jaafari@users.noreply.github.com> Date: Sun, 15 May 2022 11:01:07 +0430 Subject: [PATCH 53/54] better naming, unbind instead of remove. --- include/rpc/dispatcher.h | 8 ++++---- include/rpc/server.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/rpc/dispatcher.h b/include/rpc/dispatcher.h index 5e298854..18dca30f 100644 --- a/include/rpc/dispatcher.h +++ b/include/rpc/dispatcher.h @@ -60,13 +60,13 @@ class dispatcher { detail::tags::nonvoid_result const &, detail::tags::nonzero_arg const &); - //! \brief removes a functor with given name from callable functors. - void remove(std::string const &name) { + //! \brief Unbind a functor with a given name from callable functors. + void unbind(std::string const &name) { funcs_.erase(name); } - //! \brief returns a list name of all functors binded - std::vector names() { + //! \brief returns a list of all names which functors are binded to + std::vector names() const { std::vector names; for(auto it = funcs_.begin(); it != funcs_.end(); ++it) names.push_back(it->first); diff --git a/include/rpc/server.h b/include/rpc/server.h index b5628042..baeb9f7c 100644 --- a/include/rpc/server.h +++ b/include/rpc/server.h @@ -99,7 +99,7 @@ class server { //! //! \param name The name of the functor. void unbind(std::string const &name) { - disp_->remove(name); + disp_->unbind(name); } //! \brief Returns all binded names @@ -107,7 +107,7 @@ class server { //! This function returns a list of all names which functors are binded to //! //! \param name The name of the functor. - std::vector names() { + std::vector names() const { return disp_->names(); } From 463887f16ffcc4cf9ee0421bf25d49165b5e36f9 Mon Sep 17 00:00:00 2001 From: Quentin Chateau Date: Tue, 22 Nov 2022 21:53:58 +0100 Subject: [PATCH 54/54] Update readme --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f6017b82..9f008715 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,12 @@ +# rpclib ![MIT](https://img.shields.io/badge/license-MIT-blue.svg) [![Build Status](https://travis-ci.org/rpclib/rpclib.svg?branch=master)](https://travis-ci.org/rpclib/rpclib) [![Build status](https://ci.appveyor.com/api/projects/status/9lft2tlamcox8epq?svg=true)](https://ci.appveyor.com/project/sztomi/callme) [![Coverage Status](https://img.shields.io/codecov/c/github/rpclib/rpclib/dev.svg)](https://img.shields.io/codecov/c/github/rpclib/rpclib/dev.svg) ![Coverity](https://scan.coverity.com/projects/7259/badge.svg?flat=1) [![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg?maxAge=2592000)](https://gitter.im/rpclib/Lobby) + +## Status + **[rpclib is looking for maintainers](https://github.com/rpclib/rpclib/issues/273)** -# rpclib ![MIT](https://img.shields.io/badge/license-MIT-blue.svg) [![Build Status](https://travis-ci.org/rpclib/rpclib.svg?branch=master)](https://travis-ci.org/rpclib/rpclib) [![Build status](https://ci.appveyor.com/api/projects/status/9lft2tlamcox8epq?svg=true)](https://ci.appveyor.com/project/sztomi/callme) [![Coverage Status](https://img.shields.io/codecov/c/github/rpclib/rpclib/dev.svg)](https://img.shields.io/codecov/c/github/rpclib/rpclib/dev.svg) ![Coverity](https://scan.coverity.com/projects/7259/badge.svg?flat=1) [![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg?maxAge=2592000)](https://gitter.im/rpclib/Lobby) +If you're looking for a similar library with support for JSON-RPC and async operations, check out **[packio](https://github.com/qchateau/packio)**. + +## Overview `rpclib` is a RPC library for C++, providing both a client and server implementation. It is built using modern C++14, and as such, requires a recent compiler. Main highlights: