Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mDNS stops working after two minutes #4406

Closed
leifclaesson opened this issue Oct 10, 2020 · 28 comments
Closed

mDNS stops working after two minutes #4406

leifclaesson opened this issue Oct 10, 2020 · 28 comments

Comments

@leifclaesson
Copy link
Contributor

This issue has been previously posted by others but was erroneously closed as "stale" without resolution. It is still a problem.

Hardware:

Board: LOLIN32, MH-ET-LIVE, DOIT devkit v1 and others. Happens with all ESP32 hardware I've tested.
Core Installation version: 1.0.4
IDE name: Arduino IDE
Flash Frequency: 80Mhz
PSRAM enabled: no

Description:

I'm trying to use MDNS. Using the mDNS_Web_Server example, when the device starts, I am able to access the page at 'esp32.local/'. However, after two minutes, this stops working.

Manually resolving the mDNS address shows the same behavior - it works for the first two minutes after the device is started, then simply stops working.

I did a Wireshark capture on the IP address of the ESP32. It broadcasts the mDNS messages, with a TTL of 2 minutes. It only ever broadcasts those messages at startup (I left the device for ~20m).

If I manually call MDNS.begin periodically, it works, but the correct function for this is update() which is missing from the ESP32 version.

I was able to reproduce this on multiple dev boards, and several others have reported the same issue.

Sketch:

mDNS_Web_Server example (only modified to set the ssid/password)

Debug Messages:

None

@felmue
Copy link

felmue commented Oct 11, 2020

HI @leifclaesson

I am running the mDNS_Web_Server example on a ESP32_LyraT board and I can ping 'local.ESP32' after start and also after waiting for more than 2 minutes just fine. I wonder if it has something to do with the OS from which the ping is originated from. I am using MacOSX. What is the OS you are testing with?

BTW: I only very quickly looked into how mDNS is supposed to work, so I could be wrong about it. So far it is my understanding that the server only is supposed to send out it's mDNS information when a client asks for it, so I would not expect it to broadcast its information periodically on it's own (except for when it is started), but only upon request. That is why I think it might be related to the mDNS implementation of the OS used to ping the ESP32 board.

Thanks
Felix

@EricDuminil
Copy link

Hello.

For what it's worth, I can reproduce this behaviour with espressif8266.
Same sketch (mDNS_Web_Server example, only modified to set the ssid/password).
Compiling with Arduino IDE or pio doesn't seem to make any difference.
Here are my pio libs:

❯ pio update
Updating platformio/contrib-piohome           3.3.1 @ ~3.3.1                     [Up-to-date]
Updating platformio/tool-unity                1.20500.200612 @ ~1.20500.0        [Up-to-date]
Updating platformio/tool-scons                4.40001.0 @ ~4.40001.0             [Up-to-date]

Platform Manager
================
Platform atmelavr
--------
Updating platformio/atmelavr                  3.0.0                              [Up-to-date]
Updating platformio/toolchain-atmelavr        1.50400.190710 @ ~1.50400.0        [Up-to-date]
Updating platformio/framework-arduino-avr     5.1.0 @ ~5.1.0                     [Up-to-date]

Platform espressif8266
--------
Updating platformio/espressif8266             2.6.2                              [Up-to-date]
Updating platformio/toolchain-xtensa          2.40802.200502 @ ~2.40802.191122   [Up-to-date]
Updating platformio/framework-arduinoespressif8266 3.20704.0 @ ~3.20704.0             [Up-to-date]
Updating platformio/tool-esptool              1.413.0 @ <2                       [Up-to-date]
Updating platformio/tool-esptoolpy            1.20800.0 @ ~1.20800.0             [Up-to-date]
Updating platformio/tool-mkspiffs             1.200.0 @ ~1.200.0                 [Up-to-date]
Updating platformio/tool-mklittlefs           1.203.200522 @ ~1.203.0            [Up-to-date]

I can ping esp8266.local at first (both from Linux Mint 19.3 and OS X El Capitan), but after 2 minutes, it returns ping: esp8266.local: Name or service not known.

I wrote a small bash loop to time it. I start the loop, wait 10 seconds, start the board and let loop and board run:

