#include #include #include #include #include #include "internal/argh.h" #include "proto/google/rpc/code.pb.h" #include "proto/mrpc.pb.h" #include "proto/mvlc.pb.h" #include "proto/service.pb.h" using namespace mesytec; using namespace std::literals; using namespace mesytec::mnode::cpp_types; 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) { auto sd = service.GetDescriptor(); spdlog::info("service: full_name={}, index={}, method_count={}", sd->full_name(), sd->index(), sd->method_count()); for (int i = 0; i < sd->method_count(); ++i) { auto md = sd->method(i); auto it = md->input_type(); auto ot = md->output_type(); spdlog::info(" method: full_name={}, index={}, input_type={}, output_type={}", md->full_name(), md->index(), it->full_name(), ot->full_name()); } } struct RPCClosure: public google::protobuf::Closure { void Run() override { } }; struct RPCController: public google::protobuf::RpcController { void Reset() override { } bool Failed() const override { return false; } std::string ErrorText() const override { return ""; } void StartCancel() override { } void SetFailed(const std::string &reason) override { } bool IsCanceled() const override { return false; } void NotifyOnCancel(google::protobuf::Closure *callback) override { } }; struct RpcChannel: public google::protobuf::RpcChannel { explicit RpcChannel(nng_socket socket) : socket_(socket) { } int send_request(const mnode::proto::mrpc::MethodCall &methodCall) { auto methodCallSize = methodCall.ByteSizeLong(); auto msg = mnode::nng::allocate_message(sizeof(u32) + methodCallSize); *reinterpret_cast(nng_msg_body(msg.get())) = methodCallSize; if (!methodCall.SerializeToArray(reinterpret_cast(nng_msg_body(msg.get())) + sizeof(u32), methodCallSize)) { 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, google::protobuf::RpcController *controller, const google::protobuf::Message *request, google::protobuf::Message *response, google::protobuf::Closure *done) override { spdlog::info("RpcChannel::CallMethod: method={}, request={}, response={}", method->full_name(), request->ShortDebugString(), response->ShortDebugString()); methodCall_.set_service(method->service()->full_name()); methodCall_.set_method(method->full_name()); methodCall_.mutable_request()->PackFrom(*request); if (auto nng_res = send_request(methodCall_)) { spdlog::error("nng_sendmsg: {}", nng_strerror(nng_res)); return; } auto [nng_response, nng_res] = mnode::nng::receive_message(socket_); if (nng_res) { spdlog::error("nng_recvmsg: {}", nng_strerror(nng_res)); return; } else if (nng_res == NNG_ETIMEDOUT) { spdlog::trace("nng_recvmsg: NNG_ETIMEDOUT"); return; } auto callResponseSize = mnode::nng::msg_trim_read(nng_response.get()); } nng_socket socket_; mnode::proto::mrpc::MethodCall methodCall_; mnode::proto::mrpc::MethodCallResponse callResponse_; }; int main() { namespace nng = mnode::nng; spdlog::set_level(spdlog::level::debug); auto socket = nng::make_req_socket(); if (int res = nng_dial(socket, "tcp://localhost:5555", nullptr, NNG_FLAG_NONBLOCK)) { nng::mnode_nng_error("nng_dial", res); return res; } RPCController rpcController; RPCClosure done; RpcChannel rpcChannel(socket); mnode::proto::mvlc::MVLCService::Stub mvlcService(&rpcChannel); for (int i = 0; i < 10; ++i) { mnode::proto::vme::ReadRequest request; request.set_address(0xffff600e); request.mutable_amod()->set_value(mesytec::mvlc::vme_amods::A32); request.set_data_width(mnode::proto::vme::DataWidth::D32); mnode::proto::vme::ReadResponse response; spdlog::info("request: {}", request.ShortDebugString()); mvlcService.VMERead(&rpcController, &request, &response, &done); spdlog::info("response: {}", response.ShortDebugString()); } return 0; }