Gazebo Transport

API Reference

11.4.1
gz/transport/SubscriptionHandler.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_SUBSCRIPTIONHANDLER_HH_
19 #define GZ_TRANSPORT_SUBSCRIPTIONHANDLER_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 <google/protobuf/stubs/common.h>
30 
31 #if GOOGLE_PROTOBUF_VERSION >= 3000000 && GOOGLE_PROTOBUF_VERSION < 4022000
32 #include <google/protobuf/stubs/casts.h>
33 #endif
34 
35 #include <chrono>
36 #include <iostream>
37 #include <memory>
38 #include <string>
39 #include <utility>
40 
41 #include <gz/msgs/Factory.hh>
42 
43 #include "gz/transport/config.hh"
44 #include "gz/transport/Export.hh"
48 #include "gz/transport/Uuid.hh"
49 
50 namespace ignition::transport
51 {
52  // Inline bracket to help doxygen filtering.
53  inline namespace IGNITION_TRANSPORT_VERSION_NAMESPACE {
54  //
57  class IGNITION_TRANSPORT_VISIBLE SubscriptionHandlerBase
58  {
62  public: explicit SubscriptionHandlerBase(
63  const std::string &_nUuid,
64  const SubscribeOptions &_opts = SubscribeOptions());
65 
67  public: virtual ~SubscriptionHandlerBase() = default;
68 
72  public: virtual std::string TypeName() = 0;
73 
76  public: std::string NodeUuid() const;
77 
80  public: std::string HandlerUuid() const;
81 
85  protected: bool UpdateThrottling();
86 
88  protected: SubscribeOptions opts;
89 
92  protected: double periodNs;
93 
94 #ifdef _WIN32
95 // Disable warning C4251 which is triggered by
96 // std::*
97 #pragma warning(push)
98 #pragma warning(disable: 4251)
99 #endif
100  protected: std::string hUuid;
102 
105 
107  private: std::string nUuid;
108 #ifdef _WIN32
109 #pragma warning(pop)
110 #endif
111  };
112 
121  class IGNITION_TRANSPORT_VISIBLE ISubscriptionHandler
122  : public SubscriptionHandlerBase
123  {
127  public: explicit ISubscriptionHandler(
128  const std::string &_nUuid,
129  const SubscribeOptions &_opts = SubscribeOptions());
130 
132  public: virtual ~ISubscriptionHandler() = default;
133 
138  public: virtual bool RunLocalCallback(
139  const ProtoMsg &_msg,
140  const MessageInfo &_info) = 0;
141 
146  public: virtual const std::shared_ptr<ProtoMsg> CreateMsg(
147  const std::string &_data,
148  const std::string &_type) const = 0;
149  };
150 
155  template <typename T> class SubscriptionHandler
156  : public ISubscriptionHandler
157  {
158  // Documentation inherited.
159  public: explicit SubscriptionHandler(const std::string &_nUuid,
160  const SubscribeOptions &_opts = SubscribeOptions())
161  : ISubscriptionHandler(_nUuid, _opts)
162  {
163  }
164 
165  // Documentation inherited.
167  const std::string &_data,
168  const std::string &/*_type*/) const
169  {
170  // Instantiate a specific protobuf message
171  auto msgPtr = std::make_shared<T>();
172 
173  // Create the message using some serialized data
174  if (!msgPtr->ParseFromString(_data))
175  {
176  std::cerr << "SubscriptionHandler::CreateMsg() error: ParseFromString"
177  << " failed" << std::endl;
178  }
179 
180  return msgPtr;
181  }
182 
183  // Documentation inherited.
185  {
186  return std::string(T().GetTypeName());
187  }
188 
191  public: void SetCallback(const MsgCallback<T> &_cb)
192  {
193  this->cb = _cb;
194  }
195 
196  // Documentation inherited.
197  public: bool RunLocalCallback(const ProtoMsg &_msg,
198  const MessageInfo &_info)
199  {
200  // No callback stored.
201  if (!this->cb)
202  {
203  std::cerr << "SubscriptionHandler::RunLocalCallback() error: "
204  << "Callback is NULL" << std::endl;
205  return false;
206  }
207 
208  // Check the subscription throttling option.
209  if (!this->UpdateThrottling())
210  return true;
211 
212 #if GOOGLE_PROTOBUF_VERSION >= 5028000
213  auto msgPtr = google::protobuf::DynamicCastMessage<T>(&_msg);
214 #elif GOOGLE_PROTOBUF_VERSION >= 4022000
215  auto msgPtr = google::protobuf::internal::DownCast<const T*>(&_msg);
216 #elif GOOGLE_PROTOBUF_VERSION >= 3000000
217  auto msgPtr = google::protobuf::down_cast<const T*>(&_msg);
218 #else
219  auto msgPtr = google::protobuf::internal::down_cast<const T*>(&_msg);
220 #endif
221 
222  // Verify the dynamically casted message is valid
223  if (msgPtr == nullptr)
224  {
225  if (_msg.GetDescriptor() != nullptr)
226  {
227  std::cerr << "SubscriptionHandler::RunLocalCallback() error: "
228  << "Failed to cast the message of the type "
229  << _msg.GetDescriptor()->full_name()
230  << " to the specified type" << '\n';
231  }
232  else
233  {
234  std::cerr << "SubscriptionHandler::RunLocalCallback() error: "
235  << "Failed to cast the message of an unknown type"
236  << " to the specified type" << '\n';
237  }
238  std::cerr.flush();
239  return false;
240  }
241 
242  this->cb(*msgPtr, _info);
243  return true;
244  }
245 
247  private: MsgCallback<T> cb;
248  };
249 
252  template <> class SubscriptionHandler<ProtoMsg>
253  : public ISubscriptionHandler
254  {
255  // Documentation inherited.
256  public: explicit SubscriptionHandler(const std::string &_nUuid,
257  const SubscribeOptions &_opts = SubscribeOptions())
258  : ISubscriptionHandler(_nUuid, _opts)
259  {
260  }
261 
262  // Documentation inherited.
264  const std::string &_data,
265  const std::string &_type) const
266  {
268 
269  const google::protobuf::Descriptor *desc =
270  google::protobuf::DescriptorPool::generated_pool()
271  ->FindMessageTypeByName(_type);
272 
273  // First, check if we have the descriptor from the generated proto
274  // classes.
275  if (desc)
276  {
277  msgPtr.reset(google::protobuf::MessageFactory::generated_factory()
278  ->GetPrototype(desc)->New());
279  }
280  else
281  {
282  // Fallback on Ignition Msgs if the message type is not found.
283  msgPtr = gz::msgs::Factory::New(_type);
284  }
285 
286  if (!msgPtr)
287  return nullptr;
288 
289  // Create the message using some serialized data
290  if (!msgPtr->ParseFromString(_data))
291  {
292  std::cerr << "CreateMsg() error: ParseFromString failed" << std::endl;
293  return nullptr;
294  }
295 
296  return msgPtr;
297  }
298 
299  // Documentation inherited.
301  {
302  return kGenericMessageType;
303  }
304 
307  public: void SetCallback(const MsgCallback<ProtoMsg> &_cb)
308  {
309  this->cb = _cb;
310  }
311 
312  // Documentation inherited.
313  public: bool RunLocalCallback(const ProtoMsg &_msg,
314  const MessageInfo &_info)
315  {
316  // No callback stored.
317  if (!this->cb)
318  {
319  std::cerr << "SubscriptionHandler::RunLocalCallback() "
320  << "error: Callback is NULL" << std::endl;
321  return false;
322  }
323 
324  // Check the subscription throttling option.
325  if (!this->UpdateThrottling())
326  return true;
327 
328  this->cb(_msg, _info);
329  return true;
330  }
331 
333  private: MsgCallback<ProtoMsg> cb;
334  };
335 
340  {
347  public: explicit RawSubscriptionHandler(
348  const std::string &_nUuid,
349  const std::string &_msgType = kGenericMessageType,
350  const SubscribeOptions &_opts = SubscribeOptions());
351 
352  // Documentation inherited
353  public: std::string TypeName() override;
354 
358  public: void SetCallback(const RawCallback &_callback);
359 
366  public: bool RunRawCallback(const char *_msgData, const size_t _size,
367  const MessageInfo &_info);
368 
370  public: ~RawSubscriptionHandler();
371 
372  private: class Implementation;
373 
374 #ifdef _WIN32
375 // Disable warning C4251 which is triggered by
376 // std::unique_ptr
377 #pragma warning(push)
378 #pragma warning(disable: 4251)
379 #endif
380  private: std::unique_ptr<Implementation> pimpl;
383 #ifdef _WIN32
384 #pragma warning(pop)
385 #endif
386  };
387  }
388 }
389 
390 #endif
bool RunRawCallback(const char *_msgData, const size_t _size, const MessageInfo &_info)
Executes the raw callback registered for this handler.
SubscriptionHandler(const std::string &_nUuid, const SubscribeOptions &_opts=SubscribeOptions())
Definition: gz/transport/SubscriptionHandler.hh:256
STL class.
STL class.
double periodNs
If throttling is enabled, the minimum period for receiving a message in nanoseconds.
Definition: gz/transport/SubscriptionHandler.hh:92
google::protobuf::Message ProtoMsg
Definition: gz/transport/TransportTypes.hh:68
RawSubscriptionHandler(const std::string &_nUuid, const std::string &_msgType=kGenericMessageType, const SubscribeOptions &_opts=SubscribeOptions())
Constructor.
SubscriptionHandlerBase contains functions and data which are common to all SubscriptionHandler types...
Definition: gz/transport/SubscriptionHandler.hh:57
std::string TypeName()
Get the type of the messages from which this subscriber handler is subscribed.
Definition: gz/transport/SubscriptionHandler.hh:300
virtual ~ISubscriptionHandler()=default
Destructor.
std::string hUuid
Unique handler's UUID.
Definition: gz/transport/SubscriptionHandler.hh:101
SubscriptionHandlerBase(const std::string &_nUuid, const SubscribeOptions &_opts=SubscribeOptions())
Constructor.
bool UpdateThrottling()
Check if message subscription is throttled. If so, verify whether the callback should be executed or ...
T reset(T... args)
bool RunLocalCallback(const ProtoMsg &_msg, const MessageInfo &_info)
Executes the local callback registered for this handler.
Definition: gz/transport/SubscriptionHandler.hh:313
A class to provide different options for a subscription.
Definition: gz/transport/SubscribeOptions.hh:37
void SetCallback(const RawCallback &_callback)
Set the callback of this handler.
virtual ~SubscriptionHandlerBase()=default
Destructor.
Timestamp lastCbTimestamp
Timestamp of the last callback executed.
Definition: gz/transport/SubscriptionHandler.hh:104
virtual const std::shared_ptr< ProtoMsg > CreateMsg(const std::string &_data, const std::string &_type) const =0
Create a specific protobuf message given its serialized data.
std::chrono::steady_clock::time_point Timestamp
Definition: gz/transport/TransportTypes.hh:153
std::string TypeName() override
Get the type of the messages from which this subscriber handler is subscribed.
A class that provides information about the message received.
Definition: gz/transport/MessageInfo.hh:35
bool RunLocalCallback(const ProtoMsg &_msg, const MessageInfo &_info)
Executes the local callback registered for this handler.
Definition: gz/transport/SubscriptionHandler.hh:197
SubscribeOptions opts
Subscribe options.
Definition: gz/transport/SubscriptionHandler.hh:88
It creates a subscription handler for a specific protobuf message. 'T' is the Protobuf message type t...
Definition: gz/transport/SubscriptionHandler.hh:155
std::string NodeUuid() const
Get the node UUID.
Interface class used to manage generic protobuf messages.
Definition: gz/transport/SubscriptionHandler.hh:121
const std::shared_ptr< ProtoMsg > CreateMsg(const std::string &_data, const std::string &_type) const
Create a specific protobuf message given its serialized data.
Definition: gz/transport/SubscriptionHandler.hh:263
void SetCallback(const MsgCallback< ProtoMsg > &_cb)
Set the callback for this handler.
Definition: gz/transport/SubscriptionHandler.hh:307
T endl(T... args)
Definition: gz/transport/AdvertiseOptions.hh:28
std::string TypeName()
Get the type of the messages from which this subscriber handler is subscribed.
Definition: gz/transport/SubscriptionHandler.hh:184
const std::string kGenericMessageType
The string type used for generic messages.
Definition: gz/transport/TransportTypes.hh:172
std::string HandlerUuid() const
Get the unique UUID of this handler.
ISubscriptionHandler(const std::string &_nUuid, const SubscribeOptions &_opts=SubscribeOptions())
Constructor.
SubscriptionHandler(const std::string &_nUuid, const SubscribeOptions &_opts=SubscribeOptions())
Definition: gz/transport/SubscriptionHandler.hh:159
virtual bool RunLocalCallback(const ProtoMsg &_msg, const MessageInfo &_info)=0
Executes the local callback registered for this handler.
const std::shared_ptr< ProtoMsg > CreateMsg(const std::string &_data, const std::string &) const
Create a specific protobuf message given its serialized data.
Definition: gz/transport/SubscriptionHandler.hh:166
Definition: gz/transport/SubscriptionHandler.hh:339
void SetCallback(const MsgCallback< T > &_cb)
Set the callback for this handler.
Definition: gz/transport/SubscriptionHandler.hh:191
virtual std::string TypeName()=0
Get the type of the messages from which this subscriber handler is subscribed.