mirror of
https://github.com/BotChain-Robots/rpc.git
synced 2026-03-09 23:12:27 +01:00
Finish implementation
This commit is contained in:
12
.clang-format
Normal file
12
.clang-format
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
BasedOnStyle: LLVM
|
||||||
|
IndentWidth: 4
|
||||||
|
UseTab: Never
|
||||||
|
ColumnLimit: 100
|
||||||
|
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||||
|
MaxEmptyLinesToKeep: 2
|
||||||
|
AllowShortBlocksOnASingleLine: Never
|
||||||
|
AllowShortIfStatementsOnASingleLine: Never
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: None
|
||||||
|
ReflowComments: false
|
||||||
@@ -8,7 +8,7 @@ find_package(Threads REQUIRED)
|
|||||||
find_package(flatbuffers REQUIRED)
|
find_package(flatbuffers REQUIRED)
|
||||||
find_package(spdlog REQUIRED)
|
find_package(spdlog REQUIRED)
|
||||||
|
|
||||||
add_library(rpc src/librpc.cpp src/TCPClient.cpp src/UDPClient.cpp src/mDNSDiscoveryService.cpp src/MPIMessageBuilder.cpp
|
add_library(rpc src/librpc.cpp src/TCPClient.cpp src/UDPClient.cpp src/mDNSDiscoveryService.cpp src/MPIMessageBuilder.cpp src/CallBuilder.cpp
|
||||||
include/util/log.h)
|
include/util/log.h)
|
||||||
target_include_directories(rpc
|
target_include_directories(rpc
|
||||||
PUBLIC
|
PUBLIC
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
"conan": {}
|
"conan": {}
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"build/Release/generators/CMakePresets.json"
|
"build/Release/generators/CMakePresets.json",
|
||||||
|
"build/RelWithDebInfo/generators/CMakePresets.json"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
10
conanfile.py
10
conanfile.py
@@ -1,11 +1,13 @@
|
|||||||
from conan import ConanFile
|
|
||||||
from conan.tools.cmake import CMake, cmake_layout, CMakeToolchain, CMakeDeps
|
|
||||||
from conan.tools.files import copy
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from conan import ConanFile
|
||||||
|
from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout
|
||||||
|
from conan.tools.files import copy
|
||||||
|
|
||||||
|
|
||||||
class MyLibraryConan(ConanFile):
|
class MyLibraryConan(ConanFile):
|
||||||
name = "librpc"
|
name = "librpc"
|
||||||
version = "1.1.6"
|
version = "1.1.7"
|
||||||
|
|
||||||
settings = "os", "compiler", "build_type", "arch"
|
settings = "os", "compiler", "build_type", "arch"
|
||||||
options = {"shared": [True, False], "fPIC": [True, False]}
|
options = {"shared": [True, False], "fPIC": [True, False]}
|
||||||
|
|||||||
29
include/flatbuffers/CallBuilder.h
Normal file
29
include/flatbuffers/CallBuilder.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
#ifndef CALLBUILDER_H
|
||||||
|
#define CALLBUILDER_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "SerializedMessage.h"
|
||||||
|
#include "flatbuffers/flatbuffers.h"
|
||||||
|
#include "flatbuffers_generated/ReturnCall_generated.h"
|
||||||
|
#include "flatbuffers_generated/SendCall_generated.h"
|
||||||
|
|
||||||
|
namespace Flatbuffers {
|
||||||
|
|
||||||
|
class CallBuilder {
|
||||||
|
public:
|
||||||
|
CallBuilder() : builder_(1024) {
|
||||||
|
}
|
||||||
|
|
||||||
|
SerializedMessage build_send_call(uint8_t tag, uint8_t unique_id,
|
||||||
|
const std::vector<uint8_t> ¶meters);
|
||||||
|
|
||||||
|
static const Messaging::ReturnCall *parse_return_call(const uint8_t *buffer);
|
||||||
|
|
||||||
|
private:
|
||||||
|
flatbuffers::FlatBufferBuilder builder_;
|
||||||
|
};
|
||||||
|
} // namespace Flatbuffers
|
||||||
|
|
||||||
|
#endif // CALLBUILDER_H
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
// automatically generated by the FlatBuffers compiler, do not modify
|
// automatically generated by the FlatBuffers compiler, do not modify
|
||||||
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_GENERATED_MPIMESSAGE_MESSAGING_H_
|
#ifndef FLATBUFFERS_GENERATED_MPIMESSAGE_MESSAGING_H_
|
||||||
#define FLATBUFFERS_GENERATED_MPIMESSAGE_MESSAGING_H_
|
#define FLATBUFFERS_GENERATED_MPIMESSAGE_MESSAGING_H_
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// automatically generated by the FlatBuffers compiler, do not modify
|
// automatically generated by the FlatBuffers compiler, do not modify
|
||||||
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_GENERATED_RETURNCALL_MESSAGING_H_
|
#ifndef FLATBUFFERS_GENERATED_RETURNCALL_MESSAGING_H_
|
||||||
#define FLATBUFFERS_GENERATED_RETURNCALL_MESSAGING_H_
|
#define FLATBUFFERS_GENERATED_RETURNCALL_MESSAGING_H_
|
||||||
|
|
||||||
@@ -35,11 +34,9 @@ struct ReturnCall FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
|||||||
return GetPointer<const ::flatbuffers::Vector<uint8_t> *>(VT_RETURN_VALUE);
|
return GetPointer<const ::flatbuffers::Vector<uint8_t> *>(VT_RETURN_VALUE);
|
||||||
}
|
}
|
||||||
bool Verify(::flatbuffers::Verifier &verifier) const {
|
bool Verify(::flatbuffers::Verifier &verifier) const {
|
||||||
return VerifyTableStart(verifier) &&
|
return VerifyTableStart(verifier) && VerifyField<uint8_t>(verifier, VT_UNIQUE_ID, 1) &&
|
||||||
VerifyField<uint8_t>(verifier, VT_UNIQUE_ID, 1) &&
|
|
||||||
VerifyField<uint16_t>(verifier, VT_LENGTH, 2) &&
|
VerifyField<uint16_t>(verifier, VT_LENGTH, 2) &&
|
||||||
VerifyOffset(verifier, VT_RETURN_VALUE) &&
|
VerifyOffset(verifier, VT_RETURN_VALUE) && verifier.VerifyVector(return_value()) &&
|
||||||
verifier.VerifyVector(return_value()) &&
|
|
||||||
verifier.EndTable();
|
verifier.EndTable();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -57,8 +54,7 @@ struct ReturnCallBuilder {
|
|||||||
void add_return_value(::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> return_value) {
|
void add_return_value(::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> return_value) {
|
||||||
fbb_.AddOffset(ReturnCall::VT_RETURN_VALUE, return_value);
|
fbb_.AddOffset(ReturnCall::VT_RETURN_VALUE, return_value);
|
||||||
}
|
}
|
||||||
explicit ReturnCallBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
|
explicit ReturnCallBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) {
|
||||||
: fbb_(_fbb) {
|
|
||||||
start_ = fbb_.StartTable();
|
start_ = fbb_.StartTable();
|
||||||
}
|
}
|
||||||
::flatbuffers::Offset<ReturnCall> Finish() {
|
::flatbuffers::Offset<ReturnCall> Finish() {
|
||||||
@@ -68,10 +64,8 @@ struct ReturnCallBuilder {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline ::flatbuffers::Offset<ReturnCall> CreateReturnCall(
|
inline ::flatbuffers::Offset<ReturnCall>
|
||||||
::flatbuffers::FlatBufferBuilder &_fbb,
|
CreateReturnCall(::flatbuffers::FlatBufferBuilder &_fbb, uint8_t unique_id = 0, uint16_t length = 0,
|
||||||
uint8_t unique_id = 0,
|
|
||||||
uint16_t length = 0,
|
|
||||||
::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> return_value = 0) {
|
::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> return_value = 0) {
|
||||||
ReturnCallBuilder builder_(_fbb);
|
ReturnCallBuilder builder_(_fbb);
|
||||||
builder_.add_return_value(return_value);
|
builder_.add_return_value(return_value);
|
||||||
@@ -80,17 +74,11 @@ inline ::flatbuffers::Offset<ReturnCall> CreateReturnCall(
|
|||||||
return builder_.Finish();
|
return builder_.Finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ::flatbuffers::Offset<ReturnCall> CreateReturnCallDirect(
|
inline ::flatbuffers::Offset<ReturnCall>
|
||||||
::flatbuffers::FlatBufferBuilder &_fbb,
|
CreateReturnCallDirect(::flatbuffers::FlatBufferBuilder &_fbb, uint8_t unique_id = 0,
|
||||||
uint8_t unique_id = 0,
|
uint16_t length = 0, const std::vector<uint8_t> *return_value = nullptr) {
|
||||||
uint16_t length = 0,
|
|
||||||
const std::vector<uint8_t> *return_value = nullptr) {
|
|
||||||
auto return_value__ = return_value ? _fbb.CreateVector<uint8_t>(*return_value) : 0;
|
auto return_value__ = return_value ? _fbb.CreateVector<uint8_t>(*return_value) : 0;
|
||||||
return Messaging::CreateReturnCall(
|
return Messaging::CreateReturnCall(_fbb, unique_id, length, return_value__);
|
||||||
_fbb,
|
|
||||||
unique_id,
|
|
||||||
length,
|
|
||||||
return_value__);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const Messaging::ReturnCall *GetReturnCall(const void *buf) {
|
inline const Messaging::ReturnCall *GetReturnCall(const void *buf) {
|
||||||
@@ -101,24 +89,20 @@ inline const Messaging::ReturnCall *GetSizePrefixedReturnCall(const void *buf) {
|
|||||||
return ::flatbuffers::GetSizePrefixedRoot<Messaging::ReturnCall>(buf);
|
return ::flatbuffers::GetSizePrefixedRoot<Messaging::ReturnCall>(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool VerifyReturnCallBuffer(
|
inline bool VerifyReturnCallBuffer(::flatbuffers::Verifier &verifier) {
|
||||||
::flatbuffers::Verifier &verifier) {
|
|
||||||
return verifier.VerifyBuffer<Messaging::ReturnCall>(nullptr);
|
return verifier.VerifyBuffer<Messaging::ReturnCall>(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool VerifySizePrefixedReturnCallBuffer(
|
inline bool VerifySizePrefixedReturnCallBuffer(::flatbuffers::Verifier &verifier) {
|
||||||
::flatbuffers::Verifier &verifier) {
|
|
||||||
return verifier.VerifySizePrefixedBuffer<Messaging::ReturnCall>(nullptr);
|
return verifier.VerifySizePrefixedBuffer<Messaging::ReturnCall>(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void FinishReturnCallBuffer(
|
inline void FinishReturnCallBuffer(::flatbuffers::FlatBufferBuilder &fbb,
|
||||||
::flatbuffers::FlatBufferBuilder &fbb,
|
|
||||||
::flatbuffers::Offset<Messaging::ReturnCall> root) {
|
::flatbuffers::Offset<Messaging::ReturnCall> root) {
|
||||||
fbb.Finish(root);
|
fbb.Finish(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void FinishSizePrefixedReturnCallBuffer(
|
inline void FinishSizePrefixedReturnCallBuffer(::flatbuffers::FlatBufferBuilder &fbb,
|
||||||
::flatbuffers::FlatBufferBuilder &fbb,
|
|
||||||
::flatbuffers::Offset<Messaging::ReturnCall> root) {
|
::flatbuffers::Offset<Messaging::ReturnCall> root) {
|
||||||
fbb.FinishSizePrefixed(root);
|
fbb.FinishSizePrefixed(root);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// automatically generated by the FlatBuffers compiler, do not modify
|
// automatically generated by the FlatBuffers compiler, do not modify
|
||||||
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_GENERATED_ROBOTMODULE_H_
|
#ifndef FLATBUFFERS_GENERATED_ROBOTMODULE_H_
|
||||||
#define FLATBUFFERS_GENERATED_ROBOTMODULE_H_
|
#define FLATBUFFERS_GENERATED_ROBOTMODULE_H_
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// automatically generated by the FlatBuffers compiler, do not modify
|
// automatically generated by the FlatBuffers compiler, do not modify
|
||||||
|
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_GENERATED_SENDCALL_MESSAGING_H_
|
#ifndef FLATBUFFERS_GENERATED_SENDCALL_MESSAGING_H_
|
||||||
#define FLATBUFFERS_GENERATED_SENDCALL_MESSAGING_H_
|
#define FLATBUFFERS_GENERATED_SENDCALL_MESSAGING_H_
|
||||||
|
|
||||||
@@ -39,12 +38,10 @@ struct SendCall FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
|||||||
return GetPointer<const ::flatbuffers::Vector<uint8_t> *>(VT_PARAMETERS);
|
return GetPointer<const ::flatbuffers::Vector<uint8_t> *>(VT_PARAMETERS);
|
||||||
}
|
}
|
||||||
bool Verify(::flatbuffers::Verifier &verifier) const {
|
bool Verify(::flatbuffers::Verifier &verifier) const {
|
||||||
return VerifyTableStart(verifier) &&
|
return VerifyTableStart(verifier) && VerifyField<uint8_t>(verifier, VT_TAG, 1) &&
|
||||||
VerifyField<uint8_t>(verifier, VT_TAG, 1) &&
|
|
||||||
VerifyField<uint8_t>(verifier, VT_UNIQUE_ID, 1) &&
|
VerifyField<uint8_t>(verifier, VT_UNIQUE_ID, 1) &&
|
||||||
VerifyField<uint16_t>(verifier, VT_LENGTH, 2) &&
|
VerifyField<uint16_t>(verifier, VT_LENGTH, 2) &&
|
||||||
VerifyOffset(verifier, VT_PARAMETERS) &&
|
VerifyOffset(verifier, VT_PARAMETERS) && verifier.VerifyVector(parameters()) &&
|
||||||
verifier.VerifyVector(parameters()) &&
|
|
||||||
verifier.EndTable();
|
verifier.EndTable();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -65,8 +62,7 @@ struct SendCallBuilder {
|
|||||||
void add_parameters(::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> parameters) {
|
void add_parameters(::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> parameters) {
|
||||||
fbb_.AddOffset(SendCall::VT_PARAMETERS, parameters);
|
fbb_.AddOffset(SendCall::VT_PARAMETERS, parameters);
|
||||||
}
|
}
|
||||||
explicit SendCallBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
|
explicit SendCallBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) {
|
||||||
: fbb_(_fbb) {
|
|
||||||
start_ = fbb_.StartTable();
|
start_ = fbb_.StartTable();
|
||||||
}
|
}
|
||||||
::flatbuffers::Offset<SendCall> Finish() {
|
::flatbuffers::Offset<SendCall> Finish() {
|
||||||
@@ -76,10 +72,8 @@ struct SendCallBuilder {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline ::flatbuffers::Offset<SendCall> CreateSendCall(
|
inline ::flatbuffers::Offset<SendCall>
|
||||||
::flatbuffers::FlatBufferBuilder &_fbb,
|
CreateSendCall(::flatbuffers::FlatBufferBuilder &_fbb, uint8_t tag = 0, uint8_t unique_id = 0,
|
||||||
uint8_t tag = 0,
|
|
||||||
uint8_t unique_id = 0,
|
|
||||||
uint16_t length = 0,
|
uint16_t length = 0,
|
||||||
::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> parameters = 0) {
|
::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> parameters = 0) {
|
||||||
SendCallBuilder builder_(_fbb);
|
SendCallBuilder builder_(_fbb);
|
||||||
@@ -90,19 +84,11 @@ inline ::flatbuffers::Offset<SendCall> CreateSendCall(
|
|||||||
return builder_.Finish();
|
return builder_.Finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ::flatbuffers::Offset<SendCall> CreateSendCallDirect(
|
inline ::flatbuffers::Offset<SendCall>
|
||||||
::flatbuffers::FlatBufferBuilder &_fbb,
|
CreateSendCallDirect(::flatbuffers::FlatBufferBuilder &_fbb, uint8_t tag = 0, uint8_t unique_id = 0,
|
||||||
uint8_t tag = 0,
|
uint16_t length = 0, const std::vector<uint8_t> *parameters = nullptr) {
|
||||||
uint8_t unique_id = 0,
|
|
||||||
uint16_t length = 0,
|
|
||||||
const std::vector<uint8_t> *parameters = nullptr) {
|
|
||||||
auto parameters__ = parameters ? _fbb.CreateVector<uint8_t>(*parameters) : 0;
|
auto parameters__ = parameters ? _fbb.CreateVector<uint8_t>(*parameters) : 0;
|
||||||
return Messaging::CreateSendCall(
|
return Messaging::CreateSendCall(_fbb, tag, unique_id, length, parameters__);
|
||||||
_fbb,
|
|
||||||
tag,
|
|
||||||
unique_id,
|
|
||||||
length,
|
|
||||||
parameters__);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const Messaging::SendCall *GetSendCall(const void *buf) {
|
inline const Messaging::SendCall *GetSendCall(const void *buf) {
|
||||||
@@ -113,24 +99,20 @@ inline const Messaging::SendCall *GetSizePrefixedSendCall(const void *buf) {
|
|||||||
return ::flatbuffers::GetSizePrefixedRoot<Messaging::SendCall>(buf);
|
return ::flatbuffers::GetSizePrefixedRoot<Messaging::SendCall>(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool VerifySendCallBuffer(
|
inline bool VerifySendCallBuffer(::flatbuffers::Verifier &verifier) {
|
||||||
::flatbuffers::Verifier &verifier) {
|
|
||||||
return verifier.VerifyBuffer<Messaging::SendCall>(nullptr);
|
return verifier.VerifyBuffer<Messaging::SendCall>(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool VerifySizePrefixedSendCallBuffer(
|
inline bool VerifySizePrefixedSendCallBuffer(::flatbuffers::Verifier &verifier) {
|
||||||
::flatbuffers::Verifier &verifier) {
|
|
||||||
return verifier.VerifySizePrefixedBuffer<Messaging::SendCall>(nullptr);
|
return verifier.VerifySizePrefixedBuffer<Messaging::SendCall>(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void FinishSendCallBuffer(
|
inline void FinishSendCallBuffer(::flatbuffers::FlatBufferBuilder &fbb,
|
||||||
::flatbuffers::FlatBufferBuilder &fbb,
|
|
||||||
::flatbuffers::Offset<Messaging::SendCall> root) {
|
::flatbuffers::Offset<Messaging::SendCall> root) {
|
||||||
fbb.Finish(root);
|
fbb.Finish(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void FinishSizePrefixedSendCallBuffer(
|
inline void FinishSizePrefixedSendCallBuffer(::flatbuffers::FlatBufferBuilder &fbb,
|
||||||
::flatbuffers::FlatBufferBuilder &fbb,
|
|
||||||
::flatbuffers::Offset<Messaging::SendCall> root) {
|
::flatbuffers::Offset<Messaging::SendCall> root) {
|
||||||
fbb.FinishSizePrefixed(root);
|
fbb.FinishSizePrefixed(root);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,15 +3,18 @@
|
|||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <semaphore>
|
||||||
#include <shared_mutex>
|
#include <shared_mutex>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include "BlockingQueue.h"
|
#include "BlockingQueue.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
|
#include "flatbuffers/CallBuilder.h"
|
||||||
#include "mDNSDiscoveryService.h"
|
#include "mDNSDiscoveryService.h"
|
||||||
|
|
||||||
|
|
||||||
constexpr auto RX_QUEUE_SIZE = 100;
|
constexpr auto RX_QUEUE_SIZE = 100;
|
||||||
|
constexpr auto FN_CALL_TAG = 100; // reserved tag for RPC functionality
|
||||||
|
constexpr auto FN_CALL_TIMEOUT = std::chrono::seconds(3);
|
||||||
|
|
||||||
struct SizeAndSource {
|
struct SizeAndSource {
|
||||||
size_t bytes_written;
|
size_t bytes_written;
|
||||||
@@ -22,6 +25,7 @@ class MessagingInterface {
|
|||||||
public:
|
public:
|
||||||
MessagingInterface()
|
MessagingInterface()
|
||||||
: m_stop_flag(false), m_rx_thread(std::thread(&MessagingInterface::handle_recv, this)),
|
: m_stop_flag(false), m_rx_thread(std::thread(&MessagingInterface::handle_recv, this)),
|
||||||
|
m_fn_rx_thread(std::thread(&MessagingInterface::handle_fn_recv, this)),
|
||||||
m_rx_queue(std::make_shared<BlockingQueue<std::unique_ptr<std::vector<uint8_t>>>>(
|
m_rx_queue(std::make_shared<BlockingQueue<std::unique_ptr<std::vector<uint8_t>>>>(
|
||||||
RX_QUEUE_SIZE)) {
|
RX_QUEUE_SIZE)) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@@ -37,23 +41,36 @@ class MessagingInterface {
|
|||||||
int broadcast(uint8_t *buffer, size_t size, bool durable); // todo
|
int broadcast(uint8_t *buffer, size_t size, bool durable); // todo
|
||||||
std::optional<SizeAndSource> recv(uint8_t *buffer, size_t size, uint8_t tag);
|
std::optional<SizeAndSource> recv(uint8_t *buffer, size_t size, uint8_t tag);
|
||||||
int sendrecv(uint8_t *send_buffer, size_t send_size, uint8_t dest, uint8_t send_tag,
|
int sendrecv(uint8_t *send_buffer, size_t send_size, uint8_t dest, uint8_t send_tag,
|
||||||
uint8_t *recv_buffer, size_t recv_size, uint8_t recv_tag); // todo
|
uint8_t *recv_buffer, size_t recv_size,
|
||||||
|
uint8_t recv_tag); // todo
|
||||||
|
std::optional<std::unique_ptr<std::vector<uint8_t>>>
|
||||||
|
remote_call(uint8_t function_tag, uint8_t module, const std::vector<uint8_t> ¶meters);
|
||||||
std::unordered_set<uint8_t> find_connected_modules(std::chrono::duration<double> scan_duration);
|
std::unordered_set<uint8_t> find_connected_modules(std::chrono::duration<double> scan_duration);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handle_recv();
|
void handle_recv();
|
||||||
|
void handle_fn_recv();
|
||||||
|
|
||||||
uint16_t m_sequence_number = 0;
|
uint16_t m_sequence_number = 0;
|
||||||
|
uint8_t unique_fn_call_id = 0; // this is designed to overflow, change to uint16_t if we plan on
|
||||||
|
// having way more calls per second.
|
||||||
std::unordered_map<uint8_t, std::shared_ptr<ICommunicationClient>> m_id_to_lossless_client;
|
std::unordered_map<uint8_t, std::shared_ptr<ICommunicationClient>> m_id_to_lossless_client;
|
||||||
std::unordered_map<uint8_t, std::shared_ptr<ICommunicationClient>> m_id_to_lossy_client;
|
std::unordered_map<uint8_t, std::shared_ptr<ICommunicationClient>> m_id_to_lossy_client;
|
||||||
std::unordered_map<int, std::unique_ptr<BlockingQueue<std::unique_ptr<std::vector<uint8_t>>>>>
|
std::unordered_map<int, std::unique_ptr<BlockingQueue<std::unique_ptr<std::vector<uint8_t>>>>>
|
||||||
m_tag_to_queue_map;
|
m_tag_to_queue_map;
|
||||||
|
// The semaphore needs to be in a unique_ptr, since it is not copyable or
|
||||||
|
// movable unordered_maps need to copy/move to reshuffle.
|
||||||
|
std::unordered_map<uint8_t, std::unique_ptr<std::binary_semaphore>> m_fn_call_to_semaphore;
|
||||||
|
std::unordered_map<uint8_t, std::unique_ptr<std::vector<uint8_t>>> m_fn_call_to_result;
|
||||||
std::unique_ptr<IDiscoveryService> m_discovery_service;
|
std::unique_ptr<IDiscoveryService> m_discovery_service;
|
||||||
std::atomic<bool> m_stop_flag;
|
std::atomic<bool> m_stop_flag;
|
||||||
std::thread m_rx_thread;
|
std::thread m_rx_thread;
|
||||||
|
std::thread m_fn_rx_thread;
|
||||||
std::shared_ptr<BlockingQueue<std::unique_ptr<std::vector<uint8_t>>>> m_rx_queue;
|
std::shared_ptr<BlockingQueue<std::unique_ptr<std::vector<uint8_t>>>> m_rx_queue;
|
||||||
std::shared_mutex m_client_mutex;
|
std::shared_mutex m_client_mutex;
|
||||||
std::shared_mutex m_scan_mutex;
|
std::shared_mutex m_scan_mutex;
|
||||||
|
std::mutex m_fn_call_mutex;
|
||||||
|
std::mutex m_tag_queue_mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // RPC_LIBRARY_H
|
#endif // RPC_LIBRARY_H
|
||||||
|
|||||||
23
src/CallBuilder.cpp
Normal file
23
src/CallBuilder.cpp
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#include "flatbuffers/CallBuilder.h"
|
||||||
|
#include "flatbuffers/SerializedMessage.h"
|
||||||
|
|
||||||
|
namespace Flatbuffers {
|
||||||
|
SerializedMessage CallBuilder::build_send_call(uint8_t tag, uint8_t unique_id,
|
||||||
|
const std::vector<uint8_t> ¶meters) {
|
||||||
|
builder_.Clear();
|
||||||
|
|
||||||
|
const auto parameters_vector = builder_.CreateVector(parameters);
|
||||||
|
|
||||||
|
const auto message = Messaging::CreateSendCall(
|
||||||
|
builder_, tag, unique_id, static_cast<int>(parameters.size()), parameters_vector);
|
||||||
|
|
||||||
|
builder_.Finish(message);
|
||||||
|
|
||||||
|
return {builder_.GetBufferPointer(), builder_.GetSize()};
|
||||||
|
}
|
||||||
|
|
||||||
|
const Messaging::ReturnCall *CallBuilder::parse_return_call(const uint8_t *buffer) {
|
||||||
|
return flatbuffers::GetRoot<Messaging::ReturnCall>(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Flatbuffers
|
||||||
100
src/librpc.cpp
100
src/librpc.cpp
@@ -1,12 +1,19 @@
|
|||||||
#include "librpc.h"
|
#include "librpc.h"
|
||||||
|
#include "flatbuffers_generated/ReturnCall_generated.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <functional>
|
||||||
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <semaphore>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#undef min
|
#undef min
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "flatbuffers/CallBuilder.h"
|
||||||
#include "flatbuffers/MPIMessageBuilder.h"
|
#include "flatbuffers/MPIMessageBuilder.h"
|
||||||
#include "spdlog/spdlog.h"
|
#include "spdlog/spdlog.h"
|
||||||
|
|
||||||
@@ -14,10 +21,12 @@ constexpr auto MAX_RECV_WAIT_TIME = std::chrono::seconds(3);
|
|||||||
constexpr auto PER_TAG_MAX_QUEUE_SIZE = 50;
|
constexpr auto PER_TAG_MAX_QUEUE_SIZE = 50;
|
||||||
constexpr auto MAX_WAIT_TIME_TAG_ENQUEUE = std::chrono::milliseconds(250);
|
constexpr auto MAX_WAIT_TIME_TAG_ENQUEUE = std::chrono::milliseconds(250);
|
||||||
constexpr auto MAX_WAIT_TIME_RX_THREAD_DEQUEUE = std::chrono::milliseconds(250);
|
constexpr auto MAX_WAIT_TIME_RX_THREAD_DEQUEUE = std::chrono::milliseconds(250);
|
||||||
|
constexpr auto FN_RETURN_BUFFER_SIZE = 1024;
|
||||||
|
|
||||||
MessagingInterface::~MessagingInterface() {
|
MessagingInterface::~MessagingInterface() {
|
||||||
m_stop_flag = true;
|
m_stop_flag = true;
|
||||||
m_rx_thread.join();
|
m_rx_thread.join();
|
||||||
|
m_fn_rx_thread.join();
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
@@ -51,11 +60,13 @@ int MessagingInterface::broadcast(uint8_t *buffer, size_t size, bool durable) {
|
|||||||
|
|
||||||
std::optional<SizeAndSource> MessagingInterface::recv(uint8_t *buffer, const size_t size,
|
std::optional<SizeAndSource> MessagingInterface::recv(uint8_t *buffer, const size_t size,
|
||||||
uint8_t tag) {
|
uint8_t tag) {
|
||||||
|
std::unique_lock lock(m_tag_queue_mutex);
|
||||||
if (!m_tag_to_queue_map.contains(tag)) {
|
if (!m_tag_to_queue_map.contains(tag)) {
|
||||||
m_tag_to_queue_map.insert(
|
m_tag_to_queue_map.insert(
|
||||||
{tag, std::make_unique<BlockingQueue<std::unique_ptr<std::vector<uint8_t>>>>(
|
{tag, std::make_unique<BlockingQueue<std::unique_ptr<std::vector<uint8_t>>>>(
|
||||||
PER_TAG_MAX_QUEUE_SIZE)});
|
PER_TAG_MAX_QUEUE_SIZE)});
|
||||||
}
|
}
|
||||||
|
lock.unlock();
|
||||||
|
|
||||||
const auto data = m_tag_to_queue_map[tag]->dequeue(MAX_RECV_WAIT_TIME);
|
const auto data = m_tag_to_queue_map[tag]->dequeue(MAX_RECV_WAIT_TIME);
|
||||||
|
|
||||||
@@ -82,7 +93,8 @@ int MessagingInterface::sendrecv(uint8_t *send_buffer, size_t send_size, uint8_t
|
|||||||
|
|
||||||
std::unordered_set<uint8_t>
|
std::unordered_set<uint8_t>
|
||||||
MessagingInterface::find_connected_modules(const std::chrono::duration<double> scan_duration) {
|
MessagingInterface::find_connected_modules(const std::chrono::duration<double> scan_duration) {
|
||||||
// Cannot just skip the call if already running, since the caller needs the list of modules.
|
// Cannot just skip the call if already running, since the caller needs the
|
||||||
|
// list of modules.
|
||||||
std::unique_lock scan_lock(m_scan_mutex);
|
std::unique_lock scan_lock(m_scan_mutex);
|
||||||
const auto foundModules = this->m_discovery_service->find_modules(scan_duration);
|
const auto foundModules = this->m_discovery_service->find_modules(scan_duration);
|
||||||
scan_lock.unlock();
|
scan_lock.unlock();
|
||||||
@@ -120,15 +132,101 @@ void MessagingInterface::handle_recv() {
|
|||||||
const auto &mpi_message =
|
const auto &mpi_message =
|
||||||
Flatbuffers::MPIMessageBuilder::parse_mpi_message(data.value()->data());
|
Flatbuffers::MPIMessageBuilder::parse_mpi_message(data.value()->data());
|
||||||
|
|
||||||
|
std::unique_lock lock(m_tag_queue_mutex);
|
||||||
if (!m_tag_to_queue_map.contains(mpi_message->tag())) {
|
if (!m_tag_to_queue_map.contains(mpi_message->tag())) {
|
||||||
m_tag_to_queue_map.insert(
|
m_tag_to_queue_map.insert(
|
||||||
{mpi_message->tag(),
|
{mpi_message->tag(),
|
||||||
std::make_unique<BlockingQueue<std::unique_ptr<std::vector<uint8_t>>>>(
|
std::make_unique<BlockingQueue<std::unique_ptr<std::vector<uint8_t>>>>(
|
||||||
PER_TAG_MAX_QUEUE_SIZE)});
|
PER_TAG_MAX_QUEUE_SIZE)});
|
||||||
}
|
}
|
||||||
|
lock.unlock();
|
||||||
|
|
||||||
m_tag_to_queue_map[mpi_message->tag()]->enqueue(std::move(data.value()),
|
m_tag_to_queue_map[mpi_message->tag()]->enqueue(std::move(data.value()),
|
||||||
MAX_WAIT_TIME_TAG_ENQUEUE);
|
MAX_WAIT_TIME_TAG_ENQUEUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<std::unique_ptr<std::vector<uint8_t>>>
|
||||||
|
MessagingInterface::remote_call(uint8_t function_tag, uint8_t module_id,
|
||||||
|
const std::vector<uint8_t> ¶meters) {
|
||||||
|
std::unique_lock lock(m_fn_call_mutex);
|
||||||
|
const auto unique_id = unique_fn_call_id++;
|
||||||
|
auto sem = std::make_unique<std::counting_semaphore<1>>(0);
|
||||||
|
m_fn_call_to_semaphore.insert_or_assign(unique_id, std::move(sem));
|
||||||
|
lock.unlock();
|
||||||
|
|
||||||
|
Flatbuffers::CallBuilder builder{};
|
||||||
|
auto [data, size] = builder.build_send_call(function_tag, unique_id, parameters);
|
||||||
|
|
||||||
|
// Assume durable transmission, non-durable RPC calls do not make sense.
|
||||||
|
// If a message is lost, we will block unnecessarily until the timeout.
|
||||||
|
// todo: is this thread safe? especially if other threads will be calling send
|
||||||
|
// themselves.
|
||||||
|
send((uint8_t *)data, size, module_id, FN_CALL_TAG, true);
|
||||||
|
|
||||||
|
if (m_fn_call_to_semaphore[unique_id]->try_acquire_for(FN_CALL_TIMEOUT)) {
|
||||||
|
lock.lock();
|
||||||
|
|
||||||
|
if (!m_fn_call_to_result[unique_id]) {
|
||||||
|
m_fn_call_to_semaphore.erase(unique_id);
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = std::move(m_fn_call_to_result[unique_id]);
|
||||||
|
m_fn_call_to_result.erase(unique_id);
|
||||||
|
m_fn_call_to_semaphore.erase(unique_id);
|
||||||
|
return std::move(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
lock.lock();
|
||||||
|
m_fn_call_to_semaphore.erase(unique_id);
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessagingInterface::handle_fn_recv() {
|
||||||
|
while (!m_stop_flag) {
|
||||||
|
auto buffer = std::make_unique<std::vector<uint8_t>>();
|
||||||
|
buffer->resize(FN_RETURN_BUFFER_SIZE);
|
||||||
|
|
||||||
|
std::optional<SizeAndSource> maybe_result;
|
||||||
|
SizeAndSource result;
|
||||||
|
do {
|
||||||
|
maybe_result = recv(buffer->data(), FN_RETURN_BUFFER_SIZE, FN_CALL_TAG);
|
||||||
|
} while (!m_stop_flag && !maybe_result);
|
||||||
|
if (m_stop_flag) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Flatbuffers::CallBuilder builder{};
|
||||||
|
std::unique_lock lock(m_fn_call_mutex);
|
||||||
|
result = *maybe_result;
|
||||||
|
|
||||||
|
flatbuffers::Verifier verifier(buffer->data(), result.bytes_written);
|
||||||
|
bool ok = Messaging::VerifyReturnCallBuffer(verifier);
|
||||||
|
if (!ok) {
|
||||||
|
spdlog::error("[LibRPC] Got an invalid return buffer");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto return_data = builder.parse_return_call(buffer->data());
|
||||||
|
if (return_data->length() > FN_RETURN_BUFFER_SIZE) {
|
||||||
|
spdlog::warn("[LibRPC] Got a return buffer with return data that is too large");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = m_fn_call_to_semaphore.find(return_data->unique_id());
|
||||||
|
if (it == m_fn_call_to_semaphore.end() || !it->second) {
|
||||||
|
spdlog::warn("[LibRPC] Previously timed out RPC call completed, "
|
||||||
|
"discarding result");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto raw_data = std::make_unique<std::vector<uint8_t>>();
|
||||||
|
raw_data->resize(return_data->length());
|
||||||
|
std::memcpy(raw_data->data(), return_data->return_value()->data(), return_data->length());
|
||||||
|
m_fn_call_to_result[return_data->unique_id()] = std::move(raw_data);
|
||||||
|
it->second->release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user