2013-08-16 1 views
2

Я зарегистрировал запись, используя API Bonjour. Теперь я хочу знать содержимое записи, которую я только что опубликовал. Я создал его, указав NULL имя хоста, то есть «использовать демона по умолчанию», но я не могу найти простой способ запросить то, что это такое!Как узнать имя моего многоадресного (Bonjour)?

С avahi это легко: я вызываю avahi_client_get_host_name(), чтобы получить начальное значение имени машины.

Как для avahi, так и для Bonjour значение записи SRV может меняться в течение срока действия регистрации - если регистрация была выполнена с именем NULL, имя хоста записи обновляется автоматически, когда это необходимо. Все, что я хочу, это способ получить значение начального значения имени хоста в то время, когда я выполняю регистрацию.

Обратите внимание, что на моей тестовой машине Snow Leopard по умолчанию многоадресное имя хоста - , а не такое же, как имя машины от gethostname(2).

Четыре решения я могу думать:

  1. захватить имя хоста в моем процессе. Это может быть где-то там. Я сделал strings(3) поиск на дампе памяти моего процесса и нашел четыре экземпляра имени многоадресной передачи в моем адресном пространстве, но это может быть совпадением, поскольку имя используется для других целей. Даже если строка, в которой я работаю, находится где-то в моем процессе, я не могу найти API, чтобы восстановить его.
  2. Запросить имя хоста от демона. Может быть какой-то запрос, который я могу отправить через порт mach к демону, который его извлекает? Я не могу найти API снова. Соответствующий фрагмент кода находится в файле uDNS.c в mDNSResponder и, похоже, не отображается через интерфейс RPC.
  3. Я мог бы просто найти сервис, который я зарегистрировал. Это может быть связано с небольшим сетевым трафиком, поэтому, если нет какой-либо гарантии, что этого не произойдет, я не хочу этого делать.
  4. Повторно реализовать логику в uDNS.c. Она захватывает имя хоста машины из комбинации:

    • конфигурации Динамический DNS
    • Статически сконфигурировано имя хоста многоадресной рассылки
    • обратный поиск адреса IPv4 первичного интерфейса
    • Он, в частности не использует gethostname(2) или эквивалент

    Повторная реализация этой логики кажется неосуществимой.

На данный момент я стремлюсь к поиску, чтобы получить значение начальной регистрации SRV, но это не кажется идеальным. Какое правильное решение?

+1

Я не знаю, есть ли более эффективный метод, но я не думаю, что # 3 включает сетевой трафик, потому что локальный mDNSResponder знает ответ. Это выглядит как самый надежный метод для меня. –

+0

Состояние гонки меня раздражает - если демона обнаруживает конфликт, он выведет запись, и поиск может вызвать трафик (хотя и маловероятно). Хотя это сносно. –

ответ

0

Для записи я пошел с (4), схватив конфигурацию машины, чтобы спрятать имя хоста, которое использует демон, без запроса.

static char* getBonjourDefaultHost() 
{ 
    char* rv = 0; 
#ifdef __APPLE__ 
    CFStringRef name = SCDynamicStoreCopyLocalHostName(NULL); 
    if (name) { 
    int len = CFStringGetLength(name); 
    rv = new char[len*4+1]; 
    CFStringGetCString(name, rv, len*4+1, kCFStringEncodingUTF8); 
    CFRelease(name); 
    } 
    // This fallback is completely incorrect, but why should we care... 
    // Mac does something crazy like <sysctl hw.model>-<MAC address>. 
    if (!rv) 
    rv = GetHostname(); // using gethostname(2) 

#elif defined(WIN32) 
    CHAR tmp[256+1]; 
    ULONG namelength = sizeof(tmp); 
    DynamicFn<BOOL (WINAPI*)(COMPUTER_NAME_FORMAT,LPSTR,LPDWORD)> 
    GetComputerNameExA_("Kernel32", "GetComputerNameExA"); 
    if (!GetComputerNameExA_.isValid() || 
     !(*GetComputerNameExA_)(ComputerNamePhysicalDnsHostname, tmp, &namelength)) 
    tmp[0] = 0; 
    // Roughly correct; there's some obscure string cleaning mDNSResponder does 
    // to tidy up funny international strings. 
    rv = tmp[0] ? strdup(tmp) : strdup("My Computer"); 

#elif defined(__sun) 
    // This is exactly correct! What a relief. 
    rv = GetHostName(); 

#else 
#error Must add platform mDNS daemon scheme 
#endif 
    return rv; 
} 
2

Мне нужно было сделать именно это. Вы хотите использовать макрос ConvertDomainNameToCString (входит в mDNSEmbeddedAPI.h), и вам нужен доступ к основной структуре mDNS.

Вот как вы получите точный Bonjour/Zeroconf имя хоста, которое было зарегистрировано:

char szHostname[512]; 
extern mDNS m; 

ConvertDomainNameToCString(&m.MulticastHostname, szHostname); 

Я надеюсь, что это поможет вам.

+0

Yikes! Это не публичный заголовок. Это тоже подозрительно короткое имя символа - где я могу найти этот символ? Я только что связал тестовое приложение, которое использует некоторые функции mDNS, и оно получает символы из /usr/lib/libSystem.B.dylib. Неудивительно, что в основной системной библиотеке не хватает символов «_m». Вы не описываете статическую связь в клиентской библиотеке, которая говорит с демоном, не так ли? –

+0

В моем случае у меня есть прямая реализация Zeroconf на языке C, в которой служба mDNS работает как поток на моем встроенном устройстве. Экземпляр основной структуры mDNS (который в моем случае был назван просто «m»), был доступен для моего кода. Теперь я вижу, что вы, вероятно, проходите через dns_sd.h API для демона на Mac или ПК. В этом случае демонам пришлось бы зарегистрировать начальное имя узла с его объектом mDNS, а затем переопределить его в полное доменное имя с помощью «xx.local». Первоначальное имя хоста, вероятно, является частью имени службы, вплоть до первого периода (.). –

+0

Да, этот вопрос явно посвящен настольным приложениям с использованием общедоступного API Bonjour (dns_sd.h). Демон определенно знает, что такое текущее имя хоста, но эта информация просто не доступна для клиентов, не выполняя поиск службы. Название записи SRV (string-i-selected._http._tcp), безусловно, не содержит имя хоста («computer-name.local.»), Которое является содержимым записи. Я думаю, что дублирование логики, используемой для создания имени хоста на всех трех платформах (Win, Mac, Solaris), является самым простым способом. –

0

Из командной строки можно получить локальный (Bonjour) имя хоста с помощью команды scutil:

scutil --get LocalHostName 

Программным это можно получить с помощью kSCPropNetLocalHostName ключа через SystemConfiguration Framework.

+0

Это то же самое, что и мой ответ - решение (4), пытаясь воссоздать логику, используемую демоном mDNS. Демон использует LocalHostName в качестве своего первого предпочтения, но, конечно же, его не нужно устанавливать, и в этом случае различные резервные копии срабатывают ... –

+0

Я достаточно справедлив, хотя я думал показать решение командной строки и информацию о соответствующем API/Framework был полезен, поскольку было не так ясно, какой из них использовать. – Pierz

Смежные вопросы