❯ while sleep 10; do; date; ping -c1 -w3 -O -q esp8266.local | grep received; done
Sat Dec  5 12:43:45 CET 2020
ping: esp8266.local: Name or service not known
Sat Dec  5 12:44:00 CET 2020
1 packets transmitted, 1 received, 0% packet loss, time 0ms
Sat Dec  5 12:44:13 CET 2020
1 packets transmitted, 1 received, 0% packet loss, time 0ms
Sat Dec  5 12:44:23 CET 2020
1 packets transmitted, 1 received, 0% packet loss, time 0ms
Sat Dec  5 12:44:33 CET 2020
1 packets transmitted, 1 received, 0% packet loss, time 0ms
Sat Dec  5 12:44:43 CET 2020
1 packets transmitted, 1 received, 0% packet loss, time 0ms
Sat Dec  5 12:44:53 CET 2020
1 packets transmitted, 1 received, 0% packet loss, time 0ms
Sat Dec  5 12:45:03 CET 2020
1 packets transmitted, 1 received, 0% packet loss, time 0ms
Sat Dec  5 12:45:13 CET 2020
1 packets transmitted, 1 received, 0% packet loss, time 0ms
Sat Dec  5 12:45:23 CET 2020
1 packets transmitted, 1 received, 0% packet loss, time 0ms
Sat Dec  5 12:45:33 CET 2020
1 packets transmitted, 1 received, 0% packet loss, time 0ms
Sat Dec  5 12:45:43 CET 2020
1 packets transmitted, 1 received, 0% packet loss, time 0ms
Sat Dec  5 12:45:53 CET 2020
1 packets transmitted, 1 received, 0% packet loss, time 0ms
Sat Dec  5 12:46:03 CET 2020
1 packets transmitted, 1 received, 0% packet loss, time 0ms
Sat Dec  5 12:46:13 CET 2020
ping: esp8266.local: Name or service not known
Sat Dec  5 12:46:28 CET 2020
ping: esp8266.local: Name or service not known
Sat Dec  5 12:46:44 CET 2020
ping: esp8266.local: Name or service not known
Sat Dec  5 12:46:59 CET 2020
ping: esp8266.local: Name or service not known
Sat Dec  5 12:47:14 CET 2020

What's weird is that it might randomly start again after a while (2 or 3 minutes), without rebooting the board:

Sat Dec  5 12:47:59 CET 2020
ping: esp8266.local: Name or service not known
Sat Dec  5 12:48:14 CET 2020
ping: esp8266.local: Name or service not known
Sat Dec  5 12:48:29 CET 2020
ping: esp8266.local: Name or service not known
Sat Dec  5 12:48:44 CET 2020
1 packets transmitted, 1 received, 0% packet loss, time 0ms
Sat Dec  5 12:48:54 CET 2020
1 packets transmitted, 1 received, 0% packet loss, time 0ms
Sat Dec  5 12:49:04 CET 2020
1 packets transmitted, 1 received, 0% packet loss, time 0ms
Sat Dec  5 12:49:14 CET 2020
1 packets transmitted, 1 received, 0% packet loss, time 0ms
Sat Dec  5 12:49:24 CET 2020

It will stop again after exactly 2 minutes, though.

I realize my board isn't an esp32, but it seems to have the same problem as yours, though, so it might help spotting where the actual problem comes from.

@stale
Copy link

stale bot commented Feb 4, 2021

[STALE_SET] This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions.

@stale stale bot added the Status: Stale Issue is stale stage (outdated/stuck) label Feb 4, 2021
@mjcross
Copy link

mjcross commented Feb 17, 2021

Just doing some testing on this; will report back

@stale
Copy link

stale bot commented Feb 17, 2021

[STALE_CLR] This issue has been removed from the stale queue. Please ensure activity to keep it openin the future.

@stale stale bot removed the Status: Stale Issue is stale stage (outdated/stuck) label Feb 17, 2021
@mjcross
Copy link

mjcross commented Feb 17, 2021

OK I've made some checks with tcpdump.

I can confirm that with the mDNS server in the Espressif native framework (ESP-IDF v4.2), the same pattern of packets is sent.
At startup, after obtaining an IP address the ESP32 first broadcasts an mDNS query for the hostname it is about to use (with a TTL of 2 minutes). It does this three times.

