openthread-br  0.3.0-72c0388
mdns.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017, The OpenThread Authors.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * 3. Neither the name of the copyright holder nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
34 #ifndef OTBR_AGENT_MDNS_HPP_
35 #define OTBR_AGENT_MDNS_HPP_
36 
37 #include <functional>
38 #include <map>
39 #include <memory>
40 #include <string>
41 #include <vector>
42 
43 #include <sys/select.h>
44 
45 #include "common/callback.hpp"
46 #include "common/code_utils.hpp"
47 #include "common/time.hpp"
48 #include "common/types.hpp"
49 
50 namespace otbr {
51 
52 namespace Mdns {
53 
67 class Publisher : private NonCopyable
68 {
69 public:
74  struct TxtEntry
75  {
76  std::string mName;
77  std::vector<uint8_t> mValue;
78 
79  TxtEntry(const char *aName, const char *aValue)
80  : TxtEntry(aName, reinterpret_cast<const uint8_t *>(aValue), strlen(aValue))
81  {
82  }
83 
84  TxtEntry(const char *aName, const uint8_t *aValue, size_t aValueLength)
85  : TxtEntry(aName, strlen(aName), aValue, aValueLength)
86  {
87  }
88 
89  TxtEntry(const char *aName, size_t aNameLength, const uint8_t *aValue, size_t aValueLength)
90  : mName(aName, aNameLength)
91  , mValue(aValue, aValue + aValueLength)
92  {
93  }
94 
95  bool operator==(const TxtEntry &aOther) const { return mName == aOther.mName && mValue == aOther.mValue; }
96  };
97 
98  typedef std::vector<TxtEntry> TxtList;
99  typedef std::vector<std::string> SubTypeList;
100  typedef std::vector<Ip6Address> AddressList;
101 
107  {
108  bool mRemoved = false;
109  uint32_t mNetifIndex = 0;
110  std::string mName;
111  std::string mHostName;
112  std::vector<Ip6Address> mAddresses;
113  uint16_t mPort = 0;
114  uint16_t mPriority = 0;
115  uint16_t mWeight = 0;
116  std::vector<uint8_t> mTxtData;
117  uint32_t mTtl = 0;
118  };
119 
125  {
126  std::string mHostName;
127  std::vector<Ip6Address> mAddresses;
128  uint32_t mTtl = 0;
129  };
130 
136  std::function<void(const std::string &aType, const DiscoveredInstanceInfo &aInstanceInfo)>;
137 
142  using DiscoveredHostCallback =
143  std::function<void(const std::string &aHostName, const DiscoveredHostInfo &aHostInfo)>;
144 
149  enum class State
150  {
151  kIdle,
152  kReady,
153  };
154 
156  using StateCallback = std::function<void(State aNewState)>;
157 
159  using ResultCallback = OnceCallback<void(otbrError aError)>;
160 
168  virtual otbrError Start(void) = 0;
169 
174  virtual void Stop(void) = 0;
175 
183  virtual bool IsStarted(void) const = 0;
184 
204  void PublishService(const std::string &aHostName,
205  const std::string &aName,
206  const std::string &aType,
207  const SubTypeList &aSubTypeList,
208  uint16_t aPort,
209  const TxtList & aTxtList,
210  ResultCallback && aCallback);
211 
220  virtual void UnpublishService(const std::string &aName, const std::string &aType, ResultCallback &&aCallback) = 0;
221 
237  void PublishHost(const std::string &aName, const std::vector<Ip6Address> &aAddresses, ResultCallback &&aCallback);
238 
246  virtual void UnpublishHost(const std::string &aName, ResultCallback &&aCallback) = 0;
247 
262  virtual void SubscribeService(const std::string &aType, const std::string &aInstanceName) = 0;
263 
276  virtual void UnsubscribeService(const std::string &aType, const std::string &aInstanceName) = 0;
277 
288  virtual void SubscribeHost(const std::string &aHostName) = 0;
289 
298  virtual void UnsubscribeHost(const std::string &aHostName) = 0;
299 
310  DiscoveredHostCallback aHostCallback);
311 
318  void RemoveSubscriptionCallbacks(uint64_t aSubscriberId);
319 
326  const MdnsTelemetryInfo &GetMdnsTelemetryInfo() const { return mTelemetryInfo; }
327 
328  virtual ~Publisher(void) = default;
329 
338  static Publisher *Create(StateCallback aCallback);
339 
346  static void Destroy(Publisher *aPublisher);
347 
364  static otbrError EncodeTxtData(const TxtList &aTxtList, std::vector<uint8_t> &aTxtData);
365 
382  static otbrError DecodeTxtData(TxtList &aTxtList, const uint8_t *aTxtData, uint16_t aTxtLength);
383 
384 protected:
385  static constexpr uint8_t kMaxTextEntrySize = 255;
386 
388  {
389  public:
390  ResultCallback mCallback;
391  Publisher * mPublisher;
392 
393  Registration(ResultCallback &&aCallback, Publisher *aPublisher)
394  : mCallback(std::move(aCallback))
395  , mPublisher(aPublisher)
396  {
397  }
398  virtual ~Registration(void);
399 
400  // Tells whether the service registration has been completed (typically by calling
401  // `ServiceRegistration::Complete`).
402  bool IsCompleted() const { return mCallback.IsNull(); }
403 
404  protected:
405  // Completes the service registration with given result/error.
406  void TriggerCompleteCallback(otbrError aError)
407  {
408  if (!IsCompleted())
409  {
410  std::move(mCallback)(aError);
411  }
412  }
413  };
414 
416  {
417  public:
418  std::string mHostName;
419  std::string mName;
420  std::string mType;
421  SubTypeList mSubTypeList;
422  uint16_t mPort;
423  TxtList mTxtList;
424 
425  ServiceRegistration(std::string aHostName,
426  std::string aName,
427  std::string aType,
428  SubTypeList aSubTypeList,
429  uint16_t aPort,
430  TxtList aTxtList,
431  ResultCallback &&aCallback,
432  Publisher * aPublisher)
433  : Registration(std::move(aCallback), aPublisher)
434  , mHostName(std::move(aHostName))
435  , mName(std::move(aName))
436  , mType(std::move(aType))
437  , mSubTypeList(SortSubTypeList(std::move(aSubTypeList)))
438  , mPort(aPort)
439  , mTxtList(SortTxtList(std::move(aTxtList)))
440  {
441  }
442  ~ServiceRegistration(void) override { OnComplete(OTBR_ERROR_ABORTED); }
443 
444  void Complete(otbrError aError);
445 
446  void OnComplete(otbrError aError);
447 
448  // Tells whether this `ServiceRegistration` object is outdated comparing to the given parameters.
449  bool IsOutdated(const std::string &aHostName,
450  const std::string &aName,
451  const std::string &aType,
452  const SubTypeList &aSubTypeList,
453  uint16_t aPort,
454  const TxtList & aTxtList) const;
455  };
456 
458  {
459  public:
460  std::string mName;
461  std::vector<Ip6Address> mAddresses;
462 
463  HostRegistration(std::string aName, AddressList aAddresses, ResultCallback &&aCallback, Publisher *aPublisher)
464  : Registration(std::move(aCallback), aPublisher)
465  , mName(std::move(aName))
466  , mAddresses(SortAddressList(std::move(aAddresses)))
467  {
468  }
469 
470  ~HostRegistration(void) { OnComplete(OTBR_ERROR_ABORTED); }
471 
472  void Complete(otbrError aError);
473 
474  void OnComplete(otbrError);
475 
476  // Tells whether this `HostRegistration` object is outdated comparing to the given parameters.
477  bool IsOutdated(const std::string &aName, const std::vector<Ip6Address> &aAddresses) const;
478  };
479 
480  using ServiceRegistrationPtr = std::unique_ptr<ServiceRegistration>;
481  using ServiceRegistrationMap = std::map<std::string, ServiceRegistrationPtr>;
482  using HostRegistrationPtr = std::unique_ptr<HostRegistration>;
483  using HostRegistrationMap = std::map<std::string, HostRegistrationPtr>;
484 
485  static SubTypeList SortSubTypeList(SubTypeList aSubTypeList);
486  static TxtList SortTxtList(TxtList aTxtList);
487  static AddressList SortAddressList(AddressList aAddressList);
488  static std::string MakeFullServiceName(const std::string &aName, const std::string &aType);
489  static std::string MakeFullHostName(const std::string &aName);
490 
491  virtual otbrError PublishServiceImpl(const std::string &aHostName,
492  const std::string &aName,
493  const std::string &aType,
494  const SubTypeList &aSubTypeList,
495  uint16_t aPort,
496  const TxtList & aTxtList,
497  ResultCallback && aCallback) = 0;
498  virtual otbrError PublishHostImpl(const std::string & aName,
499  const std::vector<Ip6Address> &aAddresses,
500  ResultCallback && aCallback) = 0;
501  virtual void OnServiceResolveFailedImpl(const std::string &aType,
502  const std::string &aInstanceName,
503  int32_t aErrorCode) = 0;
504  virtual void OnHostResolveFailedImpl(const std::string &aHostName, int32_t aErrorCode) = 0;
505 
506  virtual otbrError DnsErrorToOtbrError(int32_t aError) = 0;
507 
508  void AddServiceRegistration(ServiceRegistrationPtr &&aServiceReg);
509  void RemoveServiceRegistration(const std::string &aName, const std::string &aType, otbrError aError);
510  ServiceRegistration *FindServiceRegistration(const std::string &aName, const std::string &aType);
511  void OnServiceResolved(const std::string &aType, const DiscoveredInstanceInfo &aInstanceInfo);
512  void OnServiceResolveFailed(const std::string &aType, const std::string &aInstanceName, int32_t aErrorCode);
513  void OnServiceRemoved(uint32_t aNetifIndex, const std::string &aType, const std::string &aInstanceName);
514  void OnHostResolved(const std::string &aHostName, const DiscoveredHostInfo &aHostInfo);
515  void OnHostResolveFailed(const std::string &aHostName, int32_t aErrorCode);
516 
517  // Handles the cases that there is already a registration for the same service.
518  // If the returned callback is completed, current registration should be considered
519  // success and no further action should be performed.
520  ResultCallback HandleDuplicateServiceRegistration(const std::string &aHostName,
521  const std::string &aName,
522  const std::string &aType,
523  const SubTypeList &aSubTypeList,
524  uint16_t aPort,
525  const TxtList & aTxtList,
526  ResultCallback && aCallback);
527 
528  ResultCallback HandleDuplicateHostRegistration(const std::string & aName,
529  const std::vector<Ip6Address> &aAddresses,
530  ResultCallback && aCallback);
531 
532  void AddHostRegistration(HostRegistrationPtr &&aHostReg);
533  void RemoveHostRegistration(const std::string &aName, otbrError aError);
534  HostRegistration *FindHostRegistration(const std::string &aName);
535 
536  static void UpdateMdnsResponseCounters(otbr::MdnsResponseCounters &aCounters, otbrError aError);
537  static void UpdateEmaLatency(uint32_t &aEmaLatency, uint32_t aLatency, otbrError aError);
538 
539  void UpdateServiceRegistrationEmaLatency(const std::string &aInstanceName,
540  const std::string &aType,
541  otbrError aError);
542  void UpdateHostRegistrationEmaLatency(const std::string &aHostName, otbrError aError);
543  void UpdateServiceInstanceResolutionEmaLatency(const std::string &aInstanceName,
544  const std::string &aType,
545  otbrError aError);
546  void UpdateHostResolutionEmaLatency(const std::string &aHostName, otbrError aError);
547 
548  ServiceRegistrationMap mServiceRegistrations;
549  HostRegistrationMap mHostRegistrations;
550 
551  uint64_t mNextSubscriberId = 1;
552 
553  std::map<uint64_t, std::pair<DiscoveredServiceInstanceCallback, DiscoveredHostCallback>> mDiscoveredCallbacks;
554  // {instance name, service type} -> the timepoint to begin service registration
555  std::map<std::pair<std::string, std::string>, Timepoint> mServiceRegistrationBeginTime;
556  // host name -> the timepoint to begin host registration
557  std::map<std::string, Timepoint> mHostRegistrationBeginTime;
558  // {instance name, service type} -> the timepoint to begin service resolution
559  std::map<std::pair<std::string, std::string>, Timepoint> mServiceInstanceResolutionBeginTime;
560  // host name -> the timepoint to begin host resolution
561  std::map<std::string, Timepoint> mHostResolutionBeginTime;
562 
563  otbr::MdnsTelemetryInfo mTelemetryInfo{};
564 };
565 
570 } // namespace Mdns
571 
572 } // namespace otbr
573 
574 #endif // OTBR_AGENT_MDNS_HPP_
otbr::Mdns::Publisher::SubscribeService
virtual void SubscribeService(const std::string &aType, const std::string &aInstanceName)=0
otbr::Mdns::Publisher::DecodeTxtData
static otbrError DecodeTxtData(TxtList &aTxtList, const uint8_t *aTxtData, uint16_t aTxtLength)
Definition: mdns.cpp:120
otbr::Mdns::Publisher::TxtEntry
Definition: mdns.hpp:74
otbr::Mdns::Publisher::UnsubscribeHost
virtual void UnsubscribeHost(const std::string &aHostName)=0
otbr::Mdns::Publisher::Start
virtual otbrError Start(void)=0
otbr::Mdns::Publisher::SubscribeHost
virtual void SubscribeHost(const std::string &aHostName)=0
otbr::Mdns::Publisher::DiscoveredInstanceInfo
Definition: mdns.hpp:106
otbr::Mdns::Publisher::AddSubscriptionCallbacks
uint64_t AddSubscriptionCallbacks(DiscoveredServiceInstanceCallback aInstanceCallback, DiscoveredHostCallback aHostCallback)
Definition: mdns.cpp:167
otbr::Mdns::Publisher::UnsubscribeService
virtual void UnsubscribeService(const std::string &aType, const std::string &aInstanceName)=0
otbr::Mdns::Publisher::GetMdnsTelemetryInfo
const MdnsTelemetryInfo & GetMdnsTelemetryInfo() const
Definition: mdns.hpp:326
otbr::Mdns::Publisher::EncodeTxtData
static otbrError EncodeTxtData(const TxtList &aTxtList, std::vector< uint8_t > &aTxtData)
Definition: mdns.cpp:98
otbr::Mdns::Publisher::DiscoveredHostInfo::mTtl
uint32_t mTtl
Host TTL.
Definition: mdns.hpp:128
otbr::Mdns::Publisher::TxtEntry::mValue
std::vector< uint8_t > mValue
The value of the TXT entry.
Definition: mdns.hpp:77
otbr::Mdns::Publisher::PublishService
void PublishService(const std::string &aHostName, const std::string &aName, const std::string &aType, const SubTypeList &aSubTypeList, uint16_t aPort, const TxtList &aTxtList, ResultCallback &&aCallback)
Definition: mdns.cpp:50
otbr::Mdns::Publisher::UnpublishHost
virtual void UnpublishHost(const std::string &aName, ResultCallback &&aCallback)=0
otbr::Mdns::Publisher::Registration
Definition: mdns.hpp:387
otbr::Mdns::Publisher::State::kReady
@ kReady
Ready to publish service.
otbr::Mdns::Publisher::HostRegistration
Definition: mdns.hpp:457
otbr::Mdns::Publisher::ServiceRegistration
Definition: mdns.hpp:415
otbr::Mdns::Publisher::DiscoveredInstanceInfo::mNetifIndex
uint32_t mNetifIndex
Network interface.
Definition: mdns.hpp:109
otbr::Mdns::Publisher::IsStarted
virtual bool IsStarted(void) const =0
otbr::Mdns::Publisher::State::kIdle
@ kIdle
Unable to publish service.
code_utils.hpp
otbr::Mdns::Publisher::DiscoveredHostInfo::mAddresses
std::vector< Ip6Address > mAddresses
IP6 addresses.
Definition: mdns.hpp:127
otbr::Mdns::Publisher::DiscoveredServiceInstanceCallback
std::function< void(const std::string &aType, const DiscoveredInstanceInfo &aInstanceInfo)> DiscoveredServiceInstanceCallback
Definition: mdns.hpp:136
otbr::Mdns::Publisher::Create
static Publisher * Create(StateCallback aCallback)
Definition: mdns_avahi.cpp:968
otbr::Mdns::Publisher::State
State
Definition: mdns.hpp:149
otbr::Mdns::Publisher::DiscoveredInstanceInfo::mTtl
uint32_t mTtl
Service TTL.
Definition: mdns.hpp:117
otbr::Mdns::Publisher::DiscoveredInstanceInfo::mName
std::string mName
Instance name.
Definition: mdns.hpp:110
OTBR_ERROR_ABORTED
@ OTBR_ERROR_ABORTED
The operation is aborted.
Definition: types.hpp:85
otbr::Mdns::Publisher::DiscoveredHostInfo
Definition: mdns.hpp:124
otbr::Mdns::Publisher::Stop
virtual void Stop(void)=0
otbr::Mdns::Publisher::StateCallback
std::function< void(State aNewState)> StateCallback
Definition: mdns.hpp:156
otbr::Mdns::Publisher::UnpublishService
virtual void UnpublishService(const std::string &aName, const std::string &aType, ResultCallback &&aCallback)=0
otbr::Mdns::Publisher::DiscoveredHostCallback
std::function< void(const std::string &aHostName, const DiscoveredHostInfo &aHostInfo)> DiscoveredHostCallback
Definition: mdns.hpp:143
otbr::Mdns::Publisher
Definition: mdns.hpp:67
otbr::Mdns::Publisher::RemoveSubscriptionCallbacks
void RemoveSubscriptionCallbacks(uint64_t aSubscriberId)
Definition: mdns.cpp:154
otbr::Mdns::Publisher::DiscoveredHostInfo::mHostName
std::string mHostName
Full host name.
Definition: mdns.hpp:126
otbr::Mdns::Publisher::TxtEntry::mName
std::string mName
The name of the TXT entry.
Definition: mdns.hpp:76
otbr::Mdns::Publisher::DiscoveredInstanceInfo::mPriority
uint16_t mPriority
Service priority.
Definition: mdns.hpp:114
otbr::MdnsTelemetryInfo
Definition: types.hpp:395
otbr::Mdns::Publisher::DiscoveredInstanceInfo::mHostName
std::string mHostName
Full host name.
Definition: mdns.hpp:111
otbrError
otbrError
Definition: types.hpp:70
otbr::Mdns::Publisher::DiscoveredInstanceInfo::mRemoved
bool mRemoved
The Service Instance is removed.
Definition: mdns.hpp:108
otbr::MdnsResponseCounters
Definition: types.hpp:383
otbr::Mdns::Publisher::DiscoveredInstanceInfo::mTxtData
std::vector< uint8_t > mTxtData
TXT RDATA bytes.
Definition: mdns.hpp:116
otbr::Mdns::Publisher::DiscoveredInstanceInfo::mPort
uint16_t mPort
Port.
Definition: mdns.hpp:113
otbr::Mdns::Publisher::PublishHost
void PublishHost(const std::string &aName, const std::vector< Ip6Address > &aAddresses, ResultCallback &&aCallback)
Definition: mdns.cpp:69
otbr::Mdns::Publisher::DiscoveredInstanceInfo::mWeight
uint16_t mWeight
Service weight.
Definition: mdns.hpp:115
time.hpp
otbr::Mdns::Publisher::Destroy
static void Destroy(Publisher *aPublisher)
Definition: mdns_avahi.cpp:973
otbr::OnceCallback< void(otbrError aError)>
NonCopyable
Definition: code_utils.hpp:169
otbr::Mdns::Publisher::DiscoveredInstanceInfo::mAddresses
std::vector< Ip6Address > mAddresses
IPv6 addresses.
Definition: mdns.hpp:112