47 #ifndef _MIRA_RPCSERVER_H_ 48 #define _MIRA_RPCSERVER_H_ 53 #include <boost/preprocessor/repetition.hpp> 54 #include <boost/thread/mutex.hpp> 122 template<
typename Reflector>
125 r.member(
"Name",
name,
"");
162 mReflectMethodParamsDocumentation =
false;
164 <<
"MIRA_RPC_METHODS_REFLECT_NO_PARAMS_DOCUMENTATION " 165 <<
"- RPC parameter documentation will not be shared with " 166 <<
"remote frameworks (ensuring backward compatibility)";
175 bool mReflectMethodParamsDocumentation;
188 template<
typename Reflector>
194 r.member(
"Comment",
comment,
"");
205 template<
typename Reflector>
211 version = r.version(2,
this);
214 r.member(
"Comment",
comment,
"");
223 template<
typename Stream>
230 template<
typename Stream>
280 template<
typename Backend>
283 invokers.insert(std::make_pair(typeId<Backend>(),
284 boost::shared_ptr<RPCInvoker>(invoker)));
288 std::map<int, boost::shared_ptr<RPCInvoker>>
invokers;
301 template <
typename TMethodSet>
307 template<
typename Reflector>
310 r.member(
"Name",
name,
"");
311 r.member(
"Methods",
methods,
"");
355 mService(iService) {}
361 template <
typename Base>
371 return mAddedMethods;
376 return mAddedInterfaces;
382 if(mService.
interfaces.insert(std::string(name)).second)
383 mAddedInterfaces.insert(std::string(name));
386 template<
typename R,
typename... Args,
typename F,
typename... Description>
388 method(
const char*, F&&, Description&&...)
393 template<
typename F,
typename... Description>
395 method(
const char*, F&&, Description&&...)
400 template<
typename R,
typename Class,
typename... Args,
typename... Description>
407 template<
typename R,
typename Class,
typename... Args,
typename... Description>
414 template<
typename R,
typename... Args,
typename F,
typename... Description>
416 method(
const char* name, F&& fn, Description&&... descriptions)
418 concreteMethod<R, Args...>(name, std::forward<F>(fn), std::forward<Description>(descriptions)...);
421 template<
typename F,
typename... Description>
423 method(
const char* name, F&& fn, Description&&... descriptions)
425 concreteMethodHelper<typename Private::FunctionTraits<F>::ReturnValue>(
427 std::forward<Description>(descriptions)...);
430 template<
typename R,
typename Class,
typename... Args,
typename... Description>
432 method(
const char* name, R (
Class::*fn)(Args...),
Class* This, Description&&... descriptions)
435 concreteMethod<R, Args...>(name, std::move(func), std::forward<Description>(descriptions)...);
438 template<
typename R,
typename Class,
typename... Args,
typename... Description>
440 method(
const char* name, R (
Class::*fn)(Args...)
const,
Class* This, Description&&... descriptions)
443 concreteMethod<R, Args...>(name, std::move(func), std::forward<Description>(descriptions)...);
447 template<
typename R,
typename... Args,
typename F,
typename... Description>
449 Description&&... descriptions)
451 concreteMethod<R, Args...>(name, std::forward<F>(fn), std::forward<Description>(descriptions)...);
454 template<
typename R,
typename... Args,
typename F,
typename Comment,
typename... Description>
455 void concreteMethod(
const char* name, F&& fn, Comment&& comment, Description&&... descriptions)
457 Method m(makeRPCSignature<R, Args...>(name), std::forward<Comment>(comment));
458 m.parameterDesc.reserve(
sizeof...(Args));
459 addParameterDescription<Args...>(m, std::forward<Description>(descriptions)...);
460 m.addInvoker(make_RPCInvoker<BinaryRPCBackend, R, Args...>(fn));
461 m.addInvoker(make_RPCInvoker<BinaryRPCBackendLegacy, R, Args...>(fn));
462 m.addInvoker(make_RPCInvoker<JSONRPCBackend, R, Args...>(fn));
468 void addMethod(
const Method&
method) {
469 foreach (
const MethodInfo& m, mService.
methods) {
471 if ((m.signature.name ==
method.signature.name) &&
472 (m.signature.parameterTypes.size() ==
method.signature.parameterTypes.size())) {
475 <<
" are ambiguous when called through JSON RPC" 476 <<
" - choosing different method names is strongly recommended!";
481 mAddedMethods.insert(
method.signature);
485 template<
typename... RECURSIONSTOP>
486 typename std::enable_if<(
sizeof...(RECURSIONSTOP)) == 0>
::type addParameterDescription(Method& m)
489 template<
typename ParameterType,
typename... Args>
490 MIRA_DEPRECATED(
"_________________Please provide parameter descriptions (and sample values, if appropriate) for RPC methods!_________________",
491 void addParameterDescription(Method& m)
493 m.parameterSamples.emplace_back(createParameterSample<Private::StrippedType<ParameterType>>());
494 addParameterDescription<Args...>(m);
498 template<
typename ParameterType,
typename... Args,
class Name,
class Description,
typename... Tail,
499 typename =
typename std::enable_if<(
sizeof...(Args)) * 2 ==
sizeof...(Tail)>
::type>
500 void addParameterDescription(Method& m, Name&& name, Description&& description, Tail&&... tail)
502 m.parameterDesc.emplace_back(std::forward<Name>(name), std::forward<Description>(description));
503 m.parameterSamples.emplace_back(createParameterSample<Private::StrippedType<ParameterType>>());
504 addParameterDescription<Args...>(m, std::forward<Tail>(tail)...);
507 template<
typename ParameterType,
typename... Args,
class Name,
class Description,
class Example,
509 typename =
typename std::enable_if<(
sizeof...(Args)) * 3 ==
sizeof...(Tail)>::
type>
510 void addParameterDescription(Method& m, Name&& name, Description&& description, Example&& example,
513 m.parameterDesc.emplace_back(std::forward<Name>(name), std::forward<Description>(description));
514 m.parameterSamples.emplace_back(
515 createParameterSample<Private::StrippedType<ParameterType>>(std::forward<Example>(example)));
516 m.parameterSamplesDefault =
false;
518 addParameterDescription<Args...>(m, std::forward<Tail>(tail)...);
522 json::Value createParameterSample(
const T& v = T())
524 return mJSONSerializer.serialize(v);
528 JSONSerializer mJSONSerializer;
536 std::set<RPCSignature> mAddedMethods;
539 std::set<std::string> mAddedInterfaces;
551 template <
typename T>
554 std::set<RPCSignature>* addedMethods = NULL,
555 std::set<std::string>* addedInterfaces = NULL)
557 boost::mutex::scoped_lock lock(mMutex);
560 ServiceMap::iterator it = mServices.find(serviceName);
561 if (it==mServices.end())
562 it = mServices.insert(std::make_pair(serviceName,
568 serviceObject.reflect(r);
571 serviceName <<
"'. With the following new methods:";
575 if(addedMethods!=NULL)
578 if(addedInterfaces!=NULL)
590 boost::mutex::scoped_lock lock(mMutex);
591 MIRA_LOG(
NOTICE) <<
"Unregistering service: '" << serviceName <<
"'.";
592 mServices.erase(serviceName);
612 boost::mutex::scoped_lock lock(mMutex);
613 auto i = mServices.find(name);
614 if (i == mServices.end())
615 MIRA_THROW(XInvalidParameter,
"No such service '" << name <<
"'");
625 boost::mutex::scoped_lock lock(mMutex);
626 auto i = mServices.find(name);
627 return i!= mServices.end();
636 boost::mutex::scoped_lock lock(mMutex);
637 std::list<std::string> res;
639 for(
auto it=mServices.begin(); it!=mServices.end(); ++it)
641 if(it->second.interfaces.count(interface)!=0)
642 res.push_back(it->second.name);
651 boost::mutex::scoped_lock lock(mMutex);
652 auto it = mServices.find(name);
653 if (it == mServices.end())
655 return it->second.interfaces.count(interface) > 0;
666 template <
typename Backend>
668 typename Backend::ServerResponse& response)
670 boost::shared_ptr<TRPCInvoker<Backend>> invoker;
675 if(!processCallCommon<Backend>(request, response, callId, invoker, service, method))
679 response.setHeader(callId);
682 invoker->invoke(request, response);
684 catch(std::exception& ex) {
698 template <
typename Backend>
703 typename Backend::ServerResponse& response,
704 const std::string& callId,
705 const std::string& service,
706 const std::string& method,
709 mRequest(request), mResponse(response),
716 mInvoker->invoke(mRequest, mResponse);
718 catch(std::exception& ex) {
726 }
catch(std::exception& ex) {
732 typename Backend::ServerRequest& mRequest;
733 typename Backend::ServerResponse& mResponse;
734 boost::shared_ptr<TRPCInvoker<Backend>> mInvoker;
748 template <
typename Backend>
750 typename Backend::ServerResponse& response)
752 boost::shared_ptr<TRPCInvoker<Backend>> invoker;
758 if(processCallCommon<Backend>(request, response, callId, invoker, service, method)) {
759 assert(service!=NULL);
764 return deferredInvoker;
774 template <
typename Backend>
776 typename Backend::ServerResponse& response,
777 std::string &oCallId,
783 std::string serviceStr;
786 request.getHeader(callId, serviceStr);
787 }
catch(std::exception& ex) {
794 boost::mutex::scoped_lock lock(mMutex);
797 auto serviceIt = mServices.find(serviceStr);
799 if(serviceIt==mServices.end()) {
802 "Cannot process RPC call, a service named '" 803 + serviceStr +
"' does not exist", response);
807 Service& service = serviceIt->second;
815 if(request.checkSignature(m.
signature)) {
817 method =
const_cast<Method*
>(&m);
825 std::string methodName = request.getSignature().name;
826 std::string candidates;
830 if(!candidates.empty())
836 if(!candidates.empty())
837 candidates =
" Candidates are: " + candidates;
839 candidates =
" No candidates found.";
843 <<
", candidates: " << candidates;
844 generateErrorResponse<Backend>(callId,
846 serviceStr +
"' does not have a method '" +
847 toString(request.getSignature()) +
"'." + candidates,
853 auto invokerIt = method->
invokers.find(typeId<Backend>());
854 if(invokerIt == method->
invokers.end())
855 MIRA_THROW(XLogical,
"Cannot process RPC call, no invoker for service method '" <<
856 serviceStr <<
"." << request.getSignature() <<
857 "' was registered for backend type '" <<
858 typeName<Backend>() <<
"'.");
870 template <
typename Backend>
872 RPCError reason,
const std::string& message,
873 typename Backend::ServerResponse& oResponse)
875 oResponse.setHeader(callId);
876 oResponse.returnException(reason, message);
882 mutable boost::mutex mMutex;
DeferredInvoker(typename Backend::ServerRequest &request, typename Backend::ServerResponse &response, const std::string &callId, const std::string &service, const std::string &method, boost::shared_ptr< TRPCInvoker< Backend >> invoker)
Definition: RPCServer.h:702
ServiceInfo< MethodSet > Service
Definition: RPCServer.h:323
MethodInfo(const RPCSignature &iSignature, const std::string &iComment)
Definition: RPCServer.h:180
Definition: BinarySerializer.h:324
Contains all available information about a single RPC service, including the service' name...
Definition: RPCServer.h:302
AbstractDeferredInvokerPtr processCallDeferred(typename Backend::ServerRequest &request, typename Backend::ServerResponse &response)
Similar to processCall() this method decodes the RPCRequest which was received from the client-side...
Definition: RPCServer.h:749
void unregisterService(const std::string &serviceName)
Unregisters the specified service with all methods of all service objects that were registered...
Definition: RPCServer.h:588
Method(const RPCSignature &signature, const std::string &comment, const ParameterDescriptions ¶meterDescriptions)
Definition: RPCServer.h:275
Provides binary client and server side requests and responses.
bool implementsInterface(const std::string &name, const std::string &interface) const
Returns if the given service implements a certain interface.
Definition: RPCServer.h:649
std::string comment
User comments and description.
Definition: RPCServer.h:255
Definition: RPCPatternCheck.h:82
Contains information on an RPC method's parameter: name, description.
Definition: RPCServer.h:115
Invalid parameters were specified for the method.
Definition: RPCError.h:68
void reflect(ConcreteBinarySerializer< Stream, 0 > &r)
Definition: RPCServer.h:224
RPCReflector(Service &iService)
Definition: RPCServer.h:354
const std::set< std::string > & getAddedInterfaces() const
Returns all interfaces that were added to the service while visiting the service object.
Definition: RPCServer.h:375
ValidRPCDescription< R(Class::*)(Args...), Description... > method(const char *name, R(Class::*fn)(Args...), Class *This, Description &&... descriptions)
Definition: RPCServer.h:432
Implementation of the CreationPolicy that is used by the Singleton template.
Definition: Singleton.h:174
Contains information on an existing RPC method: the signature of the method, comments, etc.
Definition: RPCServer.h:150
MethodInfo()
Definition: RPCServer.h:178
static Type & instance()
Returns a reference to the singleton instance.
Definition: Singleton.h:544
bool existsService(const std::string &name) const
Returns true, if a service with the specified name exists, otherwise false.
Definition: RPCServer.h:623
InvalidRPCDescription< R(Args...), Description... > method(const char *, F &&, Description &&...)
Definition: RPCServer.h:388
specialize cv::DataType for our ImgPixel and inherit from cv::DataType<Vec>
Definition: IOService.h:67
Error codes for reasons of errors/exceptions while processing an rpc call.
std::map< int, boost::shared_ptr< RPCInvoker > > invokers
stores corresponding RPCInvoker for each backend type
Definition: RPCServer.h:288
InvalidRPCDescription< R(Class::*)(Args...) const, Description... > method(const char *, R(Class::*)(Args...) const, Class *, Description &&...)
Definition: RPCServer.h:409
ReflectMethodParamsDocumentation()
Definition: RPCServer.h:157
Invoker that is used to invoke an RPC method call for a special backend.
Definition: RPCInvoker.h:94
#define MIRA_LOG(level)
Use this macro to log data.
Definition: LoggingCore.h:529
std::string description
Parameter description.
Definition: RPCServer.h:133
Class object which supports some kind of class reflection.
Definition: Class.h:97
std::list< json::Value > parameterSamples
Definition: RPCServer.h:262
ParameterInfo()
Definition: RPCServer.h:117
Abstract interface for DeferredInvoker which is a class to support different RPC backends.
Definition: AbstractDeferredInvoker.h:80
Contains toString and fromString functions for converting data types to strings and the other way rou...
Definition: BinarySerializer.h:991
std::string extendedSignature() const
void reflect(Reflector &r)
Definition: RPCServer.h:123
Definition: RPCServer.h:152
bool processCallCommon(typename Backend::ServerRequest &request, typename Backend::ServerResponse &response, std::string &oCallId, boost::shared_ptr< TRPCInvoker< Backend >> &oInvoker, Service *&oService, Method *&oMethod)
contains common functionality that is used by processCall() and processCallDeferred() ...
Definition: RPCServer.h:775
uint8 VersionType
Definition: ReflectorInterface.h:72
#define MIRA_THROW(ex, msg)
Macro for throwing an exception.
Definition: Exception.h:82
This is the public interface of all reflectors that are able to visit a class' reflect() method...
Definition: ReflectorInterface.h:111
Provides JSON client and server side requests and responses.
Definition: RPCInvoker.h:181
std::string toString(const T &value, int precision=-1)
Converts any data type to string (the data type must support the stream << operator).
Definition: ToString.h:256
void reflectBinaryV0(Reflector &r)
Definition: RPCServer.h:206
const Service & registerServiceObject(const std::string &serviceName, T &serviceObject, std::set< RPCSignature > *addedMethods=NULL, std::set< std::string > *addedInterfaces=NULL)
Registers the methods of the specified service object under the specified service name...
Definition: RPCServer.h:552
TMethodSet methods
All methods that were registered for this service.
Definition: RPCServer.h:318
Contains the base interface of all Reflectors, Serializers, etc.
Special visitor for the reflect() method that visits all method() and interface() calls within the re...
Definition: RPCServer.h:339
void interface(const char *name)
Definition: RPCServer.h:381
Auxiliary logging macros for special entities like exceptions, etc.
InvalidRPCDescription< F, Description... > method(const char *, F &&, Description &&...)
Definition: RPCServer.h:395
A singleton template class that can be freely configured using policies that control the instantiatio...
Definition: Singleton.h:531
MIRA_BASE_EXPORT std::string resolveEnvironmentVariable(const std::string &envVar)
Resolves an environmental variable.
PropertyHint type(const std::string &t)
Sets the attribute "type" to the specified value.
Definition: PropertyHint.h:295
Core class of the logging library.
std::string name
Parameter name.
Definition: RPCServer.h:130
RPCSignature for storing all information about an RPC method signature.
Contains all information on a registered RPC method, including the signature of the method...
Definition: RPCServer.h:270
Implements the RPCInvoker and TRPCInvoker classes.
bool operator<(const MethodInfo &rhs) const
Definition: RPCServer.h:236
void reflect(Reflector &r)
Definition: RPCServer.h:308
Abstract interface for DeferredInvoker.
ServiceInfo(const std::string &iName="")
Definition: RPCServer.h:304
std::string sampleParametersSet(bool formatted=false) const
std::string name
The method's name.
Definition: RPCSignature.h:134
std::string mCallId
Definition: AbstractDeferredInvoker.h:113
bool operator==(const MethodInfo &rhs) const
Definition: RPCServer.h:240
void generateErrorResponse(const std::string &callId, RPCError reason, const std::string &message, typename Backend::ServerResponse &oResponse)
Definition: RPCServer.h:871
RPCError
enumeration of possible reasons for errors/exceptions while performing an RPC call ...
Definition: RPCError.h:64
typename std::enable_if< Private::rpc::isValid< F, Description... >()>::type ValidRPCDescription
Definition: RPCPatternCheck.h:307
const std::set< RPCSignature > & getAddedMethods() const
Returns all methods that were added to the service while visiting the service object.
Definition: RPCServer.h:370
typename std::enable_if<!Private::rpc::isValid< F, Description... >()>::type InvalidRPCDescription
Definition: RPCPatternCheck.h:310
json_spirit::mValue Value
A value is an abstract description of data in JSON (underlying data can either be one of the JSON bas...
Definition: JSON.h:176
virtual void invoke()
Invokes the RPC call that is represented by this DeferredInvoker.
Definition: RPCServer.h:712
void addInvoker(TRPCInvoker< Backend > *invoker)
adds a new invoker that processes the method for a certain backend
Definition: RPCServer.h:281
void processCall(typename Backend::ServerRequest &request, typename Backend::ServerResponse &response)
Decodes the Request which was received from the client-side and invokes the RPC call immediately...
Definition: RPCServer.h:667
void reflectBase(Base &base)
implements ReflectorInterface (for documentation see ReflectorInterface)
Definition: RPCServer.h:362
InvalidRPCDescription< R(Class::*)(Args...), Description... > method(const char *, R(Class::*)(Args...), Class *, Description &&...)
Definition: RPCServer.h:402
std::list< std::string > queryServicesForInterface(const std::string &interface) const
Returns a string list with the names of all registered services, that implement the specified interfa...
Definition: RPCServer.h:634
#define MIRA_LOG_EXCEPTION(level, ex)
Log the specified exception, including all information that the exception object carries.
Definition: LoggingAux.h:107
std::set< MethodInfo > MethodInfoSet
Definition: RPCServer.h:293
std::map< std::string, Service > ServiceMap
Definition: RPCServer.h:325
Definition: RPCPatternCheck.h:88
Definition: LoggingCore.h:76
ValidRPCDescription< R(Class::*)(Args...) const, Description... > method(const char *name, R(Class::*fn)(Args...) const, Class *This, Description &&... descriptions)
Definition: RPCServer.h:440
Functions for platform independent resolving of environment variables.
friend std::ostream & operator<<(std::ostream &s, const ParameterInfo &v)
Definition: RPCServer.h:137
RPCSignature signature
The signature of the method (including its name)
Definition: RPCServer.h:252
std::set< Method > MethodSet
Definition: RPCServer.h:291
std::set< std::string > interfaces
All interfaces that this service supports.
Definition: RPCServer.h:320
Requested method was not found.
Definition: RPCError.h:67
std::string name
The name of this service.
Definition: RPCServer.h:316
void reflect(ConcreteBinaryDeserializer< Stream, 0 > &r)
Definition: RPCServer.h:231
static bool enabled()
Definition: RPCServer.h:172
Definition: LoggingCore.h:75
const ServiceMap & getServices() const
Returns the map with all known services.
Definition: RPCServer.h:600
Stores the signature of an RPC method including the methods name and its parameter types...
Definition: RPCSignature.h:68
ParameterDescriptions parameterDesc
User info on method parameters.
Definition: RPCServer.h:258
The request is invalid or can not be parsed.
Definition: RPCError.h:66
virtual void onRPCfinished(AbstractDeferredInvoker *invoker)=0
called upon finish of the RPC call, the ID of the call is passed as parameter.
void reflect(Reflector &r)
Definition: RPCServer.h:189
ParameterInfo(const std::string &iName, const std::string &iDescription)
Definition: RPCServer.h:119
const Service & getService(const std::string &name) const
Returns a reference to the service with the given name.
Definition: RPCServer.h:610
bool parameterSamplesDefault
Sample parameter values.
Definition: RPCServer.h:261
Method(const RPCSignature &signature, const std::string &comment)
Definition: RPCServer.h:272
boost::shared_ptr< AbstractDeferredInvoker > AbstractDeferredInvokerPtr
Definition: AbstractDeferredInvoker.h:119
std::string parameterDescriptions(const std::string &prefix="") const
The RPCServer is responsible for handling the server-side of an rpc call.
Definition: RPCServer.h:107
MethodInfo(const RPCSignature &iSignature, const std::string &iComment, const ParameterDescriptions &iParameterDescriptions)
Definition: RPCServer.h:183
std::vector< ParameterInfo > ParameterDescriptions
Definition: RPCServer.h:144
ValidRPCDescription< R(Args...), Description... > method(const char *name, F &&fn, Description &&... descriptions)
Definition: RPCServer.h:416
Definition: LoggingCore.h:77
constexpr std::enable_if<!FunctionTraits< F >::isFunction >::type invalidAssertion()
Definition: RPCPatternCheck.h:282
DeferredInvokerFinishHandler * mFinishHandler
Definition: AbstractDeferredInvoker.h:116
ValidRPCDescription< F, Description... > method(const char *name, F &&fn, Description &&... descriptions)
Definition: RPCServer.h:423
Stores all necessary information to invoke a previously decoded and prepared RPC call.
Definition: RPCServer.h:699