static int publish_main_service(struct userdata *u) { DNSServiceErrorType err; TXTRecordRef txt; pa_assert(u); if (u->main_service) { DNSServiceRefDeallocate(u->main_service); u->main_service = NULL; } TXTRecordCreate(&txt, 0, NULL); txt_record_server_data(u->core, &txt); err = DNSServiceRegister(&u->main_service, 0, /* flags */ kDNSServiceInterfaceIndexAny, u->service_name, SERVICE_TYPE_SERVER, NULL, /* domain */ NULL, /* host */ compute_port(u), TXTRecordGetLength(&txt), TXTRecordGetBytesPtr(&txt), NULL, NULL); if (err != kDNSServiceErr_NoError) { pa_log("%s(): DNSServiceRegister() returned err %d", __func__, err); return err; } TXTRecordDeallocate(&txt); return 0; }
bool announce( const unsigned short port, const std::string& instance ) { #ifdef LUNCHBOX_USE_DNSSD if( service_ ) return false; TXTRecordRef record; createTXTRecord_( record ); const DNSServiceErrorType error = DNSServiceRegister( &service_, 0 /* flags */, 0 /* all interfaces */, instance.empty() ? 0 : instance.c_str(), name_.c_str(), 0 /* default domains */, 0 /* hostname */, htons( port ), TXTRecordGetLength( &record ), TXTRecordGetBytesPtr( &record ), (DNSServiceRegisterReply)registerCBS_, this ); TXTRecordDeallocate( &record ); if( error == kDNSServiceErr_NoError ) { handleEvents_( service_ ); return service_ != 0; } LBWARN << "DNSServiceRegister returned: " << error << std::endl; #endif return false; }
int mdns_register(char *name, char *regtype, int port, char **txt) { struct mdns_service *s; DNSServiceErrorType err; int i; char *eq; DPRINTF(E_DBG, L_MDNS, "Adding mDNS service '%s.%s'\n", name, regtype); s = calloc(1, sizeof(*s)); if (!s) { DPRINTF(E_LOG, L_MDNS, "Out of memory registering service.\n"); return -1; } TXTRecordCreate(&(s->txtRecord), 0, NULL); for (i = 0; txt && txt[i]; i++) { if ((eq = strchr(txt[i], '='))) { *eq = '\0'; eq++; err = TXTRecordSetValue(&(s->txtRecord), txt[i], strlen(eq) * sizeof(char), eq); *(--eq) = '='; if (err != kDNSServiceErr_NoError) { DPRINTF(E_LOG, L_MDNS, "Could not set TXT record value\n"); return mdns_service_free(s); } } } s->sdref = mdns_sdref_main; err = DNSServiceRegister(&(s->sdref), kDNSServiceFlagsShareConnection, 0, name, regtype, NULL, NULL, htons(port), TXTRecordGetLength(&(s->txtRecord)), TXTRecordGetBytesPtr(&(s->txtRecord)), mdns_register_callback, NULL); if (err != kDNSServiceErr_NoError) { DPRINTF(E_LOG, L_MDNS, "Error registering service '%s.%s'\n", name, regtype); s->sdref = NULL; return mdns_service_free(s); } s->next = mdns_services; mdns_services = s; return 0; }
void updateRecord_() { if( !service_ ) return; TXTRecordRef record; createTXTRecord_( record ); const DNSServiceErrorType error = DNSServiceUpdateRecord( service_, 0, 0, TXTRecordGetLength( &record ), TXTRecordGetBytesPtr( &record ), -1 ); TXTRecordDeallocate( &record ); if( error != kDNSServiceErr_NoError ) LBWARN << "DNSServiceUpdateRecord error: " << error << std::endl; }
bool CZeroconfMDNS::doForceReAnnounceService(const std::string& fcr_identifier) { bool ret = false; CSingleLock lock(m_data_guard); tServiceMap::iterator it = m_services.find(fcr_identifier); if(it != m_services.end()) { // for force announcing a service with mdns we need // to change a txt record - so we diddle between // even and odd dummy records here if ( (it->second.updateNumber % 2) == 0) TXTRecordSetValue(&it->second.txtRecordRef, "xbmcdummy", strlen("evendummy"), "evendummy"); else TXTRecordSetValue(&it->second.txtRecordRef, "xbmcdummy", strlen("odddummy"), "odddummy"); it->second.updateNumber++; if (DNSServiceUpdateRecord(it->second.serviceRef, NULL, 0, TXTRecordGetLength(&it->second.txtRecordRef), TXTRecordGetBytesPtr(&it->second.txtRecordRef), 0) == kDNSServiceErr_NoError) ret = true; } return ret; }
void PublicService::publishAsync() { K_D; if (d->isRunning()) stop(); TXTRecordRef txt; TXTRecordCreate(&txt,0,0); QMap<QString,QByteArray>::ConstIterator itEnd = d->m_textData.end(); for (QMap<QString,QByteArray>::ConstIterator it = d->m_textData.begin(); it!=itEnd ; ++it) { if (TXTRecordSetValue(&txt,it.key().toUtf8(),it.value().length(),it.value())!=kDNSServiceErr_NoError) { TXTRecordDeallocate(&txt); emit published(false); return; } } DNSServiceRef ref; QString fullType=d->m_type; Q_FOREACH(const QString &subtype, d->m_subtypes) fullType+=','+subtype; if (DNSServiceRegister(&ref,0,0,d->m_serviceName.toUtf8(),fullType.toAscii().constData(),domainToDNS(d->m_domain),NULL, htons(d->m_port),TXTRecordGetLength(&txt),TXTRecordGetBytesPtr(&txt),publish_callback, reinterpret_cast<void*>(d)) == kDNSServiceErr_NoError) d->setRef(ref); TXTRecordDeallocate(&txt); if (!d->isRunning()) emit published(false); }
bool YMmDNSServiceStart( YMmDNSServiceRef s_ ) { __ym_mdns_service_t *s = (__ym_mdns_service_t *)s_; DNSServiceRef *serviceRef = (DNSServiceRef *)calloc( 1, sizeof(DNSServiceRef) ); uint16_t netPort = htons(s->port); bool txtExists = (s->txtRecord != NULL); uint16_t txtLength = txtExists ? TXTRecordGetLength((TXTRecordRef *)s->txtRecord) : 0; const void *txt = txtExists ? TXTRecordGetBytesPtr((TXTRecordRef *)s->txtRecord) : NULL; DNSServiceErrorType result = DNSServiceRegister(serviceRef, 0, // DNSServiceFlags 0, // interfaceIndex (0=all) YMSTR(s->name), YMSTR(s->type), NULL, // domain NULL, // host netPort, txtLength, txt, __ymmdns_register_callback, // DNSServiceRegisterReply s); // context if( result != kDNSServiceErr_NoError ) { // on error "the callback is never invoked and the DNSServiceRef is not initialized" // leading me to think we free instead of DNSServiceRefDeallocate free(serviceRef); ymlog("mdns: DNSServiceRegister failed: %s/%s:%u: %d",YMSTR(s->type),YMSTR(s->name),(unsigned)s->port,result); return false; } s->dnsService = serviceRef; s->advertising = true; ymlog("mdns: published %s/%s:%u",YMSTR(s->type),YMSTR(s->name),(unsigned)s->port); return true; }
int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char *argv[]) { const char *r; TXTRecordRef ref; uint8_t l; const void *p; char k[256]; TXTRecordCreate(&ref, 0, NULL); hexdump(TXTRecordGetBytesPtr(&ref), TXTRecordGetLength(&ref)); TXTRecordSetValue(&ref, "foo", 7, "lennart"); hexdump(TXTRecordGetBytesPtr(&ref), TXTRecordGetLength(&ref)); TXTRecordSetValue(&ref, "waldo", 5, "rocks"); hexdump(TXTRecordGetBytesPtr(&ref), TXTRecordGetLength(&ref)); TXTRecordSetValue(&ref, "quux", 9, "the_house"); hexdump(TXTRecordGetBytesPtr(&ref), TXTRecordGetLength(&ref)); TXTRecordSetValue(&ref, "yeah", 0, NULL); hexdump(TXTRecordGetBytesPtr(&ref), TXTRecordGetLength(&ref)); TXTRecordSetValue(&ref, "waldo", 6, "rocked"); hexdump(TXTRecordGetBytesPtr(&ref), TXTRecordGetLength(&ref)); TXTRecordRemoveValue(&ref, "foo"); hexdump(TXTRecordGetBytesPtr(&ref), TXTRecordGetLength(&ref)); TXTRecordRemoveValue(&ref, "waldo"); hexdump(TXTRecordGetBytesPtr(&ref), TXTRecordGetLength(&ref)); TXTRecordSetValue(&ref, "kawumm", 6, "bloerb"); hexdump(TXTRecordGetBytesPtr(&ref), TXTRecordGetLength(&ref)); TXTRecordSetValue(&ref, "one", 1, "1"); hexdump(TXTRecordGetBytesPtr(&ref), TXTRecordGetLength(&ref)); TXTRecordSetValue(&ref, "two", 1, "2"); hexdump(TXTRecordGetBytesPtr(&ref), TXTRecordGetLength(&ref)); TXTRecordSetValue(&ref, "three", 1, "3"); hexdump(TXTRecordGetBytesPtr(&ref), TXTRecordGetLength(&ref)); assert(TXTRecordContainsKey(TXTRecordGetLength(&ref), TXTRecordGetBytesPtr(&ref), "two")); assert(!TXTRecordContainsKey(TXTRecordGetLength(&ref), TXTRecordGetBytesPtr(&ref), "four")); r = TXTRecordGetValuePtr(TXTRecordGetLength(&ref), TXTRecordGetBytesPtr(&ref), "kawumm", &l); hexdump(r, l); assert(TXTRecordGetCount(TXTRecordGetLength(&ref), TXTRecordGetBytesPtr(&ref)) == 6); TXTRecordGetItemAtIndex(TXTRecordGetLength(&ref), TXTRecordGetBytesPtr(&ref), 2, sizeof(k), k, &l, &p); fprintf(stderr, "key=<%s>\n", k); hexdump(p, l); assert(TXTRecordGetItemAtIndex(TXTRecordGetLength(&ref), TXTRecordGetBytesPtr(&ref), 20, sizeof(k), k, &l, &p) == kDNSServiceErr_Invalid); TXTRecordDeallocate(&ref); }
int player_sd_register(player_sd_t* sd, const char* name, player_devaddr_t addr) { DNSServiceErrorType sdErr; char recordval[PLAYER_SD_TXT_MAXLEN]; int i,j; player_sd_mdns_t* mdns = (player_sd_mdns_t*)(sd->sdRef); player_sd_mdns_dev_t* dev; char nameBuf[PLAYER_SD_NAME_MAXLEN]; // Find a spot for this device for(i=0;i<mdns->mdnsDevs_len;i++) { if(!mdns->mdnsDevs[i].valid) break; } if(i==mdns->mdnsDevs_len) { // Make the list bigger if(!mdns->mdnsDevs_len) mdns->mdnsDevs_len = PLAYER_SD_MDNS_DEVS_LEN_INITIAL; else mdns->mdnsDevs_len *= PLAYER_SD_MDNS_DEVS_LEN_MULTIPLIER; mdns->mdnsDevs = (player_sd_mdns_dev_t*)realloc(mdns->mdnsDevs, (mdns->mdnsDevs_len * sizeof(player_sd_mdns_dev_t))); assert(mdns->mdnsDevs); for(j=i;j<mdns->mdnsDevs_len;j++) mdns->mdnsDevs[j].valid = 0; } dev = mdns->mdnsDevs + i; dev->fail = 0; memset(dev->sdDev.name,0,sizeof(dev->sdDev.name)); strncpy(dev->sdDev.name,name,sizeof(dev->sdDev.name)-1); memset(dev->sdDev.hostname,0,sizeof(dev->sdDev.hostname)); packedaddr_to_dottedip(dev->sdDev.hostname,sizeof(dev->sdDev.hostname), addr.host); dev->sdDev.robot = addr.robot; dev->sdDev.interf = addr.interf; dev->sdDev.index = addr.index; dev->nameIdx = 1; TXTRecordCreate(&(dev->txtRecord),sizeof(dev->txtBuf),dev->txtBuf); memset(recordval,0,sizeof(recordval)); snprintf(recordval, sizeof(recordval), "%s:%u", interf_to_str(addr.interf), addr.index); if((sdErr = TXTRecordSetValue(&(dev->txtRecord), "device", strlen(recordval), recordval))) { PLAYER_ERROR1("TXTRecordSetValue returned error: %d", sdErr); return(-1); } memset(nameBuf,0,sizeof(nameBuf)); strncpy(nameBuf,name,sizeof(nameBuf)-1); sdErr = kDNSServiceErr_NameConflict; // Avahi can return the kDNSServiceErr_NameConflict immediately. while(sdErr == kDNSServiceErr_NameConflict) { sdErr = DNSServiceRegister(&(dev->regRef), 0, 0, nameBuf, PLAYER_SD_SERVICENAME, NULL, NULL, addr.robot, TXTRecordGetLength(&(dev->txtRecord)), TXTRecordGetBytesPtr(&(dev->txtRecord)), registerCB, (void*)dev); if(sdErr == kDNSServiceErr_NameConflict) { // Pick a new name memset(nameBuf,0,sizeof(nameBuf)); snprintf(nameBuf,sizeof(nameBuf),"%s (%d)", name,dev->nameIdx++); } } if(sdErr != kDNSServiceErr_NoError) { PLAYER_ERROR1("DNSServiceRegister returned error: %d", sdErr); return(-1); } else { dev->valid = 1; if(strcmp(nameBuf,name)) PLAYER_WARN2("Changing service name of %s to %s\n", name,nameBuf); PLAYER_MSG1(2,"Registration of %s successful", name); return(0); } }
//methods to implement for concrete implementations bool CZeroconfWIN::doPublishService(const std::string& fcr_identifier, const std::string& fcr_type, const std::string& fcr_name, unsigned int f_port, std::map<std::string, std::string> txt) { DNSServiceRef netService = NULL; TXTRecordRef txtRecord; TXTRecordCreate(&txtRecord, 0, NULL); CLog::Log(LOGDEBUG, "CZeroconfWIN::doPublishService identifier: %s type: %s name:%s port:%i", fcr_identifier.c_str(), fcr_type.c_str(), fcr_name.c_str(), f_port); //add txt records if(!txt.empty()) { for(std::map<std::string, std::string>::const_iterator it = txt.begin(); it != txt.end(); ++it) { CLog::Log(LOGDEBUG, "CZeroconfWIN: key:%s, value:%s",it->first.c_str(),it->second.c_str()); uint8_t txtLen = (uint8_t)strlen(it->second.c_str()); TXTRecordSetValue(&txtRecord, it->first.c_str(), txtLen, it->second.c_str()); } } DNSServiceErrorType err = DNSServiceRegister(&netService, 0, 0, fcr_name.c_str(), fcr_type.c_str(), NULL, NULL, htons(f_port), TXTRecordGetLength(&txtRecord), TXTRecordGetBytesPtr(&txtRecord), registerCallback, NULL); if(err != kDNSServiceErr_ServiceNotRunning) DNSServiceProcessResult(netService); if (err != kDNSServiceErr_NoError) { // Something went wrong so lets clean up. if (netService) DNSServiceRefDeallocate(netService); CLog::Log(LOGERROR, "CZeroconfWIN::doPublishService CFNetServiceRegister returned (error = %ld)\n", (int) err); if(err == kDNSServiceErr_ServiceNotRunning) { CLog::Log(LOGERROR, "CZeroconfWIN: 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)"); CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, "Failed to start zeroconf", "Is Apple's Bonjour Service installed? See log for more info.", 10000, true); } } else { CSingleLock lock(m_data_guard); m_services.insert(make_pair(fcr_identifier, netService)); } TXTRecordDeallocate(&txtRecord); return err == kDNSServiceErr_NoError; }
nsresult RegisterOperator::Start() { nsresult rv; rv = MDNSResponderOperator::Start(); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } uint16_t port; if (NS_WARN_IF(NS_FAILED(rv = mServiceInfo->GetPort(&port)))) { return rv; } nsAutoCString type; if (NS_WARN_IF(NS_FAILED(rv = mServiceInfo->GetServiceType(type)))) { return rv; } TXTRecordRef txtRecord; char buf[TXT_BUFFER_SIZE] = { 0 }; TXTRecordCreate(&txtRecord, TXT_BUFFER_SIZE, buf); nsCOMPtr<nsIPropertyBag2> attributes; if (NS_FAILED(rv = mServiceInfo->GetAttributes(getter_AddRefs(attributes)))) { LOG_I("register: no attributes"); } else { nsCOMPtr<nsISimpleEnumerator> enumerator; if (NS_WARN_IF(NS_FAILED(rv = attributes->GetEnumerator(getter_AddRefs(enumerator))))) { return rv; } bool hasMoreElements; while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreElements)) && hasMoreElements) { nsCOMPtr<nsISupports> element; MOZ_ALWAYS_TRUE(NS_SUCCEEDED(enumerator->GetNext(getter_AddRefs(element)))); nsCOMPtr<nsIProperty> property = do_QueryInterface(element); MOZ_ASSERT(property); nsAutoString name; nsCOMPtr<nsIVariant> value; MOZ_ALWAYS_TRUE(NS_SUCCEEDED(property->GetName(name))); MOZ_ALWAYS_TRUE(NS_SUCCEEDED(property->GetValue(getter_AddRefs(value)))); nsAutoCString str; if (NS_WARN_IF(NS_FAILED(value->GetAsACString(str)))) { continue; } TXTRecordSetValue(&txtRecord, /* it's safe because key name is ASCII only. */ NS_LossyConvertUTF16toASCII(name).get(), str.Length(), str.get()); } } nsAutoCString host; nsAutoCString name; nsAutoCString domain; DNSServiceRef service = nullptr; DNSServiceErrorType err = DNSServiceRegister(&service, 0, 0, NS_SUCCEEDED(mServiceInfo->GetServiceName(name)) ? name.get() : nullptr, type.get(), NS_SUCCEEDED(mServiceInfo->GetDomainName(domain)) ? domain.get() : nullptr, NS_SUCCEEDED(mServiceInfo->GetHost(host)) ? host.get() : nullptr, NativeEndian::swapToNetworkOrder(port), TXTRecordGetLength(&txtRecord), TXTRecordGetBytesPtr(&txtRecord), &RegisterReplyRunnable::Reply, this); NS_WARN_IF(kDNSServiceErr_NoError != err); TXTRecordDeallocate(&txtRecord); if (NS_WARN_IF(kDNSServiceErr_NoError != err)) { if (mListener) { mListener->OnRegistrationFailed(mServiceInfo, err); } return NS_ERROR_FAILURE; } return ResetService(service); }
static int /* O - 1 on success, 0 on failure */ dnssdRegisterInstance( cupsd_srv_t *srv, /* O - Service */ cupsd_printer_t *p, /* I - Printer */ char *name, /* I - DNS-SD service name */ const char *type, /* I - DNS-SD service type */ const char *subtypes, /* I - Subtypes to register or NULL */ int port, /* I - Port number or 0 */ cupsd_txt_t *txt, /* I - TXT record */ int commit, /* I - Commit registration? */ int from_callback) /* I - Called from callback? */ { char temp[256], /* Temporary string */ *ptr; /* Pointer into string */ int error; /* Any error */ # ifdef HAVE_DNSSD (void)from_callback; # endif /* HAVE_DNSSD */ cupsdLogMessage(CUPSD_LOG_DEBUG, "Registering \"%s\" with DNS-SD type \"%s\".", name, type); if (p && !srv) { /* * Assign the correct pointer for "srv"... */ # ifdef HAVE_DNSSD if (!strcmp(type, "_printer._tcp")) srv = &p->printer_srv; /* Target LPD service */ # ifdef HAVE_SSL else if (!strcmp(type, "_ipps._tcp")) srv = &p->ipps_srv; /* Target IPPS service */ # endif /* HAVE_SSL */ else srv = &p->ipp_srv; /* Target IPP service */ # else /* HAVE_AVAHI */ srv = &p->ipp_srv; /* Target service group */ # endif /* HAVE_DNSSD */ } # ifdef HAVE_DNSSD (void)commit; # else /* HAVE_AVAHI */ if (!from_callback) avahi_threaded_poll_lock(DNSSDMaster); if (!*srv) *srv = avahi_entry_group_new(DNSSDClient, dnssdRegisterCallback, NULL); if (!*srv) { if (!from_callback) avahi_threaded_poll_unlock(DNSSDMaster); cupsdLogMessage(CUPSD_LOG_WARN, "DNS-SD registration of \"%s\" failed: %s", name, dnssdErrorString(avahi_client_errno(DNSSDClient))); return (0); } # endif /* HAVE_DNSSD */ /* * Make sure the name is <= 63 octets, and when we truncate be sure to * properly truncate any UTF-8 characters... */ ptr = name + strlen(name); while ((ptr - name) > 63) { do { ptr --; } while (ptr > name && (*ptr & 0xc0) == 0x80); if (ptr > name) *ptr = '\0'; } /* * Register the service... */ # ifdef HAVE_DNSSD if (subtypes) snprintf(temp, sizeof(temp), "%s,%s", type, subtypes); else strlcpy(temp, type, sizeof(temp)); *srv = DNSSDMaster; error = DNSServiceRegister(srv, kDNSServiceFlagsShareConnection, 0, name, temp, NULL, NULL, htons(port), txt ? TXTRecordGetLength(txt) : 0, txt ? TXTRecordGetBytesPtr(txt) : NULL, dnssdRegisterCallback, p); # else /* HAVE_AVAHI */ if (txt) { AvahiStringList *temptxt; for (temptxt = *txt; temptxt; temptxt = temptxt->next) cupsdLogMessage(CUPSD_LOG_DEBUG, "DNS_SD \"%s\" %s", name, temptxt->text); } error = avahi_entry_group_add_service_strlst(*srv, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, name, type, NULL, NULL, port, txt ? *txt : NULL); if (error) cupsdLogMessage(CUPSD_LOG_DEBUG, "DNS-SD service add for \"%s\" failed.", name); if (!error && subtypes) { /* * Register all of the subtypes... */ char *start, /* Start of subtype */ subtype[256]; /* Subtype string */ strlcpy(temp, subtypes, sizeof(temp)); for (start = temp; *start; start = ptr) { /* * Skip leading whitespace... */ while (*start && isspace(*start & 255)) start ++; /* * Grab everything up to the next comma or the end of the string... */ for (ptr = start; *ptr && *ptr != ','; ptr ++); if (*ptr) *ptr++ = '\0'; if (!*start) break; /* * Register the subtype... */ snprintf(subtype, sizeof(subtype), "%s._sub.%s", start, type); error = avahi_entry_group_add_service_subtype(*srv, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, name, type, NULL, subtype); if (error) { cupsdLogMessage(CUPSD_LOG_DEBUG, "DNS-SD subtype %s registration for \"%s\" failed." , subtype, name); break; } } } if (!error && commit) { if ((error = avahi_entry_group_commit(*srv)) != 0) cupsdLogMessage(CUPSD_LOG_DEBUG, "DNS-SD commit of \"%s\" failed.", name); } if (!from_callback) avahi_threaded_poll_unlock(DNSSDMaster); # endif /* HAVE_DNSSD */ if (error) { cupsdLogMessage(CUPSD_LOG_WARN, "DNS-SD registration of \"%s\" failed: %s", name, dnssdErrorString(error)); cupsdLogMessage(CUPSD_LOG_DEBUG, "DNS-SD type: %s", type); if (subtypes) cupsdLogMessage(CUPSD_LOG_DEBUG, "DNS-SD sub-types: %s", subtypes); } return (!error); }
Handle<Value> DNSServiceRegister(Arguments const& args) { HandleScope scope; if (argumentCountMismatch(args, 11)) { return throwArgumentCountMismatchException(args, 11); } if ( ! ServiceRef::HasInstance(args[0])) { return throwTypeError("argument 1 must be a DNSServiceRef (sdRef)"); } ServiceRef * serviceRef = ObjectWrap::Unwrap<ServiceRef>(args[0]->ToObject()); if (serviceRef->IsInitialized()) { return throwError("DNSServiceRef is already initialized"); } if ( ! args[1]->IsInt32()) { return throwError("argument 2 must be an integer (DNSServiceFlags)"); } DNSServiceFlags flags = args[1]->ToInteger()->Int32Value(); if ( ! args[2]->IsInt32()) { return throwTypeError("argument 3 must be an integer (interfaceIndex)"); } uint32_t interfaceIndex = args[2]->ToInteger()->Int32Value(); bool has_name = false; if ( ! args[3]->IsNull() && ! args[3]->IsUndefined()) { if ( ! args[3]->IsString()) { return throwTypeError("argument 4 must be a string (name)"); } has_name = true; } String::Utf8Value name(args[3]); if ( ! args[4]->IsString()) { return throwTypeError("argument 5 must be a string (service type)"); } String::Utf8Value serviceType(args[4]->ToString()); bool has_domain = false; if ( ! args[5]->IsNull() && ! args[5]->IsUndefined()) { if ( ! args[5]->IsString()) { return throwTypeError("argument 6 must be a string (domain)"); } has_domain = true; } String::Utf8Value domain(args[5]); bool has_host = false; if ( ! args[6]->IsNull() && ! args[6]->IsUndefined()) { if ( ! args[6]->IsString()) { return throwTypeError("argument 7 must be a string (host)"); } has_host = true; } String::Utf8Value host(args[6]); if ( ! args[7]->IsInt32()) { return throwTypeError("argument 8 must be an integer (port)"); } int raw_port = args[7]->ToInteger()->Int32Value(); if (raw_port > std::numeric_limits<uint16_t>::max() || raw_port < 0) { return throwError("argument 8: port number is out of bounds."); } uint16_t port = static_cast<uint16_t>(raw_port); uint16_t txtLen(0); const void * txtRecord(NULL); if ( ! args[8]->IsNull() && ! args[8]->IsUndefined()) { if (Buffer::HasInstance(args[8])) { Local<Object> bufferObject = args[8]->ToObject(); txtRecord = Buffer::Data(bufferObject); txtLen = Buffer::Length(bufferObject); } else if (TxtRecordRef::HasInstance(args[8])) { TxtRecordRef * ref = ObjectWrap::Unwrap<TxtRecordRef>(args[8]->ToObject()); txtLen = TXTRecordGetLength( & ref->GetTxtRecordRef()); txtRecord = TXTRecordGetBytesPtr( & ref->GetTxtRecordRef()); } else { return throwTypeError("argument 9 must be a buffer or a dns_sd.TXTRecordRef"); } } if ( ! args[9]->IsNull() && ! args[9]->IsUndefined()) { if ( ! args[9]->IsFunction()) { return throwTypeError("argument 10 must be a function (callBack)"); } serviceRef->SetCallback(Local<Function>::Cast(args[9])); } if ( ! args[10]->IsNull() && ! args[10]->IsUndefined()) { serviceRef->SetContext(args[10]); } // eleven arguments ... srsly? DNSServiceErrorType error = DNSServiceRegister( & serviceRef->GetServiceRef(), flags, interfaceIndex, has_name ? * name : NULL, *serviceType, has_domain ? * domain : NULL, has_host ? * host : NULL, htons(port), txtLen, txtRecord, args[9]->IsFunction() ? OnServiceRegistered : NULL, serviceRef); if (error != kDNSServiceErr_NoError) { return throwMdnsError("DNSServiceRegister()", error); } if ( ! serviceRef->SetSocketFlags()) { return throwError("Failed to set socket flags (O_NONBLOCK, FD_CLOEXEC)"); } return Undefined(); }
void PublicService::publishAsync() { if(d->isRunning()) stop(); #ifdef HAVE_DNSSD if(ServiceBrowser::isAvailable() == ServiceBrowser::Working) { TXTRecordRef txt; TXTRecordCreate(&txt, 0, 0); QMap< QString, QString >::ConstIterator itEnd = m_textData.end(); for(QMap< QString, QString >::ConstIterator it = m_textData.begin(); it != itEnd; ++it) { QCString value = it.data().utf8(); if(TXTRecordSetValue(&txt, it.key().utf8(), value.length(), value) != kDNSServiceErr_NoError) { TXTRecordDeallocate(&txt); emit published(false); return; } } DNSServiceRef ref; if(DNSServiceRegister(&ref, 0, 0, m_serviceName.utf8(), m_type.ascii(), domainToDNS(m_domain), NULL, htons(m_port), TXTRecordGetLength(&txt), TXTRecordGetBytesPtr(&txt), publish_callback, reinterpret_cast< void * >(this)) == kDNSServiceErr_NoError) d->setRef(ref); TXTRecordDeallocate(&txt); } #endif if(!d->isRunning()) emit published(false); }
/* * This function tries to register the AFP DNS * SRV service type. */ static void register_stuff(const AFPObj *obj) { uint port; const struct vol *volume; char name[MAXINSTANCENAMELEN+1]; DNSServiceErrorType error; TXTRecordRef txt_adisk; TXTRecordRef txt_devinfo; char tmpname[256]; // If we had already registered, then we will unregister and re-register if(svc_refs) unregister_stuff(); /* Register our service, prepare the TXT record */ TXTRecordCreate(&txt_adisk, 0, NULL); if( 0 > TXTRecordPrintf(&txt_adisk, "sys", "waMa=0,adVF=0x100") ) { LOG ( log_error, logtype_afpd, "Could not create Zeroconf TXTRecord for sys"); goto fail; } /* Build AFP volumes list */ int i = 0; for (volume = getvolumes(); volume; volume = volume->v_next) { if (convert_string(CH_UCS2, CH_UTF8_MAC, volume->v_u8mname, -1, tmpname, 255) <= 0) { LOG ( log_error, logtype_afpd, "Could not set Zeroconf volume name for TimeMachine"); goto fail; } if (volume->v_flags & AFPVOL_TM) { if (volume->v_uuid) { LOG(log_info, logtype_afpd, "Registering volume '%s' with UUID: '%s' for TimeMachine", volume->v_localname, volume->v_uuid); if( 0 > TXTRecordKeyPrintf(&txt_adisk, "dk%u", i++, "adVN=%s,adVF=0xa1,adVU=%s", tmpname, volume->v_uuid) ) { LOG ( log_error, logtype_afpd, "Could not set Zeroconf TXTRecord for dk%u", i); goto fail; } } else { LOG(log_warning, logtype_afpd, "Registering volume '%s' for TimeMachine. But UUID is invalid.", volume->v_localname); if( 0 > TXTRecordKeyPrintf(&txt_adisk, "dk%u", i++, "adVN=%s,adVF=0xa1", tmpname) ) { LOG ( log_error, logtype_afpd, "Could not set Zeroconf TXTRecord for dk%u", i); goto fail; } } } } /* AFP_DNS_SERVICE_TYPE */ svc_ref_count = 1; if (i) { /* ADISK_SERVICE_TYPE */ svc_ref_count++; } if (obj->options.mimicmodel) { /* DEV_INFO_SERVICE_TYPE */ svc_ref_count++; } // Allocate the memory to store our service refs svc_refs = calloc(svc_ref_count, sizeof(DNSServiceRef)); assert(svc_refs); svc_ref_count = 0; port = atoi(obj->options.port); if (convert_string(obj->options.unixcharset, CH_UTF8, obj->options.hostname, -1, name, MAXINSTANCENAMELEN) <= 0) { LOG(log_error, logtype_afpd, "Could not set Zeroconf instance name"); goto fail; } error = DNSServiceRegister(&svc_refs[svc_ref_count++], 0, // no flags 0, // all network interfaces name, AFP_DNS_SERVICE_TYPE, "", // default domains NULL, // default host name htons(port), 0, // length of TXT NULL, // no TXT RegisterReply, // callback NULL); // no context if (error != kDNSServiceErr_NoError) { LOG(log_error, logtype_afpd, "Failed to add service: %s, error=%d", AFP_DNS_SERVICE_TYPE, error); goto fail; } if (i) { error = DNSServiceRegister(&svc_refs[svc_ref_count++], 0, // no flags 0, // all network interfaces name, ADISK_SERVICE_TYPE, "", // default domains NULL, // default host name htons(port), TXTRecordGetLength(&txt_adisk), TXTRecordGetBytesPtr(&txt_adisk), RegisterReply, // callback NULL); // no context if (error != kDNSServiceErr_NoError) { LOG(log_error, logtype_afpd, "Failed to add service: %s, error=%d", ADISK_SERVICE_TYPE, error); goto fail; } } if (obj->options.mimicmodel) { LOG(log_info, logtype_afpd, "Registering server as model '%s'", obj->options.mimicmodel); TXTRecordCreate(&txt_devinfo, 0, NULL); if ( 0 > TXTRecordPrintf(&txt_devinfo, "model", obj->options.mimicmodel) ) { LOG ( log_error, logtype_afpd, "Could not create Zeroconf TXTRecord for model"); goto fail; } error = DNSServiceRegister(&svc_refs[svc_ref_count++], 0, // no flags 0, // all network interfaces name, DEV_INFO_SERVICE_TYPE, "", // default domains NULL, // default host name /* * We would probably use port 0 zero, but we can't, from man DNSServiceRegister: * "A value of 0 for a port is passed to register placeholder services. * Place holder services are not found when browsing, but other * clients cannot register with the same name as the placeholder service." * We therefor use port 9 which is used by the adisk service type. */ htons(9), TXTRecordGetLength(&txt_devinfo), TXTRecordGetBytesPtr(&txt_devinfo), RegisterReply, // callback NULL); // no context TXTRecordDeallocate(&txt_devinfo); if (error != kDNSServiceErr_NoError) { LOG(log_error, logtype_afpd, "Failed to add service: %s, error=%d", DEV_INFO_SERVICE_TYPE, error); goto fail; } } /* if (config->obj.options.mimicmodel) */ /* * Now we can create the thread that will poll for the results * and handle the calling of the callbacks */ if(pthread_create(&poller, NULL, polling_thread, NULL) != 0) { LOG(log_error, logtype_afpd, "Unable to start mDNS polling thread"); goto fail; } fail: TXTRecordDeallocate(&txt_adisk); return; }
static int publish_service(struct service *s) { int r = -1; TXTRecordRef txt; DNSServiceErrorType err; const char *name = NULL, *t; pa_proplist *proplist = NULL; pa_sample_spec ss; pa_channel_map map; char cm[PA_CHANNEL_MAP_SNPRINT_MAX], tmp[64]; enum service_subtype subtype; const char * const subtype_text[] = { [SUBTYPE_HARDWARE] = "hardware", [SUBTYPE_VIRTUAL] = "virtual", [SUBTYPE_MONITOR] = "monitor" }; pa_assert(s); if (s->service) { DNSServiceRefDeallocate(s->service); s->service = NULL; } TXTRecordCreate(&txt, 0, NULL); txt_record_server_data(s->userdata->core, &txt); get_service_data(s, &ss, &map, &name, &proplist, &subtype); TXTRecordSetValue(&txt, "device", strlen(name), name); snprintf(tmp, sizeof(tmp), "%u", ss.rate); TXTRecordSetValue(&txt, "rate", strlen(tmp), tmp); snprintf(tmp, sizeof(tmp), "%u", ss.channels); TXTRecordSetValue(&txt, "channels", strlen(tmp), tmp); t = pa_sample_format_to_string(ss.format); TXTRecordSetValue(&txt, "format", strlen(t), t); t = pa_channel_map_snprint(cm, sizeof(cm), &map); TXTRecordSetValue(&txt, "channel_map", strlen(t), t); t = subtype_text[subtype]; TXTRecordSetValue(&txt, "subtype", strlen(t), t); if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_DESCRIPTION))) TXTRecordSetValue(&txt, "description", strlen(t), t); if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_ICON_NAME))) TXTRecordSetValue(&txt, "icon-name", strlen(t), t); if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_VENDOR_NAME))) TXTRecordSetValue(&txt, "vendor-name", strlen(t), t); if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_PRODUCT_NAME))) TXTRecordSetValue(&txt, "product-name", strlen(t), t); if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_CLASS))) TXTRecordSetValue(&txt, "class", strlen(t), t); if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_FORM_FACTOR))) TXTRecordSetValue(&txt, "form-factor", strlen(t), t); err = DNSServiceRegister(&s->service, 0, /* flags */ kDNSServiceInterfaceIndexAny, s->service_name, pa_sink_isinstance(s->device) ? SERVICE_TYPE_SINK : SERVICE_TYPE_SOURCE, NULL, /* domain */ NULL, /* host */ compute_port(s->userdata), TXTRecordGetLength(&txt), TXTRecordGetBytesPtr(&txt), dns_service_register_reply, s); if (err != kDNSServiceErr_NoError) { pa_log("DNSServiceRegister() returned err %d", err); goto finish; } pa_log_debug("Successfully registered Bonjour services for >%s<.", s->service_name); return 0; finish: /* Remove this service */ if (r < 0) service_free(s); TXTRecordDeallocate(&txt); return r; }
//methods to implement for concrete implementations bool CZeroconfWIN::doPublishService(const std::string& fcr_identifier, const std::string& fcr_type, const std::string& fcr_name, unsigned int f_port, std::map<std::string, std::string> txt) { DNSServiceRef netService = NULL; TXTRecordRef txtRecord; TXTRecordCreate(&txtRecord, 0, NULL); CLog::Log(LOGDEBUG, __FUNCTION__ " identifier: %s type: %s name:%s port:%i", fcr_identifier.c_str(), fcr_type.c_str(), fcr_name.c_str(), f_port); //add txt records if(!txt.empty()) { for(std::map<std::string, std::string>::const_iterator it = txt.begin(); it != txt.end(); ++it) { CLog::Log(LOGDEBUG, "ZeroconfWIN: key:%s, value:%s",it->first.c_str(),it->second.c_str()); uint8_t txtLen = (uint8_t)strlen(it->second.c_str()); TXTRecordSetValue(&txtRecord, it->first.c_str(), txtLen, it->second.c_str()); } } DNSServiceErrorType err = DNSServiceRegister(&netService, 0, 0, fcr_name.c_str(), fcr_type.c_str(), NULL, NULL, htons(f_port), TXTRecordGetLength(&txtRecord), TXTRecordGetBytesPtr(&txtRecord), registerCallback, NULL); if (err != kDNSServiceErr_NoError) { // Something went wrong so lets clean up. if (netService) DNSServiceRefDeallocate(netService); CLog::Log(LOGERROR, __FUNCTION__ " DNSServiceRegister returned (error = %ld)", (int) err); } else { err = DNSServiceProcessResult(netService); if (err != kDNSServiceErr_NoError) CLog::Log(LOGERROR, __FUNCTION__ " DNSServiceProcessResult returned (error = %ld)", (int) err); CSingleLock lock(m_data_guard); m_services.insert(make_pair(fcr_identifier, netService)); } TXTRecordDeallocate(&txtRecord); return err == kDNSServiceErr_NoError; }
//methods to implement for concrete implementations bool CZeroconfWIN::doPublishService(const std::string& fcr_identifier, const std::string& fcr_type, const std::string& fcr_name, unsigned int f_port, const std::vector<std::pair<std::string, std::string> >& txt) { DNSServiceRef netService = NULL; TXTRecordRef txtRecord; DNSServiceErrorType err; TXTRecordCreate(&txtRecord, 0, NULL); if(m_service == NULL) { err = DNSServiceCreateConnection(&m_service); if (err != kDNSServiceErr_NoError) { CLog::Log(LOGERROR, "ZeroconfWIN: DNSServiceCreateConnection failed with error = %ld", (int) err); return false; } err = WSAAsyncSelect( (SOCKET) DNSServiceRefSockFD( m_service ), g_hWnd, BONJOUR_EVENT, FD_READ | FD_CLOSE ); if (err != kDNSServiceErr_NoError) CLog::Log(LOGERROR, "ZeroconfWIN: WSAAsyncSelect failed with error = %ld", (int) err); } 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); //add txt records if(!txt.empty()) { for(std::vector<std::pair<std::string, std::string> >::const_iterator it = txt.begin(); it != txt.end(); ++it) { CLog::Log(LOGDEBUG, "ZeroconfWIN: key:%s, value:%s",it->first.c_str(),it->second.c_str()); uint8_t txtLen = (uint8_t)strlen(it->second.c_str()); TXTRecordSetValue(&txtRecord, it->first.c_str(), txtLen, it->second.c_str()); } } { CSingleLock lock(m_data_guard); netService = m_service; err = DNSServiceRegister(&netService, kDNSServiceFlagsShareConnection, 0, fcr_name.c_str(), fcr_type.c_str(), NULL, NULL, htons(f_port), TXTRecordGetLength(&txtRecord), TXTRecordGetBytesPtr(&txtRecord), registerCallback, NULL); } if (err != kDNSServiceErr_NoError) { // Something went wrong so lets clean up. if (netService) DNSServiceRefDeallocate(netService); CLog::Log(LOGERROR, "ZeroconfWIN: DNSServiceRegister returned (error = %ld)", (int) err); } else { CSingleLock lock(m_data_guard); m_services.insert(make_pair(fcr_identifier, netService)); } TXTRecordDeallocate(&txtRecord); return err == kDNSServiceErr_NoError; }
uint8_t getSize() const { return recordPtr != NULL? TXTRecordGetLength(recordPtr) : 0; }