MIRA
BinaryRPCBackend.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_BINARYRPCBACKEND_H_
48 #define _MIRA_BINARYRPCBACKEND_H_
49 
50 #ifndef Q_MOC_RUN
51 #include <boost/thread/future.hpp>
52 #endif
54 #include <rpc/RPCError.h>
55 
56 #include <thread/Atomic.h>
57 
58 namespace mira {
59 
61 template <typename R>
62 inline void binaryRPCreturnHelper(boost::promise<R>& promise, BinaryBufferDeserializer& in)
63 {
64  R value;
65  in.deserialize(value);
66  promise.set_value(std::move(value));
67 }
68 
69 template <>
70 inline void binaryRPCreturnHelper(boost::promise<void>& promise, BinaryBufferDeserializer& in)
71 {
72  promise.set_value();
73 }
74 
75 template <uint8 BinaryFormatVersion>
76 struct binaryRPCdeserializeHelper;
77 
79 
80 
81 
116 template <uint8 BinaryFormatVersion>
118 {
119 public:
120  // must be a non-printable character that is not used by JSON-RPC or other RPC protocols
121  // it is used to identify the requests and responses as binary ones
122  enum {
123  BINARY_RPC_MARKER = 27 // Escape Character
124  };
125 
127 
129 
140  {
141  public:
146  };
147  public:
148 
149  ClientResponse(ContainerType* buffer) : mIn(buffer) {}
150 
156  void getHeader(std::string& callId)
157  {
158  uint8 marker;
159  mIn.deserialize(marker, false);
160  if(marker!=BINARY_RPC_MARKER)
161  MIRA_THROW(XRuntime, "The buffer does not contain a valid binary response");
162 
163  mIn.deserialize(callId);
164  }
165 
173  template<typename R>
174  void getReturn(boost::promise<R>& promise)
175  {
176  ReturnStatus status;
177  binaryRPCdeserializeHelper<BinaryFormatVersion>::deserialize(status, mIn);
178  switch ( status )
179  {
180 
181  case RETURN_VOID :
182  case RETURN_RESULT:
183  binaryRPCreturnHelper(promise, mIn);
184  break;
185  case RETURN_EXCEPTION : {
186  std::string error;
187  mIn.deserialize(error);
188  XRPC ex(error);
189  CallStack stack;
190  ThreadID thread;
191  try {
192  mIn.deserialize(stack);
193  mIn.deserialize(thread);
194  ex.addExternalStackInfo<XRPC>(stack, thread);
195 
196  // try to deserialize and add the original exception
197  SerializableException* origEx;
198  mIn.deserialize(origEx);
199  ex.setOrigException(origEx);
200  }
201  catch(...) {
202  ex.addInfo("There is no stack trace from the RPC method or it is unreadable.");
203  }
204  promise.set_exception(boost::copy_exception(ex));
205  break;
206  }
207  default :
208  {
209  // we should never reach here
210  MIRA_THROW(XLogical, "Unknown return status.");
211  }
212  }
213  }
214 
215 
216  private:
218  };
219 
229  {
230  public:
231  ClientRequest(ContainerType* buffer) : mOut(buffer) {}
232 
237  std::string generateCallID() {
238  static uint32 sID = 0;
239  return toString(atomic::inc(&sID));
240  }
241 
248  void setHeader(const std::string& callId, const std::string& service,
249  const RPCSignature& signature)
250  {
251  uint8 marker = BINARY_RPC_MARKER;
252  mOut.serialize(marker, false);
253 
254  mOut.serialize(callId);
255  mOut.serialize(service);
256  mOut.serialize(signature);
257  }
258 
264  template <typename P>
265  void setParameter(const P& param) {
266  mOut.serialize(param);
267  }
268 
269  private:
271  };
272 
282  {
283  public:
284 
285  ServerResponse(ContainerType* buffer) : mOut(buffer) {}
286 
294  void setHeader(const std::string& callId)
295  {
296  uint8 marker = BINARY_RPC_MARKER;
297  mOut.serialize(marker, false);
298 
299  mOut.serialize(callId);
300  }
301 
307  void returnException(RPCError reason, const std::string& message) {
308  mOut.serialize(ClientResponse::RETURN_EXCEPTION);
309  mOut.serialize(message);
310  }
311 
317  void returnException(RPCError reason, const std::string& message,
318  const CallStack& callstack)
319  {
320  mOut.serialize(ClientResponse::RETURN_EXCEPTION);
321  mOut.serialize(message);
322  mOut.serialize(callstack);
323  mOut.serialize(getCurrentThreadID());
324  }
325 
332  {
333  mOut.serialize(ClientResponse::RETURN_EXCEPTION);
334  mOut.serialize(std::string(ex.what()));
335  mOut.serialize(ex.callStack());
336  mOut.serialize(getCurrentThreadID());
337  mOut.serialize(&ex);
338  }
339 
345  template<typename R>
346  void returnResult(const R& res) {
347  mOut.serialize(ClientResponse::RETURN_RESULT);
348  mOut.serialize(res);
349  }
350 
356  void returnVoid() {
357  mOut.serialize(ClientResponse::RETURN_VOID);
358  }
359 
360  private:
362  };
363 
374  {
375  public:
376 
377  ServerRequest(ContainerType* buffer) : mIn(buffer) {}
378 
379  public:
388  void getHeader(std::string& oCallId, std::string& oService)
389  {
390  uint8 marker;
391  mIn.deserialize(marker, false);
392  if(marker!=BINARY_RPC_MARKER)
393  MIRA_THROW(XRuntime, "The buffer does not contain a valid binary response");
394 
395  mIn.deserialize(oCallId);
396  mIn.deserialize(oService);
397  mIn.deserialize(mSignature);
398  }
399 
404  bool checkSignature(const RPCSignature& signature)
405  {
406  return signature == mSignature;
407  }
408 
414  {
415  return mSignature;
416  }
417 
422  template <typename P>
423  void getParameter(P& oParam)
424  {
425  // no need to do type check here, since it is done by BinaryBufferDeserializer
426  mIn.deserialize(oParam);
427  }
428 
429  private:
431  RPCSignature mSignature;
432  };
433 
434 };
435 
438 
440 template <uint8 BinaryFormatVersion>
441 struct binaryRPCdeserializeHelper
442 {
443 
444  static void deserialize(typename BinaryRPCBackendTempl<BinaryFormatVersion>::ClientResponse::ReturnStatus& status,
445  BinaryBufferDeserializer& deserializer)
446  {
447  deserializer.deserialize(status);
448  }
449 };
450 
451 template <>
452 struct binaryRPCdeserializeHelper<0>
453 {
454  static void deserialize(BinaryRPCBackendTempl<0>::ClientResponse::ReturnStatus& status,
455  BinaryBufferDeserializer& deserializer)
456  {
457  // need to read the typename separately and suppress the type check
458  // (because the type's name is NOT the same anymore)
459  std::string fulltypename;
460  deserializer.deserialize(fulltypename, false);
461 
462  assert(fulltypename == "mira::BinaryRPCBackend::ClientResponse::ReturnStatus");
463 
464  deserializer.deserialize(status, false);
465  }
466 };
467 
469 
471 
472 } // namespace
473 
474 #endif /* _MIRA_BINARYRPCBACKEND_H_ */
void setHeader(const std::string &callId, const std::string &service, const RPCSignature &signature)
Write the request header consisting of the call ID, the service name and the signature of the request...
Definition: BinaryRPCBackend.h:248
ConcreteBinaryDeserializer< BinaryBufferIstream, 2 > BinaryBufferDeserializer
Typedef for BinaryDeserializer based on a Buffer.
Definition: BinarySerializer.h:1603
void getHeader(std::string &callId)
Read the response header (i.e.
Definition: BinaryRPCBackend.h:156
Definition: BinarySerializer.h:324
void getParameter(P &oParam)
Read and deserializes the next parameter from the request.
Definition: BinaryRPCBackend.h:423
BinaryRPCBackendTempl< 2 > BinaryRPCBackend
Definition: BinaryRPCBackend.h:437
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.
Provides binary client and server side requests and responses.
Definition: BinaryRPCBackend.h:117
void returnVoid()
Write successful end of an RPC call.
Definition: BinaryRPCBackend.h:356
void setHeader(const std::string &callId)
Write the response header consisting of the ID of the call.
Definition: BinaryRPCBackend.h:294
Binary client-side request.
Definition: BinaryRPCBackend.h:228
uint32 ThreadID
Platform independent thread ID.
Definition: ThreadID.h:68
Buffer< uint8 > ContainerType
Definition: BinaryRPCBackend.h:126
BinaryRPCBackendTempl< 0 > BinaryRPCBackendLegacy
Definition: BinaryRPCBackend.h:436
ServerResponse(ContainerType *buffer)
Definition: BinaryRPCBackend.h:285
Binary server-side response.
Definition: BinaryRPCBackend.h:281
#define MIRA_THROW(ex, msg)
Macro for throwing an exception.
Definition: Exception.h:82
void getReturn(boost::promise< R > &promise)
Obtain return value from response and set it using promise.set_value() or set exception using promise...
Definition: BinaryRPCBackend.h:174
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 returnException(RPCError reason, const std::string &message)
Write exception as result of an RPC call.
Definition: BinaryRPCBackend.h:307
Binary server-side request.
Definition: BinaryRPCBackend.h:373
An exception that is thrown by the RPCServer if an RPC call fails.
Definition: RPCError.h:76
Binary serializer and deserializer.
void returnResult(const R &res)
Write result of an RPC call.
Definition: BinaryRPCBackend.h:346
const CallStack & callStack() const
Returns the state of the callstack at the moment when the exception was thrown.
Definition: Exception.h:257
ServerRequest(ContainerType *buffer)
Definition: BinaryRPCBackend.h:377
RPCError
enumeration of possible reasons for errors/exceptions while performing an RPC call ...
Definition: RPCError.h:64
void returnException(RPCError reason, SerializableException &ex)
Write exception as result of an RPC call.
Definition: BinaryRPCBackend.h:331
void returnException(RPCError reason, const std::string &message, const CallStack &callstack)
Write exception as result of an RPC call.
Definition: BinaryRPCBackend.h:317
const RPCSignature & getSignature()
Return the signature, that was read from the request header in the previous getHeader() call above...
Definition: BinaryRPCBackend.h:413
ReturnStatus
Definition: BinaryRPCBackend.h:142
Contains methods for simple atomic operations (such as increment, etc.) that are thread-safe without ...
void setOrigException(SerializableException *ex)
takes ownership of ex
Definition: RPCError.h:106
bool checkSignature(const RPCSignature &signature)
Check, if the passed signature is compatible with the signature that was read from the request header...
Definition: BinaryRPCBackend.h:404
ClientRequest(ContainerType *buffer)
Definition: BinaryRPCBackend.h:231
std::string generateCallID()
Generates a unique call ID for a client request of this backend.
Definition: BinaryRPCBackend.h:237
void getHeader(std::string &oCallId, std::string &oService)
Read the request header including the call ID, the service name and the signature of the method...
Definition: BinaryRPCBackend.h:388
void deserialize(T &value, bool enableTypeCheck=true, bool recursive=false)
Provides a special deserialize interface for the BinaryDeserializer.
Definition: BinarySerializer.h:1340
Encapsulates unix call stack functionality.
Definition: CallStack.h:86
ClientResponse(ContainerType *buffer)
Definition: BinaryRPCBackend.h:149
void setParameter(const P &param)
Write the value of the next parameter to the request.
Definition: BinaryRPCBackend.h:265
virtual const char * what() const MIRA_NOEXCEPT_OR_NOTHROW
Returns the text of exception containing the information given in MIRA_THROW and MIRA_RETHROW as well...
Stores the signature of an RPC method including the methods name and its parameter types...
Definition: RPCSignature.h:68
Definition: BinaryRPCBackend.h:123
Binary client-side response.
Definition: BinaryRPCBackend.h:139
uint32 inc(volatile uint32 *var)
Increments the value of the variable pointed to by var and returns its old value. ...
Definition: Atomic.h:82
Definition: Exceptions.h:85