Gazebo Transport

API Reference

12.2.2
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)
23 #pragma warning(disable: 4251)
24 #endif
25 #include <google/protobuf/message.h>
26 #ifdef _MSC_VER
27 #pragma warning(pop)
28 #endif
29 
30 #include <condition_variable>
31 #include <functional>
32 #include <memory>
33 #include <string>
34 
35 #include "gz/transport/config.hh"
36 #include "gz/transport/Export.hh"
38 #include "gz/transport/Uuid.hh"
39 
40 namespace gz
41 {
42  namespace transport
43  {
44  // Inline bracket to help doxygen filtering.
45  inline namespace GZ_TRANSPORT_VERSION_NAMESPACE {
46  //
49  class GZ_TRANSPORT_VISIBLE IReqHandler
50  {
53  public: explicit IReqHandler(const std::string &_nUuid)
54  : rep(""),
55  hUuid(Uuid().ToString()),
56  nUuid(_nUuid),
57  result(false),
58  requested(false),
59  repAvailable(false)
60  {
61  }
62 
64  public: virtual ~IReqHandler() = default;
65 
72  public: virtual void NotifyResult(const std::string &_rep,
73  const bool _result) = 0;
74 
77  public: std::string NodeUuid() const
78  {
79  return this->nUuid;
80  }
81 
84  public: std::string Response() const
85  {
86  return this->rep;
87  }
88 
91  public: bool Result() const
92  {
93  return this->result;
94  }
95 
98  public: bool Requested() const
99  {
100  return this->requested;
101  }
102 
105  public: void Requested(const bool _value)
106  {
107  this->requested = _value;
108  }
109 
113  public: virtual bool Serialize(std::string &_buffer) const = 0;
114 
117  public: std::string HandlerUuid() const
118  {
119  return this->hUuid;
120  }
121 
129  public: template<typename Lock> bool WaitUntil(Lock &_lock,
130  const unsigned int _timeout)
131  {
132  auto now = std::chrono::steady_clock::now();
133  return this->condition.wait_until(_lock,
134  now + std::chrono::milliseconds(_timeout),
135  [this]
136  {
137  return this->repAvailable;
138  });
139  }
140 
143  public: virtual std::string ReqTypeName() const = 0;
144 
147  public: virtual std::string RepTypeName() const = 0;
148 
149 #ifdef _WIN32
150 // Disable warning C4251 which is triggered by
151 // std::*
152 #pragma warning(push)
153 #pragma warning(disable: 4251)
154 #endif
155  protected: std::condition_variable_any condition;
158 
160  protected: std::string rep;
161 
163  protected: std::string hUuid;
164 
166  private: std::string nUuid;
167 #ifdef _WIN32
168 #pragma warning(pop)
169 #endif
170 
172  protected: bool result;
173 
176  private: bool requested;
177 
181  public: bool repAvailable;
182  };
183 
189  template <typename Req, typename Rep> class ReqHandler
190  : public IReqHandler
191  {
192  // Documentation inherited.
193  public: explicit ReqHandler(const std::string &_nUuid)
194  : IReqHandler(_nUuid)
195  {
196  }
197 
201  public: std::shared_ptr<Rep> CreateMsg(const std::string &_data) const
202  {
203  // Instantiate a specific protobuf message
204  std::shared_ptr<Rep> msgPtr(new Rep());
205 
206  // Create the message using some serialized data
207  if (!msgPtr->ParseFromString(_data))
208  {
209  std::cerr << "ReqHandler::CreateMsg() error: ParseFromString failed"
210  << std::endl;
211  }
212 
213  return msgPtr;
214  }
215 
221  public: void SetCallback(const std::function <void(
222  const Rep &_rep, const bool _result)> &_cb)
223  {
224  this->cb = _cb;
225  }
226 
230  public: void SetMessage(const Req *_reqMsg)
231  {
232  if (!_reqMsg)
233  {
234  std::cerr << "ReqHandler::SetMessage() _reqMsg is null" << std::endl;
235  return;
236  }
237 
238  this->reqMsg.CopyFrom(*_reqMsg);
239  }
240 
246  public: void SetResponse(const Rep *_repMsg)
247  {
248  (void)_repMsg;
249  }
250 
251  // Documentation inherited
252  public: bool Serialize(std::string &_buffer) const
253  {
254  if (!this->reqMsg.SerializeToString(&_buffer))
255  {
256  std::cerr << "ReqHandler::Serialize(): Error serializing the request"
257  << std::endl;
258  return false;
259  }
260 
261  return true;
262  }
263 
264  // Documentation inherited.
265  public: void NotifyResult(const std::string &_rep, const bool _result)
266  {
267  // Execute the callback (if existing).
268  if (this->cb)
269  {
270  // Instantiate the specific protobuf message associated to this topic.
271  auto msg = this->CreateMsg(_rep);
272 
273  this->cb(*msg, _result);
274  }
275  else
276  {
277  this->rep = _rep;
278  this->result = _result;
279  }
280 
281  this->repAvailable = true;
282  this->condition.notify_one();
283  }
284 
285  // Documentation inherited.
286  public: virtual std::string ReqTypeName() const
287  {
288  return Req().GetTypeName();
289  }
290 
291  // Documentation inherited.
292  public: virtual std::string RepTypeName() const
293  {
294  return Rep().GetTypeName();
295  }
296 
298  private: Req reqMsg;
299 
305  private: std::function<void(const Rep &_rep, const bool _result)> cb;
306  };
307 
311  template <> class ReqHandler<google::protobuf::Message,
312  google::protobuf::Message>
313  : public IReqHandler
314  {
315  // Documentation inherited.
316  public: explicit ReqHandler(const std::string &_nUuid)
317  : IReqHandler(_nUuid)
318  {
319  }
320 
324  public: void SetMessage(const google::protobuf::Message *_reqMsg)
325  {
326  if (!_reqMsg)
327  {
328  std::cerr << "ReqHandler::SetMessage() _reqMsg is null" << std::endl;
329  return;
330  }
331 
332  this->reqMsg = _reqMsg->New();
333  this->reqMsg->CopyFrom(*_reqMsg);
334  }
335 
340  public: void SetResponse(const google::protobuf::Message *_repMsg)
341  {
342  if (!_repMsg)
343  {
344  std::cerr << "ReqHandler::SetResponse() _repMsg is null" << std::endl;
345  return;
346  }
347 
348  this->repMsg = _repMsg->New();
349  this->repMsg->CopyFrom(*_repMsg);
350  }
351 
352  // Documentation inherited
353  public: bool Serialize(std::string &_buffer) const
354  {
355  if (!this->reqMsg)
356  {
357  std::cerr << "ReqHandler::Serialize() reqMsg is null" << std::endl;
358  return false;
359  }
360 
361  if (!this->reqMsg->SerializeToString(&_buffer))
362  {
363  std::cerr << "ReqHandler::Serialize(): Error serializing the request"
364  << std::endl;
365  return false;
366  }
367 
368  return true;
369  }
370 
371  // Documentation inherited.
372  public: void NotifyResult(const std::string &_rep, const bool _result)
373  {
374  this->rep = _rep;
375  this->result = _result;
376 
377  this->repAvailable = true;
378  this->condition.notify_one();
379  }
380 
381  // Documentation inherited.
382  public: virtual std::string ReqTypeName() const
383  {
384  if (this->reqMsg)
385  return this->reqMsg->GetTypeName();
386  else
387  {
388  std::cerr << "ReqHandler::ReqTypeName() Warning: Using ReqTypeName() "
389  << "without type information" << std::endl;
390  return "";
391  }
392  }
393 
395  public: virtual std::string RepTypeName() const
396  {
397  if (this->repMsg)
398  return this->repMsg->GetTypeName();
399  else
400  {
401  std::cerr << "ReqHandler::RepTypeName() Warning: Using RepTypeName() "
402  << "without type information" << std::endl;
403  return "";
404  }
405  }
406 
408  private: google::protobuf::Message *reqMsg = nullptr;
409 
411  private: google::protobuf::Message *repMsg = nullptr;
412  };
413  }
414  }
415 }
416 
417 #endif