feat update rpc_core
This commit is contained in:
parent
b412e7e11c
commit
a3ba7c6045
@ -1,5 +0,0 @@
|
|||||||
Language: Cpp
|
|
||||||
BasedOnStyle: Google
|
|
||||||
ColumnLimit: 150
|
|
||||||
AllowShortFunctionsOnASingleLine: Empty
|
|
||||||
AllowShortLambdasOnASingleLine: Empty
|
|
29
3party/rpc_core/.github/workflows/build.yml
vendored
29
3party/rpc_core/.github/workflows/build.yml
vendored
@ -1,29 +0,0 @@
|
|||||||
name: build
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
paths-ignore:
|
|
||||||
- '**.md'
|
|
||||||
pull_request:
|
|
||||||
paths-ignore:
|
|
||||||
- '**.md'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
Linux:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: CMake
|
|
||||||
run: |
|
|
||||||
mkdir build && cd build
|
|
||||||
cmake -DCMAKE_BUILD_TYPE=Debug -DRPC_CORE_TEST_PLUGIN=ON ..
|
|
||||||
|
|
||||||
- name: Init thirdparty
|
|
||||||
run: cd build && make rpc_core_test_init
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: cd build && make -j2
|
|
||||||
|
|
||||||
- name: Run
|
|
||||||
run: cd build && ./rpc_core_test
|
|
14
3party/rpc_core/.gitignore
vendored
14
3party/rpc_core/.gitignore
vendored
@ -1,14 +0,0 @@
|
|||||||
build/
|
|
||||||
|
|
||||||
# clion
|
|
||||||
.idea/
|
|
||||||
cmake-build-*/
|
|
||||||
|
|
||||||
# qt creator
|
|
||||||
CMakeLists.txt.user
|
|
||||||
|
|
||||||
# vscode
|
|
||||||
.vscode/
|
|
||||||
|
|
||||||
# thirdparty
|
|
||||||
/thirdparty/
|
|
@ -2,6 +2,11 @@ cmake_minimum_required(VERSION 3.5)
|
|||||||
|
|
||||||
project(rpc_core CXX)
|
project(rpc_core CXX)
|
||||||
|
|
||||||
|
# config
|
||||||
|
option(RPC_CORE_SERIALIZE_USE_CUSTOM "" "")
|
||||||
|
option(RPC_CORE_SERIALIZE_USE_NLOHMANN_JSON "" ON)
|
||||||
|
|
||||||
|
# test
|
||||||
option(RPC_CORE_BUILD_TEST "" OFF)
|
option(RPC_CORE_BUILD_TEST "" OFF)
|
||||||
option(RPC_CORE_TEST_PLUGIN "" OFF)
|
option(RPC_CORE_TEST_PLUGIN "" OFF)
|
||||||
option(RPC_CORE_TEST_LINK_PTHREAD "" OFF)
|
option(RPC_CORE_TEST_LINK_PTHREAD "" OFF)
|
||||||
@ -16,15 +21,26 @@ add_compile_options(-Wall -Wunused-parameter)
|
|||||||
add_library(${PROJECT_NAME} INTERFACE)
|
add_library(${PROJECT_NAME} INTERFACE)
|
||||||
target_include_directories(${PROJECT_NAME} INTERFACE include)
|
target_include_directories(${PROJECT_NAME} INTERFACE include)
|
||||||
|
|
||||||
|
if(RPC_CORE_SERIALIZE_USE_CUSTOM)
|
||||||
|
target_compile_definitions(
|
||||||
|
${PROJECT_NAME}
|
||||||
|
INTERFACE -DRPC_CORE_SERIALIZE_USE_CUSTOM="${RPC_CORE_SERIALIZE_USE_CUSTOM}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(RPC_CORE_SERIALIZE_USE_NLOHMANN_JSON)
|
||||||
|
target_compile_definitions(${PROJECT_NAME}
|
||||||
|
INTERFACE -DRPC_CORE_SERIALIZE_USE_NLOHMANN_JSON)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(RPC_CORE_BUILD_TEST)
|
if(RPC_CORE_BUILD_TEST)
|
||||||
set(EXAMPLE_COMPILE_DEFINE
|
set(EXAMPLE_COMPILE_DEFINE ANDROID_STANDALONE RPC_CORE_LOG_SHOW_DEBUG
|
||||||
ANDROID_STANDALONE
|
|
||||||
RPC_CORE_LOG_SHOW_DEBUG
|
|
||||||
# RPC_CORE_LOG_SHOW_VERBOSE
|
# RPC_CORE_LOG_SHOW_VERBOSE
|
||||||
)
|
)
|
||||||
|
|
||||||
set(TARGET_NAME ${PROJECT_NAME}_test)
|
set(TARGET_NAME ${PROJECT_NAME}_test)
|
||||||
file(GLOB SRCS test/main.cpp test/test_rpc.cpp test/test_serialize.cpp test/test_data_packer.cpp)
|
file(GLOB SRCS test/main.cpp test/test_rpc.cpp test/test_serialize.cpp
|
||||||
|
test/test_data_packer.cpp)
|
||||||
add_executable(${TARGET_NAME})
|
add_executable(${TARGET_NAME})
|
||||||
if(RPC_CORE_TEST_LINK_PTHREAD)
|
if(RPC_CORE_TEST_LINK_PTHREAD)
|
||||||
# some linux platform need link -pthread for std::future api
|
# some linux platform need link -pthread for std::future api
|
||||||
@ -36,19 +52,23 @@ if (RPC_CORE_BUILD_TEST)
|
|||||||
if(RPC_CORE_TEST_PLUGIN)
|
if(RPC_CORE_TEST_PLUGIN)
|
||||||
list(APPEND SRCS test/test_plugin.cpp)
|
list(APPEND SRCS test/test_plugin.cpp)
|
||||||
target_compile_definitions(${TARGET_NAME} PRIVATE "RPC_CORE_TEST_PLUGIN")
|
target_compile_definitions(${TARGET_NAME} PRIVATE "RPC_CORE_TEST_PLUGIN")
|
||||||
add_custom_target(${TARGET_NAME}_init
|
add_custom_target(
|
||||||
|
${TARGET_NAME}_init
|
||||||
# clear dir
|
# clear dir
|
||||||
COMMAND rm -rf ${CMAKE_CURRENT_LIST_DIR}/thirdparty
|
COMMAND rm -rf ${CMAKE_CURRENT_LIST_DIR}/thirdparty
|
||||||
# json
|
# json
|
||||||
COMMAND mkdir -p ${CMAKE_CURRENT_LIST_DIR}/thirdparty/nlohmann
|
COMMAND mkdir -p ${CMAKE_CURRENT_LIST_DIR}/thirdparty/nlohmann
|
||||||
COMMAND curl -L -o ${CMAKE_CURRENT_LIST_DIR}/thirdparty/nlohmann/json.hpp https://github.com/nlohmann/json/releases/download/v3.11.2/json.hpp
|
COMMAND
|
||||||
|
curl -L -o ${CMAKE_CURRENT_LIST_DIR}/thirdparty/nlohmann/json.hpp
|
||||||
|
https://github.com/nlohmann/json/releases/download/v3.11.2/json.hpp
|
||||||
# flatbuffers
|
# flatbuffers
|
||||||
COMMAND git clone https://github.com/google/flatbuffers.git --depth=1 --branch=v23.1.21 ${CMAKE_CURRENT_LIST_DIR}/thirdparty/flatbuffers
|
COMMAND git clone https://github.com/google/flatbuffers.git --depth=1
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
|
--branch=v23.1.21 ${CMAKE_CURRENT_LIST_DIR}/thirdparty/flatbuffers
|
||||||
)
|
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})
|
||||||
|
|
||||||
target_include_directories(${TARGET_NAME} PRIVATE thirdparty)
|
target_include_directories(${TARGET_NAME} PRIVATE thirdparty)
|
||||||
target_include_directories(${TARGET_NAME} PRIVATE thirdparty/flatbuffers/include)
|
target_include_directories(${TARGET_NAME}
|
||||||
|
PRIVATE thirdparty/flatbuffers/include)
|
||||||
endif()
|
endif()
|
||||||
target_sources(${TARGET_NAME} PRIVATE ${SRCS})
|
target_sources(${TARGET_NAME} PRIVATE ${SRCS})
|
||||||
endif()
|
endif()
|
||||||
|
21
3party/rpc_core/LICENSE
Normal file
21
3party/rpc_core/LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2023-2024 liushuai
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
@ -1,6 +1,7 @@
|
|||||||
# rpc_core
|
# rpc_core
|
||||||
|
|
||||||
[![Build Status](https://github.com/shuai132/rpc_core/workflows/build/badge.svg)](https://github.com/shuai132/rpc_core/actions?workflow=build)
|
[![Build Status](https://github.com/shuai132/rpc_core/workflows/cpp/badge.svg)](https://github.com/shuai132/rpc_core/actions?workflow=cpp)
|
||||||
|
[![Build Status](https://github.com/shuai132/rpc_core/workflows/rust/badge.svg)](https://github.com/shuai132/rpc_core/actions?workflow=rust)
|
||||||
|
|
||||||
a tiny c++11 rpc library, supports all platforms (macOS, Linux, Windows, iOS, Android, etc.) and most microchips (
|
a tiny c++11 rpc library, supports all platforms (macOS, Linux, Windows, iOS, Android, etc.) and most microchips (
|
||||||
Arduino, STM32, ESP32/ESP8266, etc.)
|
Arduino, STM32, ESP32/ESP8266, etc.)
|
||||||
@ -30,6 +31,14 @@ For TCP-based implementations: [asio_net](https://github.com/shuai132/asio_net)
|
|||||||
* Timeout and Retry API
|
* Timeout and Retry API
|
||||||
* Support `std::future` interface
|
* Support `std::future` interface
|
||||||
|
|
||||||
|
## Language supports
|
||||||
|
|
||||||
|
* C++
|
||||||
|
- [asio_net](https://github.com/shuai132/asio_net): based on [asio](https://think-async.com/Asio/#)
|
||||||
|
|
||||||
|
* Rust
|
||||||
|
- [./rust](./rust): based on [tokio](https://github.com/tokio-rs/tokio)
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
* C++11
|
* C++11
|
||||||
@ -139,6 +148,10 @@ json: `{"id":1,"age":18,"name":"test"}`
|
|||||||
* [json.hpp](include/rpc_core/plugin/json.hpp)
|
* [json.hpp](include/rpc_core/plugin/json.hpp)
|
||||||
A flexible way to use `nlohmann/json`
|
A flexible way to use `nlohmann/json`
|
||||||
|
|
||||||
|
# License
|
||||||
|
|
||||||
|
This project is licensed under the [MIT license](LICENSE).
|
||||||
|
|
||||||
## Links
|
## Links
|
||||||
|
|
||||||
* Implementation based on asio: [asio_net](https://github.com/shuai132/asio_net)
|
* Implementation based on asio: [asio_net](https://github.com/shuai132/asio_net)
|
||||||
|
@ -43,10 +43,18 @@ struct default_connection : connection {
|
|||||||
* Loopback connection for testing
|
* Loopback connection for testing
|
||||||
*/
|
*/
|
||||||
struct loopback_connection : public connection {
|
struct loopback_connection : public connection {
|
||||||
loopback_connection() {
|
static std::pair<std::shared_ptr<connection>, std::shared_ptr<connection>> create() {
|
||||||
send_package_impl = [this](std::string payload) {
|
auto c1 = std::make_shared<connection>();
|
||||||
on_recv_package(std::move(payload));
|
auto c1_weak = std::weak_ptr<connection>(c1);
|
||||||
|
auto c2 = std::make_shared<connection>();
|
||||||
|
auto c2_weak = std::weak_ptr<connection>(c2);
|
||||||
|
c1->send_package_impl = [c2_weak](std::string package) {
|
||||||
|
c2_weak.lock()->on_recv_package(std::move(package));
|
||||||
};
|
};
|
||||||
|
c2->send_package_impl = [c1_weak](std::string package) {
|
||||||
|
c1_weak.lock()->on_recv_package(std::move(package));
|
||||||
|
};
|
||||||
|
return std::make_pair(c1, c2);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
namespace rpc_core {
|
namespace rpc_core {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
class msg_dispatcher : noncopyable {
|
class msg_dispatcher : public std::enable_shared_from_this<msg_dispatcher>, noncopyable {
|
||||||
public:
|
public:
|
||||||
using cmd_handle = std::function<std::pair<bool, msg_wrapper>(msg_wrapper)>;
|
using cmd_handle = std::function<std::pair<bool, msg_wrapper>(msg_wrapper)>;
|
||||||
using rsp_handle = std::function<bool(msg_wrapper)>;
|
using rsp_handle = std::function<bool(msg_wrapper)>;
|
||||||
@ -21,17 +21,20 @@ class msg_dispatcher : noncopyable {
|
|||||||
using timer_impl = std::function<void(uint32_t ms, timeout_cb)>;
|
using timer_impl = std::function<void(uint32_t ms, timeout_cb)>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit msg_dispatcher(std::shared_ptr<connection> conn) : conn_(std::move(conn)) {
|
explicit msg_dispatcher(std::shared_ptr<connection> conn) : conn_(std::move(conn)) {}
|
||||||
auto alive = std::weak_ptr<void>(is_alive_);
|
|
||||||
conn_->on_recv_package = ([this, RPC_CORE_MOVE_LAMBDA(alive)](const std::string& payload) {
|
void init() {
|
||||||
if (alive.expired()) {
|
auto self = std::weak_ptr<msg_dispatcher>(shared_from_this());
|
||||||
|
conn_->on_recv_package = ([RPC_CORE_MOVE_LAMBDA(self)](const std::string& payload) {
|
||||||
|
auto self_lock = self.lock();
|
||||||
|
if (!self_lock) {
|
||||||
RPC_CORE_LOGD("msg_dispatcher expired");
|
RPC_CORE_LOGD("msg_dispatcher expired");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bool success;
|
bool success;
|
||||||
auto msg = coder::deserialize(payload, success);
|
auto msg = coder::deserialize(payload, success);
|
||||||
if (success) {
|
if (success) {
|
||||||
this->dispatch(std::move(msg));
|
self_lock->dispatch(std::move(msg));
|
||||||
} else {
|
} else {
|
||||||
RPC_CORE_LOGE("payload deserialize error");
|
RPC_CORE_LOGE("payload deserialize error");
|
||||||
}
|
}
|
||||||
@ -70,21 +73,18 @@ class msg_dispatcher : noncopyable {
|
|||||||
}
|
}
|
||||||
const auto& fn = it->second;
|
const auto& fn = it->second;
|
||||||
const bool need_rsp = msg.type & msg_wrapper::need_rsp;
|
const bool need_rsp = msg.type & msg_wrapper::need_rsp;
|
||||||
auto resp = fn(msg);
|
auto resp = fn(std::move(msg));
|
||||||
if (need_rsp && resp.first) {
|
if (need_rsp && resp.first) {
|
||||||
RPC_CORE_LOGD("=> seq:%u type:rsp", msg.seq);
|
RPC_CORE_LOGD("=> seq:%u type:rsp", resp.second.seq);
|
||||||
conn_->send_package_impl(coder::serialize(resp.second));
|
conn_->send_package_impl(coder::serialize(resp.second));
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case msg_wrapper::response: {
|
case msg_wrapper::response: {
|
||||||
// pong or response
|
// pong or response
|
||||||
const bool isPong = msg.type & msg_wrapper::pong;
|
|
||||||
const auto handleMap = isPong ? &pong_handle_map_ : &rsp_handle_map_;
|
|
||||||
|
|
||||||
RPC_CORE_LOGD("<= seq:%u type:%s", msg.seq, (msg.type & detail::msg_wrapper::msg_type::pong) ? "pong" : "rsp");
|
RPC_CORE_LOGD("<= seq:%u type:%s", msg.seq, (msg.type & detail::msg_wrapper::msg_type::pong) ? "pong" : "rsp");
|
||||||
auto it = handleMap->find(msg.seq);
|
auto it = rsp_handle_map_.find(msg.seq);
|
||||||
if (it == handleMap->cend()) {
|
if (it == rsp_handle_map_.cend()) {
|
||||||
RPC_CORE_LOGD("no rsp for seq:%u", msg.seq);
|
RPC_CORE_LOGD("no rsp for seq:%u", msg.seq);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -94,11 +94,11 @@ class msg_dispatcher : noncopyable {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (cb(std::move(msg))) {
|
if (cb(std::move(msg))) {
|
||||||
handleMap->erase(it);
|
RPC_CORE_LOGV("rsp_handle_map_.size=%zu", rsp_handle_map_.size());
|
||||||
RPC_CORE_LOGV("handleMap->size=%zu", handleMap->size());
|
|
||||||
} else {
|
} else {
|
||||||
RPC_CORE_LOGE("may deserialize error");
|
RPC_CORE_LOGE("may deserialize error");
|
||||||
}
|
}
|
||||||
|
rsp_handle_map_.erase(it);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -122,31 +122,30 @@ class msg_dispatcher : noncopyable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void subscribe_rsp(seq_type seq, rsp_handle handle, RPC_CORE_MOVE_PARAM(timeout_cb) timeout_cb, uint32_t timeout_ms, bool is_ping) {
|
void subscribe_rsp(seq_type seq, rsp_handle handle, RPC_CORE_MOVE_PARAM(timeout_cb) timeout_cb, uint32_t timeout_ms) {
|
||||||
RPC_CORE_LOGD("subscribe_rsp seq:%u", seq);
|
RPC_CORE_LOGD("subscribe_rsp seq:%u", seq);
|
||||||
if (handle == nullptr) return;
|
if (handle == nullptr) return;
|
||||||
const auto handleMap = is_ping ? &pong_handle_map_ : &rsp_handle_map_;
|
|
||||||
|
|
||||||
(*handleMap)[seq] = std::move(handle);
|
|
||||||
|
|
||||||
if (timer_impl_ == nullptr) {
|
if (timer_impl_ == nullptr) {
|
||||||
RPC_CORE_LOGW("no timeout will cause memory leak!");
|
RPC_CORE_LOGW("no timeout will cause memory leak!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto alive = std::weak_ptr<void>(is_alive_);
|
rsp_handle_map_[seq] = std::move(handle);
|
||||||
timer_impl_(timeout_ms, [handleMap, seq, RPC_CORE_MOVE_LAMBDA(timeout_cb), RPC_CORE_MOVE_LAMBDA(alive)] {
|
auto self = std::weak_ptr<msg_dispatcher>(shared_from_this());
|
||||||
if (alive.expired()) {
|
timer_impl_(timeout_ms, [RPC_CORE_MOVE_LAMBDA(self), seq, RPC_CORE_MOVE_LAMBDA(timeout_cb)] {
|
||||||
|
auto self_lock = self.lock();
|
||||||
|
if (!self_lock) {
|
||||||
RPC_CORE_LOGD("seq:%u timeout after destroy", seq);
|
RPC_CORE_LOGD("seq:%u timeout after destroy", seq);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto it = handleMap->find(seq);
|
auto it = self_lock->rsp_handle_map_.find(seq);
|
||||||
if (it != handleMap->cend()) {
|
if (it != self_lock->rsp_handle_map_.cend()) {
|
||||||
if (timeout_cb) {
|
if (timeout_cb) {
|
||||||
timeout_cb();
|
timeout_cb();
|
||||||
}
|
}
|
||||||
handleMap->erase(seq);
|
self_lock->rsp_handle_map_.erase(seq);
|
||||||
RPC_CORE_LOGV("Timeout seq=%d, handleMap.size=%zu", seq, handleMap->size());
|
RPC_CORE_LOGV("Timeout seq=%d, rsp_handle_map_.size=%zu", seq, this->rsp_handle_map_.size());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -159,9 +158,7 @@ class msg_dispatcher : noncopyable {
|
|||||||
std::shared_ptr<connection> conn_;
|
std::shared_ptr<connection> conn_;
|
||||||
std::map<cmd_type, cmd_handle> cmd_handle_map_;
|
std::map<cmd_type, cmd_handle> cmd_handle_map_;
|
||||||
std::map<seq_type, rsp_handle> rsp_handle_map_;
|
std::map<seq_type, rsp_handle> rsp_handle_map_;
|
||||||
std::map<seq_type, rsp_handle> pong_handle_map_;
|
|
||||||
timer_impl timer_impl_;
|
timer_impl timer_impl_;
|
||||||
std::shared_ptr<void> is_alive_ = std::make_shared<uint8_t>();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
@ -25,7 +25,7 @@ struct msg_wrapper : copyable { // NOLINT
|
|||||||
cmd_type cmd;
|
cmd_type cmd;
|
||||||
msg_type type;
|
msg_type type;
|
||||||
std::string data;
|
std::string data;
|
||||||
std::string* request_payload = nullptr;
|
std::string const* request_payload = nullptr;
|
||||||
|
|
||||||
std::string dump() const {
|
std::string dump() const {
|
||||||
char tmp[100];
|
char tmp[100];
|
||||||
|
@ -29,7 +29,7 @@ class request : detail::noncopyable, public std::enable_shared_from_this<request
|
|||||||
struct rpc_proto {
|
struct rpc_proto {
|
||||||
virtual ~rpc_proto() = default;
|
virtual ~rpc_proto() = default;
|
||||||
virtual seq_type make_seq() = 0;
|
virtual seq_type make_seq() = 0;
|
||||||
virtual void send_request(const request_s&) = 0;
|
virtual void send_request(request const*) = 0;
|
||||||
virtual bool is_ready() const = 0;
|
virtual bool is_ready() const = 0;
|
||||||
};
|
};
|
||||||
using send_proto_s = std::shared_ptr<rpc_proto>;
|
using send_proto_s = std::shared_ptr<rpc_proto>;
|
||||||
@ -80,7 +80,7 @@ class request : detail::noncopyable, public std::enable_shared_from_this<request
|
|||||||
auto r = std::shared_ptr<request>(new request(std::forward<Args>(args)...), [](request* p) {
|
auto r = std::shared_ptr<request>(new request(std::forward<Args>(args)...), [](request* p) {
|
||||||
delete p;
|
delete p;
|
||||||
});
|
});
|
||||||
r->init();
|
r->timeout(nullptr);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,7 +189,7 @@ class request : detail::noncopyable, public std::enable_shared_from_this<request
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
seq_ = r->make_seq();
|
seq_ = r->make_seq();
|
||||||
r->send_request(self_keeper_);
|
r->send_request(this);
|
||||||
if (!need_rsp_) {
|
if (!need_rsp_) {
|
||||||
on_finish(finally_t::no_need_rsp);
|
on_finish(finally_t::no_need_rsp);
|
||||||
}
|
}
|
||||||
@ -268,7 +268,7 @@ class request : detail::noncopyable, public std::enable_shared_from_this<request
|
|||||||
return rpc_;
|
return rpc_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool canceled() const {
|
bool is_canceled() const {
|
||||||
return canceled_;
|
return canceled_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,10 +301,6 @@ class request : detail::noncopyable, public std::enable_shared_from_this<request
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init() {
|
|
||||||
timeout(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_finish(finally_t type) {
|
void on_finish(finally_t type) {
|
||||||
if (!waiting_rsp_) return;
|
if (!waiting_rsp_) return;
|
||||||
waiting_rsp_ = false;
|
waiting_rsp_ = false;
|
||||||
|
@ -28,7 +28,9 @@ class rpc : detail::noncopyable, public std::enable_shared_from_this<rpc>, publi
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit rpc(std::shared_ptr<connection> conn = std::make_shared<default_connection>()) : conn_(conn), dispatcher_(std::move(conn)) {
|
explicit rpc(std::shared_ptr<connection> conn = std::make_shared<default_connection>())
|
||||||
|
: conn_(conn), dispatcher_(std::make_shared<detail::msg_dispatcher>(std::move(conn))) {
|
||||||
|
dispatcher_->init();
|
||||||
RPC_CORE_LOGD("rpc: %p", this);
|
RPC_CORE_LOGD("rpc: %p", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +44,7 @@ class rpc : detail::noncopyable, public std::enable_shared_from_this<rpc>, publi
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void set_timer(detail::msg_dispatcher::timer_impl timer_impl) {
|
inline void set_timer(detail::msg_dispatcher::timer_impl timer_impl) {
|
||||||
dispatcher_.set_timer_impl(std::move(timer_impl));
|
dispatcher_->set_timer_impl(std::move(timer_impl));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void set_ready(bool ready) {
|
inline void set_ready(bool ready) {
|
||||||
@ -54,11 +56,11 @@ class rpc : detail::noncopyable, public std::enable_shared_from_this<rpc>, publi
|
|||||||
void subscribe(const cmd_type& cmd, RPC_CORE_MOVE_PARAM(F) handle) {
|
void subscribe(const cmd_type& cmd, RPC_CORE_MOVE_PARAM(F) handle) {
|
||||||
constexpr bool F_ReturnIsEmpty = std::is_void<typename detail::callable_traits<F>::return_type>::value;
|
constexpr bool F_ReturnIsEmpty = std::is_void<typename detail::callable_traits<F>::return_type>::value;
|
||||||
constexpr bool F_ParamIsEmpty = detail::callable_traits<F>::argc == 0;
|
constexpr bool F_ParamIsEmpty = detail::callable_traits<F>::argc == 0;
|
||||||
subscribe_helper<F, F_ReturnIsEmpty, F_ParamIsEmpty>()(cmd, std::move(handle), &dispatcher_);
|
subscribe_helper<F, F_ReturnIsEmpty, F_ParamIsEmpty>()(cmd, std::move(handle), dispatcher_.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void unsubscribe(const cmd_type& cmd) {
|
inline void unsubscribe(const cmd_type& cmd) {
|
||||||
dispatcher_.unsubscribe_cmd(cmd);
|
dispatcher_->unsubscribe_cmd(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -79,9 +81,9 @@ class rpc : detail::noncopyable, public std::enable_shared_from_this<rpc>, publi
|
|||||||
return seq_++;
|
return seq_++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void send_request(const request_s& request) override {
|
void send_request(request const* request) override {
|
||||||
if (request->need_rsp_) {
|
if (request->need_rsp_) {
|
||||||
dispatcher_.subscribe_rsp(request->seq_, request->rsp_handle_, request->timeout_cb_, request->timeout_ms_, request->is_ping_);
|
dispatcher_->subscribe_rsp(request->seq_, request->rsp_handle_, request->timeout_cb_, request->timeout_ms_);
|
||||||
}
|
}
|
||||||
detail::msg_wrapper msg;
|
detail::msg_wrapper msg;
|
||||||
msg.type = static_cast<detail::msg_wrapper::msg_type>(detail::msg_wrapper::command | (request->is_ping_ ? detail::msg_wrapper::ping : 0) |
|
msg.type = static_cast<detail::msg_wrapper::msg_type>(detail::msg_wrapper::command | (request->is_ping_ ? detail::msg_wrapper::ping : 0) |
|
||||||
@ -157,7 +159,7 @@ class rpc : detail::noncopyable, public std::enable_shared_from_this<rpc>, publi
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<connection> conn_;
|
std::shared_ptr<connection> conn_;
|
||||||
detail::msg_dispatcher dispatcher_;
|
std::shared_ptr<detail::msg_dispatcher> dispatcher_;
|
||||||
seq_type seq_{0};
|
seq_type seq_{0};
|
||||||
bool is_ready_ = false;
|
bool is_ready_ = false;
|
||||||
};
|
};
|
||||||
|
@ -3,6 +3,16 @@
|
|||||||
// config
|
// config
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
|
|
||||||
|
#if defined(RPC_CORE_SERIALIZE_USE_CUSTOM)
|
||||||
|
|
||||||
|
#include RPC_CORE_SERIALIZE_USE_CUSTOM
|
||||||
|
|
||||||
|
#elif defined(RPC_CORE_SERIALIZE_USE_NLOHMANN_JSON)
|
||||||
|
|
||||||
|
#include "serialize_nlohmann_json.hpp"
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
// type traits
|
// type traits
|
||||||
#include "detail/type_traits.hpp"
|
#include "detail/type_traits.hpp"
|
||||||
|
|
||||||
@ -32,3 +42,5 @@
|
|||||||
#include "serialize/type_ptr.hpp"
|
#include "serialize/type_ptr.hpp"
|
||||||
#include "serialize/type_struct.hpp"
|
#include "serialize/type_struct.hpp"
|
||||||
#include "serialize/type_void.hpp"
|
#include "serialize/type_void.hpp"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
25
3party/rpc_core/include/rpc_core/serialize_nlohmann_json.hpp
Normal file
25
3party/rpc_core/include/rpc_core/serialize_nlohmann_json.hpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "detail/log.h"
|
||||||
|
#include "detail/string_view.hpp"
|
||||||
|
#include "nlohmann/json.hpp"
|
||||||
|
|
||||||
|
namespace rpc_core {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline std::string serialize(T&& t) {
|
||||||
|
return nlohmann::json(t).dump(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline bool deserialize(const detail::string_view& data, T& t) {
|
||||||
|
try {
|
||||||
|
t = nlohmann::json::parse(data.data(), data.data() + data.size()).get<T>();
|
||||||
|
return true;
|
||||||
|
} catch (std::exception& e) {
|
||||||
|
RPC_CORE_LOGE("deserialize: %s", e.what());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace rpc_core
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#define RPC_CORE_VER_MAJOR 2
|
#define RPC_CORE_VER_MAJOR 2
|
||||||
#define RPC_CORE_VER_MINOR 0
|
#define RPC_CORE_VER_MINOR 0
|
||||||
#define RPC_CORE_VER_PATCH 1
|
#define RPC_CORE_VER_PATCH 2
|
||||||
|
|
||||||
#define RPC_CORE_TO_VERSION(major, minor, patch) (major * 10000 + minor * 100 + patch)
|
#define RPC_CORE_TO_VERSION(major, minor, patch) (major * 10000 + minor * 100 + patch)
|
||||||
#define RPC_CORE_VERSION RPC_CORE_TO_VERSION(RPC_CORE_VER_MAJOR, RPC_CORE_VER_MINOR, RPC_CORE_VER_PATCH)
|
#define RPC_CORE_VERSION RPC_CORE_TO_VERSION(RPC_CORE_VER_MAJOR, RPC_CORE_VER_MINOR, RPC_CORE_VER_PATCH)
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "rpc_core",
|
|
||||||
"description": "a tiny c++11 rpc library, supports all platforms (macOS, Linux, Windows, iOS, Android, etc.) and most microchips (Arduino, STM32, ESP32/ESP8266, etc.)",
|
|
||||||
"keywords": "rpc",
|
|
||||||
"authors": {
|
|
||||||
"name": "shuai132",
|
|
||||||
"maintainer": true
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/shuai132/rpc_core.git"
|
|
||||||
},
|
|
||||||
"version": "2.0.1",
|
|
||||||
"build": {
|
|
||||||
"srcDir": "_",
|
|
||||||
"flags": [
|
|
||||||
"-I include"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
@ -190,6 +190,7 @@ if(SLED_BUILD_TESTS)
|
|||||||
sled_add_test(NAME sled_symbolize_test SRCS
|
sled_add_test(NAME sled_symbolize_test SRCS
|
||||||
src/sled/debugging/symbolize_test.cc NO_MAIN)
|
src/sled/debugging/symbolize_test.cc NO_MAIN)
|
||||||
sled_add_test(NAME sled_sigslot_test SRCS src/sled/sigslot_test.cc)
|
sled_add_test(NAME sled_sigslot_test SRCS src/sled/sigslot_test.cc)
|
||||||
|
sled_add_test(NAME sled_rpc_test SRCS src/sled/network/rpc_test.cc)
|
||||||
endif(SLED_BUILD_TESTS)
|
endif(SLED_BUILD_TESTS)
|
||||||
|
|
||||||
if(SLED_BUILD_FUZZ)
|
if(SLED_BUILD_FUZZ)
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
#define SLED_THREAD_ANNOTATION_ATTRIBUTE__(x)// no-op
|
#define SLED_THREAD_ANNOTATION_ATTRIBUTE__(x)// no-op
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SLED_UNUSED(x) (void) (x)
|
||||||
|
|
||||||
#define SLED_CAPABILITY(x) SLED_THREAD_ANNOTATION_ATTRIBUTE__(capability(x))
|
#define SLED_CAPABILITY(x) SLED_THREAD_ANNOTATION_ATTRIBUTE__(capability(x))
|
||||||
|
|
||||||
#define SLED_SCOPED_CAPABILITY SLED_THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
|
#define SLED_SCOPED_CAPABILITY SLED_THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
|
||||||
|
6
src/sled/network/rpc.h
Normal file
6
src/sled/network/rpc.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include <rpc_core.hpp>
|
||||||
|
#include <rpc_core/serialize.hpp>
|
||||||
|
|
||||||
|
namespace sled {
|
||||||
|
using namespace rpc_core;
|
||||||
|
}// namespace sled
|
33
src/sled/network/rpc_test.cc
Normal file
33
src/sled/network/rpc_test.cc
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#include <sled/lang/attributes.h>
|
||||||
|
#include <sled/network/rpc.h>
|
||||||
|
#include <sled/random.h>
|
||||||
|
#include <sled/time_utils.h>
|
||||||
|
|
||||||
|
TEST_SUITE("RPC")
|
||||||
|
{
|
||||||
|
TEST_CASE("loopback")
|
||||||
|
{
|
||||||
|
auto conn = sled::loopback_connection::create();
|
||||||
|
auto rpc_client = sled::rpc::create(conn.first);
|
||||||
|
auto rpc_server = sled::rpc::create(conn.second);
|
||||||
|
rpc_server->set_timer([](uint32_t ms, const sled::rpc::timeout_cb &cb) {
|
||||||
|
SLED_UNUSED(ms);
|
||||||
|
SLED_UNUSED(cb);
|
||||||
|
});
|
||||||
|
rpc_client->set_timer([](uint32_t ms, const sled::rpc::timeout_cb &cb) {
|
||||||
|
SLED_UNUSED(ms);
|
||||||
|
SLED_UNUSED(cb);
|
||||||
|
});
|
||||||
|
rpc_server->set_ready(true);
|
||||||
|
rpc_client->set_ready(true);
|
||||||
|
sled::Random rand(sled::TimeUTCMicros());
|
||||||
|
|
||||||
|
rpc_server->subscribe("cmd", [](int x) { return x + 1; });
|
||||||
|
|
||||||
|
int random_value = rand.Rand(0, 10000);
|
||||||
|
rpc_client->cmd("cmd")
|
||||||
|
->msg(random_value)
|
||||||
|
->rsp([random_value](int x) { CHECK_EQ(x, random_value + 1); })
|
||||||
|
->call();
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user