Gazebo Transport

API Reference

11.4.1
gz/transport/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 GZ_TRANSPORT_REQHANDLER_HH_
19 #define GZ_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 "gz/transport/config.hh"
35 #include "gz/transport/Export.hh"
37 #include "gz/transport/Uuid.hh"
38 
39 namespace ignition::transport
40 {
41  // Inline bracket to help doxygen filtering.
42  inline namespace IGNITION_TRANSPORT_VERSION_NAMESPACE {
43  //
46  class IGNITION_TRANSPORT_VISIBLE IReqHandler
47  {
50  public: explicit IReqHandler(const std::string &_nUuid)
51  : rep(""),
52  hUuid(Uuid().ToString()),
53  nUuid(_nUuid),
54  result(false),
55  requested(false),
56  repAvailable(false)
57  {
58  }
59 
61  public: virtual ~IReqHandler() = default;
62 
69  public: virtual void NotifyResult(const std::string &_rep,
70  const bool _result) = 0;
71 
74  public: std::string NodeUuid() const
75  {
76  return this->nUuid;
77  }
78 
81  public: std::string Response() const
82  {
83  return this->rep;
84  }
85 
88  public: bool Result() const
89  {
90  return this->result;
91  }
92 
95  public: bool Requested() const
96  {
97  return this->requested;
98  }
99 
102  public: void Requested(const bool _value)
103  {
104  this->requested = _value;
105  }
106 
110  public: virtual bool Serialize(std::string &_buffer) const = 0;
111 
114  public: std::string HandlerUuid() const
115  {
116  return this->hUuid;
117  }
118 
126  public: template<typename Lock> bool WaitUntil(Lock &_lock,
127  const unsigned int _timeout)
128  {
129  auto now = std::chrono::steady_clock::now();
130  return this->condition.wait_until(_lock,
131  now + std::chrono::milliseconds(_timeout),
132  [this]
133  {
134  return this->repAvailable;
135  });
136  }
137 
140  public: virtual std::string ReqTypeName() const = 0;
141 
144  public: virtual std::string RepTypeName() const = 0;
145 
146 #ifdef _WIN32
147 // Disable warning C4251 which is triggered by
148 // std::*
149 #pragma warning(push)
150 #pragma warning(disable: 4251)
151 #endif
152  protected: std::condition_variable_any condition;
155 
157  protected: std::string rep;
158 
160  protected: std::string hUuid;
161 
163  private: std::string nUuid;
164 #ifdef _WIN32
165 #pragma warning(pop)
166 #endif
167 
169  protected: bool result;
170 
173  private: bool requested;
174 
178  public: bool repAvailable;
179  };
180 
186  template <typename Req, typename Rep> class ReqHandler
187  : public IReqHandler
188  {
189  // Documentation inherited.
190  public: explicit ReqHandler(const std::string &_nUuid)
191  : IReqHandler(_nUuid)
192  {
193  }
194 
198  public: std::shared_ptr<Rep> CreateMsg(const std::string &_data) const
199  {
200  // Instantiate a specific protobuf message
201  std::shared_ptr<Rep> msgPtr(new Rep());
202 
203  // Create the message using some serialized data
204  if (!msgPtr->ParseFromString(_data))
205  {
206  std::cerr << "ReqHandler::CreateMsg() error: ParseFromString failed"
207  << std::endl;
208  }
209 
210  return msgPtr;
211  }
212 
218  public: void SetCallback(const std::function <void(
219  const Rep &_rep, const bool _result)> &_cb)
220  {
221  this->cb = _cb;
222  }
223 
227  public: void SetMessage(const Req *_reqMsg)
228  {
229  if (!_reqMsg)
230  {
231  std::cerr << "ReqHandler::SetMessage() _reqMsg is null" << std::endl;
232  return;
233  }
234 
235  this->reqMsg.CopyFrom(*_reqMsg);
236  }
237 
243  public: void SetResponse(const Rep *_repMsg)
244  {
245  (void)_repMsg;
246  }
247 
248  // Documentation inherited
249  public: bool Serialize(std::string &_buffer) const
250  {
251  if (!this->reqMsg.SerializeToString(&_buffer))
252  {
253  std::cerr << "ReqHandler::Serialize(): Error serializing the request"
254  << std::endl;
255  return false;
256  }
257 
258  return true;
259  }
260 
261  // Documentation inherited.
262  public: void NotifyResult(const std::string &_rep, const bool _result)
263  {
264  // Execute the callback (if existing).
265  if (this->cb)
266  {
267  // Instantiate the specific protobuf message associated to this topic.
268  auto msg = this->CreateMsg(_rep);
269 
270  this->cb(*msg, _result);
271  }
272  else
273  {
274  this->rep = _rep;
275  this->result = _result;
276  }
277 
278  this->repAvailable = true;
279  this->condition.notify_one();
280  }
281 
282  // Documentation inherited.
283  public: virtual std::string ReqTypeName() const
284  {
285  return std::string(Req().GetTypeName());
286  }
287 
288  // Documentation inherited.
289  public: virtual std::string RepTypeName() const
290  {
291  return std::string(Rep().GetTypeName());
292  }
293 
295  private: Req reqMsg;
296 
302  private: std::function<void(const Rep &_rep, const bool _result)> cb;
303  };
304 
308  template <> class ReqHandler<google::protobuf::Message,
309  google::protobuf::Message>
310  : public IReqHandler
311  {
312  // Documentation inherited.
313  public: explicit ReqHandler(const std::string &_nUuid)
314  : IReqHandler(_nUuid)
315  {
316  }
317 
321  public: void SetMessage(const google::protobuf::Message *_reqMsg)
322  {
323  if (!_reqMsg)
324  {
325  std::cerr << "ReqHandler::SetMessage() _reqMsg is null" << std::endl;
326  return;
327  }
328 
329  this->reqMsg = _reqMsg->New();
330  this->reqMsg->CopyFrom(*_reqMsg);
331  }
332 
337  public: void SetResponse(const google::protobuf::Message *_repMsg)
338  {
339  if (!_repMsg)
340  {
341  std::cerr << "ReqHandler::SetResponse() _repMsg is null" << std::endl;
342  return;
343  }
344 
345  this->repMsg = _repMsg->New();
346  this->repMsg->CopyFrom(*_repMsg);
347  }
348 
349  // Documentation inherited
350  public: bool Serialize(std::string &_buffer) const
351  {
352  if (!this->reqMsg)
353  {
354  std::cerr << "ReqHandler::Serialize() reqMsg is null" << std::endl;
355  return false;
356  }
357 
358  if (!this->reqMsg->SerializeToString(&_buffer))
359  {
360  std::cerr << "ReqHandler::Serialize(): Error serializing the request"
361  << std::endl;
362  return false;
363  }
364 
365  return true;
366  }
367 
368  // Documentation inherited.
369  public: void NotifyResult(const std::string &_rep, const bool _result)
370  {
371  this->rep = _rep;
372  this->result = _result;
373 
374  this->repAvailable = true;
375  this->condition.notify_one();
376  }
377 
378  // Documentation inherited.
379  public: virtual std::string ReqTypeName() const
380  {
381  if (this->reqMsg)
382  return std::string(this->reqMsg->GetTypeName());
383  else
384  {
385  std::cerr << "ReqHandler::ReqTypeName() Warning: Using ReqTypeName() "
386  << "without type information" << std::endl;
387  return "";
388  }
389  }
390 
392  public: virtual std::string RepTypeName() const
393  {
394  if (this->repMsg)
395  return std::string(this->repMsg->GetTypeName());
396  else
397  {
398  std::cerr << "ReqHandler::RepTypeName() Warning: Using RepTypeName() "
399  << "without type information" << std::endl;
400  return "";
401  }
402  }
403 
405  private: google::protobuf::Message *reqMsg = nullptr;
406 
408  private: google::protobuf::Message *repMsg = nullptr;
409  };
410  }
411 }
412 
413 #endif
ReqHandler(const std::string &_nUuid)
Definition: gz/transport/ReqHandler.hh:313
STL class.
STL class.
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: gz/transport/ReqHandler.hh:262
std::string rep
Stores the service response as raw bytes.
Definition: gz/transport/ReqHandler.hh:157
bool Result() const
Get the result of the service response.
Definition: gz/transport/ReqHandler.hh:88
It creates a reply handler for the specific protobuf messages used. 'Req' is a protobuf message type ...
Definition: gz/transport/ReqHandler.hh:186
std::condition_variable_any condition
Condition variable used to wait until a service call REP is available.
Definition: gz/transport/ReqHandler.hh:154
IReqHandler(const std::string &_nUuid)
Constructor.
Definition: gz/transport/ReqHandler.hh:50
virtual std::string RepTypeName() const
Get the message type name used in the service response.
Definition: gz/transport/ReqHandler.hh:289
std::string NodeUuid() const
Get the node UUID.
Definition: gz/transport/ReqHandler.hh:74
std::string hUuid
Unique handler's UUID.
Definition: gz/transport/ReqHandler.hh:160
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: gz/transport/ReqHandler.hh:126
virtual std::string ReqTypeName() const
Get the message type name used in the service request.
Definition: gz/transport/ReqHandler.hh:379
bool Requested() const
Returns if this service call request has already been requested.
Definition: gz/transport/ReqHandler.hh:95
void SetResponse(const Rep *_repMsg)
This function is only used for compatibility with SetResponse() when [REP = google::protobuf::Message...
Definition: gz/transport/ReqHandler.hh:243
void Requested(const bool _value)
Mark the service call as requested (or not).
Definition: gz/transport/ReqHandler.hh:102
ReqHandler(const std::string &_nUuid)
Definition: gz/transport/ReqHandler.hh:190
bool result
Stores the result of the service call.
Definition: gz/transport/ReqHandler.hh:169
void SetMessage(const google::protobuf::Message *_reqMsg)
Set the REQ protobuf message for this handler.
Definition: gz/transport/ReqHandler.hh:321
virtual bool Serialize(std::string &_buffer) const =0
Serialize the Req protobuf message stored.
A portable class for representing a Universally Unique Identifier.
Definition: gz/transport/Uuid.hh:43
virtual ~IReqHandler()=default
Destructor.
Interface class used to manage a request handler.
Definition: gz/transport/ReqHandler.hh:46
virtual std::string ReqTypeName() const =0
Get the message type name used in the service request.
void SetMessage(const Req *_reqMsg)
Set the REQ protobuf message for this handler.
Definition: gz/transport/ReqHandler.hh:227
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: gz/transport/ReqHandler.hh:369
virtual std::string RepTypeName() const
Get the message type name used in the service response.
Definition: gz/transport/ReqHandler.hh:392
void SetCallback(const std::function< void(const Rep &_rep, const bool _result)> &_cb)
Set the callback for this handler.
Definition: gz/transport/ReqHandler.hh:218
bool Serialize(std::string &_buffer) const
Serialize the Req protobuf message stored.
Definition: gz/transport/ReqHandler.hh:249
virtual std::string RepTypeName() const =0
Get the message type name used in the service response.
std::string HandlerUuid() const
Returns the unique handler UUID.
Definition: gz/transport/ReqHandler.hh:114
T endl(T... args)
Definition: gz/transport/AdvertiseOptions.hh:28
bool repAvailable
When there is a blocking service call request, the call can be unlocked when a service call REP is av...
Definition: gz/transport/ReqHandler.hh:178
bool Serialize(std::string &_buffer) const
Serialize the Req protobuf message stored.
Definition: gz/transport/ReqHandler.hh:350
std::string Response() const
Get the service response as raw bytes.
Definition: gz/transport/ReqHandler.hh:81
virtual void NotifyResult(const std::string &_rep, const bool _result)=0
Executes the callback registered for this handler and notify a potential requester waiting on a block...
std::shared_ptr< Rep > CreateMsg(const std::string &_data) const
Create a specific protobuf message given its serialized data.
Definition: gz/transport/ReqHandler.hh:198
void SetResponse(const google::protobuf::Message *_repMsg)
Set the REP protobuf message for this handler.
Definition: gz/transport/ReqHandler.hh:337
virtual std::string ReqTypeName() const
Get the message type name used in the service request.
Definition: gz/transport/ReqHandler.hh:283