Ignition Transport

API Reference

4.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/Export.hh"
37
38namespace ignition
39{
40 namespace transport
41 {
44 class IGNITION_TRANSPORT_VISIBLE IReqHandler
45 {
48 public: explicit IReqHandler(const std::string &_nUuid)
49 : rep(""),
50 result(false),
51 hUuid(Uuid().ToString()),
52 nUuid(_nUuid),
53 requested(false),
54 repAvailable(false)
55 {
56 }
57
59 public: virtual ~IReqHandler() = default;
60
67 public: virtual void NotifyResult(const std::string &_rep,
68 const bool _result) = 0;
69
72 public: std::string NodeUuid() const
73 {
74 return this->nUuid;
75 }
76
79 public: std::string Response() const
80 {
81 return this->rep;
82 }
83
86 public: bool Result() const
87 {
88 return this->result;
89 }
90
93 public: bool Requested() const
94 {
95 return this->requested;
96 }
97
100 public: void Requested(const bool _value)
101 {
102 this->requested = _value;
103 }
104
108 public: virtual bool Serialize(std::string &_buffer) const = 0;
109
112 public: std::string HandlerUuid() const
113 {
114 return this->hUuid;
115 }
116
124 public: template<typename Lock> bool WaitUntil(Lock &_lock,
125 const unsigned int _timeout)
126 {
128 return this->condition.wait_until(_lock,
129 now + std::chrono::milliseconds(_timeout),
130 [this]
131 {
132 return this->repAvailable;
133 });
134 }
135
138 public: virtual std::string ReqTypeName() const = 0;
139
142 public: virtual std::string RepTypeName() const = 0;
143
147
149 protected: std::string rep;
150
152 protected: bool result;
153
155 protected: std::string hUuid;
156
158 private: std::string nUuid;
159
162 private: bool requested;
163
167 public: bool repAvailable;
168 };
169
175 template <typename Req, typename Rep> class ReqHandler
176 : public IReqHandler
177 {
178 // Documentation inherited.
179 public: explicit ReqHandler(const std::string &_nUuid)
180 : IReqHandler(_nUuid)
181 {
182 }
183
187 public: std::shared_ptr<Rep> CreateMsg(const std::string &_data) const
188 {
189 // Instantiate a specific protobuf message
190 std::shared_ptr<Rep> msgPtr(new Rep());
191
192 // Create the message using some serialized data
193 if (!msgPtr->ParseFromString(_data))
194 {
195 std::cerr << "ReqHandler::CreateMsg() error: ParseFromString failed"
196 << std::endl;
197 }
198
199 return msgPtr;
200 }
201
207 public: void SetCallback(const std::function <void(
208 const Rep &_rep, const bool _result)> &_cb)
209 {
210 this->cb = _cb;
211 }
212
216 public: void SetMessage(const Req *_reqMsg)
217 {
218 if (!_reqMsg)
219 {
220 std::cerr << "ReqHandler::SetMessage() _reqMsg is null" << std::endl;
221 return;
222 }
223
224 this->reqMsg.CopyFrom(*_reqMsg);
225 }
226
232 public: void SetResponse(const Rep * /*_repMsg*/)
233 {
234 }
235
236 // Documentation inherited
237 public: bool Serialize(std::string &_buffer) const
238 {
239 if (!this->reqMsg.SerializeToString(&_buffer))
240 {
241 std::cerr << "ReqHandler::Serialize(): Error serializing the request"
242 << std::endl;
243 return false;
244 }
245
246 return true;
247 }
248
249 // Documentation inherited.
250 public: void NotifyResult(const std::string &_rep, const bool _result)
251 {
252 // Execute the callback (if existing).
253 if (this->cb)
254 {
255 // Instantiate the specific protobuf message associated to this topic.
256 auto msg = this->CreateMsg(_rep);
257
258 this->cb(*msg, _result);
259 }
260 else
261 {
262 this->rep = _rep;
263 this->result = _result;
264 }
265
266 this->repAvailable = true;
267 this->condition.notify_one();
268 }
269
270 // Documentation inherited.
271 public: virtual std::string ReqTypeName() const
272 {
273 return Req().GetTypeName();
274 }
275
276 // Documentation inherited.
277 public: virtual std::string RepTypeName() const
278 {
279 return Rep().GetTypeName();
280 }
281
283 private: Req reqMsg;
284
290 private: std::function<void(const Rep &_rep, const bool _result)> cb;
291 };
292
296 template <> class ReqHandler<google::protobuf::Message,
297 google::protobuf::Message>
298 : public IReqHandler
299 {
300 // Documentation inherited.
301 public: explicit ReqHandler(const std::string &_nUuid)
302 : IReqHandler(_nUuid)
303 {
304 }
305
309 public: void SetMessage(const google::protobuf::Message *_reqMsg)
310 {
311 if (!_reqMsg)
312 {
313 std::cerr << "ReqHandler::SetMessage() _reqMsg is null" << std::endl;
314 return;
315 }
316
317 this->reqMsg = _reqMsg->New();
318 this->reqMsg->CopyFrom(*_reqMsg);
319 }
320
325 public: void SetResponse(const google::protobuf::Message *_repMsg)
326 {
327 if (!_repMsg)
328 {
329 std::cerr << "ReqHandler::SetResponse() _repMsg is null" << std::endl;
330 return;
331 }
332
333 this->repMsg = _repMsg->New();
334 this->repMsg->CopyFrom(*_repMsg);
335 }
336
337 // Documentation inherited
338 public: bool Serialize(std::string &_buffer) const
339 {
340 if (!this->reqMsg)
341 {
342 std::cerr << "ReqHandler::Serialize() reqMsg is null" << std::endl;
343 return false;
344 }
345
346 if (!this->reqMsg->SerializeToString(&_buffer))
347 {
348 std::cerr << "ReqHandler::Serialize(): Error serializing the request"
349 << std::endl;
350 return false;
351 }
352
353 return true;
354 }
355
356 // Documentation inherited.
357 public: void NotifyResult(const std::string &_rep, const bool _result)
358 {
359 this->rep = _rep;
360 this->result = _result;
361
362 this->repAvailable = true;
363 this->condition.notify_one();
364 }
365
366 // Documentation inherited.
367 public: virtual std::string ReqTypeName() const
368 {
369 if (this->reqMsg)
370 return this->reqMsg->GetTypeName();
371 else
372 {
373 std::cerr << "ReqHandler::ReqTypeName() Warning: Using ReqTypeName() "
374 << "without type information" << std::endl;
375 return "";
376 }
377 }
378
380 public: virtual std::string RepTypeName() const
381 {
382 if (this->repMsg)
383 return this->repMsg->GetTypeName();
384 else
385 {
386 std::cerr << "ReqHandler::RepTypeName() Warning: Using RepTypeName() "
387 << "without type information" << std::endl;
388 return "";
389 }
390 }
391
393 private: google::protobuf::Message *reqMsg = nullptr;
394
396 private: google::protobuf::Message *repMsg = nullptr;
397 };
398 }
399}
400
401#endif
Interface class used to manage a request handler.
Definition ReqHandler.hh:45
IReqHandler(const std::string &_nUuid)
Constructor.
Definition ReqHandler.hh:48
bool Result() const
Get the result of the service response.
Definition ReqHandler.hh:86
void Requested(const bool _value)
Mark the service call as requested (or not).
Definition ReqHandler.hh:100
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:167
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...
bool result
Stores the result of the service call.
Definition ReqHandler.hh:152
bool Requested() const
Returns if this service call request has already been requested.
Definition ReqHandler.hh:93
std::string Response() const
Get the service response as raw bytes.
Definition ReqHandler.hh:79
std::string HandlerUuid() const
Returns the unique handler UUID.
Definition ReqHandler.hh:112
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:124
virtual bool Serialize(std::string &_buffer) const =0
Serialize the Req protobuf message stored.
std::string hUuid
Unique handler's UUID.
Definition ReqHandler.hh:155
virtual ~IReqHandler()=default
Destructor.
std::string rep
Stores the service response as raw bytes.
Definition ReqHandler.hh:149
std::condition_variable_any condition
Condition variable used to wait until a service call REP is available.
Definition ReqHandler.hh:146
virtual std::string RepTypeName() const =0
Get the message type name used in the service response.
std::string NodeUuid() const
Get the node UUID.
Definition ReqHandler.hh:72
virtual std::string ReqTypeName() const =0
Get the message type name used in the service request.
void SetResponse(const google::protobuf::Message *_repMsg)
Set the REP protobuf message for this handler.
Definition ReqHandler.hh:325
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:357
bool Serialize(std::string &_buffer) const
Serialize the Req protobuf message stored.
Definition ReqHandler.hh:338
void SetMessage(const google::protobuf::Message *_reqMsg)
Set the REQ protobuf message for this handler.
Definition ReqHandler.hh:309
virtual std::string RepTypeName() const
Get the message type name used in the service response.
Definition ReqHandler.hh:380
virtual std::string ReqTypeName() const
Get the message type name used in the service request.
Definition ReqHandler.hh:367
It creates a reply handler for the specific protobuf messages used. 'Req' is a protobuf message type ...
Definition ReqHandler.hh:177
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:250
std::shared_ptr< Rep > CreateMsg(const std::string &_data) const
Create a specific protobuf message given its serialized data.
Definition ReqHandler.hh:187
bool Serialize(std::string &_buffer) const
Serialize the Req protobuf message stored.
Definition ReqHandler.hh:237
void SetMessage(const Req *_reqMsg)
Set the REQ protobuf message for this handler.
Definition ReqHandler.hh:216
ReqHandler(const std::string &_nUuid)
Definition ReqHandler.hh:179
virtual std::string RepTypeName() const
Get the message type name used in the service response.
Definition ReqHandler.hh:277
void SetCallback(const std::function< void(const Rep &_rep, const bool _result)> &_cb)
Set the callback for this handler.
Definition ReqHandler.hh:207
virtual std::string ReqTypeName() const
Get the message type name used in the service request.
Definition ReqHandler.hh:271
void SetResponse(const Rep *)
This function is only used for compatibility with SetResponse() when [REP = google::protobuf::Message...
Definition ReqHandler.hh:232
A portable class for representing a Universally Unique Identifier.
Definition Uuid.hh:42
T endl(T... args)
_result
Definition Node.hh:1167
*brief Advertise a new service without any output parameter *In this version the callback is a free function *param[in] _topic Topic name associated to the service *param[in] _cb Callback to handle the service request with the *following void(* _cb)(const RequestT &_req)
Definition Node.hh:527
Definition AdvertiseOptions.hh:28