Ignition Transport

API Reference

11.0.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  (void)_repMsg;
248  }
249 
250  // Documentation inherited
251  public: bool Serialize(std::string &_buffer) const
252  {
253  if (!this->reqMsg.SerializeToString(&_buffer))
254  {
255  std::cerr << "ReqHandler::Serialize(): Error serializing the request"
256  << std::endl;
257  return false;
258  }
259 
260  return true;
261  }
262 
263  // Documentation inherited.
264  public: void NotifyResult(const std::string &_rep, const bool _result)
265  {
266  // Execute the callback (if existing).
267  if (this->cb)
268  {
269  // Instantiate the specific protobuf message associated to this topic.
270  auto msg = this->CreateMsg(_rep);
271 
272  this->cb(*msg, _result);
273  }
274  else
275  {
276  this->rep = _rep;
277  this->result = _result;
278  }
279 
280  this->repAvailable = true;
281  this->condition.notify_one();
282  }
283 
284  // Documentation inherited.
285  public: virtual std::string ReqTypeName() const
286  {
287  return Req().GetTypeName();
288  }
289 
290  // Documentation inherited.
291  public: virtual std::string RepTypeName() const
292  {
293  return Rep().GetTypeName();
294  }
295 
297  private: Req reqMsg;
298 
305  };
306 
310  template <> class ReqHandler<google::protobuf::Message,
311  google::protobuf::Message>
312  : public IReqHandler
313  {
314  // Documentation inherited.
315  public: explicit ReqHandler(const std::string &_nUuid)
316  : IReqHandler(_nUuid)
317  {
318  }
319 
323  public: void SetMessage(const google::protobuf::Message *_reqMsg)
324  {
325  if (!_reqMsg)
326  {
327  std::cerr << "ReqHandler::SetMessage() _reqMsg is null" << std::endl;
328  return;
329  }
330 
331  this->reqMsg = _reqMsg->New();
332  this->reqMsg->CopyFrom(*_reqMsg);
333  }
334 
339  public: void SetResponse(const google::protobuf::Message *_repMsg)
340  {
341  if (!_repMsg)
342  {
343  std::cerr << "ReqHandler::SetResponse() _repMsg is null" << std::endl;
344  return;
345  }
346 
347  this->repMsg = _repMsg->New();
348  this->repMsg->CopyFrom(*_repMsg);
349  }
350 
351  // Documentation inherited
352  public: bool Serialize(std::string &_buffer) const
353  {
354  if (!this->reqMsg)
355  {
356  std::cerr << "ReqHandler::Serialize() reqMsg is null" << std::endl;
357  return false;
358  }
359 
360  if (!this->reqMsg->SerializeToString(&_buffer))
361  {
362  std::cerr << "ReqHandler::Serialize(): Error serializing the request"
363  << std::endl;
364  return false;
365  }
366 
367  return true;
368  }
369 
370  // Documentation inherited.
371  public: void NotifyResult(const std::string &_rep, const bool _result)
372  {
373  this->rep = _rep;
374  this->result = _result;
375 
376  this->repAvailable = true;
377  this->condition.notify_one();
378  }
379 
380  // Documentation inherited.
381  public: virtual std::string ReqTypeName() const
382  {
383  if (this->reqMsg)
384  return this->reqMsg->GetTypeName();
385  else
386  {
387  std::cerr << "ReqHandler::ReqTypeName() Warning: Using ReqTypeName() "
388  << "without type information" << std::endl;
389  return "";
390  }
391  }
392 
394  public: virtual std::string RepTypeName() const
395  {
396  if (this->repMsg)
397  return this->repMsg->GetTypeName();
398  else
399  {
400  std::cerr << "ReqHandler::RepTypeName() Warning: Using RepTypeName() "
401  << "without type information" << std::endl;
402  return "";
403  }
404  }
405 
407  private: google::protobuf::Message *reqMsg = nullptr;
408 
410  private: google::protobuf::Message *repMsg = nullptr;
411  };
412  }
413  }
414 }
415 
416 #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:285
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:371
virtual std::string RepTypeName() const
Get the message type name used in the service response.
Definition: ReqHandler.hh:291
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:315
STL class.
void SetMessage(const google::protobuf::Message *_reqMsg)
Set the REQ protobuf message for this handler.
Definition: ReqHandler.hh:323
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:251
virtual std::string RepTypeName() const
Get the message type name used in the service response.
Definition: ReqHandler.hh:394
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:381
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 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:264
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:339
void SetResponse(const Rep *_repMsg)
This function is only used for compatibility with SetResponse() when [REP = google::protobuf::Message...
Definition: ReqHandler.hh:245
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:352