/* * Copyright © 2014 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Authored by: Alan Griffiths */ #ifndef ANBOX_RPC_TEMPLATE_MESSAGE_PROCESSOR_H_ #define ANBOX_RPC_TEMPLATE_MESSAGE_PROCESSOR_H_ #include #ifdef USE_PROTOBUF_CALLBACK_HEADER #include #endif #include "anbox/rpc/message_processor.h" #include "anbox_rpc.pb.h" namespace anbox { namespace rpc { // Utility metafunction result_ptr_t<> allows invoke() to pick the right // send_response() overload. The base template resolves to the prototype // "send_response(::google::protobuf::uint32 id, ::google::protobuf::Message* // response)" // Client code may specialize result_ptr_t to resolve to another overload. template struct result_ptr_t { typedef ::google::protobuf::MessageLite* type; }; // Boiler plate for unpacking a parameter message, invoking a server function, // and // sending the result message. Assumes the existence of Self::send_response(). template void invoke(Self* self, Bridge* rpc, void (BridgeX::*function)(ParameterMessage const* request, ResultMessage* response, ::google::protobuf::Closure* done), Invocation const& invocation) { ParameterMessage parameter_message; if (!parameter_message.ParseFromString(invocation.parameters())) throw std::runtime_error("Failed to parse message parameters!"); ResultMessage result_message; try { std::unique_ptr callback( google::protobuf::NewPermanentCallback< Self, ::google::protobuf::uint32, typename result_ptr_t::type>( self, &Self::send_response, invocation.id(), &result_message)); (rpc->*function)(¶meter_message, &result_message, callback.get()); } catch (std::exception const& x) { result_message.set_error(std::string("Error processing request: ") + x.what()); self->send_response(invocation.id(), &result_message); } } } // namespace rpc } // namespace anbox #endif