| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 | 
							- #include <arpa/inet.h>
 
- #include <ifaddrs.h>
 
- #include <net/if.h>
 
- #include <netdb.h>
 
- #include <unistd.h>
 
- #include <cstring>
 
- #include <vector>
 
- #if __has_include("avahi-client/client.h")
 
- #include <avahi-client/client.h>
 
- #include <avahi-client/publish.h>
 
- #include <avahi-common/alternative.h>
 
- #include <avahi-common/simple-watch.h>
 
- #elif !defined(BELL_DISABLE_AVAHI)
 
- #define BELL_DISABLE_AVAHI
 
- #endif
 
- #include "BellLogger.h"
 
- #include "MDNSService.h"
 
- #include "mdnssvc.h"
 
- using namespace bell;
 
- #ifndef BELL_DISABLE_AVAHI
 
- static void groupHandler(AvahiEntryGroup* g, AvahiEntryGroupState state,
 
-                          AVAHI_GCC_UNUSED void* userdata) {}
 
- #endif
 
- class implMDNSService : public MDNSService {
 
-  private:
 
- #ifndef BELL_DISABLE_AVAHI
 
-   AvahiEntryGroup* avahiGroup;
 
- #endif
 
-   struct mdns_service* service;
 
-  public:
 
- #ifndef BELL_DISABLE_AVAHI
 
-   static AvahiClient* avahiClient;
 
-   static AvahiSimplePoll* avahiPoll;
 
- #endif
 
-   static struct mdnsd* mdnsServer;
 
-   static in_addr_t host;
 
-   implMDNSService(struct mdns_service* service) : service(service){};
 
- #ifndef BELL_DISABLE_AVAHI
 
-   implMDNSService(AvahiEntryGroup* avahiGroup) : avahiGroup(avahiGroup){};
 
- #endif
 
-   void unregisterService();
 
- };
 
- struct mdnsd* implMDNSService::mdnsServer = NULL;
 
- in_addr_t implMDNSService::host = INADDR_ANY;
 
- static std::mutex registerMutex;
 
- #ifndef BELL_DISABLE_AVAHI
 
- AvahiClient* implMDNSService::avahiClient = NULL;
 
- AvahiSimplePoll* implMDNSService::avahiPoll = NULL;
 
- #endif
 
- /**
 
-  * Linux implementation of MDNSService using avahi.
 
-  * @see https://www.avahi.org/doxygen/html/
 
-  **/
 
- void implMDNSService::unregisterService() {
 
- #ifndef BELL_DISABLE_AVAHI
 
-   if (avahiGroup) {
 
-     avahi_entry_group_free(avahiGroup);
 
-   } else
 
- #endif
 
-   {
 
-     mdns_service_remove(implMDNSService::mdnsServer, service);
 
-   }
 
- }
 
