Ignition Transport

API Reference

8.1.0
ReqHandler.hh
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Open Source Robotics Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16 */
17 
18 #ifndef IGN_TRANSPORT_REQHANDLER_HH_
19 #define IGN_TRANSPORT_REQHANDLER_HH_
20 
21 #ifdef _MSC_VER
22 #pragma warning(push, 0)
23 #endif
24 #include <google/protobuf/message.h>
25 #ifdef _MSC_VER
26 #pragma warning(pop)
27 #endif
28 
29 #include <condition_variable>
30 #include <functional>
31 #include <memory>
32 #include <string>
33 
34 #include "ignition/transport/config.hh"
35 #include "ignition/transport/Export.hh"
38 
39 namespace ignition
40 {
41  namespace transport
42  {
43  // Inline bracket to help doxygen filtering.
44  inline namespace IGNITION_TRANSPORT_VERSION_NAMESPACE {
45  //
48  class IGNITION_TRANSPORT_VISIBLE IReqHandler
49  {
52  public: explicit IReqHandler(const std::string &_nUuid)
53  : rep(""),
54  hUuid(Uuid().ToString()),
55  nUuid(_nUuid),
56  result(false),
57  requested(false),
58  repAvailable(false)
59  {
60  }
61 
63  public: virtual ~IReqHandler() = default;
64 
71  public: virtual void NotifyResult(const std::string &_rep,
72  const bool _result) = 0;
73 
76  public: std::string NodeUuid() const
77  {
78  return this->nUuid;
79  }
80 
83  public: std::string Response() const
84  {
85  return this->rep;
86  }
87 
90  public: bool Result() const
91  {
92  return this->result;
93  }
94 
97  public: bool Requested() const
98  {
99  return this->requested;
100  }
101 
104  public: void Requested(const bool _value)
105  {
106  this->requested = _value;
107  }
108 
112  public: virtual bool Serialize(std::string &_buffer) const = 0;
113 
116  public: std::string HandlerUuid() const
117  {
118  return this->hUuid;
119  }
120 
128  public: template<typename Lock> bool WaitUntil(Lock &_lock,
129  const unsigned int _timeout)
130  {
131  auto now = std::chrono::steady_clock::now();
132  return this->condition.wait_until(_lock,
133  now + std::chrono::milliseconds(_timeout),
134  [this]
135  {
136  return this->repAvailable;
137  });
138  }
139 
142  public: virtual std::string ReqTypeName() const = 0;
143 
146  public: virtual std::string RepTypeName() const = 0;
147 
148 #ifdef _WIN32
149 // Disable warning C4251 which is triggered by
150 // std::*
151 #pragma warning(push)
152 #pragma warning(disable: 4251)
153 #endif
154  protected: std::condition_variable_any condition;
157 
159  protected: std::string rep;
160 
162  protected: std::string hUuid;
163 
165  private: std::string nUuid;
166 #ifdef _WIN32
167 #pragma warning(pop)
168 #endif
169 
171  protected: bool result;
172 
175  private: bool requested;
176 
180  public: bool repAvailable;
181  };
182 
188  template <typename Req, typename Rep> class ReqHandler
189  : public IReqHandler
190  {
191  // Documentation inherited.
192  public: explicit ReqHandler(const std::string &_nUuid)
193  : IReqHandler(_nUuid)
194  {
195  }
196 
200  public: std::shared_ptr<Rep> CreateMsg(const std::string &_data) const
201  {
202  // Instantiate a specific protobuf message
203  std::shared_ptr<Rep> msgPtr(new Rep());
204 
205  // Create the message using some serialized data
206  if (!msgPtr->ParseFromString(_data))
207  {
208  std::cerr << "ReqHandler::CreateMsg() error: ParseFromString failed"
209  << std::endl;
210  }
211 
212  return msgPtr;
213  }
214 
220  public: void SetCallback(const std::function <void(
221  const Rep &_rep, const bool _result)> &_cb)
222  {
223  this->cb = _cb;
224  }
225 
229  public: void SetMessage(const Req *_reqMsg)
230  {
231  if (!_reqMsg)
232  {
233  std::cerr << "ReqHandler::SetMessage() _reqMsg is null" << std::endl;
234  return;
235  }
236 
237  this->reqMsg.CopyFrom(*_reqMsg);
238  }
239 
245  public: void SetResponse(const Rep * /*_repMsg*/)
246  {
247  }
248 
249  // Documentation inherited
250  public: bool Serialize(std::string &_buffer) const
251  {
252  if (!this->reqMsg.SerializeToString(&_buffer))
253  {
254  std::cerr << "ReqHandler::Serialize(): Error serializing the request"
255  << std::endl;
256  return false;
257  }
258 
259  return true;
260  }
261 
262  // Documentation inherited.
263  public: void NotifyResult(const std::string &_rep, const bool _result)
264  {
265  // Execute the callback (if existing).
266  if (this->cb)
267  {
268  // Instantiate the specific protobuf message associated to this topic.
269  auto msg = this->CreateMsg(_rep);
270 
271  this->cb(*msg, _result);
272  }
273  else
274  {
275  this->rep = _rep;
276  this->result = _result;
277  }
278 
279  this->repAvailable = true;
280  this->condition.notify_one();
281  }
282 
283  // Documentation inherited.
284  public: virtual std::string ReqTypeName() const
285  {
286  return Req().GetTypeName();
287  }
288 
289  // Documentation inherited.
290  public: virtual std::string RepTypeName() const
291  {
292  return Rep().GetTypeName();
293  }
294 
296  private: Req reqMsg;
297 
304  };
305 
309  template <> class ReqHandler<google::protobuf::Message,
310  google::protobuf::Message>
311  : public IReqHandler
312  {
313  // Documentation inherited.
314  public: explicit ReqHandler(const std::string &_nUuid)
315  : IReqHandler(_nUuid)
316  {
317  }
318 
322  public: void SetMessage(const google::protobuf::Message *_reqMsg)
323  {
324  if (!_reqMsg)
325  {
326  std::cerr << "ReqHandler::SetMessage() _reqMsg is null" << std::endl;
327  return;
328  }
329 
330  this->reqMsg = _reqMsg->New();
331  this->reqMsg->CopyFrom(*_reqMsg);
332  }
333 
338  public: void SetResponse(const google::protobuf::Message *_repMsg)
339  {
340  if (!_repMsg)
341  {
342  std::cerr << "ReqHandler::SetResponse() _repMsg is null" << std::endl;
343  return;
344  }
345 
346  this->repMsg = _repMsg->New();
347  this->repMsg->CopyFrom(*_repMsg);
348  }
349 
350  // Documentation inherited
351  public: bool Serialize(std::string &_buffer) const
352  {
353  if (!this->reqMsg)
354  {
355  std::cerr << "ReqHandler::Serialize() reqMsg is null" << std::endl;
356  return false;
357  }
358 
359  if (!this->reqMsg->SerializeToString(&_buffer))
360  {
361  std::cerr << "ReqHandler::Serialize(): Error serializing the request"
362  << std::endl;
363  return false;
364  }
365 
366  return true;
367  }
368 
369  // Documentation inherited.
370  public: void NotifyResult(const std::string &_rep, const bool _result)
371  {
372  this->rep = _rep;
373  this->result = _result;
374 
375  this->repAvailable = true;
376  this->condition.notify_one();
377  }
378 
379  // Documentation inherited.
380  public: virtual std::string ReqTypeName() const
381  {
382  if (this->reqMsg)
383  return this->reqMsg->GetTypeName();
384  else
385  {
386  std::cerr << "ReqHandler::ReqTypeName() Warning: Using ReqTypeName() "
387  << "without type information" << std::endl;
388  return "";
389  }
390  }
391 
393  public: virtual std::string RepTypeName() const
394  {
395  if (this->repMsg)
396  return this->repMsg->GetTypeName();
397  else
398  {
399  std::cerr << "ReqHandler::RepTypeName() Warning: Using RepTypeName() "
400  << "without type information" << std::endl;
401  return "";
402  }
403  }
404 
406  private: google::protobuf::Message *reqMsg = nullptr;
407 
409  private: google::protobuf::Message *repMsg = nullptr;
410  };
411  }
412  }
413 }
414 
415 #endif
bool Requested() const
Returns if this service call request has already been requested.
Definition: ReqHandler.hh:97
virtual std::string ReqTypeName() const
Get the message type name used in the service request.
Definition: ReqHandler.hh:284
void NotifyResult(const std::string &_rep, const bool _result)
Executes the callback registered for this handler and notify a potential requester waiting on a block...
Definition: ReqHandler.hh:370
virtual std::string RepTypeName() const
Get the message type name used in the service response.
Definition: ReqHandler.hh:290
std::string NodeUuid() const
Get the node UUID.
Definition: ReqHandler.hh:76
It creates a reply handler for the specific protobuf messages used. &#39;Req&#39; is a protobuf message type ...
Definition: ReqHandler.hh:188
T endl(T... args)
void SetCallback(const std::function< void(const Rep &_rep, const bool _result)> &_cb)
Set the callback for this handler.
Definition: ReqHandler.hh:220
std::string Response() const
Get the service response as raw bytes.
Definition: ReqHandler.hh:83
ReqHandler(const std::string &_nUuid)
Definition: ReqHandler.hh:314
STL class.
void SetMessage(const google::protobuf::Message *_reqMsg)
Set the REQ protobuf message for this handler.
Definition: ReqHandler.hh:322
A portable class for representing a Universally Unique Identifier.
Definition: Uuid.hh:45
Interface class used to manage a request handler.
Definition: ReqHandler.hh:48
std::shared_ptr< Rep > CreateMsg(const std::string &_data) const
Create a specific protobuf message given its serialized data.
Definition: ReqHandler.hh:200
std::string HandlerUuid() const
Returns the unique handler UUID.
Definition: ReqHandler.hh:116
bool result
Stores the result of the service call.
Definition: ReqHandler.hh:171
bool Serialize(std::string &_buffer) const
Serialize the Req protobuf message stored.
Definition: ReqHandler.hh:250
virtual std::string RepTypeName() const
Get the message type name used in the service response.
Definition: ReqHandler.hh:393
void Requested(const bool _value)
Mark the service call as requested (or not).
Definition: ReqHandler.hh:104
bool WaitUntil(Lock &_lock, const unsigned int _timeout)
Block the current thread until the response to the service request is available or until the timeout ...
Definition: ReqHandler.hh:128
virtual std::string ReqTypeName() const
Get the message type name used in the service request.
Definition: ReqHandler.hh:380
bool repAvailable
When there is a blocking service call request, the call can be unlocked when a service call REP is av...
Definition: ReqHandler.hh:180
void SetResponse(const Rep *)
This function is only used for compatibility with SetResponse() when [REP = google::protobuf::Message...
Definition: ReqHandler.hh:245
void NotifyResult(const std::string &_rep, const bool _result)
Executes the callback registered for this handler and notify a potential requester waiting on a block...
Definition: ReqHandler.hh:263
std::string hUuid
Unique handler&#39;s UUID.
Definition: ReqHandler.hh:162
void SetResponse(const google::protobuf::Message *_repMsg)
Set the REP protobuf message for this handler.
Definition: ReqHandler.hh:338
IReqHandler(const std::string &_nUuid)
Constructor.
Definition: ReqHandler.hh:52
ReqHandler(const std::string &_nUuid)
Definition: ReqHandler.hh:192
Definition: AdvertiseOptions.hh:28
std::string rep
Stores the service response as raw bytes.
Definition: ReqHandler.hh:159
void SetMessage(const Req *_reqMsg)
Set the REQ protobuf message for this handler.
Definition: ReqHandler.hh:229
bool Result() const
Get the result of the service response.
Definition: ReqHandler.hh:90
bool Serialize(std::string &_buffer) const
Serialize the Req protobuf message stored.
Definition: ReqHandler.hh:351