If no other machine responds (which would indicate this hostname is already assigned to another machine), the ESP32 then broadcasts an mDNS response to its own query, advertising its IP address (with a TTL of 2 mins). It does this three times.

After this initial announcement I did not see the ESP32 send any further mDNS packets during the 30min period of my test - although it did continue to send periodic ARP broadcasts (which are not related to mDNS).

However unlike the OP, I do not lose the ability to resolve the hostname after the 2 minute period... indeed all the machines on my LAN were still able to resolve and ping the host four hours later.

Looking into this a little more closely, I can see that it is in fact my residential gateway (FritzBox 7530) that has cached the mDNS result for the ESP32, and is serving it to other local clients via the 'normal' DNS service on port 53.

@me-no-dev
Copy link
Member

I can agree with @mjcross here. If resolution stops after 2 minutes, that means that the client did not re-query to refresh the record and so made it invalid. Generally it should have asked for the host about 1 minute in (half the TTL).

The MDNS lib in IDF is fully compliant and much tested.

@mjcross
Copy link

mjcross commented Feb 18, 2021

If your application has long gaps between a client accessing the ESP32 via its mDNS hostname, then you might try getting the ESP32 to do an mDNS lookup of its own hostname using the resolve_mdns_host() API call every couple of minutes. This should keep the record 'fresh' in the cache of other machines on the LAN.

If that doesn't work then you might try periodically restarting the mDNS service on the ESP32 every couple of minutes using mdns_free() and mdns_init(), which should cause a re-broadcast of the initial mDNS registration.

@leifclaesson
Copy link
Contributor Author

