int OTAClass::beginArduinoMdnsService(char *device_name, uint16_t port) { int ret = -1; mdns_buf = (unsigned char *) malloc (DEFAULT_OTA_MDNS_BUF); txtRecord = malloc (sizeof(TXTRecordRef)); do { if (mDNSResponderInit() != 0) { OTA_PRINTF("Fail to init mDNS service\r\n"); break; } TXTRecordCreate((TXTRecordRef *)txtRecord, DEFAULT_OTA_MDNS_BUF, mdns_buf); TXTRecordSetValue((TXTRecordRef *)txtRecord, "board", strlen("ameba_rtl8195a"), "ameba_rtl8195a"); TXTRecordSetValue((TXTRecordRef *)txtRecord, "auth_upload", strlen("no"), "no"); TXTRecordSetValue((TXTRecordRef *)txtRecord, "tcp_check", strlen("no"), "no"); TXTRecordSetValue((TXTRecordRef *)txtRecord, "ssh_upload", strlen("no"), "no"); mdns_service_id = mDNSRegisterService(device_name, "_arduino._tcp", "local", port, (TXTRecordRef *)txtRecord); TXTRecordDeallocate((TXTRecordRef *)txtRecord); ret = 0; } while (0); if (ret < 0) { OTA_PRINTF("Fail to begin Arduino mDNS service\r\n"); } return ret; }
STDMETHODIMP CTXTRecord::SetValue(BSTR key, VARIANT value) { std::string keyUTF8; ByteArray valueArray; BOOL ok; DNSServiceErrorType err; HRESULT hr = S_OK; if ( !m_allocated ) { TXTRecordCreate( &m_tref, 0, NULL ); m_allocated = TRUE; } ok = BSTRToUTF8( key, keyUTF8 ); require_action( ok, exit, hr = S_FALSE ); ok = VariantToByteArray( &value, valueArray ); require_action( ok, exit, hr = S_FALSE ); err = TXTRecordSetValue( &m_tref, keyUTF8.c_str(), ( uint8_t ) valueArray.size(), &valueArray[ 0 ] ); require_action( !err, exit, hr = S_FALSE ); exit: return hr; }
int TXTRecordKeyPrintf(TXTRecordRef * rec, const char * key_fmt, int key_var, const char * fmt, ...) { int ret = 0; char *key = NULL, *str = NULL; va_list ap; if( 0 > asprintf(&key, key_fmt, key_var)) return -1; va_start( ap, fmt ); if( 0 > vasprintf(&str, fmt, ap )) { va_end(ap); ret = -1; goto exit; } va_end(ap); if( kDNSServiceErr_NoError != TXTRecordSetValue(rec, key, strlen(str), str) ) { ret = -1; goto exit; } exit: if (str) free(str); if (key) free(key); return ret; }
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); }
Handle<Value> TXTRecordSetValue(Arguments const& args) { HandleScope scope; if (argumentCountMismatch(args, 3)) { return throwArgumentCountMismatchException(args, 3); } if ( ! args[0]->IsObject() || ! TxtRecordRef::HasInstance(args[0]->ToObject())) { return throwTypeError("argument 1 must be a TXTRecordRef object"); } TxtRecordRef * ref = ObjectWrap::Unwrap<TxtRecordRef>(args[0]->ToObject()); if ( ! args[1]->IsString()) { return throwTypeError("argument 1 must be a string (key)"); } String::Utf8Value key(args[1]); if ( ! (args[2]->IsNull() || args[2]->IsUndefined() || Buffer::HasInstance(args[2]) || args[2]->IsString())) { return throwTypeError("argument 1 must be null, undefined, a buffer or a string (value)"); } DNSServiceErrorType code = TXTRecordSetValue( & ref->GetTxtRecordRef(), *key, length(args[2]), ((args[2]->IsNull()||args[2]->IsUndefined()) ? NULL : args[2]->IsString() ? *String::Utf8Value(args[2]->ToString()) : Buffer::Data(args[2]->ToObject()))); if (code != kDNSServiceErr_NoError) { return throwMdnsError("failed to set txt record value", code); } return Undefined(); }
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; }
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 createTXTRecord_( TXTRecordRef& record ) { TXTRecordCreate( &record, 0, 0 ); for( ValueMapCIter i = data_.begin(); i != data_.end(); ++i ) { const std::string& key = i->first; const std::string& value = i->second; const uint8_t valueSize = value.length() > 255 ? 255 : uint8_t( value.length( )); TXTRecordSetValue( &record, key.c_str(), valueSize, value.c_str( )); } }
static void txt_record_server_data(pa_core *c, TXTRecordRef *txt) { char s[128]; char *t; pa_assert(c); TXTRecordSetValue(txt, "server-version", strlen(PACKAGE_NAME" "PACKAGE_VERSION), PACKAGE_NAME" "PACKAGE_VERSION); t = pa_get_user_name_malloc(); TXTRecordSetValue(txt, "user-name", strlen(t), t); pa_xfree(t); t = pa_machine_id(); TXTRecordSetValue(txt, "machine-id", strlen(t), t); pa_xfree(t); t = pa_uname_string(); TXTRecordSetValue(txt, "uname", strlen(t), t); pa_xfree(t); t = pa_get_fqdn(s, sizeof(s)); TXTRecordSetValue(txt, "fqdn", strlen(t), t); snprintf(s, sizeof(s), "0x%08x", c->cookie); TXTRecordSetValue(txt, "cookie", strlen(s), s); }
static void example_mdns_thread(void *param) { DNSServiceRef dnsServiceRef = NULL; TXTRecordRef txtRecord; unsigned char txt_buf[100]; // use fixed buffer for text record to prevent malloc/free // Delay to wait for IP by DHCP vTaskDelay(10000); printf("\nmDNS Init\n"); if(mDNSResponderInit() == 0) { printf("mDNS Register service\n"); TXTRecordCreate(&txtRecord, sizeof(txt_buf), txt_buf); TXTRecordSetValue(&txtRecord, "text1", strlen("text1_content"), "text1_content"); TXTRecordSetValue(&txtRecord, "text2", strlen("text2_content"), "text2_content"); dnsServiceRef = mDNSRegisterService("ameba", "_service1._tcp", "local", 5000, &txtRecord); TXTRecordDeallocate(&txtRecord); printf("wait for 30s ... \n"); vTaskDelay(30*1000); printf("mDNS Update service\n"); TXTRecordCreate(&txtRecord, sizeof(txt_buf), txt_buf); TXTRecordSetValue(&txtRecord, "text1", strlen("text1_content_new"), "text1_content_new"); mDNSUpdateService(dnsServiceRef, &txtRecord, 0); TXTRecordDeallocate(&txtRecord); printf("wait for 30s ... \n"); vTaskDelay(30*1000); if(dnsServiceRef) mDNSDeregisterService(dnsServiceRef); // deregister service before mdns deinit is not necessary // mDNS deinit will also deregister all services printf("mDNS Deinit\n"); mDNSResponderDeinit(); } vTaskDelete(NULL); }
//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; }
//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; }
int TXTRecordPrintf(TXTRecordRef * rec, const char * key, const char * fmt, ... ) { int ret = 0; char *str; va_list ap; va_start( ap, fmt ); if( 0 > vasprintf(&str, fmt, ap ) ) { va_end(ap); return -1; } va_end(ap); if( kDNSServiceErr_NoError != TXTRecordSetValue(rec, key, strlen(str), str) ) { ret = -1; } free(str); 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 YMmDNSServiceSetTXTRecord( YMmDNSServiceRef s_, YMmDNSTxtRecordKeyPair *keyPairs[], size_t nPairs ) { __ym_mdns_service_t *s = (__ym_mdns_service_t *)s_; if ( keyPairs == NULL || nPairs == 0 ) return false; size_t idx; TXTRecordRef *txtRecord = (TXTRecordRef *)YMALLOC(sizeof(TXTRecordRef)); TXTRecordCreate(txtRecord, 0, NULL); for ( idx = 0; idx < nPairs; idx++ ) { YMmDNSTxtRecordKeyPair **_keyPairs = (YMmDNSTxtRecordKeyPair **)keyPairs; const char *key = YMSTR(_keyPairs[idx]->key); const uint8_t *value = _keyPairs[idx]->value; uint8_t valueLen = _keyPairs[idx]->valueLen; TXTRecordSetValue(txtRecord, key, valueLen, value); } s->txtRecord = (uint8_t *)txtRecord; return true; }
//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; }
static cupsd_txt_t /* O - TXT record */ dnssdBuildTxtRecord( cupsd_printer_t *p, /* I - Printer information */ int for_lpd) /* I - 1 = LPD, 0 = IPP */ { int i, /* Looping var */ count; /* Count of key/value pairs */ char admin_hostname[256], /* .local hostname for admin page */ adminurl_str[256], /* URL for the admin page */ type_str[32], /* Type to string buffer */ state_str[32], /* State to string buffer */ rp_str[1024], /* Queue name string buffer */ air_str[1024], /* auth-info-required string buffer */ *keyvalue[32][2]; /* Table of key/value pairs */ cupsd_txt_t txt; /* TXT record */ /* * Load up the key value pairs... */ count = 0; if (!for_lpd || (BrowseLocalProtocols & BROWSE_LPD)) { keyvalue[count ][0] = "txtvers"; keyvalue[count++][1] = "1"; keyvalue[count ][0] = "qtotal"; keyvalue[count++][1] = "1"; keyvalue[count ][0] = "rp"; keyvalue[count++][1] = rp_str; if (for_lpd) strlcpy(rp_str, p->name, sizeof(rp_str)); else snprintf(rp_str, sizeof(rp_str), "%s/%s", (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers", p->name); keyvalue[count ][0] = "ty"; keyvalue[count++][1] = p->make_model ? p->make_model : "Unknown"; if (strstr(DNSSDHostName, ".local")) strlcpy(admin_hostname, DNSSDHostName, sizeof(admin_hostname)); else snprintf(admin_hostname, sizeof(admin_hostname), "%s.local.", DNSSDHostName); httpAssembleURIf(HTTP_URI_CODING_ALL, adminurl_str, sizeof(adminurl_str), # ifdef HAVE_SSL "https", # else "http", # endif /* HAVE_SSL */ NULL, admin_hostname, DNSSDPort, "/%s/%s", (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers", p->name); keyvalue[count ][0] = "adminurl"; keyvalue[count++][1] = adminurl_str; if (p->location) { keyvalue[count ][0] = "note"; keyvalue[count++][1] = p->location; } keyvalue[count ][0] = "priority"; keyvalue[count++][1] = for_lpd ? "100" : "0"; keyvalue[count ][0] = "product"; keyvalue[count++][1] = p->pc && p->pc->product ? p->pc->product : "Unknown"; keyvalue[count ][0] = "pdl"; keyvalue[count++][1] = p->pdl ? p->pdl : "application/postscript"; if (get_auth_info_required(p, air_str, sizeof(air_str))) { keyvalue[count ][0] = "air"; keyvalue[count++][1] = air_str; } keyvalue[count ][0] = "UUID"; keyvalue[count++][1] = p->uuid + 9; #ifdef HAVE_SSL keyvalue[count ][0] = "TLS"; keyvalue[count++][1] = "1.2"; #endif /* HAVE_SSL */ if (p->type & CUPS_PRINTER_FAX) { keyvalue[count ][0] = "Fax"; keyvalue[count++][1] = "T"; keyvalue[count ][0] = "rfo"; keyvalue[count++][1] = rp_str; } if (p->type & CUPS_PRINTER_COLOR) { keyvalue[count ][0] = "Color"; keyvalue[count++][1] = (p->type & CUPS_PRINTER_COLOR) ? "T" : "F"; } if (p->type & CUPS_PRINTER_DUPLEX) { keyvalue[count ][0] = "Duplex"; keyvalue[count++][1] = (p->type & CUPS_PRINTER_DUPLEX) ? "T" : "F"; } if (p->type & CUPS_PRINTER_STAPLE) { keyvalue[count ][0] = "Staple"; keyvalue[count++][1] = (p->type & CUPS_PRINTER_STAPLE) ? "T" : "F"; } if (p->type & CUPS_PRINTER_COPIES) { keyvalue[count ][0] = "Copies"; keyvalue[count++][1] = (p->type & CUPS_PRINTER_COPIES) ? "T" : "F"; } if (p->type & CUPS_PRINTER_COLLATE) { keyvalue[count ][0] = "Collate"; keyvalue[count++][1] = (p->type & CUPS_PRINTER_COLLATE) ? "T" : "F"; } if (p->type & CUPS_PRINTER_PUNCH) { keyvalue[count ][0] = "Punch"; keyvalue[count++][1] = (p->type & CUPS_PRINTER_PUNCH) ? "T" : "F"; } if (p->type & CUPS_PRINTER_BIND) { keyvalue[count ][0] = "Bind"; keyvalue[count++][1] = (p->type & CUPS_PRINTER_BIND) ? "T" : "F"; } if (p->type & CUPS_PRINTER_SORT) { keyvalue[count ][0] = "Sort"; keyvalue[count++][1] = (p->type & CUPS_PRINTER_SORT) ? "T" : "F"; } if (p->type & CUPS_PRINTER_MFP) { keyvalue[count ][0] = "Scan"; keyvalue[count++][1] = (p->type & CUPS_PRINTER_MFP) ? "T" : "F"; } snprintf(type_str, sizeof(type_str), "0x%X", p->type | CUPS_PRINTER_REMOTE); snprintf(state_str, sizeof(state_str), "%d", p->state); keyvalue[count ][0] = "printer-state"; keyvalue[count++][1] = state_str; keyvalue[count ][0] = "printer-type"; keyvalue[count++][1] = type_str; } /* * Then pack them into a proper txt record... */ # ifdef HAVE_DNSSD TXTRecordCreate(&txt, 0, NULL); for (i = 0; i < count; i ++) { size_t len = strlen(keyvalue[i][1]); if (len < 256) TXTRecordSetValue(&txt, keyvalue[i][0], (uint8_t)len, keyvalue[i][1]); } # else for (i = 0, txt = NULL; i < count; i ++) txt = avahi_string_list_add_printf(txt, "%s=%s", keyvalue[i][0], keyvalue[i][1]); # endif /* HAVE_DNSSD */ return (txt); }
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); } }
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); }
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); }
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; }
DNSServiceErrorType setValue(const char *k, uint8_t len, const void *val) { return TXTRecordSetValue(recordPtr, k, len, val); }
void cmd_mdns(int argc, char **argv) { static DNSServiceRef dnsServiceRef = NULL; static char hostname[32]; if(argc == 1) goto error; if(strcmp(argv[1], "init") == 0) { WACPersistentConfig_t config; WACPlatformReadConfig(&config); if((config.name_len > 0) && (config.name_len < 32)) { strcpy(hostname, config.name); } else { uint8_t *mac = LwIP_GetMAC(&xnetif[0]); sprintf(hostname, "AMEBA%02x%02x%02x", mac[3], mac[4], mac[5]); } netif_set_hostname(&xnetif[0], hostname); if(mDNSResponderInit() == 0) printf("mDNS initialized\n"); else printf("mDNS init failed\n"); } else if(strcmp(argv[1], "deinit") == 0) { mDNSResponderDeinit(); printf("mDNS de-initialized\n"); } else if(strcmp(argv[1], "reg") == 0) { if(argc != 5) { printf("Usage: mdns reg NAME TYPE PORT\n"); return; } if(atoi(argv[4]) == 0) printf("mDNS service incorrect port\n"); if(dnsServiceRef) { mDNSDeregisterService(dnsServiceRef); dnsServiceRef = NULL; } if((dnsServiceRef = mDNSRegisterService(argv[2], argv[3], "local", atoi(argv[4]), NULL)) != NULL) printf("mDNS service %s.%s registered\n", argv[2], argv[3]); else printf("mDNS service %s.%s register failed\n", argv[2], argv[3]); } else if(strcmp(argv[1], "dereg") == 0) { if(dnsServiceRef) { mDNSDeregisterService(dnsServiceRef); dnsServiceRef = NULL; printf("mDNS service de-registered\n"); } else { printf("mDNS no service\n"); } } else if(strcmp(argv[1], "update") == 0) { if(argc != 5) { printf("Usage: mdns update TXT_KEY TXT_VALUE TTL\n"); return; } if(dnsServiceRef) { TXTRecordRef txtRecord; unsigned char txt_buf[100]; TXTRecordCreate(&txtRecord, sizeof(txt_buf), txt_buf); TXTRecordSetValue(&txtRecord, argv[2], strlen(argv[3]), argv[3]); mDNSUpdateService(dnsServiceRef, &txtRecord, atoi(argv[4])); TXTRecordDeallocate(&txtRecord); printf("mDNS service updated\n"); } else { printf("mDNS no service\n"); } } // For BCT mDNS manual name change test else if(strcmp(argv[1], "name_test") == 0) { char *new_name = "New - Bonjour Service Name"; printf("Rename HAP service to \"%s\"._hap._tcp.local. %s\n", new_name, (RenameHAPBonjourService(new_name) == 0) ? "success":"fail"); } else { error: printf("Usage: mdns init|deinit|reg|dereg|name_test\n"); } }