work on rpc
This commit is contained in:
parent
bf03a19820
commit
17787b8ab1
8 changed files with 189 additions and 77 deletions
2
external/mesytec-mvlc
vendored
2
external/mesytec-mvlc
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 31606b39eab4b3581633d6693329082328ff7c62
|
Subproject commit 3347a186c7c3eb0a12b6baa76b90e71d573fcd39
|
|
@ -3,9 +3,10 @@
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace mesytec::mnode::cpp_types
|
namespace mesytec::mnode
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
using u8 = std::uint8_t;
|
using u8 = std::uint8_t;
|
||||||
using u16 = std::uint16_t;
|
using u16 = std::uint16_t;
|
||||||
using u32 = std::uint32_t;
|
using u32 = std::uint32_t;
|
||||||
|
@ -15,6 +16,7 @@ using s8 = std::int8_t;
|
||||||
using s16 = std::int16_t;
|
using s16 = std::int16_t;
|
||||||
using s32 = std::int32_t;
|
using s32 = std::int32_t;
|
||||||
using s64 = std::int64_t;
|
using s64 = std::int64_t;
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
} // namespace mesytec::mnode::cpp_types
|
} // namespace mesytec::mnode::cpp_types
|
||||||
|
|
||||||
|
|
16
include/mesytec-mnode/mnode_nng_proto.h
Normal file
16
include/mesytec-mnode/mnode_nng_proto.h
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#ifndef D9BA34A9_3472_4E22_8E82_5C335EDA67C7
|
||||||
|
#define D9BA34A9_3472_4E22_8E82_5C335EDA67C7
|
||||||
|
|
||||||
|
#include <google/protobuf/message_lite.h>
|
||||||
|
#include <nng/nng.h>
|
||||||
|
|
||||||
|
namespace mesytec::mnode::nng
|
||||||
|
{
|
||||||
|
|
||||||
|
size_t serialize_proto_to_nng(const google::protobuf::MessageLite &message, nng_msg *msg);
|
||||||
|
size_t deserialize_proto_from_nng(google::protobuf::MessageLite &message, nng_msg *msg);
|
||||||
|
size_t deserialize_proto_from_nng_trim(google::protobuf::MessageLite &message, nng_msg *msg);
|
||||||
|
|
||||||
|
} // namespace mesytec::mnode::nng
|
||||||
|
|
||||||
|
#endif /* D9BA34A9_3472_4E22_8E82_5C335EDA67C7 */
|
|
@ -7,13 +7,17 @@ package mesytec.mnode.proto.mrpc;
|
||||||
|
|
||||||
message MethodCall
|
message MethodCall
|
||||||
{
|
{
|
||||||
|
// Service::GetDescriptor()->full_name()
|
||||||
string service = 1;
|
string service = 1;
|
||||||
|
// MethodDescriptor::full_name()
|
||||||
string method = 2;
|
string method = 2;
|
||||||
|
// Must be of type Service::GetRequestPrototype(method)
|
||||||
google.protobuf.Any request = 3;
|
google.protobuf.Any request = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message MethodCallResponse
|
message MethodCallResponse
|
||||||
{
|
{
|
||||||
google.rpc.Status status = 1;
|
google.rpc.Status status = 1;
|
||||||
|
// Is of type Service::GetResponsePrototype(method)
|
||||||
google.protobuf.Any response = 2;
|
google.protobuf.Any response = 2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,11 +6,11 @@ set(MVLC_NNG_MNODE_WARN_FLAGS -Wall -Wextra -Wpedantic)
|
||||||
# set(CMAKE_CXX_CLANG_TIDY clang-tidy -p ${CMAKE_BINARY_DIR} --extra-arg=-std=c++17)
|
# set(CMAKE_CXX_CLANG_TIDY clang-tidy -p ${CMAKE_BINARY_DIR} --extra-arg=-std=c++17)
|
||||||
#endif()
|
#endif()
|
||||||
|
|
||||||
add_library(mesytec-mnode mnode_nng.cc mnode_nng_async.cc)
|
add_library(mesytec-mnode mnode_nng.cc mnode_nng_async.cc mnode_nng_proto.cc)
|
||||||
target_include_directories(mesytec-mnode
|
target_include_directories(mesytec-mnode
|
||||||
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include>
|
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include>
|
||||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/mesytec-mnode)
|
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/mesytec-mnode)
|
||||||
target_link_libraries(mesytec-mnode PUBLIC nng PRIVATE spdlog)
|
target_link_libraries(mesytec-mnode PUBLIC nng mnode-proto PRIVATE spdlog)
|
||||||
target_compile_features(mesytec-mnode PRIVATE cxx_std_17)
|
target_compile_features(mesytec-mnode PRIVATE cxx_std_17)
|
||||||
|
|
||||||
add_library(mesytec-mnode-dev INTERFACE)
|
add_library(mesytec-mnode-dev INTERFACE)
|
||||||
|
|
57
src/mnode_nng_proto.cc
Normal file
57
src/mnode_nng_proto.cc
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
#include <mesytec-mnode/mnode_nng_proto.h>
|
||||||
|
#include <mesytec-mnode/mnode_nng.h>
|
||||||
|
#include <mesytec-mnode/mnode_cpp_types.h>
|
||||||
|
|
||||||
|
namespace mesytec::mnode::nng
|
||||||
|
{
|
||||||
|
|
||||||
|
size_t serialize_proto_to_nng(const google::protobuf::MessageLite &message, nng_msg *msg)
|
||||||
|
{
|
||||||
|
auto messageSize = message.ByteSizeLong();
|
||||||
|
|
||||||
|
if (auto res = nng_msg_realloc(msg, nng_msg_len(msg) + sizeof(u32) + messageSize))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*reinterpret_cast<u32 *>(nng_msg_body(msg)) = messageSize;
|
||||||
|
if (!message.SerializeToArray(reinterpret_cast<u8 *>(nng_msg_body(msg)) + sizeof(u32),
|
||||||
|
messageSize))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return sizeof(u32) + messageSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t deserialize_proto_from_nng(google::protobuf::MessageLite &message, nng_msg *msg)
|
||||||
|
{
|
||||||
|
if (nng_msg_len(msg) < sizeof(u32))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
auto messageSize = *reinterpret_cast<u32 *>(nng_msg_body(msg));
|
||||||
|
|
||||||
|
if (messageSize == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (nng_msg_len(msg) < sizeof(u32) + messageSize)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!message.ParseFromArray(reinterpret_cast<u8 *>(nng_msg_body(msg)) + sizeof(u32),
|
||||||
|
messageSize))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sizeof(u32) + messageSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t deserialize_proto_from_nng_trim(google::protobuf::MessageLite &message, nng_msg *msg)
|
||||||
|
{
|
||||||
|
if (auto result = deserialize_proto_from_nng(message, msg))
|
||||||
|
{
|
||||||
|
nng_msg_trim(msg, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mesytec::mnode::nng
|
|
@ -2,8 +2,9 @@
|
||||||
|
|
||||||
#include <mesytec-mvlc/mesytec-mvlc.h>
|
#include <mesytec-mvlc/mesytec-mvlc.h>
|
||||||
#include <mesytec-mvlc/util/signal_handling.h>
|
#include <mesytec-mvlc/util/signal_handling.h>
|
||||||
#include <mesytec-mnode/mnode_nng_async.h>
|
|
||||||
#include <mesytec-mnode/mnode_cpp_types.h>
|
#include <mesytec-mnode/mnode_cpp_types.h>
|
||||||
|
#include <mesytec-mnode/mnode_nng_async.h>
|
||||||
|
#include <mesytec-mnode/mnode_nng_proto.h>
|
||||||
#include "internal/argh.h"
|
#include "internal/argh.h"
|
||||||
#include "proto/google/rpc/code.pb.h"
|
#include "proto/google/rpc/code.pb.h"
|
||||||
#include "proto/mrpc.pb.h"
|
#include "proto/mrpc.pb.h"
|
||||||
|
@ -12,39 +13,7 @@
|
||||||
|
|
||||||
using namespace mesytec;
|
using namespace mesytec;
|
||||||
using namespace std::literals;
|
using namespace std::literals;
|
||||||
using namespace mesytec::mnode::cpp_types;
|
using namespace mesytec::mnode;
|
||||||
|
|
||||||
class MVLCService: public mnode::proto::mvlc::MVLCService
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit MVLCService(mesytec::mvlc::MVLC mvlc)
|
|
||||||
: mvlc_(mvlc)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
void ReadRegister(::google::protobuf::RpcController *controller,
|
|
||||||
const mnode::proto::mvlc::ReadRegisterRequest *request,
|
|
||||||
mnode::proto::mvlc::ReadRegisterResponse *response,
|
|
||||||
::google::protobuf::Closure *done) override
|
|
||||||
{
|
|
||||||
spdlog::info("MVLCService::ReadRegister");
|
|
||||||
u32 value;
|
|
||||||
if (auto ec = mvlc_.readRegister(request->address(), value))
|
|
||||||
{
|
|
||||||
response->mutable_status()->set_code(ec.value());
|
|
||||||
response->mutable_status()->set_message(ec.message());
|
|
||||||
controller->SetFailed(ec.message());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
response->set_value(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
done->Run();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
mesytec::mvlc::MVLC mvlc_;
|
|
||||||
};
|
|
||||||
|
|
||||||
void print_service_descriptors(google::protobuf::Service &service)
|
void print_service_descriptors(google::protobuf::Service &service)
|
||||||
{
|
{
|
||||||
|
@ -62,20 +31,32 @@ void print_service_descriptors(google::protobuf::Service &service)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RPCClosure: public google::protobuf::Closure
|
struct RpcClosure: public google::protobuf::Closure
|
||||||
{
|
{
|
||||||
void Run() override { }
|
void Run() override { }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RPCController: public google::protobuf::RpcController
|
struct RpcController: public google::protobuf::RpcController
|
||||||
{
|
{
|
||||||
void Reset() override { }
|
void Reset() override
|
||||||
bool Failed() const override { return false; }
|
{
|
||||||
std::string ErrorText() const override { return ""; }
|
failed_ = false;
|
||||||
|
canceled_ = false;
|
||||||
|
errorText_.clear();
|
||||||
|
cancelCallback_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Failed() const override { return failed_; }
|
||||||
|
std::string ErrorText() const override { return errorText_; }
|
||||||
void StartCancel() override { }
|
void StartCancel() override { }
|
||||||
void SetFailed(const std::string &reason) override { }
|
void SetFailed(const std::string &reason) override { errorText_ = reason; failed_ = true; }
|
||||||
bool IsCanceled() const override { return false; }
|
bool IsCanceled() const override { return canceled_; }
|
||||||
void NotifyOnCancel(google::protobuf::Closure *callback) override { }
|
void NotifyOnCancel(google::protobuf::Closure *callback) override { cancelCallback_ = callback; }
|
||||||
|
|
||||||
|
bool failed_ = false;
|
||||||
|
bool canceled_ = false;
|
||||||
|
std::string errorText_;
|
||||||
|
google::protobuf::Closure *cancelCallback_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RpcChannel: public google::protobuf::RpcChannel
|
struct RpcChannel: public google::protobuf::RpcChannel
|
||||||
|
@ -85,17 +66,12 @@ struct RpcChannel: public google::protobuf::RpcChannel
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int send_request(const mnode::proto::mrpc::MethodCall &methodCall)
|
void fail(google::protobuf::RpcController *controller, const std::string &reason, google::rpc::Code code)
|
||||||
{
|
{
|
||||||
auto methodCallSize = methodCall.ByteSizeLong();
|
controller->SetFailed(reason);
|
||||||
auto msg = mnode::nng::allocate_message(sizeof(u32) + methodCallSize);
|
callResponse_.mutable_status()->set_code(code);
|
||||||
*reinterpret_cast<u32 *>(nng_msg_body(msg.get())) = methodCallSize;
|
callResponse_.mutable_status()->set_message(reason);
|
||||||
if (!methodCall.SerializeToArray(reinterpret_cast<u8 *>(nng_msg_body(msg.get())) + sizeof(u32), methodCallSize))
|
callResponse_.mutable_status()->clear_details();
|
||||||
{
|
|
||||||
spdlog::error("methodCall.SerializeToArray failed");
|
|
||||||
}
|
|
||||||
spdlog::info("sending request: nng_msg_len={}, methodCallSize={}", nng_msg_len(msg.get()), methodCallSize);
|
|
||||||
return mnode::nng::send_message(socket_, msg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallMethod(const google::protobuf::MethodDescriptor *method,
|
void CallMethod(const google::protobuf::MethodDescriptor *method,
|
||||||
|
@ -109,9 +85,25 @@ struct RpcChannel: public google::protobuf::RpcChannel
|
||||||
|
|
||||||
methodCall_.set_service(method->service()->full_name());
|
methodCall_.set_service(method->service()->full_name());
|
||||||
methodCall_.set_method(method->full_name());
|
methodCall_.set_method(method->full_name());
|
||||||
methodCall_.mutable_request()->PackFrom(*request);
|
|
||||||
|
|
||||||
if (auto nng_res = send_request(methodCall_))
|
if (!methodCall_.mutable_request()->PackFrom(*request))
|
||||||
|
{
|
||||||
|
fail(controller, "PackFrom failed", google::rpc::Code::INTERNAL);
|
||||||
|
spdlog::error("PackFrom failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto msg = mnode::nng::allocate_message(0);
|
||||||
|
|
||||||
|
if (mnode::nng::serialize_proto_to_nng(methodCall_, msg.get()) == 0)
|
||||||
|
{
|
||||||
|
spdlog::error("serialize_proto_to_nng failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
spdlog::info("sending request: nng_msg_len={}", nng_msg_len(msg.get()));
|
||||||
|
|
||||||
|
if (auto nng_res = mnode::nng::send_message(socket_, msg))
|
||||||
{
|
{
|
||||||
spdlog::error("nng_sendmsg: {}", nng_strerror(nng_res));
|
spdlog::error("nng_sendmsg: {}", nng_strerror(nng_res));
|
||||||
return;
|
return;
|
||||||
|
@ -130,7 +122,19 @@ struct RpcChannel: public google::protobuf::RpcChannel
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto callResponseSize = mnode::nng::msg_trim_read<u32>(nng_response.get());
|
if (mnode::nng::deserialize_proto_from_nng_trim(callResponse_, nng_response.get()) == 0)
|
||||||
|
{
|
||||||
|
spdlog::error("deserialize_proto_from_nng_trim failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!callResponse_.response().UnpackTo(response))
|
||||||
|
{
|
||||||
|
spdlog::error("UnpackTo failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
done->Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
nng_socket socket_;
|
nng_socket socket_;
|
||||||
|
@ -151,8 +155,8 @@ int main()
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
RPCController rpcController;
|
RpcController rpcController;
|
||||||
RPCClosure done;
|
RpcClosure done;
|
||||||
RpcChannel rpcChannel(socket);
|
RpcChannel rpcChannel(socket);
|
||||||
mnode::proto::mvlc::MVLCService::Stub mvlcService(&rpcChannel);
|
mnode::proto::mvlc::MVLCService::Stub mvlcService(&rpcChannel);
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
using namespace mesytec;
|
using namespace mesytec;
|
||||||
using namespace std::literals;
|
using namespace std::literals;
|
||||||
using namespace mesytec::mnode::cpp_types;
|
using namespace mesytec::mnode;
|
||||||
|
|
||||||
class MVLCService: public mnode::proto::mvlc::MVLCService
|
class MVLCService: public mnode::proto::mvlc::MVLCService
|
||||||
{
|
{
|
||||||
|
@ -95,23 +95,20 @@ void print_service_descriptors(google::protobuf::Service &service)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RPCClosure: public google::protobuf::Closure
|
struct RpcClosure: public google::protobuf::Closure
|
||||||
{
|
{
|
||||||
void Run() override {}
|
void Run() override {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RPCController: public google::protobuf::RpcController
|
struct RpcController: public google::protobuf::RpcController
|
||||||
{
|
{
|
||||||
void Reset() override
|
void Reset() override { spdlog::debug("RpcController::Reset"); }
|
||||||
{
|
|
||||||
spdlog::debug("RPCController::Reset");
|
|
||||||
}
|
|
||||||
bool Failed() const override { return false; }
|
bool Failed() const override { return false; }
|
||||||
std::string ErrorText() const override { return ""; }
|
std::string ErrorText() const override { return ""; }
|
||||||
void StartCancel() override {}
|
void StartCancel() override {}
|
||||||
void SetFailed(const std::string &reason) override
|
void SetFailed(const std::string &reason) override
|
||||||
{
|
{
|
||||||
spdlog::error("RPCController::SetFailed: reason={}", reason);
|
spdlog::error("RpcController::SetFailed: reason={}", reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsCanceled() const override { return false; }
|
bool IsCanceled() const override { return false; }
|
||||||
|
@ -122,8 +119,7 @@ struct RpcChannel: public google::protobuf::RpcChannel
|
||||||
{
|
{
|
||||||
void CallMethod(const google::protobuf::MethodDescriptor *method,
|
void CallMethod(const google::protobuf::MethodDescriptor *method,
|
||||||
google::protobuf::RpcController *controller,
|
google::protobuf::RpcController *controller,
|
||||||
const google::protobuf::Message *request,
|
const google::protobuf::Message *request, google::protobuf::Message *response,
|
||||||
google::protobuf::Message *response,
|
|
||||||
google::protobuf::Closure *done) override
|
google::protobuf::Closure *done) override
|
||||||
{
|
{
|
||||||
spdlog::info("RpcChannel::CallMethod: method={}, request={}, response={}",
|
spdlog::info("RpcChannel::CallMethod: method={}, request={}, response={}",
|
||||||
|
@ -131,6 +127,39 @@ struct RpcChannel: public google::protobuf::RpcChannel
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool serialize_proto_to_nng(const google::protobuf::MessageLite &message, nng_msg *msg)
|
||||||
|
{
|
||||||
|
auto messageSize = message.ByteSizeLong();
|
||||||
|
|
||||||
|
if (auto res = nng_msg_realloc(msg, nng_msg_len(msg) + sizeof(u32) + messageSize); res != 0)
|
||||||
|
{
|
||||||
|
spdlog::error("nng_msg_realloc: {}", nng_strerror(res));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*reinterpret_cast<u32 *>(nng_msg_body(msg)) = messageSize;
|
||||||
|
return message.SerializeToArray(reinterpret_cast<u8 *>(nng_msg_body(msg)) + sizeof(u32),
|
||||||
|
messageSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool deserialize_proto_from_nng(google::protobuf::MessageLite &message, nng_msg *msg)
|
||||||
|
{
|
||||||
|
auto messageSize = mnode::nng::msg_trim_read<u32>(msg);
|
||||||
|
|
||||||
|
if (!messageSize)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (nng_msg_len(msg) < *messageSize)
|
||||||
|
{
|
||||||
|
spdlog::error("message too short");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ret = message.ParseFromArray(reinterpret_cast<u8 *>(nng_msg_body(msg)), *messageSize);
|
||||||
|
nng_msg_trim(msg, *messageSize);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
struct RPCServer
|
struct RPCServer
|
||||||
{
|
{
|
||||||
explicit RPCServer(nng_socket socket)
|
explicit RPCServer(nng_socket socket)
|
||||||
|
@ -268,8 +297,8 @@ struct RPCServer
|
||||||
nng_socket socket_;
|
nng_socket socket_;
|
||||||
std::unordered_map<std::string, google::protobuf::Service *> services_;
|
std::unordered_map<std::string, google::protobuf::Service *> services_;
|
||||||
std::unordered_map<std::string, const google::protobuf::MethodDescriptor *> methods_;
|
std::unordered_map<std::string, const google::protobuf::MethodDescriptor *> methods_;
|
||||||
RPCClosure done_;
|
RpcClosure done_;
|
||||||
RPCController controller_;
|
RpcController controller_;
|
||||||
};
|
};
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
|
|
Loading…
Reference in a new issue