Skip to content

shuai132/rpc_core

Repository files navigation

rpc_core

Build Status Build Status Release License

a tiny C++14 rpc library, supports all platforms (macOS, Linux, Windows, iOS, Android, etc.) and most microchips ( Arduino, STM32, ESP32/ESP8266, etc.)

Recommend TCP-based implementation: asio_net

Introduction

Full-feature rpc frameworks (e.g. gRPC and bRPC) are very complex and not suitable for embedded systems.

This project offers a lightweight and user-friend rpc library that is better suited for one-to-one rpc calls. It supports all platforms and a wide range of microchips, including Arduino, STM32, ESP32/ESP8266, and more.

Note: This project only offers the protocol layer and API, it does not include the implementation of the transport layer. For TCP-based implementation: asio_net

Features

  • Header-Only
  • No-Schema
  • Support performance-limited platforms including microchips
  • Support any connection type (tcp socket, serial port, etc.)
  • High Performance Serialization, support most STL containers and user type
  • Serialization plugins implementations for flatbuffers and nlohmann::json
  • RAII-based dispose for automatic cancel request
  • Timeout and Retry API
  • Support std::future interface
  • Support co_await, depend on C++20 and asio, or custom implementation

TCP-based implementations

  • C++

    • asio_net: based on asio
      Support macOS, Linux, Windows, iOS, Android, etc. and can be used on MCUs that support asio, such as ESP32.
  • Rust

Requirements

  • C++14
  • Provide your connection implementation: connection
    NOTICE: complete data packets are required for data transmission, such as websocket.
    If using tcp socket, serial port, etc., message pack and unpack need to be implemented. Or you can use stream_connection.
  • Optional: C++20 (for coroutine api, co_await async_call)

Usage

// The Receiver
rpc->subscribe("cmd", [](const std::string& msg) -> std::string {
    assert(msg == "hello");
    return "world";
});

// The Sender
rpc->cmd("cmd")
    ->msg(std::string("hello"))
    ->rsp([](const std::string& rsp) {
      assert(rsp == "world");
    })
    ->call();

// Or use C++20 co_await with asio
auto rsp = co_await rpc->cmd("cmd")->msg(std::string("hello"))->async_call<std::string>();
assert(rsp.data == "world");

// Or you can use custom async implementation, and co_await it!

Addition:

  1. msg and rsp support any serializable type, see Serialization.
  2. Detailed usages and unittests can be found here: rpc_test.cpp
  3. There is an example shows custom async impl: rpc_c_coroutine.hpp

Serialization

High-performance and memory-saving binary serialization.

For example, user data:

struct Type {
  uint8_t id = 1;
  uint8_t age = 18;
  std::string name = "test";
};

json: {"id":1,"age":18,"name":"test"}

library bytes
json 31
flatbuffers 44
protobuf 10
msgpack 8
rpc_core 8

Serialization Plugins

  • flatbuffers.hpp
    Supports using types generated by flatbuffers directly as message
    (add the option --gen-object-api when using flatc)

  • json_msg.hpp
    Supports using types supported by nlohmann/json directly as message
    (the to_json/from_json rules in nlohmann/json need to be satisfied, and use DEFINE_JSON_CLASS).

  • json.hpp
    A flexible way to use nlohmann/json

License

This project is licensed under the MIT license.

Links

  • Implementation based on asio: asio_net

  • Implementation suitable for ESP8266: esp_rpc