PageRenderTime 50ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/xbmc/network/windows/ZeroconfWIN.cpp

https://github.com/dahool84/xbmc
C++ | 184 lines | 140 code | 21 blank | 23 comment | 27 complexity | 3d3180311d98a5dc701bc97e354417e5 MD5 | raw file
  1. /*
  2. * Copyright (C) 2005-2011 Team XBMC
  3. * http://www.xbmc.org
  4. *
  5. * This Program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2, or (at your option)
  8. * any later version.
  9. *
  10. * This Program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with XBMC; see the file COPYING. If not, write to
  17. * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  18. * http://www.gnu.org/copyleft/gpl.html
  19. *
  20. */
  21. #include "ZeroconfWIN.h"
  22. #include <string>
  23. #include <sstream>
  24. #include <threads/SingleLock.h>
  25. #include <utils/log.h>
  26. #include "dialogs/GUIDialogKaiToast.h"
  27. #include "guilib/LocalizeStrings.h"
  28. #include "win32/WIN32Util.h"
  29. #pragma comment(lib, "dnssd.lib")
  30. extern HWND g_hWnd;
  31. CZeroconfWIN::CZeroconfWIN()
  32. {
  33. m_service = NULL;
  34. }
  35. CZeroconfWIN::~CZeroconfWIN()
  36. {
  37. doStop();
  38. }
  39. bool CZeroconfWIN::IsZCdaemonRunning()
  40. {
  41. uint32_t version;
  42. uint32_t size = sizeof(version);
  43. DNSServiceErrorType err = DNSServiceGetProperty(kDNSServiceProperty_DaemonVersion, &version, &size);
  44. if(err != kDNSServiceErr_NoError)
  45. {
  46. CLog::Log(LOGERROR, "ZeroconfWIN: Zeroconf can't be started probably because Apple's Bonjour Service isn't installed. You can get it by either installing Itunes or Apple's Bonjour Print Service for Windows (http://support.apple.com/kb/DL999)");
  47. CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(34300), g_localizeStrings.Get(34301), 10000, true);
  48. return false;
  49. }
  50. CLog::Log(LOGDEBUG, "ZeroconfWIN:Bonjour version is %d.%d", version / 10000, version / 100 % 100);
  51. return true;
  52. }
  53. //methods to implement for concrete implementations
  54. bool CZeroconfWIN::doPublishService(const std::string& fcr_identifier,
  55. const std::string& fcr_type,
  56. const std::string& fcr_name,
  57. unsigned int f_port,
  58. std::map<std::string, std::string> txt)
  59. {
  60. DNSServiceRef netService = NULL;
  61. TXTRecordRef txtRecord;
  62. DNSServiceErrorType err;
  63. TXTRecordCreate(&txtRecord, 0, NULL);
  64. if(m_service == NULL)
  65. {
  66. err = DNSServiceCreateConnection(&m_service);
  67. if (err != kDNSServiceErr_NoError)
  68. {
  69. CLog::Log(LOGERROR, "ZeroconfWIN: DNSServiceCreateConnection failed with error = %ld", (int) err);
  70. return false;
  71. }
  72. err = WSAAsyncSelect( (SOCKET) DNSServiceRefSockFD( m_service ), g_hWnd, BONJOUR_EVENT, FD_READ | FD_CLOSE );
  73. if (err != kDNSServiceErr_NoError)
  74. CLog::Log(LOGERROR, "ZeroconfWIN: WSAAsyncSelect failed with error = %ld", (int) err);
  75. }
  76. CLog::Log(LOGDEBUG, "ZeroconfWIN: identifier: %s type: %s name:%s port:%i", fcr_identifier.c_str(), fcr_type.c_str(), fcr_name.c_str(), f_port);
  77. //add txt records
  78. if(!txt.empty())
  79. {
  80. for(std::map<std::string, std::string>::const_iterator it = txt.begin(); it != txt.end(); ++it)
  81. {
  82. CLog::Log(LOGDEBUG, "ZeroconfWIN: key:%s, value:%s",it->first.c_str(),it->second.c_str());
  83. uint8_t txtLen = (uint8_t)strlen(it->second.c_str());
  84. TXTRecordSetValue(&txtRecord, it->first.c_str(), txtLen, it->second.c_str());
  85. }
  86. }
  87. {
  88. CSingleLock lock(m_data_guard);
  89. netService = m_service;
  90. err = DNSServiceRegister(&netService, kDNSServiceFlagsShareConnection, 0, fcr_name.c_str(), fcr_type.c_str(), NULL, NULL, htons(f_port), TXTRecordGetLength(&txtRecord), TXTRecordGetBytesPtr(&txtRecord), registerCallback, NULL);
  91. }
  92. if (err != kDNSServiceErr_NoError)
  93. {
  94. // Something went wrong so lets clean up.
  95. if (netService)
  96. DNSServiceRefDeallocate(netService);
  97. CLog::Log(LOGERROR, "ZeroconfWIN: DNSServiceRegister returned (error = %ld)", (int) err);
  98. }
  99. else
  100. {
  101. CSingleLock lock(m_data_guard);
  102. m_services.insert(make_pair(fcr_identifier, netService));
  103. }
  104. TXTRecordDeallocate(&txtRecord);
  105. return err == kDNSServiceErr_NoError;
  106. }
  107. bool CZeroconfWIN::doRemoveService(const std::string& fcr_ident)
  108. {
  109. CSingleLock lock(m_data_guard);
  110. tServiceMap::iterator it = m_services.find(fcr_ident);
  111. if(it != m_services.end())
  112. {
  113. DNSServiceRefDeallocate(it->second);
  114. m_services.erase(it);
  115. CLog::Log(LOGDEBUG, "ZeroconfWIN: Removed service %s", fcr_ident.c_str());
  116. return true;
  117. }
  118. else
  119. return false;
  120. }
  121. void CZeroconfWIN::doStop()
  122. {
  123. {
  124. CSingleLock lock(m_data_guard);
  125. CLog::Log(LOGDEBUG, "ZeroconfWIN: Shutdown services");
  126. for(tServiceMap::iterator it = m_services.begin(); it != m_services.end(); ++it)
  127. {
  128. DNSServiceRefDeallocate(it->second);
  129. CLog::Log(LOGDEBUG, "ZeroconfWIN: Removed service %s", it->first.c_str());
  130. }
  131. m_services.clear();
  132. }
  133. {
  134. CSingleLock lock(m_data_guard);
  135. WSAAsyncSelect( (SOCKET) DNSServiceRefSockFD( m_service ), g_hWnd, BONJOUR_EVENT, 0 );
  136. DNSServiceRefDeallocate(m_service);
  137. m_service = NULL;
  138. }
  139. }
  140. void DNSSD_API CZeroconfWIN::registerCallback(DNSServiceRef sdref, const DNSServiceFlags flags, DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain, void *context)
  141. {
  142. (void)sdref; // Unused
  143. (void)flags; // Unused
  144. (void)context; // Unused
  145. if (errorCode == kDNSServiceErr_NoError)
  146. {
  147. if (flags & kDNSServiceFlagsAdd)
  148. CLog::Log(LOGDEBUG, "ZeroconfWIN: %s.%s%s now registered and active", name, regtype, domain);
  149. else
  150. CLog::Log(LOGDEBUG, "ZeroconfWIN: %s.%s%s registration removed", name, regtype, domain);
  151. }
  152. else if (errorCode == kDNSServiceErr_NameConflict)
  153. CLog::Log(LOGDEBUG, "ZeroconfWIN: %s.%s%s Name in use, please choose another", name, regtype, domain);
  154. else
  155. CLog::Log(LOGDEBUG, "ZeroconfWIN: %s.%s%s error code %d", name, regtype, domain, errorCode);
  156. }
  157. void CZeroconfWIN::ProcessResults()
  158. {
  159. CSingleLock lock(m_data_guard);
  160. DNSServiceErrorType err = DNSServiceProcessResult(m_service);
  161. if (err != kDNSServiceErr_NoError)
  162. CLog::Log(LOGERROR, "ZeroconfWIN: DNSServiceProcessResult returned (error = %ld)", (int) err);
  163. }