Gazebo Transport

API Reference

13.4.1
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::transport
41 {
42  // Inline bracket to help doxygen filtering.
43  inline namespace GZ_TRANSPORT_VERSION_NAMESPACE {
44  //
47  class GZ_TRANSPORT_VISIBLE IReqHandler
48  {
51  public: explicit IReqHandler(const std::string &_nUuid)
52  : rep(""),
53  hUuid(Uuid().ToString()),
54  nUuid(_nUuid),
55  result(false),
56  requested(false),
57  repAvailable(false)
58  {
59  }
60 
62  public: virtual ~IReqHandler() = default;
63 
70  public: virtual void NotifyResult(const std::string &_rep,
71  const bool _result) = 0;
72 
75  public: std::string NodeUuid() const
76  {
77  return this->nUuid;
78  }
79 
82  public: std::string Response() const
83  {
84  return this->rep;
85  }
86 
89  public: bool Result() const
90  {
91  return this->result;
92  }
93 
96  public: bool Requested() const
97  {
98  return this->requested;
99  }
100 
103  public: void Requested(const bool _value)
104  {
105  this->requested = _value;
106  }
107 
111  public: virtual bool Serialize(std::string &_buffer) const = 0;
112 
115  public: std::string HandlerUuid() const
116  {
117  return this->hUuid;
118  }
119 
127  public: template<typename Lock> bool WaitUntil(Lock &_lock,
128  const unsigned int _timeout)
129  {
130  auto now = std::chrono::steady_clock::now();
131  return this->condition.wait_until(_lock,
132  now + std::chrono::milliseconds(_timeout),
133  [this]
134  {
135  return this->repAvailable;
136  });
137  }
138 
141  public: virtual std::string ReqTypeName() const = 0;
142 
145  public: virtual std::string RepTypeName() const = 0;
146 
147 #ifdef _WIN32
148 // Disable warning C4251 which is triggered by
149 // std::*
150 #pragma warning(push)
151 #pragma warning(disable: 4251)
152 #endif
156 
158  protected: std::string rep;
159 
161  protected: std::string hUuid;
162 
164  private: std::string nUuid;
165 #ifdef _WIN32
166 #pragma warning(pop)
167 #endif
168 
170  protected: bool result;
171 
174  private: bool requested;
175 
179  public: bool repAvailable;
180  };
181 
187  template <typename Req, typename Rep> class ReqHandler
188  : public IReqHandler
189  {
190  // Documentation inherited.
191  public: explicit ReqHandler(const std::string &_nUuid)
192  : IReqHandler(_nUuid)
193  {
194  }
195 
199  public: std::shared_ptr<Rep> CreateMsg(const std::string &_data) const
200  {
201  // Instantiate a specific protobuf message
202  auto msgPtr = std::make_shared<Rep>();
203 
204  // Create the message using some serialized data
205  if (!msgPtr->ParseFromString(_data))
206  {
207  std::cerr << "ReqHandler::CreateMsg() error: ParseFromString failed"
208  << std::endl;
209  }
210 
211  return msgPtr;
212  }
213 
219  public: void SetCallback(const std::function <void(
220  const Rep &_rep, const bool _result)> &_cb)
221  {
222  this->cb = _cb;
223  }
224 
228  public: void SetMessage(const Req *_reqMsg)
229  {
230  if (!_reqMsg)
231  {
232  std::cerr << "ReqHandler::SetMessage() _reqMsg is null" << std::endl;
233  return;
234  }
235 
236  this->reqMsg.CopyFrom(*_reqMsg);
237  }
238 
244  public: void SetResponse(const Rep *_repMsg)
245  {
246  (void)_repMsg;
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 std::string(Req().GetTypeName());
287  }
288 
289  // Documentation inherited.
290  public: virtual std::string RepTypeName() const
291  {
292  return std::string(Rep().GetTypeName());
293  }
294 
296  private: Req reqMsg;
297 
303  private: std::function<void(const Rep &_rep, const bool _result)> cb;
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 std::string(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 std::string(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 #endif