mDNS на arduino: демон avahi mDNS возвращает странную «Полученную конфликтующую запись […]. Сброс нашей записи».

#arduino #mdns

#arduino #mdns

Вопрос:

Я пытаюсь реализовать легкий диктор mDNS для arduino. Он должен объявить об услуге «apple midi rtp».

Теперь хорошая часть в том, что я могу пропинговать свое имя (mymdnstest.local) большую часть времени, и иногда оно появляется в выводе «avahi-browse-a».

Всегда демон avahi-демон отображается в журнале systemd:

 Received conflicting record [_apple-midi._udp.local IN PTR mymdnstest._apple-midi._udp.local ; ttl=120]. Resetting our record.".  

tcpdump показывает:

 22:12:00.691720 wlo1 M IP (tos 0x0, ttl 2, id 969, offset 0, flags [none], proto UDP (17), length 199) 192.168.65.215.5353 gt; 224.0.0.251.5353: [udp sum ok] 0*- [0q] 3/0/0 _apple-midi._udp.local. (Cache flush) [2m] PTR mymdnstest._apple-midi._udp.local., _apple-midi._udp.local. (Cache flush) [2m] SRV mymdnstest.local.:5004 0 0, mymdnstest.local. (Cache flush) [2m] A 192.168.65.215 (171)  

