Discovery.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_DISCOVERY_HH_INCLUDED__
19 #define __IGN_TRANSPORT_DISCOVERY_HH_INCLUDED__
20 
21 #ifdef _WIN32
22  // For socket(), connect(), send(), and recv().
23  #include <Winsock2.h>
24  // Type used for raw data on this platform.
25  using raw_type = char;
26 #else
27  // For sockaddr_in
28  #include <netinet/in.h>
29  // Type used for raw data on this platform
30  using raw_type = void;
31 #endif
32 
33 #include <memory>
34 #include <mutex>
35 #include <string>
36 #include <vector>
37 
42 
43 namespace ignition
44 {
45  namespace transport
46  {
47  class DiscoveryPrivate;
48  class Publisher;
49 
59  {
64  public: Discovery(const std::string &_pUuid,
65  const bool _verbose = false);
66 
68  public: virtual ~Discovery();
69 
73  public: void Start();
74 
79  public: bool AdvertiseMsg(const MessagePublisher &_publisher);
80 
85  public: bool AdvertiseSrv(const ServicePublisher &_publisher);
86 
97  public: bool DiscoverMsg(const std::string &_topic);
98 
109  public: bool DiscoverSrv(const std::string &_topic);
110 
113  public: const TopicStorage<MessagePublisher> &DiscoveryMsgInfo() const;
114 
117  public: const TopicStorage<ServicePublisher> &DiscoverySrvInfo() const;
118 
123  public: bool MsgPublishers(const std::string &_topic,
124  MsgAddresses_M &_publishers);
125 
130  public: bool SrvPublishers(const std::string &_topic,
131  SrvAddresses_M &_publishers);
132 
140  public: bool UnadvertiseMsg(const std::string &_topic,
141  const std::string &_nUuid);
142 
150  public: bool UnadvertiseSrv(const std::string &_topic,
151  const std::string &_nUuid);
152 
155  public: std::string HostAddr() const;
156 
161  public: unsigned int ActivityInterval() const;
162 
168  public: unsigned int HeartbeatInterval() const;
169 
174  public: unsigned int AdvertiseInterval() const;
175 
180  public: unsigned int SilenceInterval() const;
181 
185  public: void SetActivityInterval(const unsigned int _ms);
186 
190  public: void SetHeartbeatInterval(const unsigned int _ms);
191 
195  public: void SetAdvertiseInterval(const unsigned int _ms);
196 
200  public: void SetSilenceInterval(const unsigned int _ms);
201 
206  public: void ConnectionsCb(const MsgDiscoveryCallback &_cb);
207 
214  public: template<typename C> void ConnectionsCb(
215  void(C::*_cb)(const MessagePublisher &_pub),
216  C *_obj)
217  {
218  this->ConnectionsCb(std::bind(_cb, _obj, std::placeholders::_1));
219  }
220 
225  public: void DisconnectionsCb(
227 
234  public: template<typename C> void DisconnectionsCb(
235  void(C::*_cb)(const MessagePublisher &_pub),
236  C *_obj)
237  {
238  this->DisconnectionsCb(std::bind(_cb, _obj, std::placeholders::_1));
239  }
240 
246  public: void ConnectionsSrvCb(const SrvDiscoveryCallback &_cb);
247 
255  public: template<typename C> void ConnectionsSrvCb(
256  void(C::*_cb)(const ServicePublisher &_pub),
257  C *_obj)
258  {
259  this->ConnectionsSrvCb(std::bind(_cb, _obj, std::placeholders::_1));
260  }
261 
268  public: void DisconnectionsSrvCb(
270 
278  public: template<typename C> void DisconnectionsSrvCb(
279  void(C::*_cb)(const ServicePublisher &_pub), C *_obj)
280  {
281  this->DisconnectionsSrvCb(std::bind(_cb, _obj, std::placeholders::_1));
282  }
283 
285  public: void PrintCurrentState() const;
286 
289  public: void TopicList(std::vector<std::string> &_topics) const;
290 
293  public: void ServiceList(std::vector<std::string> &_services) const;
294 
297  public: std::recursive_mutex& Mutex() const;
298 
301  public: void WaitForInit() const;
302 
306  private: void RunActivityTask();
307 
309  private: void RunHeartbeatTask();
310 
312  private: void RunReceptionTask();
313 
315  private: void RecvDiscoveryUpdate();
316 
320  private: void DispatchDiscoveryMsg(const std::string &_fromIp,
321  char *_msg);
322 
329  private: template<typename T> void SendMsg(uint8_t _type,
330  const T &_pub, const uint16_t _flags = 0) const
331  {
332  // Create the header.
333  Header header(this->Version(), _pub.PUuid(), _type, _flags);
334  auto msgLength = 0;
335  std::vector<char> buffer;
336 
337  std::string topic = _pub.Topic();
338 
339  switch (_type)
340  {
341  case AdvType:
342  case UnadvType:
343  case AdvSrvType:
344  case UnadvSrvType:
345  {
346  // Create the [UN]ADVERTISE message.
347  transport::AdvertiseMessage<T> advMsg(header, _pub);
348 
349  // Allocate a buffer and serialize the message.
350  buffer.resize(advMsg.MsgLength());
351  advMsg.Pack(reinterpret_cast<char*>(&buffer[0]));
352  msgLength = static_cast<int>(advMsg.MsgLength());
353  break;
354  }
355  case SubType:
356  case SubSrvType:
357  {
358  // Create the [UN]SUBSCRIBE message.
359  SubscriptionMsg subMsg(header, topic);
360 
361  // Allocate a buffer and serialize the message.
362  buffer.resize(subMsg.MsgLength());
363  subMsg.Pack(reinterpret_cast<char*>(&buffer[0]));
364  msgLength = static_cast<int>(subMsg.MsgLength());
365  break;
366  }
367  case HeartbeatType:
368  case ByeType:
369  {
370  // Allocate a buffer and serialize the message.
371  buffer.resize(header.HeaderLength());
372  header.Pack(reinterpret_cast<char*>(&buffer[0]));
373  msgLength = header.HeaderLength();
374  break;
375  }
376  default:
377  std::cerr << "Discovery::SendMsg() error: Unrecognized message"
378  << " type [" << _type << "]" << std::endl;
379  return;
380  }
381 
382  // Send the discovery message to the multicast group through all the
383  // sockets.
384  for (const auto &sock : this->Sockets())
385  {
386  std::lock_guard<std::recursive_mutex> lock(this->Mutex());
387  if (sendto(sock, reinterpret_cast<const raw_type *>(
388  reinterpret_cast<unsigned char*>(&buffer[0])),
389  msgLength, 0, reinterpret_cast<sockaddr *>(this->MulticastAddr()),
390  sizeof(*(this->MulticastAddr()))) != msgLength)
391  {
392  std::cerr << "Exception sending a message" << std::endl;
393  return;
394  }
395  }
396 
397  if (this->Verbose())
398  {
399  std::cout << "\t* Sending " << MsgTypesStr[_type]
400  << " msg [" << topic << "]" << std::endl;
401  }
402  }
403 
406  private: std::vector<int>& Sockets() const;
407 
410  private: sockaddr_in* MulticastAddr() const;
411 
414  private: bool Verbose() const;
415 
418  private: uint8_t Version() const;
419 
424  private: bool RegisterNetIface(const std::string &_ip);
425 
428  protected: std::unique_ptr<DiscoveryPrivate> dataPtr;
429  };
430  }
431 }
432 
433 #endif
static const uint8_t AdvSrvType
Definition: Packet.hh:40
std::map< std::string, std::vector< MessagePublisher > > MsgAddresses_M
Definition: TransportTypes.hh:51
#define IGNITION_VISIBLE
Use to represent "symbol visible" if supported.
Definition: Helpers.hh:56
static const std::vector< std::string > MsgTypesStr
Used for debugging the message type received/send.
Definition: Packet.hh:47
std::map< std::string, std::vector< ServicePublisher > > SrvAddresses_M
Definition: TransportTypes.hh:58
void DisconnectionsSrvCb(void(C::*_cb)(const ServicePublisher &_pub), C *_obj)
Register a callback to receive discovery disconnection events.
Definition: Discovery.hh:278
void DisconnectionsCb(void(C::*_cb)(const MessagePublisher &_pub), C *_obj)
Register a callback to receive discovery disconnection events.
Definition: Discovery.hh:234
Header included in each discovery message containing the version of the discovery protocol...
Definition: Packet.hh:58
Subscription packet used in the discovery protocol for requesting information about a given topic...
Definition: Packet.hh:163
void raw_type
Definition: Discovery.hh:30
A discovery class that implements a distributed topic discovery protocol.
Definition: Discovery.hh:58
size_t MsgLength() const
Get the total length of the message.
Definition: Packet.hh:284
static const uint8_t HeartbeatType
Definition: Packet.hh:38
size_t MsgLength() const
Get the total length of the message.
static const uint8_t ByeType
Definition: Packet.hh:39
static const uint8_t UnadvSrvType
Definition: Packet.hh:42
static const uint8_t SubType
Definition: Packet.hh:36
std::unique_ptr< DiscoveryPrivate > dataPtr
Definition: Discovery.hh:428
Advertise packet used in the discovery protocol to broadcast information about the node advertising a...
Definition: Packet.hh:235
std::function< void(const ServicePublisher &_publisher)> SrvDiscoveryCallback
Definition: TransportTypes.hh:110
std::function< void(const MessagePublisher &_publisher)> MsgDiscoveryCallback
Definition: TransportTypes.hh:102
ignition/transport/Publisher.hh
Definition: Publisher.hh:175
ignition/transport/Publisher.hh
Definition: Publisher.hh:264
void ConnectionsCb(void(C::*_cb)(const MessagePublisher &_pub), C *_obj)
Register a callback to receive discovery connection events.
Definition: Discovery.hh:214
static const uint8_t SubSrvType
Definition: Packet.hh:41
size_t Pack(char *_buffer) const
Serialize the advertise message.
Definition: Packet.hh:292
Definition: AdvertiseOptions.hh:25
static const uint8_t AdvType
Definition: Packet.hh:35
Store address information about topics and provide convenient methods for adding new topics...
Definition: TopicStorage.hh:37
void ConnectionsSrvCb(void(C::*_cb)(const ServicePublisher &_pub), C *_obj)
Register a callback to receive discovery connection events for services.
Definition: Discovery.hh:255
size_t Pack(char *_buffer) const
Serialize the subscription message.
static const uint8_t UnadvType
Definition: Packet.hh:37