MIRA
RPCServer.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012 by
3  * MetraLabs GmbH (MLAB), GERMANY
4  * and
5  * Neuroinformatics and Cognitive Robotics Labs (NICR) at TU Ilmenau, GERMANY
6  * All rights reserved.
7  *
8  * Contact: info@mira-project.org
9  *
10  * Commercial Usage:
11  * Licensees holding valid commercial licenses may use this file in
12  * accordance with the commercial license agreement provided with the
13  * software or, alternatively, in accordance with the terms contained in
14  * a written agreement between you and MLAB or NICR.
15  *
16  * GNU General Public License Usage:
17  * Alternatively, this file may be used under the terms of the GNU
18  * General Public License version 3.0 as published by the Free Software
19  * Foundation and appearing in the file LICENSE.GPL3 included in the
20  * packaging of this file. Please review the following information to
21  * ensure the GNU General Public License version 3.0 requirements will be
22  * met: http://www.gnu.org/copyleft/gpl.html.
23  * Alternatively you may (at your option) use any later version of the GNU
24  * General Public License if such license has been publicly approved by
25  * MLAB and NICR (or its successors, if any).
26  *
27  * IN NO EVENT SHALL "MLAB" OR "NICR" BE LIABLE TO ANY PARTY FOR DIRECT,
28  * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
29  * THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF "MLAB" OR
30  * "NICR" HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * "MLAB" AND "NICR" SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
33  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
34  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
35  * ON AN "AS IS" BASIS, AND "MLAB" AND "NICR" HAVE NO OBLIGATION TO
36  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR MODIFICATIONS.
37  */
38 
47 #ifndef _MIRA_RPCSERVER_H_
48 #define _MIRA_RPCSERVER_H_
49 
50 #include <functional>
51 
52 #ifndef Q_MOC_RUN
53 #include <boost/thread/mutex.hpp>
54 #endif
55 
56 #include <platform/Environment.h>
57 
59 
60 #include <error/LoggingCore.h>
61 #include <error/LoggingAux.h>
62 
63 #include <rpc/RPCSignature.h>
64 #include <rpc/RPCInvoker.h>
65 #include <rpc/RPCError.h>
66 #include <rpc/BinaryRPCBackend.h>
67 #include <rpc/JSONRPCBackend.h>
68 
70 
71 #include <utils/ToString.h>
72 
73 namespace mira {
74 
76 
107 {
108 public:
109 
115  {
117 
118  ParameterInfo(const std::string& iName, const std::string& iDescription)
119  : name(iName), description(iDescription) {}
120 
121  template<typename Reflector>
122  void reflect(Reflector& r)
123  {
124  r.member("Name", name, "");
125  r.member("Description", description, "");
126  }
127 
129  std::string name;
130 
132  std::string description;
133 
134  public:
135 
136  friend std::ostream& operator<<(std::ostream& s, const ParameterInfo& v)
137  {
138  s << v.name << " \t: " << v.description;
139  return s;
140  }
141  };
142 
143  typedef std::vector<ParameterInfo> ParameterDescriptions;
144 
149  struct MethodInfo
150  {
151  class ReflectMethodParamsDocumentation : public Singleton<ReflectMethodParamsDocumentation>
152  {
154 
155  protected:
156  ReflectMethodParamsDocumentation() : mReflectMethodParamsDocumentation(true)
157  {
158  try {
159  resolveEnvironmentVariable("MIRA_RPC_METHODS_REFLECT_NO_PARAMS_DOCUMENTATION");
160  // if resolve succeeds (--> variable exists), do not reflect version and parameter documentation
161  mReflectMethodParamsDocumentation = false;
162  MIRA_LOG(WARNING) << "Found definition of environment variable "
163  << "MIRA_RPC_METHODS_REFLECT_NO_PARAMS_DOCUMENTATION "
164  << "- RPC parameter documentation will not be shared with "
165  << "remote frameworks (ensuring backward compatibility)";
166  }
167  catch(...) {}
168  }
169 
170  public:
171  static bool enabled() { return instance().mReflectMethodParamsDocumentation; }
172 
173  private:
174  bool mReflectMethodParamsDocumentation;
175  };
176 
178 
179  MethodInfo(const RPCSignature& iSignature, const std::string& iComment) :
180  signature(iSignature), comment(iComment), parameterSamplesDefault(true) {}
181 
182  MethodInfo(const RPCSignature& iSignature, const std::string& iComment,
183  const ParameterDescriptions& iParameterDescriptions) :
184  signature(iSignature), comment(iComment),
185  parameterDesc(iParameterDescriptions), parameterSamplesDefault(true) {}
186 
187  template<typename Reflector>
188  void reflect(Reflector& r)
189  {
190  serialization::VersionType version = r.version(3, this);
191 
192  r.member("Signature", signature, "");
193  r.member("Comment", comment, "");
194 
195  if (version >= 2) {
196  r.member("ParameterDescriptions", parameterDesc, "");
197  r.member("ParameterSamples", parameterSamples, "");
198 
199  if (version >= 3)
200  r.member("ParameterSamplesDefault", parameterSamplesDefault, "");
201  }
202  }
203 
204  template<typename Reflector>
205  void reflectBinaryV0(Reflector& r)
206  {
207  serialization::VersionType version = 0;
208 
210  version = r.version(2, this); // version 3 did not exist with serialization format v0
211 
212  r.member("Signature", signature, "");
213  r.member("Comment", comment, "");
214 
215  if (version >= 2) {
216  r.member("ParameterDescriptions", parameterDesc, "");
217  r.member("ParameterSamples", parameterSamples, "");
218  }
219  }
220 
221  // Specialization for serialization format v0
222  template<typename Stream>
224  {
225  reflectBinaryV0(r);
226  }
227 
228  // Specialization for deserialization format v0
229  template<typename Stream>
231  {
232  reflectBinaryV0(r);
233  }
234 
235  bool operator<(const MethodInfo& rhs) const {
236  return signature < rhs.signature;
237  }
238 
239  bool operator==(const MethodInfo& rhs) const {
240  return signature==rhs.signature;
241  }
242 
243  std::string extendedSignature() const;
244 
246  std::string parameterDescriptions(const std::string& prefix = "") const;
247 
248  std::string sampleParametersSet(bool formatted = false) const;
249 
252 
254  std::string comment;
255 
258 
261  std::list<json::Value> parameterSamples;
262  };
263 
269  struct Method : public MethodInfo
270  {
271  Method(const RPCSignature& signature, const std::string& comment) :
273 
274  Method(const RPCSignature& signature, const std::string& comment,
277 
279  template<typename Backend>
281  {
282  invokers.insert(std::make_pair(typeId<Backend>(),
283  boost::shared_ptr<RPCInvoker>(invoker)));
284  }
285 
287  std::map<int, boost::shared_ptr<RPCInvoker>> invokers;
288  };
289 
290  typedef std::set<Method> MethodSet;
291 
292  typedef std::set<MethodInfo> MethodInfoSet;
293 
294 
300  template <typename TMethodSet>
301  struct ServiceInfo
302  {
303  ServiceInfo(const std::string& iName="") :
304  name(iName) {}
305 
306  template<typename Reflector>
307  void reflect(Reflector& r)
308  {
309  r.member("Name", name, "");
310  r.member("Methods", methods, "");
311  r.member("Interfaces", interfaces, "");
312  }
313 
315  std::string name;
317  TMethodSet methods;
319  std::set<std::string> interfaces;
320  };
321 
323 
324  typedef std::map<std::string, Service> ServiceMap;
325 
326 
338  class RPCReflector : public ReflectorInterface<RPCReflector>
339  {
340  public:
341 
353  RPCReflector(Service& iService) :
354  mService(iService) {}
355 
356 
357  public:
358 
360  template <typename Base>
361  void reflectBase(Base& base) {
362  // simplified (compared to AbstractReflector), but should be enough for the RPCServer
363  base.reflect(*this);
364  }
365 
366  public:
367 
369  const std::set<RPCSignature>& getAddedMethods() const {
370  return mAddedMethods;
371  }
372 
374  const std::set<std::string>& getAddedInterfaces() const {
375  return mAddedInterfaces;
376  }
377 
378  public:
379 
380  void interface(const char* name) {
381  if(mService.interfaces.insert(std::string(name)).second)
382  mAddedInterfaces.insert(std::string(name));
383  }
384 
385  template<typename R, typename... Args, typename F, typename... Description>
386  InvalidRPCDescription<R(Args...), Description...>
387  method(const char*, F&&, Description&&...)
388  {
389  Private::rpc::invalidAssertion<R(Args...), Description...>();
390  }
391 
392  template<typename F, typename... Description>
393  InvalidRPCDescription<F, Description...>
394  method(const char*, F&&, Description&&...)
395  {
396  Private::rpc::invalidAssertion<F, Description...>();
397  }
398 
399  template<typename R, typename Class, typename... Args, typename... Description>
400  InvalidRPCDescription<R (Class::*)(Args...), Description...>
401  method(const char*, R (Class::*)(Args...), Class*, Description&&...)
402  {
403  Private::rpc::invalidAssertion<R (Class::*)(Args...), Description...>();
404  }
405 
406  template<typename R, typename Class, typename... Args, typename... Description>
407  InvalidRPCDescription<R (Class::*)(Args...) const, Description...>
408  method(const char*, R (Class::*)(Args...) const, Class*, Description&&...)
409  {
410  Private::rpc::invalidAssertion<R (Class::*)(Args...) const, Description...>();
411  }
412 
413  template<typename R, typename... Args, typename F, typename... Description>
414  ValidRPCDescription<R(Args...), Description...>
415  method(const char* name, F&& fn, Description&&... descriptions)
416  {
417  concreteMethod<R, Args...>(name, std::forward<F>(fn), std::forward<Description>(descriptions)...);
418  }
419 
420  template<typename F, typename... Description>
421  ValidRPCDescription<F, Description...>
422  method(const char* name, F&& fn, Description&&... descriptions)
423  {
424  concreteMethodHelper<typename Private::FunctionTraits<F>::ReturnValue>(
425  name, std::forward<F>(fn), typename Private::FunctionTraits<F>::Arguments{},
426  std::forward<Description>(descriptions)...);
427  }
428 
429  template<typename R, typename Class, typename... Args, typename... Description>
430  ValidRPCDescription<R (Class::*)(Args...), Description...>
431  method(const char* name, R (Class::*fn)(Args...), Class* This, Description&&... descriptions)
432  {
433  auto func = Private::MemberInvoker<decltype(std::mem_fn(fn)), Class>(std::mem_fn(fn), This);
434  concreteMethod<R, Args...>(name, std::move(func), std::forward<Description>(descriptions)...);
435  }
436 
437  template<typename R, typename Class, typename... Args, typename... Description>
438  ValidRPCDescription<R (Class::*)(Args...) const, Description...>
439  method(const char* name, R (Class::*fn)(Args...) const, Class* This, Description&&... descriptions)
440  {
441  auto func = Private::MemberInvoker<decltype(std::mem_fn(fn)), Class>(std::mem_fn(fn), This);
442  concreteMethod<R, Args...>(name, std::move(func), std::forward<Description>(descriptions)...);
443  }
444 
445  private:
446  template<typename R, typename... Args, typename F, typename... Description>
447  void concreteMethodHelper(const char* name, F&& fn, Private::ArgumentTuple<Args...> args,
448  Description&&... descriptions)
449  {
450  concreteMethod<R, Args...>(name, std::forward<F>(fn), std::forward<Description>(descriptions)...);
451  }
452 
453  template<typename R, typename... Args, typename F, typename Comment, typename... Description>
454  void concreteMethod(const char* name, F&& fn, Comment&& comment, Description&&... descriptions)
455  {
456  Method m(makeRPCSignature<R, Args...>(name), std::forward<Comment>(comment));
457  m.parameterDesc.reserve(sizeof...(Args));
458  addParameterDescription<Args...>(m, std::forward<Description>(descriptions)...);
459  m.addInvoker(make_RPCInvoker<BinaryRPCBackend, R, Args...>(fn));
460  m.addInvoker(make_RPCInvoker<BinaryRPCBackendLegacy, R, Args...>(fn));
461  m.addInvoker(make_RPCInvoker<JSONRPCBackend, R, Args...>(fn));
462  addMethod(m);
463  }
464 
465  private:
466 
467  void addMethod(const Method& method) {
468  foreach (const MethodInfo& m, mService.methods) {
469  // more than 1 method with same name and number of parameters?
470  if ((m.signature.name == method.signature.name) &&
471  (m.signature.parameterTypes.size() == method.signature.parameterTypes.size())) {
472  MIRA_LOG(WARNING) << mService.name << "." << m.signature << " and "
473  << mService.name << "." << method.signature
474  << " are ambiguous when called through JSON RPC"
475  << " - choosing different method names is strongly recommended!";
476  }
477  }
478 
479  if(mService.methods.insert(method).second)
480  mAddedMethods.insert(method.signature);
481  // adding the same method multiple times, is handled correctly
482  }
483 
484  template<typename... RECURSIONSTOP>
485  typename std::enable_if<(sizeof...(RECURSIONSTOP)) == 0>::type addParameterDescription(Method& m)
486  {}
487 
488  template<typename ParameterType, typename... Args>
489  MIRA_DEPRECATED("_________________Please provide parameter descriptions (and sample values, if appropriate) for RPC methods!_________________",
490  void addParameterDescription(Method& m)
491  {
492  m.parameterSamples.emplace_back(createParameterSample<Private::StrippedType<ParameterType>>());
493  addParameterDescription<Args...>(m);
494  }
495  )
496 
497  template<typename ParameterType, typename... Args, class Name, class Description, typename... Tail,
498  typename = typename std::enable_if<(sizeof...(Args)) * 2 == sizeof...(Tail)>::type>
499  void addParameterDescription(Method& m, Name&& name, Description&& description, Tail&&... tail)
500  {
501  m.parameterDesc.emplace_back(std::forward<Name>(name), std::forward<Description>(description));
502  m.parameterSamples.emplace_back(createParameterSample<Private::StrippedType<ParameterType>>());
503  addParameterDescription<Args...>(m, std::forward<Tail>(tail)...);
504  }
505 
506  template<typename ParameterType, typename... Args, class Name, class Description, class Example,
507  typename... Tail,
508  typename = typename std::enable_if<(sizeof...(Args)) * 3 == sizeof...(Tail)>::type>
509  void addParameterDescription(Method& m, Name&& name, Description&& description, Example&& example,
510  Tail&&... tail)
511  {
512  m.parameterDesc.emplace_back(std::forward<Name>(name), std::forward<Description>(description));
513  m.parameterSamples.emplace_back(
514  createParameterSample<Private::StrippedType<ParameterType>>(std::forward<Example>(example)));
515  m.parameterSamplesDefault = false; // this will be assigned multiple times in recursive calls,
516  // but the alternative seems to be to double the number of methods needed for this
517  addParameterDescription<Args...>(m, std::forward<Tail>(tail)...);
518  }
519 
520  template<typename T>
521  json::Value createParameterSample(const T& v = T())
522  {
523  return mJSONSerializer.serialize(v);
524  }
525 
527  JSONSerializer mJSONSerializer;
528 
529  private:
530 
532  Service& mService;
533 
535  std::set<RPCSignature> mAddedMethods;
536 
538  std::set<std::string> mAddedInterfaces;
539  };
540 
541 public:
542 
550  template <typename T>
551  const Service& registerServiceObject(const std::string& serviceName,
552  T& serviceObject,
553  std::set<RPCSignature>* addedMethods = NULL,
554  std::set<std::string>* addedInterfaces = NULL)
555  {
556  boost::mutex::scoped_lock lock(mMutex);
557 
558  // use already created service, or create new one
559  ServiceMap::iterator it = mServices.find(serviceName);
560  if (it==mServices.end())
561  it = mServices.insert(std::make_pair(serviceName,
562  Service(serviceName))).first;
563 
564  // reflect the service object and add its methods to the service
565  Service& s = it->second;
566  RPCReflector r(s);
567  serviceObject.reflect(r);
568 
569  MIRA_LOG(NOTICE) << "Registered service object for service: '" <<
570  serviceName << "'. With the following new methods:";
571  foreach(const RPCSignature& m, r.getAddedMethods())
572  MIRA_LOG(NOTICE) << " " << m;
573 
574  if(addedMethods!=NULL)
575  *addedMethods = r.getAddedMethods();
576 
577  if(addedInterfaces!=NULL)
578  *addedInterfaces = r.getAddedInterfaces();
579 
580  return s;
581  }
582 
587  void unregisterService(const std::string& serviceName)
588  {
589  boost::mutex::scoped_lock lock(mMutex);
590  MIRA_LOG(NOTICE) << "Unregistering service: '" << serviceName << "'.";
591  mServices.erase(serviceName);
592  }
593 
594 public:
595 
599  const ServiceMap& getServices() const
600  {
601  return mServices;
602  }
603 
609  const Service& getService(const std::string& name) const
610  {
611  boost::mutex::scoped_lock lock(mMutex);
612  auto i = mServices.find(name);
613  if (i == mServices.end())
614  MIRA_THROW(XInvalidParameter, "No such service '" << name << "'");
615 
616  return i->second;
617  }
618 
622  bool existsService(const std::string& name) const
623  {
624  boost::mutex::scoped_lock lock(mMutex);
625  auto i = mServices.find(name);
626  return i!= mServices.end();
627  }
628 
633  std::list<std::string> queryServicesForInterface(const std::string& interface) const
634  {
635  boost::mutex::scoped_lock lock(mMutex);
636  std::list<std::string> res;
637  // for all services
638  for(auto it=mServices.begin(); it!=mServices.end(); ++it)
639  // does service implements the desired interface?
640  if(it->second.interfaces.count(interface)!=0)
641  res.push_back(it->second.name); // yes? so add its name to the list
642  return res;
643  }
644 
648  bool implementsInterface(const std::string& name, const std::string& interface) const
649  {
650  boost::mutex::scoped_lock lock(mMutex);
651  auto it = mServices.find(name);
652  if (it == mServices.end())
653  return false;
654  return it->second.interfaces.count(interface) > 0;
655  }
656 
657 public:
658 
665  template <typename Backend>
666  void processCall(typename Backend::ServerRequest& request,
667  typename Backend::ServerResponse& response)
668  {
669  boost::shared_ptr<TRPCInvoker<Backend>> invoker;
670  Service* service;
671  std::string callId;
672 
673  Method* method = NULL;
674  if(!processCallCommon<Backend>(request, response, callId, invoker, service, method))
675  return; // an error has occured, abort, error already is reported in response
676 
677  // and finally invoke the method
678  response.setHeader(callId);
679  try
680  {
681  invoker->invoke(request, response);
682  }
683  catch(std::exception& ex) {
684  // handle possible exceptions in getParameter() and return them to caller
685  MIRA_LOG(WARNING) << "Invalid RPC Request: " << ex.what();
686  response.returnException(RPC_INVALID_PARAMS, ex.what());
687  }
688  }
689 
697  template <typename Backend>
699  {
700  public:
701  DeferredInvoker(typename Backend::ServerRequest& request,
702  typename Backend::ServerResponse& response,
703  const std::string& callId,
704  const std::string& service,
705  const std::string& method,
706  boost::shared_ptr<TRPCInvoker<Backend>> invoker) :
707  AbstractDeferredInvoker(callId,service,method),
708  mRequest(request), mResponse(response),
709  mInvoker(invoker) {}
710  public:
711  virtual void invoke() {
712  mResponse.setHeader(mCallId);
713  try
714  {
715  mInvoker->invoke(mRequest, mResponse);
716  }
717  catch(std::exception& ex) {
718  // handle possible exceptions in getParameter() and return them to caller
719  MIRA_LOG(WARNING) << "Invalid RPC Request: " << ex.what();
720  mResponse.returnException(RPC_INVALID_PARAMS, ex.what());
721  }
722  try {
723  if(mFinishHandler!=NULL)
725  } catch(std::exception& ex) {
726  // catch broken promise
728  }
729  }
730  private:
731  typename Backend::ServerRequest& mRequest;
732  typename Backend::ServerResponse& mResponse;
733  boost::shared_ptr<TRPCInvoker<Backend>> mInvoker;
734  };
735 
747  template <typename Backend>
748  AbstractDeferredInvokerPtr processCallDeferred(typename Backend::ServerRequest& request,
749  typename Backend::ServerResponse& response)
750  {
751  boost::shared_ptr<TRPCInvoker<Backend>> invoker;
752  Service* service = NULL;
753  std::string callId;
754 
755  Method* method;
756 
757  if(processCallCommon<Backend>(request, response, callId, invoker, service, method)) {
758  assert(service!=NULL);
759  AbstractDeferredInvokerPtr deferredInvoker(
760  new DeferredInvoker<Backend>(request, response, callId,
761  service->name,
762  method->signature.name, invoker));
763  return deferredInvoker;
764  } else {
765  // error already is reported in response
767  }
768  }
769 
770 protected:
771 
773  template <typename Backend>
774  bool processCallCommon(typename Backend::ServerRequest& request,
775  typename Backend::ServerResponse& response,
776  std::string &oCallId,
777  boost::shared_ptr<TRPCInvoker<Backend>>& oInvoker,
778  Service* &oService, Method* &oMethod)
779  {
780  std::string name;
781  std::string callId;
782  std::string serviceStr;
783 
784  try {
785  request.getHeader(callId, serviceStr);
786  } catch(std::exception& ex) {
787  // handle possible exceptions in getHeader() and return them to caller
788  MIRA_LOG(WARNING) << "Invalid RPC Request: " << ex.what();
789  generateErrorResponse<Backend>(callId, RPC_INVALID_REQUEST, ex.what(), response);
790  return false;
791  }
792 
793  boost::mutex::scoped_lock lock(mMutex);
794 
795  // find the service
796  auto serviceIt = mServices.find(serviceStr);
797 
798  if(serviceIt==mServices.end()) {
799  MIRA_LOG(WARNING) << "RPC service not found: " << serviceStr;
800  generateErrorResponse<Backend>(callId, RPC_METHOD_NOT_FOUND,
801  "Cannot process RPC call, a service named '"
802  + serviceStr + "' does not exist", response);
803  return false;
804  }
805 
806  Service& service = serviceIt->second;
807 
808  // find the method
809  oMethod=NULL;
810  Method* method = NULL;
811 
812  foreach(const Method& m, service.methods)
813  {
814  if(request.checkSignature(m.signature)) {
815  // found method with the correct signature
816  method = const_cast<Method*>(&m);
817  break; // break for each
818  }
819  }
820 
821  // abort, if we did not find the method, but produce a (hopefully)
822  // helpful exception message
823  if(method==NULL) {
824  std::string methodName = request.getSignature().name;
825  std::string candidates;
826  foreach(const Method& m, service.methods)
827  {
828  if(methodName == m.signature.name) {
829  if(!candidates.empty())
830  candidates += ", ";
831  candidates += toString(m.signature);
832  }
833  }
834 
835  if(!candidates.empty())
836  candidates = " Candidates are: " + candidates;
837  else
838  candidates = " No candidates found.";
839 
840  MIRA_LOG(WARNING) << "RPC method does not exist: "
841  << toString(request.getSignature())
842  << ", candidates: " << candidates;
843  generateErrorResponse<Backend>(callId,
844  RPC_INVALID_PARAMS, "Cannot process RPC call, the service '" +
845  serviceStr + "' does not have a method '" +
846  toString(request.getSignature()) + "'." + candidates,
847  response);
848  return false;
849  }
850 
851  // now get the invoker for our backend
852  auto invokerIt = method->invokers.find(typeId<Backend>());
853  if(invokerIt == method->invokers.end())
854  MIRA_THROW(XLogical, "Cannot process RPC call, no invoker for service method '" <<
855  serviceStr << "." << request.getSignature() <<
856  "' was registered for backend type '" <<
857  typeName<Backend>() << "'.");
858  // the above exception is not send to the caller, since it is caused by
859  // a problem here in our server
860 
861  // cast invoker into typed invoker for our Backend
862  oInvoker = boost::static_pointer_cast<TRPCInvoker<Backend>>(invokerIt->second);
863  oCallId = callId;
864  oService = &service;
865  oMethod = method;
866  return true;
867  }
868 
869  template <typename Backend>
870  void generateErrorResponse(const std::string& callId,
871  RPCError reason, const std::string& message,
872  typename Backend::ServerResponse& oResponse)
873  {
874  oResponse.setHeader(callId);
875  oResponse.returnException(reason, message);
876  }
877 
878 private:
879 
880  ServiceMap mServices;
881  mutable boost::mutex mMutex;
882 };
883 
885 
886 } // namespace
887 
888 #endif /* _MIRA_RPCSERVER_H_ */
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:701
ServiceInfo< MethodSet > Service
Definition: RPCServer.h:322
MethodInfo(const RPCSignature &iSignature, const std::string &iComment)
Definition: RPCServer.h:179
Definition: BinarySerializer.h:316
Contains all available information about a single RPC service, including the service&#39; name...
Definition: RPCServer.h:301
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:748
void unregisterService(const std::string &serviceName)
Unregisters the specified service with all methods of all service objects that were registered...
Definition: RPCServer.h:587
Method(const RPCSignature &signature, const std::string &comment, const ParameterDescriptions &parameterDescriptions)
Definition: RPCServer.h:274
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:648
std::string comment
User comments and description.
Definition: RPCServer.h:254
std::string resolveEnvironmentVariable(const std::string &envVar)
Resolves an environmental variable.
Definition: RPCPatternCheck.h:82
Contains information on an RPC method&#39;s parameter: name, description.
Definition: RPCServer.h:114
Invalid parameters were specified for the method.
Definition: RPCError.h:68
void reflect(ConcreteBinarySerializer< Stream, 0 > &r)
Definition: RPCServer.h:223
RPCReflector(Service &iService)
Definition: RPCServer.h:353
const std::set< std::string > & getAddedInterfaces() const
Returns all interfaces that were added to the service while visiting the service object.
Definition: RPCServer.h:374
ValidRPCDescription< R(Class::*)(Args...), Description... > method(const char *name, R(Class::*fn)(Args...), Class *This, Description &&... descriptions)
Definition: RPCServer.h:431
Implementation of the CreationPolicy that is used by the Singleton template.
Definition: Singleton.h:149
Contains information on an existing RPC method: the signature of the method, comments, etc.
Definition: RPCServer.h:149
MethodInfo()
Definition: RPCServer.h:177
static Type & instance()
Returns a reference to the singleton instance.
Definition: Singleton.h:508
bool existsService(const std::string &name) const
Returns true, if a service with the specified name exists, otherwise false.
Definition: RPCServer.h:622
InvalidRPCDescription< R(Args...), Description... > method(const char *, F &&, Description &&...)
Definition: RPCServer.h:387
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:287
InvalidRPCDescription< R(Class::*)(Args...) const, Description... > method(const char *, R(Class::*)(Args...) const, Class *, Description &&...)
Definition: RPCServer.h:408
Invoker that is used to invoke an RPC method call for a special backend.
Definition: RPCInvoker.h:91
#define MIRA_LOG(level)
Use this macro to log data.
Definition: LoggingCore.h:529
std::string description
Parameter description.
Definition: RPCServer.h:132
Class object which supports some kind of class reflection.
Definition: Class.h:97
std::list< json::Value > parameterSamples
Definition: RPCServer.h:261
ParameterInfo()
Definition: RPCServer.h:116
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:980
std::string extendedSignature() const
void reflect(Reflector &r)
Definition: RPCServer.h:122
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:774
uint8 VersionType
Definition: ReflectorInterface.h:72
#define MIRA_THROW(ex, msg)
Macro for throwing an exception.
Definition: Exception.h:78
This is the public interface of all reflectors that are able to visit a class&#39; reflect() method...
Definition: ReflectorInterface.h:111
Provides JSON client and server side requests and responses.
Definition: RPCInvoker.h:178
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:252
void reflectBinaryV0(Reflector &r)
Definition: RPCServer.h:205
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:551
TMethodSet methods
All methods that were registered for this service.
Definition: RPCServer.h:317
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:338
void interface(const char *name)
Definition: RPCServer.h:380
Auxiliary logging macros for special entities like exceptions, etc.
InvalidRPCDescription< F, Description... > method(const char *, F &&, Description &&...)
Definition: RPCServer.h:394
A singleton template class that can be freely configured using policies that control the instantiatio...
Definition: Singleton.h:495
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:129
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:269
Implements the RPCInvoker and TRPCInvoker classes.
bool operator<(const MethodInfo &rhs) const
Definition: RPCServer.h:235
void reflect(Reflector &r)
Definition: RPCServer.h:307
Abstract interface for DeferredInvoker.
ServiceInfo(const std::string &iName="")
Definition: RPCServer.h:303
std::string sampleParametersSet(bool formatted=false) const
std::string name
The method&#39;s name.
Definition: RPCSignature.h:130
std::string mCallId
Definition: AbstractDeferredInvoker.h:113
bool operator==(const MethodInfo &rhs) const
Definition: RPCServer.h:239
void generateErrorResponse(const std::string &callId, RPCError reason, const std::string &message, typename Backend::ServerResponse &oResponse)
Definition: RPCServer.h:870
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:369
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:174
virtual void invoke()
Invokes the RPC call that is represented by this DeferredInvoker.
Definition: RPCServer.h:711
void addInvoker(TRPCInvoker< Backend > *invoker)
adds a new invoker that processes the method for a certain backend
Definition: RPCServer.h:280
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:666
void reflectBase(Base &base)
implements ReflectorInterface (for documentation see ReflectorInterface)
Definition: RPCServer.h:361
InvalidRPCDescription< R(Class::*)(Args...), Description... > method(const char *, R(Class::*)(Args...), Class *, Description &&...)
Definition: RPCServer.h:401
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:633
#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:292
std::map< std::string, Service > ServiceMap
Definition: RPCServer.h:324
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:439
Functions for platform independent resolving of environment variables.
friend std::ostream & operator<<(std::ostream &s, const ParameterInfo &v)
Definition: RPCServer.h:136
RPCSignature signature
The signature of the method (including its name)
Definition: RPCServer.h:251
std::set< Method > MethodSet
Definition: RPCServer.h:290
std::set< std::string > interfaces
All interfaces that this service supports.
Definition: RPCServer.h:319
Requested method was not found.
Definition: RPCError.h:67
std::string name
The name of this service.
Definition: RPCServer.h:315
void reflect(ConcreteBinaryDeserializer< Stream, 0 > &r)
Definition: RPCServer.h:230
static bool enabled()
Definition: RPCServer.h:171
Definition: LoggingCore.h:75
const ServiceMap & getServices() const
Returns the map with all known services.
Definition: RPCServer.h:599
Stores the signature of an RPC method including the methods name and its parameter types...
Definition: RPCSignature.h:64
ParameterDescriptions parameterDesc
User info on method parameters.
Definition: RPCServer.h:257
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:188
ParameterInfo(const std::string &iName, const std::string &iDescription)
Definition: RPCServer.h:118
const Service & getService(const std::string &name) const
Returns a reference to the service with the given name.
Definition: RPCServer.h:609
bool parameterSamplesDefault
Sample parameter values.
Definition: RPCServer.h:260
Method(const RPCSignature &signature, const std::string &comment)
Definition: RPCServer.h:271
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:106
MethodInfo(const RPCSignature &iSignature, const std::string &iComment, const ParameterDescriptions &iParameterDescriptions)
Definition: RPCServer.h:182
std::vector< ParameterInfo > ParameterDescriptions
Definition: RPCServer.h:143
ValidRPCDescription< R(Args...), Description... > method(const char *name, F &&fn, Description &&... descriptions)
Definition: RPCServer.h:415
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:422
Stores all necessary information to invoke a previously decoded and prepared RPC call.
Definition: RPCServer.h:698