Что может быть такого, что эти ошибки видны и что он ведет себя так беспорядочно?

 #include lt;ESP8266WiFi.hgt; #include lt;WiFiClient.hgt; #include lt;WiFiUdp.hgt;  char ssid[] = " my ssid "; char pass[] = " password for my ssid ";  WiFiUDP udp;  const IPAddress tgt_ip { 224, 0, 0, 251 }; constexpr int tgt_port = 5353;  constexpr char name[] = "mymdnstest"; constexpr uint16_t port = 5004;  void update_mdns() {  static uint32_t last_msg = 0;  uint32_t now = millis();   if (last_msg == 0 || now - last_msg gt;= 750) {  last_msg = now;   static bool state = true;  digitalWrite(D0, state); // blink led  state = !state;   uint8_t response[256];  uint16_t ro = 0;   response[ro  ] = 0x00; // transaction id  response[ro  ] = 0x00;   response[ro  ] = 0x84; // standard query response, no error  response[ro  ] = 0x00;   response[ro  ] = 0x00; // 0 questions  response[ro  ] = 0x00;   response[ro  ] = 0x00; // 3 answers  response[ro  ] = 0x03;   response[ro  ] = 0x00; // 0 authority rr  response[ro  ] = 0x00;    response[ro  ] = 0x00; // 0 additional rr  response[ro  ] = 0x00;    // PTR record  constexpr char applemidi[] = "_apple-midi";  constexpr char udp_[] = "_udp";  constexpr char local[] = "local";   response[ro  ] = strlen(applemidi);  ro  = sprintf((char *)amp;response[ro], "%s", applemidi); // name itself  response[ro  ] = strlen(udp_);  ro  = sprintf((char *)amp;response[ro], "%s", udp_); // name itself  response[ro  ] = strlen(local);  ro  = sprintf((char *)amp;response[ro], "%s", local); // name itself  response[ro  ] = 0x00;   response[ro  ] = 0x00; // PTR (12)  response[ro  ] = 0x0c;   response[ro  ] = 0x80; // cache flush amp; class: in  response[ro  ] = 0x01;   response[ro  ] = 0x00; // ttl 2 minutes  response[ro  ] = 0x00;  response[ro  ] = 0x00;  response[ro  ] = 0x78;   uint16_t ptr_data_len = 1   strlen(name)    1   strlen(applemidi)    1   strlen(udp_)    1   strlen(local)    1;  response[ro  ] = ptr_data_len gt;gt; 8;  response[ro  ] = ptr_data_len;   response[ro  ] = strlen(name);  ro  = sprintf((char *)amp;response[ro], "%s", name); // name itself  response[ro  ] = strlen(applemidi);  ro  = sprintf((char *)amp;response[ro], "%s", applemidi); // name itself  response[ro  ] = strlen(udp_);  ro  = sprintf((char *)amp;response[ro], "%s", udp_); // name itself  response[ro  ] = strlen(local);  ro  = sprintf((char *)amp;response[ro], "%s", local); // name itself  response[ro  ] = 0x00;    // SRV apple midi record  response[ro  ] = strlen(applemidi); // length of name  ro  = sprintf((char *)amp;response[ro], "%s", applemidi); // name itself   response[ro  ] = strlen(udp_);  ro  = sprintf((char *)amp;response[ro], "%s", udp_); // name itself   response[ro  ] = strlen(local);  ro  = sprintf((char *)amp;response[ro], "%s", local); // name itself   response[ro  ] = 0; // string delimiter   response[ro  ] = 0x00; // type 33 SRV (server selection)  response[ro  ] = 0x21;   response[ro  ] = 0x80; // class (cache flush: True, class: in)  response[ro  ] = 0x01;   response[ro  ] = 0x00; // ttl 2 minutes  response[ro  ] = 0x00;  response[ro  ] = 0x00;  response[ro  ] = 0x78;   uint16_t srv_data_len = 2   2   2   1   strlen(name)   1   strlen(local)   1;  response[ro  ] = srv_data_len gt;gt; 8; // data len  response[ro  ] = srv_data_len;   response[ro  ] = 0x00; // priority  response[ro  ] = 0x00;   response[ro  ] = 0x00; // weight  response[ro  ] = 0x00;   response[ro  ] = port gt;gt; 8; // port on which the apple thing listens  response[ro  ] = port;   response[ro  ] = strlen(name); // length of name  ro  = sprintf((char *)amp;response[ro], "%s", name); // name itself   response[ro  ] = strlen(local);  ro  = sprintf((char *)amp;response[ro], "%s", local); // name itself   response[ro  ] = 0x00;    // A record for the hostname to the ip-address  response[ro  ] = strlen(name); // length of name  ro  = sprintf((char *)amp;response[ro], "%s", name); // name itself   response[ro  ] = strlen(local); // length of "local"  ro  = sprintf((char *)amp;response[ro], local);   response[ro  ] = 0; // string delimiter   response[ro  ] = 0x00; // type 0001 (A)  response[ro  ] = 0x01;   response[ro  ] = 0x80; // class (cache flush: True, class: in)  response[ro  ] = 0x01;   response[ro  ] = 0x00; // ttl 2 minutes  response[ro  ] = 0x00;  response[ro  ] = 0x00;  response[ro  ] = 0x78;   response[ro  ] = 0x00; // length of address  response[ro  ] = 0x04;   response[ro  ] = WiFi.localIP()[0];  response[ro  ] = WiFi.localIP()[1];  response[ro  ] = WiFi.localIP()[2];  response[ro  ] = WiFi.localIP()[3];    udp.beginPacketMulticast(tgt_ip, tgt_port, WiFi.localIP(), 2);  udp.write(response, ro);  udp.endPacket();  } }  void setup() {  Serial.begin(115200);  Serial.println(F("Go!"));   pinMode(D0, OUTPUT);   WiFi.hostname(name);  WiFi.begin(ssid, pass);   static bool state = true;   while (WiFi.status() != WL_CONNECTED) {  delay(100);  Serial.print(F("."));   digitalWrite(D0, state);  state = !state;  }   digitalWrite(D0, false);   Serial.println(F(""));   Serial.print("IP address:t");  IPAddress myIP = WiFi.localIP();  Serial.println(myIP);   udp.beginMulticast(WiFi.localIP(), tgt_ip, 5353); }  void loop() {  update_mdns(); }  

pcap: https://vps001.vanheusden.com/~фолкерт/mdns.pcap

Ответ №1:

  1. флаги каждого RR были неверными. только A и SRV должны иметь чистый кэш
  2. имя хоста отсутствовало в записи SRV

С этим все еще есть проблема: rtpmidid сигнализирует о тайм-ау при разрешении имени хоста, но это не соответствует этому вопросу.