try getting the ESP32 to do an mDNS lookup of its own hostname using the [resolve_mdns_host()](https://docs.espressif.com/projects/esp-
idf/en/latest/esp32/api-reference/protocols/mdns.html#mdns-query) API call every couple of minutes. This should keep the record 'fresh' in the cache of other machines on the LAN.

This is an interesting idea! I will try this. Thank you!

If that doesn't work then you might try periodically restarting the mDNS service on the ESP32 every couple of minutes using mdns_free() and mdns_init(), which should cause a re-broadcast of the initial mDNS registration.

That was actually the first thing I tried -- this causes the ESP to crash and reboot after ~25 hours. Took me quite a while to find why my many ESP32s had trouble staying up, because you don't immediately notice the problem after adding the periodic reinit.. so, that one is not a good solution.

@MythicalForce
Copy link

i have the exact same problem... googling my ass off trying to find a fix for this!

@khanhvu161188
Copy link

If your application has long gaps between a client accessing the ESP32 via its mDNS hostname, then you might try getting the ESP32 to do an mDNS lookup of its own hostname using the resolve_mdns_host() API call every couple of minutes. This should keep the record 'fresh' in the cache of other machines on the LAN.

I have tried but this approach does not work.

@avillacis
Copy link

Sorry if this comment is off-topic for this bug report.

At least in my case, using Arduino-ESP32 2.0.0-alpha1 with a Fedora 32 x86_64 workstation, I have verified (using Wireshark) that MDNS queries made using avahi-daemon from the Fedora machine are actually answered by the ESP32 device, but avahi-daemon rejects the response because it is considered "invalid" due to having an echoed question record in the response packet. The end result is that the device "drops out" from being locatable via MDNS.

I have opened a bug report here.

@stefat
Copy link

stefat commented Aug 31, 2021

exact same issue here with an MKR1010 SAMD 21 cpu using Mdns-generic library. Any clue ?

@nietaki
Copy link

nietaki commented Sep 21, 2021

It seems like a fix for this (or very similar) problem has been implemented in espressif/esp-idf#7453

Pardon my ignorance, but does that mean the fix is going to make it to arduino-esp32 at some point in time? Arduino-esp32 uses esp-IDF underneath, right?

Is the process for getting the latest and greatest a manual PR like this one? #5449

@me-no-dev
Copy link
Member

yes @nietaki . The latest IDF is available in that branch. We merge it into master from time to time

@nietaki
Copy link

nietaki commented Sep 22, 2021

Thanks for the info @me-no-dev 👍

deets added a commit to deets/beehive-monitor that referenced this issue Oct 11, 2021
This is described here:
espressif/arduino-esp32#4406

Otherwise we lose the MDNS listing after a couple of minutes.
@leifclaesson
Copy link
Contributor Author

FWIW, I stopped using mDNS completely, it was simply not reliable enough, and gets unwieldy when you have many devices. Getting rid of it saves firmware space too which can be crucial, especially on 1MB ESP8266 devices (such as smart light bulbs). I assign static IPs through my router instead.

@wachidsusilo
Copy link

wachidsusilo commented Dec 28, 2021

I am struggling on this issue as well. My android app cannot get answer from esp32 completely, while in Windows 10, the esp32 only answer for the first time after the esp32 has been rebooted. i've been monitoring wireshark all the time, i've seen that Windows did sent question to esp32, but the esp32 just didn't answer it.

Anyway, is there any third party library other than ESPmDNS?

@avillacis
Copy link

Just for the record, the original MDNS issue appears to be mostly fixed in ESP32-Arduino 2.0.2. Devices using firmware compiled with this version no longer drop out from being locatable via MDNS.

@nagyrobi
Copy link

nagyrobi commented Jul 3, 2022

@rradar

@renanrms
Copy link
Contributor

renanrms commented Apr 12, 2023

The header file of the MDNS lib (ESPmDNS.h) has a comment as the top of file that describes the usage. And there is this information:

"Call the update method in each iteration of the sketch's loop function."

I searched an update method but not found on this lib. Also i found a third part library (khoih-prog/MDNS_Generic), that have a method mdns.run(), what is called at each loop on the lib examples, and the examples have a comment informing that this line in necessary to work correctly.

I thinked some method called at each loop may be necessary to run the lib routines and repond to queries, but it apears to be missing on de lib. Some one else, notice this coment? Some sugestion?

PS: The ESP8266mDNS has the update method and the same comment. It is possibily a missing implementation on the ESPmDNS, I'm using.

PS2: Set the instance name on the loop, force the device to send again the response, but it is independent of any query. The ESP32 will always send again de response after call MDNS.setInstanceName(), what i think is ok in many cases.

@hitecSmartHome
Copy link

Same problem for me. MDNS stops working.
I'm on IDF 5.1 with Arduino 3x now and there is no run or update method in the ESPmDNS library.

  • No update function
  • No run function
  • No restart function
  • No internal task that runs periodically
/*
ESP8266 Multicast DNS (port of CC3000 Multicast DNS library)
Version 1.1
Copyright (c) 2013 Tony DiCola (tony@tonydicola.com)
ESP8266 port (c) 2015 Ivan Grokhotkov (ivan@esp8266.com)
MDNS-SD Suport 2015 Hristo Gochkov (hristo@espressif.com)
Extended MDNS-SD support 2016 Lars Englund (lars.englund@gmail.com)
Rewritten for ESP32 by Hristo Gochkov (hristo@espressif.com)

This is a simple implementation of multicast DNS query support for an Arduino
running on ESP32 chip. 

Usage:
- Include the ESP32 Multicast DNS library in the sketch.
- Call the begin method in the sketch's setup and provide a domain name (without
  the '.local' suffix, i.e. just provide 'foo' to resolve 'foo.local'), and the
  Adafruit CC3000 class instance.  Optionally provide a time to live (in seconds)
  for the DNS record--the default is 1 hour.
- Call the update method in each iteration of the sketch's loop function.

License (MIT license):
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:

  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE.

*/
#ifndef ESP32MDNS_H
#define ESP32MDNS_H

#include "Arduino.h"
#include "IPv6Address.h"
#include "mdns.h"

//this should be defined at build time
#ifndef ARDUINO_VARIANT
#define ARDUINO_VARIANT "esp32"
#endif

class MDNSResponder {
public:
  MDNSResponder();
  ~MDNSResponder();
  bool begin(const String& hostName);
  bool begin(const char* hostName){
    return begin(String(hostName));
  }
  void end();

  void setInstanceName(String name);
  void setInstanceName(const char * name){
    setInstanceName(String(name));
  }
  void setInstanceName(char * name){
    setInstanceName(String(name));
  }

  bool addService(char *service, char *proto, uint16_t port);
  bool addService(const char *service, const char *proto, uint16_t port){
    return addService((char *)service, (char *)proto, port);
  }
  bool addService(String service, String proto, uint16_t port){
    return addService(service.c_str(), proto.c_str(), port);
  }
  
  bool addServiceTxt(char *name, char *proto, char * key, char * value);
  void addServiceTxt(const char *name, const char *proto, const char *key,const char * value){
    addServiceTxt((char *)name, (char *)proto, (char *)key, (char *)value);
  }
  void addServiceTxt(String name, String proto, String key, String value){
    addServiceTxt(name.c_str(), proto.c_str(), key.c_str(), value.c_str());
  }

  void enableArduino(uint16_t port=3232, bool auth=false);
  void disableArduino();

  void enableWorkstation(esp_interface_t interface=ESP_IF_WIFI_STA);
  void disableWorkstation();

  IPAddress queryHost(char *host, uint32_t timeout=2000);
  IPAddress queryHost(const char *host, uint32_t timeout=2000){
    return queryHost((char *)host, timeout);
  }
  IPAddress queryHost(String host, uint32_t timeout=2000){
    return queryHost(host.c_str(), timeout);
  }
  
  int queryService(char *service, char *proto);
  int queryService(const char *service, const char *proto){
    return queryService((char *)service, (char *)proto);
  }
  int queryService(String service, String proto){
    return queryService(service.c_str(), proto.c_str());
  }

  String hostname(int idx);
  IPAddress IP(int idx);
  IPv6Address IPv6(int idx);
  uint16_t port(int idx);
  int numTxt(int idx);
  bool hasTxt(int idx, const char * key);
  String txt(int idx, const char * key);
  String txt(int idx, int txtIdx);
  String txtKey(int idx, int txtIdx);
  
private:
  String _hostname;
  mdns_result_t * results;
  mdns_result_t * _getResult(int idx);
  mdns_txt_item_t * _getResultTxt(int idx, int txtIdx);
};

extern MDNSResponder MDNS;

#endif //ESP32MDNS_H

@me-no-dev
Copy link
Member

mDNS runs on it's own. It monitors network interfaces and acts accordingly. I can also say that mDNS works just fine. If you see something else, this is result of your own environment (mDNS client used or else). The mDNS service in ESP-IDF is certified and is the main reason why things like Matter, HomeKit and others are able to work. One way to force mDNS to "restart" is by turning the interface off and on. It will issue unsolicited packets to inform others on the network that it exists. It sounds like your client is not asking about it after the TTL expired.

The "internal task" is in the esp-mdns code. Not in Arduino

@hitecSmartHome
Copy link

I see. What are the reasons that can stop it? The task does not get enough time?

@me-no-dev
Copy link
Member

There is no reason on the device itself. When interface is brought up, it broadcasts the device services. This is done unsolicited. From then on it's up to the client (your computer or whatever) to query the device. If the client heard the initial broadcast, it should add the device in it's list and provide the information until the TTL is half passed, after which point it should ask the device for update. What you see corresponds with the client not asking the device for update and only judging by the initial unsolicited broadcast, which after some time expires. Again, the service is fully automated and as long as the client obeys the rules, everything will be fine.

@me-no-dev
Copy link
Member

OK. there could be a few more reasons:

  • Your network is too busy and UDP packets are dropped
  • You have some device on the network that has bad implementation and transmits packets at the same time, leading to the condition above
  • You have some device that answers on the behalf of the ESP with wrong/old data

@hitecSmartHome
Copy link

I see. There is no way my client wont ask the esp. Iam running a web app right now and seeing the fetch requests made against the hostname in the browser over and over again. It stopped working no matter what device I try. Tried windows, IOS and Android. Ping requests also doesnt work against the hostname. I did not try via IP yet tho. Will try to trigger this again tomorrow and see what is going on. But the esp is definitely connected to the network because I see it in my routers list.

Can some conflict occour if i set up the ESPmdns directly and also with ArduinoOTA? I assume OTA lib also uses the same mdns apis.

@hitecSmartHome
Copy link

It can be that my router is acting funky.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

15 participants