MDNSService.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. #include <cassert>
  2. #include <vector>
  3. #include "BellLogger.h"
  4. #include "MDNSService.h"
  5. #ifdef _WIN32
  6. #include <WinSock2.h>
  7. #include <iphlpapi.h>
  8. #pragma comment(lib, "IPHLPAPI.lib")
  9. #include "mdnssvc.h"
  10. #else
  11. #include <arpa/inet.h>
  12. #include "mdns.h"
  13. #endif
  14. using namespace bell;
  15. class implMDNSService : public MDNSService {
  16. private:
  17. struct mdns_service* service;
  18. void unregisterService(void);
  19. public:
  20. static struct mdnsd* mdnsServer;
  21. static std::atomic<size_t> instances;
  22. implMDNSService(struct mdns_service* service) : service(service) { instances++; };
  23. };
  24. /**
  25. * Win32 implementation of MDNSService
  26. **/
  27. struct mdnsd* implMDNSService::mdnsServer = NULL;
  28. std::atomic<size_t> implMDNSService::instances = 0;
  29. static std::mutex registerMutex;
  30. void implMDNSService::unregisterService() {
  31. mdns_service_remove(implMDNSService::mdnsServer, service);
  32. if (!--instances && implMDNSService::mdnsServer) {
  33. mdnsd_stop(implMDNSService::mdnsServer);
  34. implMDNSService::mdnsServer = nullptr;
  35. }
  36. }
  37. std::unique_ptr<MDNSService> MDNSService::registerService(
  38. const std::string& serviceName, const std::string& serviceType,
  39. const std::string& serviceProto, const std::string& serviceHost,
  40. int servicePort, const std::map<std::string, std::string> txtData) {
  41. std::lock_guard lock(registerMutex);
  42. if (!implMDNSService::mdnsServer) {
  43. char hostname[128];
  44. gethostname(hostname, sizeof(hostname));
  45. struct sockaddr_in* host = NULL;
  46. ULONG size = sizeof(IP_ADAPTER_ADDRESSES) * 64;
  47. IP_ADAPTER_ADDRESSES* adapters = (IP_ADAPTER_ADDRESSES*)malloc(size);
  48. int ret = GetAdaptersAddresses(AF_UNSPEC,
  49. GAA_FLAG_INCLUDE_GATEWAYS |
  50. GAA_FLAG_SKIP_MULTICAST |
  51. GAA_FLAG_SKIP_ANYCAST,
  52. 0, adapters, &size);
  53. for (PIP_ADAPTER_ADDRESSES adapter = adapters; adapter && !host;
  54. adapter = adapter->Next) {
  55. if (adapter->TunnelType == TUNNEL_TYPE_TEREDO)
  56. continue;
  57. if (adapter->OperStatus != IfOperStatusUp)
  58. continue;
  59. for (IP_ADAPTER_UNICAST_ADDRESS* unicast = adapter->FirstUnicastAddress;
  60. unicast; unicast = unicast->Next) {
  61. if (adapter->FirstGatewayAddress &&
  62. unicast->Address.lpSockaddr->sa_family == AF_INET) {
  63. host = (struct sockaddr_in*)unicast->Address.lpSockaddr;
  64. BELL_LOG(info, "mdns", "mDNS on interface %s",
  65. inet_ntoa(host->sin_addr));
  66. implMDNSService::mdnsServer = mdnsd_start(host->sin_addr, false);
  67. break;
  68. }
  69. }
  70. }
  71. assert(implMDNSService::mdnsServer);
  72. mdnsd_set_hostname(implMDNSService::mdnsServer, hostname, host->sin_addr);
  73. free(adapters);
  74. }
  75. std::vector<const char*> txt;
  76. std::vector<std::unique_ptr<std::string>> txtStr;
  77. for (auto& [key, value] : txtData) {
  78. auto str = make_unique<std::string>(key + "=" + value);
  79. txtStr.push_back(std::move(str));
  80. txt.push_back(txtStr.back()->c_str());
  81. }
  82. txt.push_back(NULL);
  83. std::string type(serviceType + "." + serviceProto + ".local");
  84. auto service =
  85. mdnsd_register_svc(implMDNSService::mdnsServer, serviceName.c_str(),
  86. type.c_str(), servicePort, NULL, txt.data());
  87. return service ? std::make_unique<implMDNSService>(service) : nullptr;
  88. }