- std::unique_ptr<MDNSService> MDNSService::registerService(
 
-     const std::string& serviceName, const std::string& serviceType,
 
-     const std::string& serviceProto, const std::string& serviceHost,
 
-     int servicePort, const std::map<std::string, std::string> txtData) {
 
-   std::lock_guard lock(registerMutex);
 
- #ifndef BELL_DISABLE_AVAHI
 
-   // try avahi first if available
 
-   if (!implMDNSService::avahiPoll) {
 
-     implMDNSService::avahiPoll = avahi_simple_poll_new();
 
-   }
 
-   if (implMDNSService::avahiPoll && !implMDNSService::avahiClient) {
 
-     implMDNSService::avahiClient =
 
-         avahi_client_new(avahi_simple_poll_get(implMDNSService::avahiPoll),
 
-                          AvahiClientFlags(0), NULL, NULL, NULL);
 
-   }
 
-   AvahiEntryGroup* avahiGroup = NULL;
 
-   if (implMDNSService::avahiClient &&
 
-       (avahiGroup = avahi_entry_group_new(implMDNSService::avahiClient,
 
-                                           groupHandler, NULL)) == NULL) {
 
-     BELL_LOG(error, "MDNS", "cannot create service %s", serviceName.c_str());
 
-   }
 
-   if (avahiGroup != NULL) {
 
-     AvahiStringList* avahiTxt = NULL;
 
-     for (auto& [key, value] : txtData) {
 
-       avahiTxt =
 
-           avahi_string_list_add_pair(avahiTxt, key.c_str(), value.c_str());
 
-     }
 
-     std::string type(serviceType + "." + serviceProto);
 
-     int ret = avahi_entry_group_add_service_strlst(
 
-         avahiGroup, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, (AvahiPublishFlags)0,
 
-         serviceName.c_str(), type.c_str(), NULL, NULL, servicePort, avahiTxt);
 
-     avahi_string_list_free(avahiTxt);
 
-     if (ret >= 0) {
 
-       ret = avahi_entry_group_commit(avahiGroup);
 
-     }
 
-     if (ret < 0) {
 
-       BELL_LOG(error, "MDNS", "cannot run service %s", serviceName.c_str());
 
-       avahi_entry_group_free(avahiGroup);
 
-     } else {
 
-       BELL_LOG(info, "MDNS", "using avahi for %s", serviceName.c_str());
 
-       return std::make_unique<implMDNSService>(avahiGroup);
 
-     }
 
-   }
 
- #endif
 
-   // avahi failed, use build-in server
 
-   struct ifaddrs* ifaddr;
 
-   // get the host address first
 
-   if (serviceHost.size()) {
 
-     struct hostent* h = gethostbyname(serviceHost.c_str());
 
-     if (h) {
 
-       memcpy(&implMDNSService::host, h->h_addr_list[0], 4);
 
-     }
 
-   }
 
-   // try go guess ifaddr if we have nothing as listening to INADDR_ANY usually does not work
 
-   if (implMDNSService::host == INADDR_ANY && getifaddrs(&ifaddr) != -1) {
 
-     for (struct ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
 
-       if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET ||
 
-           !(ifa->ifa_flags & IFF_UP) || !(ifa->ifa_flags & IFF_MULTICAST) ||
 
-           (ifa->ifa_flags & IFF_LOOPBACK))
 
-         continue;
 
-       implMDNSService::host =
 
-           ((struct sockaddr_in*)ifa->ifa_addr)->sin_addr.s_addr;
 
-       break;
 
-     }
 
-     freeifaddrs(ifaddr);
 
-   }
 
-   if (!implMDNSService::mdnsServer) {
 
-     char hostname[256];
 
-     struct in_addr addr;
 
-     // it's the same, but who knows..
 
-     addr.s_addr = implMDNSService::host;
 
-     gethostname(hostname, sizeof(hostname));
 
-     implMDNSService::mdnsServer = mdnsd_start(addr, false);
 
-     if (implMDNSService::mdnsServer) {
 
-       mdnsd_set_hostname(implMDNSService::mdnsServer, hostname, addr);
 
-     }
 
-   }
 
-   if (implMDNSService::mdnsServer) {
 
-     std::vector<const char*> txt;
 
-     std::vector<std::unique_ptr<std::string>> txtStr;
 
-     for (auto& [key, value] : txtData) {
 
-       auto str = make_unique<std::string>(key + "=" + value);
 
-       txtStr.push_back(std::move(str));
 
-       txt.push_back(txtStr.back()->c_str());
 
-     }
 
-     txt.push_back(NULL);
 
-     std::string type(serviceType + "." + serviceProto + ".local");
 
-     BELL_LOG(info, "MDNS", "using built-in mDNS for %s", serviceName.c_str());
 
-     struct mdns_service* mdnsService =
 
-         mdnsd_register_svc(implMDNSService::mdnsServer, serviceName.c_str(),
 
-                            type.c_str(), servicePort, NULL, txt.data());
 
-     if (mdnsService) {
 
-       auto service =
 
-           mdnsd_register_svc(implMDNSService::mdnsServer, serviceName.c_str(),
 
-                              type.c_str(), servicePort, NULL, txt.data());
 
-       return std::make_unique<implMDNSService>(service);
 
-     }
 
-   }
 
-   BELL_LOG(error, "MDNS", "cannot start any mDNS listener for %s",
 
-            serviceName.c_str());
 
-   return NULL;
 
- }
 
 
  |