DNSServiceErrorType
RegisterWorkstationService(MyDNSServiceState *ref, CFStringRef serviceName)
{
	char name[64];
	DNSServiceErrorType error = kDNSServiceErr_BadParam;
	
	if (CFStringGetCString(serviceName, name, sizeof(name), kCFStringEncodingUTF8)) {

		uuid_t compUUID;
		CFDataRef cfTXTRecord = NULL;
		struct timespec waitTime = { 0 };
		
		if ( gethostuuid(compUUID, &waitTime) == 0 )
		{
			CFMutableDictionaryRef txtRecordDict = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks,
																			  &kCFTypeDictionaryValueCallBacks );
			uuid_string_t uuidstr;
			
			uuid_unparse_upper( compUUID, uuidstr );
			CFStringRef cfUUID = CFStringCreateWithCString( kCFAllocatorDefault, uuidstr, kCFStringEncodingUTF8 );
			CFDictionarySetValue( txtRecordDict, CFSTR("uuid"), cfUUID );
			DbgLog( kLogInfo, "Workstation service - uuid = %s", uuidstr );
			DSCFRelease( cfUUID );
			
			cfTXTRecord = CFNetServiceCreateTXTDataWithDictionary( kCFAllocatorDefault, txtRecordDict );
			
			DSCFRelease( txtRecordDict );
		}
		else
		{
			DbgLog( kLogError, "Failed to get host UUID from gethostuuid()" );
		}
		
		error = DNSServiceRegister(&ref->service,
								   kDNSServiceFlagsNoAutoRename,
								   kDNSServiceInterfaceIndexAny,
								   name,
								   kWorkstationType,
								   NULL,
								   NULL,
								   htons(kWorkstationPort),
								   (cfTXTRecord ? CFDataGetLength(cfTXTRecord) : 0),
								   (cfTXTRecord ? CFDataGetBytePtr(cfTXTRecord) : NULL),
								   RegisterWorkstationCallBack,
								   (void *)ref);
		
		DSCFRelease( cfTXTRecord );
	}

    if (kDNSServiceErr_NoError == error) {
        DbgLog( kLogNotice, "Registered Workstation service - %s.%s", name, kWorkstationType );
        MyDNSServiceAddToRunLoop(ref);
	}
	
    return error;
}
Beispiel #2
0
static void
bonjour_start_service(CFNetServiceRef *svc, char *service_type,
                      uint32_t port, txt_rec_t *txt)
{
  CFStringRef str;
  CFStreamError error = {0};
  CFNetServiceClientContext context = {0, NULL, NULL, NULL, NULL};
  
  str = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, service_type,
                                        kCFStringEncodingASCII,
                                        kCFAllocatorNull);

  *svc = CFNetServiceCreate(NULL, CFSTR(""), str, CFSTR("Tvheadend"), port);
  if (!*svc) {
    tvhlog(LOG_ERR, "bonjour", "service creation failed"); 
    return;
  }

  CFNetServiceSetClient(*svc, bonjour_callback, &context);
  CFNetServiceScheduleWithRunLoop(*svc, CFRunLoopGetCurrent(),
                                  kCFRunLoopCommonModes);

  if (txt) {
    CFDataRef data = NULL;
    CFMutableDictionaryRef dict;
    dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks,
                                     &kCFTypeDictionaryValueCallBacks);
    
    while(txt->key) {
      str = CFStringCreateWithCString (NULL, txt->key, kCFStringEncodingASCII);
      data = CFDataCreate (NULL, (uint8_t *) txt->value, strlen(txt->value));
      CFDictionaryAddValue(dict, str, data);
      txt++;
    }
    
    data = CFNetServiceCreateTXTDataWithDictionary(NULL, dict);
    CFNetServiceSetTXTData(*svc, data);
    CFRelease(data);
    CFRelease(dict);
  }

  if (!CFNetServiceRegisterWithOptions(*svc, 0, &error))
    tvhlog(LOG_ERR, "bonjour", "registration failed (service type = %s, "
           "domain = %ld, error =%d)", service_type, error.domain, error.error); 
  else
    tvhlog(LOG_INFO, "bonjour", "service '%s' successfully established",
           service_type);
}
Beispiel #3
0
//methods to implement for concrete implementations
bool CZeroconfOSX::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)
{
  CLog::Log(LOGDEBUG, "CZeroconfOSX::doPublishService identifier: %s type: %s name:%s port:%i", fcr_identifier.c_str(),
            fcr_type.c_str(), fcr_name.c_str(), f_port);

  CFStringRef name = CFStringCreateWithCString (NULL,
                                                fcr_name.c_str(),
                                                kCFStringEncodingUTF8
                                                );
  CFStringRef type = CFStringCreateWithCString (NULL,
                                                fcr_type.c_str(),
                                                kCFStringEncodingUTF8
                                                );
  CFNetServiceRef netService = CFNetServiceCreate(NULL, CFSTR(""), type, name, f_port);
  CFRelease(name);
  CFRelease(type);

  //now register it
  CFNetServiceClientContext clientContext = { 0, this, NULL, NULL, NULL };

  CFStreamError error;
  CFNetServiceSetClient(netService, registerCallback, &clientContext);
  CFNetServiceScheduleWithRunLoop(netService, m_runloop, kCFRunLoopCommonModes);

  //add txt records
  if(!txt.empty())
  {
    //txt map to dictionary
    CFDataRef txtData = NULL;
    CFMutableDictionaryRef txtDict = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);    
    for(std::map<std::string, std::string>::const_iterator it = txt.begin(); it != txt.end(); ++it)
    {
      CFStringRef key = CFStringCreateWithCString (NULL,
                                                   it->first.c_str(),
                                                   kCFStringEncodingUTF8
                                                  );
      CFDataRef value = CFDataCreate              ( NULL,
                                                    (UInt8 *)it->second.c_str(),
                                                    strlen(it->second.c_str())
                                                  );
                                                  
      CFDictionaryAddValue(txtDict,key, value);
    }    
    
    //add txt records to service
    txtData = CFNetServiceCreateTXTDataWithDictionary(NULL, txtDict);
    CFNetServiceSetTXTData(netService, txtData);
    CFRelease(txtData);
    CFRelease(txtDict);
  }

  Boolean result = CFNetServiceRegisterWithOptions (netService, 0, &error);
  if (result == false)
  {
    // Something went wrong so lets clean up.
    CFNetServiceUnscheduleFromRunLoop(netService, m_runloop, kCFRunLoopCommonModes);
    CFNetServiceSetClient(netService, NULL, NULL);
    CFRelease(netService);
    netService = NULL;
    CLog::Log(LOGERROR, "CZeroconfOSX::doPublishService CFNetServiceRegister returned "
      "(domain = %d, error = %"PRId64")", (int)error.domain, (int64_t)error.error);
  } else
  {
    CSingleLock lock(m_data_guard);
    m_services.insert(make_pair(fcr_identifier, netService));
  }

  return result;
}