bool CZeroconfBrowserOSX::doResolveService(CZeroconfBrowser::ZeroconfService& fr_service, double f_timeout) { bool ret = false; CFStringRef type = CFStringCreateWithCString (NULL, fr_service.GetType().c_str(), kCFStringEncodingUTF8 ); CFStringRef name = CFStringCreateWithCString (NULL, fr_service.GetName().c_str(), kCFStringEncodingUTF8 ); CFStringRef domain = CFStringCreateWithCString (NULL, fr_service.GetDomain().c_str(), kCFStringEncodingUTF8 ); CFNetServiceRef service = CFNetServiceCreate (NULL, domain, type, name, 0); if(CFNetServiceResolveWithTimeout (service, f_timeout, NULL) ) { CStdString ip; int port; ret = CopyFirstIPv4Address(service, ip, port); fr_service.SetIP(ip); fr_service.SetPort(port); } CFRelease(type); CFRelease(name); CFRelease(domain); CFRelease(service); return ret; }
void DNSSD_API CZeroconfBrowserWIN::ResolveCallback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget, uint16_t port, /* In network byte order */ uint16_t txtLen, const unsigned char *txtRecord, void *context ) { if (errorCode) { CLog::Log(LOGERROR, "ZeroconfBrowserWIN: ResolveCallback failed with error = %ld", (int) errorCode); return; } DNSServiceErrorType err; CZeroconfBrowser::ZeroconfService::tTxtRecordMap recordMap; CStdString strIP; CZeroconfBrowser::ZeroconfService* service = (CZeroconfBrowser::ZeroconfService*) context; if(!CDNSNameCache::Lookup(hosttarget, strIP)) { CLog::Log(LOGERROR, "ZeroconfBrowserWIN: Could not resolve hostname %s",hosttarget); return; } service->SetIP(strIP); for(uint16_t i = 0; i < TXTRecordGetCount(txtLen, txtRecord); ++i) { char key[256]; uint8_t valueLen; const void *value; std::string strvalue; err = TXTRecordGetItemAtIndex(txtLen, txtRecord,i ,sizeof(key) , key, &valueLen, &value); if(err != kDNSServiceErr_NoError) continue; if(value != NULL && valueLen > 0) strvalue.append((const char *)value, valueLen); recordMap.insert(std::make_pair(key, strvalue)); } service->SetTxtRecords(recordMap); service->SetPort(ntohs(port)); }
bool CZeroconfBrowserAvahi::doResolveService ( CZeroconfBrowser::ZeroconfService& fr_service, double f_timeout ) { { //wait for lock on event-loop to schedule resolving ScopedEventLoopBlock lock ( mp_poll ); //avahi can only resolve already discovered services, as it needs info from there tDiscoveredServices::const_iterator it = m_discovered_services.find( fr_service ); if ( it == m_discovered_services.end() ) { CLog::Log ( LOGERROR, "CZeroconfBrowserAvahi::doResolveService called with undiscovered service, resolving is NOT possible" ); return false; } //start resolving m_resolving_service = fr_service; m_resolved_event.Reset(); if ( !avahi_service_resolver_new ( mp_client, it->second.interface, it->second.protocol, it->first.GetName().c_str(), it->first.GetType().c_str(), it->first.GetDomain().c_str(), AVAHI_PROTO_UNSPEC, AvahiLookupFlags ( 0 ), resolveCallback, this ) ) { CLog::Log ( LOGERROR, "CZeroconfBrowserAvahi::doResolveService Failed to resolve service '%s': %s\n", it->first.GetName().c_str(), avahi_strerror ( avahi_client_errno ( mp_client ) ) ); return false; } } // end of this block releases lock of eventloop //wait for resolve to return or timeout m_resolved_event.WaitMSec(f_timeout*1000); { ScopedEventLoopBlock lock ( mp_poll ); fr_service = m_resolving_service; return (!fr_service.GetIP().empty()); } }
bool CZeroconfBrowserWIN::doResolveService(CZeroconfBrowser::ZeroconfService& fr_service, double f_timeout) { DNSServiceErrorType err; DNSServiceRef sdRef = NULL; err = DNSServiceResolve(&sdRef, 0, kDNSServiceInterfaceIndexAny, fr_service.GetName(), fr_service.GetType(), fr_service.GetDomain(), ResolveCallback, &fr_service); if( err != kDNSServiceErr_NoError ) { if (sdRef) DNSServiceRefDeallocate(sdRef); CLog::Log(LOGERROR, "ZeroconfBrowserWIN: DNSServiceResolve returned (error = %ld)", (int) err); return false; } err = DNSServiceProcessResult(sdRef); if (err != kDNSServiceErr_NoError) CLog::Log(LOGERROR, "ZeroconfBrowserWIN::doResolveService DNSServiceProcessResult returned (error = %ld)", (int) err); if (sdRef) DNSServiceRefDeallocate(sdRef); return true; }
void DNSSD_API AddrinfoCallback(DNSServiceRef sdref, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *hostname, const struct sockaddr *address, uint32_t ttl, void *context) { if (errorCode) { CLog::Log(LOGERROR, "ZeroconfBrowserWIN: AddrinfoCallback failed with error = %ld", (int) errorCode); return; } DNSServiceErrorType err; CStdString strIP; CZeroconfBrowser::ZeroconfService* service = (CZeroconfBrowser::ZeroconfService*) context; char addr[256] = ""; if (address && address->sa_family == AF_INET) { const unsigned char *b = (const unsigned char *) &((struct sockaddr_in *)address)->sin_addr; snprintf(addr, sizeof(addr), "%d.%d.%d.%d", b[0], b[1], b[2], b[3]); } strIP = addr; service->SetIP(strIP); }
bool CZeroconfBrowserMDNS::doResolveService(CZeroconfBrowser::ZeroconfService& fr_service, double f_timeout) { DNSServiceErrorType err; DNSServiceRef sdRef = NULL; //start resolving m_resolving_service = fr_service; m_resolved_event.Reset(); err = DNSServiceResolve(&sdRef, 0, kDNSServiceInterfaceIndexAny, fr_service.GetName(), fr_service.GetType(), fr_service.GetDomain(), ResolveCallback, this); if( err != kDNSServiceErr_NoError ) { if (sdRef) DNSServiceRefDeallocate(sdRef); CLog::Log(LOGERROR, "ZeroconfBrowserMDNS: DNSServiceResolve returned (error = %ld)", (int) err); return false; } err = DNSServiceProcessResult(sdRef); if (err != kDNSServiceErr_NoError) CLog::Log(LOGERROR, "ZeroconfBrowserMDNS::doResolveService DNSServiceProcessResult returned (error = %ld)", (int) err); if (sdRef) DNSServiceRefDeallocate(sdRef); #if defined(HAS_MDNS_EMBEDDED) // when using the embedded mdns service the call to DNSServiceProcessResult // above will not block until the resolving was finished - instead we have to // wait for resolve to return or timeout m_resolved_event.WaitMSec(f_timeout * 1000); #endif //HAS_MDNS_EMBEDDED fr_service = m_resolving_service; return (!fr_service.GetIP().empty()); }
bool CZeroconfBrowserAndroid::doResolveService(CZeroconfBrowser::ZeroconfService& fr_service, double f_timeout) { jni::CJNINsdServiceInfo service; service.setServiceName(fr_service.GetName()); service.setServiceType(fr_service.GetType()); CZeroconfBrowserAndroidResolve resolver; m_manager.resolveService(service, resolver); if (!resolver.m_resolutionDone.WaitMSec(f_timeout * 1000)) { CLog::Log(LOGERROR, "ZeroconfBrowserAndroid: DNSServiceResolve Timeout error"); return false; } if (resolver.m_errorCode != -1) { CLog::Log(LOGERROR, "ZeroconfBrowserAndroid: DNSServiceResolve returned (error = %ld)", resolver.m_errorCode); return false; } fr_service.SetHostname(resolver.m_retServiceInfo.getHost().getHostName()); fr_service.SetIP(resolver.m_retServiceInfo.getHost().getHostAddress()); fr_service.SetPort(resolver.m_retServiceInfo.getPort()); CZeroconfBrowser::ZeroconfService::tTxtRecordMap recordMap; jni::CJNISet<jni::jhstring> txtKey = resolver.m_retServiceInfo.getAttributes().keySet(); jni::CJNIIterator<jni::jhstring> it = txtKey.iterator(); while (it.hasNext()) { jni::jhstring k = it.next(); jni::jhbyteArray v = resolver.m_retServiceInfo.getAttributes().get(k); std::string key = jni::jcast<std::string>(k); std::vector<char> vv = jni::jcast<std::vector<char>>(v); std::string value = std::string(vv.begin(), vv.end()); CLog::Log(LOGDEBUG, "ZeroconfBrowserAndroid: TXT record %s = %s (%d)", key.c_str(), value.c_str(), vv.size()); recordMap.insert(std::make_pair(key, value)); } fr_service.SetTxtRecords(recordMap); return (!fr_service.GetIP().empty()); }
bool GetDirectoryFromTxtRecords(const CZeroconfBrowser::ZeroconfService& zeroconf_service, CURL& url, CFileItemList &items) { bool ret = false; //get the txt-records from this service CZeroconfBrowser::ZeroconfService::tTxtRecordMap txtRecords=zeroconf_service.GetTxtRecords(); //if we have some records if(!txtRecords.empty()) { std::string path; std::string username; std::string password; //search for a path key entry CZeroconfBrowser::ZeroconfService::tTxtRecordMap::iterator it = txtRecords.find(TXT_RECORD_PATH_KEY); //if we found the key - be sure there is a value there if( it != txtRecords.end() && !it->second.empty() ) { //from now on we treat the value as a path - everything else would mean //a missconfigured zeroconf server. path=it->second; } //search for a username key entry it = txtRecords.find(TXT_RECORD_USERNAME_KEY); //if we found the key - be sure there is a value there if( it != txtRecords.end() && !it->second.empty() ) { username=it->second; url.SetUserName(username); } //search for a password key entry it = txtRecords.find(TXT_RECORD_PASSWORD_KEY); //if we found the key - be sure there is a value there if( it != txtRecords.end() && !it->second.empty() ) { password=it->second; url.SetPassword(password); } //if we got a path - add a item - else at least we maybe have set username and password to theurl if( !path.empty()) { CFileItemPtr item(new CFileItem("", true)); std::string urlStr(url.Get()); //if path has a leading slash (sure it should have one) if( path.at(0) == '/' ) { URIUtils::RemoveSlashAtEnd(urlStr);//we don't need the slash at and of url then } else//path doesn't start with slash - {//this is some kind of missconfiguration - we fix it by adding a slash to the url URIUtils::AddSlashAtEnd(urlStr); } //add slash at end of path since it has to be a folder URIUtils::AddSlashAtEnd(path); //this is the full path includeing remote stuff (e.x. nfs://ip/path item->SetPath(urlStr + path); //remove the slash at the end of the path or GetFileName will not give the last dir URIUtils::RemoveSlashAtEnd(path); //set the label to the last directory in path if( !URIUtils::GetFileName(path).empty() ) item->SetLabel(URIUtils::GetFileName(path)); else item->SetLabel("/"); item->SetLabelPreformated(true); //just set the default folder icon item->FillInDefaultIcon(); item->m_bIsShareOrDrive=true; items.Add(item); ret = true; } } return ret; }
bool CZeroconfBrowserMDNS::doResolveService(CZeroconfBrowser::ZeroconfService& fr_service, double f_timeout) { DNSServiceErrorType err; DNSServiceRef sdRef = NULL; //start resolving m_resolving_service = fr_service; m_resolved_event.Reset(); err = DNSServiceResolve(&sdRef, 0, kDNSServiceInterfaceIndexAny, fr_service.GetName(), fr_service.GetType(), fr_service.GetDomain(), ResolveCallback, this); if( err != kDNSServiceErr_NoError ) { if (sdRef) DNSServiceRefDeallocate(sdRef); CLog::Log(LOGERROR, "ZeroconfBrowserMDNS: DNSServiceResolve returned (error = %ld)", (int) err); return false; } err = DNSServiceProcessResult(sdRef); if (err != kDNSServiceErr_NoError) CLog::Log(LOGERROR, "ZeroconfBrowserMDNS::doResolveService DNSServiceProcessResult returned (error = %ld)", (int) err); #if defined(HAS_MDNS_EMBEDDED) // when using the embedded mdns service the call to DNSServiceProcessResult // above will not block until the resolving was finished - instead we have to // wait for resolve to return or timeout m_resolved_event.WaitMSec(f_timeout * 1000); #endif //HAS_MDNS_EMBEDDED fr_service = m_resolving_service; if (sdRef) DNSServiceRefDeallocate(sdRef); // resolve the hostname if (!fr_service.GetHostname().empty()) { CStdString strIP; // use mdns resolving m_addrinfo_event.Reset(); sdRef = NULL; err = DNSServiceGetAddrInfo(&sdRef, 0, kDNSServiceInterfaceIndexAny, kDNSServiceProtocol_IPv4, fr_service.GetHostname(), GetAddrInfoCallback, this); if (err != kDNSServiceErr_NoError) CLog::Log(LOGERROR, "ZeroconfBrowserMDNS: DNSServiceGetAddrInfo returned (error = %ld)", (int) err); err = DNSServiceProcessResult(sdRef); if (err != kDNSServiceErr_NoError) CLog::Log(LOGERROR, "ZeroconfBrowserMDNS::doResolveService DNSServiceProcessResult returned (error = %ld)", (int) err); #if defined(HAS_MDNS_EMBEDDED) // when using the embedded mdns service the call to DNSServiceProcessResult // above will not block until the resolving was finished - instead we have to // wait for resolve to return or timeout // give it 2 secs for resolving (resolving in mdns is cached and queued // in timeslices off 1 sec m_addrinfo_event.WaitMSec(2000); #endif //HAS_MDNS_EMBEDDED fr_service = m_resolving_service; if (sdRef) DNSServiceRefDeallocate(sdRef); // fall back to our resolver if (fr_service.GetIP().empty()) { CLog::Log(LOGWARNING, "ZeroconfBrowserMDNS: Could not resolve hostname %s falling back to CDNSNameCache", fr_service.GetHostname().c_str()); if (CDNSNameCache::Lookup(fr_service.GetHostname(), strIP)) fr_service.SetIP(strIP); else CLog::Log(LOGERROR, "ZeroconfBrowserMDNS: Could not resolve hostname %s", fr_service.GetHostname().c_str()); } } return (!fr_service.GetIP().empty()); }
bool CZeroconfBrowserWIN::doResolveService(CZeroconfBrowser::ZeroconfService& fr_service, double f_timeout) { DNSServiceErrorType err; DNSServiceRef sdRef = NULL; err = DNSServiceResolve(&sdRef, 0, kDNSServiceInterfaceIndexAny, fr_service.GetName(), fr_service.GetType(), fr_service.GetDomain(), ResolveCallback, &fr_service); if( err != kDNSServiceErr_NoError ) { if (sdRef) DNSServiceRefDeallocate(sdRef); CLog::Log(LOGERROR, "ZeroconfBrowserWIN: DNSServiceResolve returned (error = %ld)", (int) err); return false; } #if defined(__VIDONME_MEDIACENTER__) //don't block in DNSServiceProcessResult, timeout is 0. int dns_sd_fd = sdRef ? DNSServiceRefSockFD(sdRef) : -1; int nfds = dns_sd_fd + 1; fd_set readfds; struct timeval tv; int result; #if 0 while (!stopNow) { // 1. Set up the fd_set as usual here. // This example client has no file descriptors of its own, // but a real application would call FD_SET to add them to the set here FD_ZERO(&readfds); // 2. Add the fd for our client(s) to the fd_set if (sdRef) FD_SET(dns_sd_fd , &readfds); // 3. Set up the timeout. tv.tv_sec = 0; tv.tv_usec = 0; result = select(nfds, &readfds, (fd_set*)NULL, (fd_set*)NULL, &tv); if (result > 0) { DNSServiceErrorType err = kDNSServiceErr_NoError; if (sdRef && FD_ISSET(dns_sd_fd , &readfds)) err = DNSServiceProcessResult(sdRef); if (err) { fprintf(stderr, "DNSServiceProcessResult returned %d\n", err); stopNow = 1; } } else { printf("select() returned %d errno %d %s\n", result, errno, strerror(errno)); if (errno != EINTR) stopNow = 1; } } #else // 1. Set up the fd_set as usual here. // This example client has no file descriptors of its own, // but a real application would call FD_SET to add them to the set here FD_ZERO(&readfds); // 2. Add the fd for our client(s) to the fd_set if (sdRef) FD_SET(dns_sd_fd , &readfds); // 3. Set up the timeout. tv.tv_sec = 1; tv.tv_usec = 0; result = select(nfds, &readfds, (fd_set*)NULL, (fd_set*)NULL, &tv); if (result > 0) { DNSServiceErrorType err = kDNSServiceErr_NoError; if (sdRef && FD_ISSET(dns_sd_fd , &readfds)) err = DNSServiceProcessResult(sdRef); if (err) { fprintf(stderr, "DNSServiceProcessResult returned %d\n", err); } } else { printf("select() returned %d errno %d %s\n", result, errno, strerror(errno)); if (errno != EINTR) { //stopNow = 1; } } #endif #else err = DNSServiceProcessResult(sdRef); #endif//__VIDONME_MEDIACENTER__ if (err != kDNSServiceErr_NoError) CLog::Log(LOGERROR, "ZeroconfBrowserWIN::doResolveService DNSServiceProcessResult returned (error = %ld)", (int) err); if (sdRef) DNSServiceRefDeallocate(sdRef); return true; }
void DNSSD_API CZeroconfBrowserWIN::ResolveCallback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget, uint16_t port, /* In network byte order */ uint16_t txtLen, const unsigned char *txtRecord, void *context ) { if (errorCode) { CLog::Log(LOGERROR, "ZeroconfBrowserWIN: ResolveCallback failed with error = %ld", (int) errorCode); return; } DNSServiceErrorType err; CZeroconfBrowser::ZeroconfService::tTxtRecordMap recordMap; CStdString strIP; CZeroconfBrowser::ZeroconfService* service = (CZeroconfBrowser::ZeroconfService*) context; #if defined(__VIDONME_MEDIACENTER__) { DNSServiceErrorType err; DNSServiceRef sdRef = NULL; err = DNSServiceGetAddrInfo(&sdRef, kDNSServiceFlagsReturnIntermediates, kDNSServiceInterfaceIndexAny,kDNSServiceProtocol_IPv4, hosttarget, AddrinfoCallback, service); if( err != kDNSServiceErr_NoError ) { if (sdRef) DNSServiceRefDeallocate(sdRef); CLog::Log(LOGERROR, "ZeroconfBrowserWIN: DNSServiceGetAddrInfo returned (error = %ld)", (int) err); return; } err = DNSServiceProcessResult(sdRef); if (err != kDNSServiceErr_NoError) CLog::Log(LOGERROR, "ZeroconfBrowserWIN::doGetAddrInfoService DNSServiceProcessResult returned (error = %ld)", (int) err); if (sdRef) DNSServiceRefDeallocate(sdRef); } #else if(!CDNSNameCache::Lookup(hosttarget, strIP)) { CLog::Log(LOGERROR, "ZeroconfBrowserWIN: Could not resolve hostname %s",hosttarget); return; } service->SetIP(strIP); #endif for(uint16_t i = 0; i < TXTRecordGetCount(txtLen, txtRecord); ++i) { char key[256]; uint8_t valueLen; const void *value; std::string strvalue; err = TXTRecordGetItemAtIndex(txtLen, txtRecord,i ,sizeof(key) , key, &valueLen, &value); if(err != kDNSServiceErr_NoError) continue; if(value != NULL && valueLen > 0) strvalue.append((const char *)value, valueLen); recordMap.insert(std::make_pair(key, strvalue)); } service->SetTxtRecords(recordMap); service->SetPort(ntohs(port)); }