ESP8266 nodemcu MDNS responder "not allowed"

after working fine for some time my "ping responder" has started failing to connect via mdns

could it be that my router is objecting to a frequent call to MDNS.update() ? or does anyone have any suggestions please?

06:30:17.507 -> 
06:30:17.507 -> connecting WiFiwwwwwwwwwwwwwwwwwwwwwwww connected.
06:30:19.959 -> mDNS responder started
06:30:21.444 -> not allowed 
06:30:21.444 -> 
06:30:21.949 -> not allowed 
06:30:21.949 -> 
06:30:22.444 -> not allowed 
06:30:22.444 -> 
06:30:22.926 -> 1: X on 
06:30:22.926 -> 
06:30:22.926 -> connecting WiFiwwwwwwwwwwwwwwwwwwwwwwww connected.
06:30:25.354 -> mDNS responder started
06:30:25.827 -> not allowed 

here is the code: the webpage tab only provides text for a simple web page.

/*
ping responder on NodeMCU ESp8266:   
wifi doesnt turn back on very quickly compared to esp32 "restart"
very quick response to ping to URL, sometimes slower via mdns
added simple static web page
NB some data pins will prevent upload if connected.
AMICA type needs pull-down on D8 to program
1p c/off c/o switch connected D5, D6
BLUE LED to ground on d7 via 1k:
ternary operator example:  largest = ((a > b) ? a : b);
*/

#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>       //support for multicast to assign name to ip address
#include <ESP8266WebServer.h>  //to create a web page response so a browser can see the unit
#include "creds.h"             // my wifi credentials
#include "webpage.h"           //simple web page to display

ESP8266WebServer server(80);  //create instance of server: need web page to give name on port scanner

constexpr int sX = D5;    //WiFi continuously on
constexpr int sY = D6;    //allow about 10% down time 30sec off 270 on
constexpr int bLED = D7;  //blue LED to show wifi state

bool oldX, newX;  //for checking / debouncing switches
bool oldY, newY;
bool changed;     // flags if switch state has changed
int swState = 0;  //state = sX + 2* sY;  state 0 - off; state 1: on; state 3 timed downtimes;
int oldState;
int wifiState = 0;
unsigned long previousMillis = 0;  // will store last time LED was updated
const long onTime = 270;            // wifi on time
const long offTime = 30;           // wifi off time (seconds)
long changeTime;

int readState() {  //read 2 way switch state
  newX = digitalRead(sX);
  newY = digitalRead(sY);
  swState = newX + 2 * newY;  //possible states are: XY 01, 11, 10
  return (swState);
}

void flashLed(int rate) {  //indicate wifi connecting
  digitalWrite(bLED, 1);
  delay(rate);
  digitalWrite(bLED, 0);
  delay(rate);
}

bool connectWiFi(int rate, String message) {  //this is deliberately blocking code.
  bool success = 0;
  WiFi.begin(ssid, password);
    Serial.print(message);
  while (WiFi.status() != WL_CONNECTED) {
    flashLed(rate);  //fast flash to show we are in the loop and trying to connect
     Serial.print("w");
  }
  success = 1;
Serial.println(" connected.");
  digitalWrite(bLED, 1);
  // Initialize mDNS
  if (!MDNS.begin("responder")) {
    Serial.println("Error setting up MDNS responder!");
  }
  Serial.println("mDNS responder started");
  return (success);
}

//Handles http request
void handleRoot() {
  String s = MAIN_page;
  server.send(200, "text/html", s);
}

void setup() {
  Serial.begin(115200);
  delay(5000);                                          //allow me time to clear serial monitor
  Serial.println("\n\n\n\n serial comms established");  //space after reset "junk"
  pinMode(sX, INPUT_PULLUP);
  pinMode(sY, INPUT_PULLUP);
  pinMode(bLED, OUTPUT);
  connectWiFi(200, "Connecting to WiFi network: ");
  Serial.print("Local IP: ");
  Serial.print(WiFi.localIP());
  Serial.print("  Signal strength (RSSI) : ");
  Serial.println(WiFi.RSSI());
  server.on("/", handleRoot);  //Associate handler function to path
  server.begin();              //Start server
  Serial.println("HTTP server started; setup complete");
  oldState = 1 + readState();  //force to process current switch state
}

void loop() {
  server.handleClient();
  MDNS.update();
  //read 2 way switch state
  swState = readState();
  changed = ((swState != oldState) ? 1 : 0);  //conditional ternary operator
  // if (swState != oldState) changed = 1;  else changed = 0;                                   
  //now handle the states
  switch (swState) {
    case 3:
      {
        if (changed) {
          Serial.println("3: both off");
          WiFi.disconnect();
          Serial.println("wifi disconnected");
          wifiState = 0;
          digitalWrite(bLED, 0);
        }
      }
      break;
    case 1:
      {
        if (changed) {
          Serial.println("1: X on \n");
          wifiState = connectWiFi(50, "connecting WiFi");
        }
      }
      break;
    case 2:
      {
        changeTime = (wifiState) ? (1000 * onTime) : (1000 * offTime);
        unsigned long currentMillis = millis();
        //Serial.printf("State 2: wifiState is: %i  changeTime is %i \n", wifiState, changeTime);
        if (currentMillis - previousMillis >= changeTime) {
          if (wifiState) {
            WiFi.disconnect();
            digitalWrite(bLED, 0);
            wifiState = 0;
          } else {
            wifiState = connectWiFi(50, "State 2: connecting WiFi");  //flash rate, message
          }
        previousMillis = currentMillis;
        }
      }
      break;
    default:
      {
        Serial.println("not allowed \n");
      }
  }
  oldState = swState;  //
  delay(500);          //no need to debounce the switch
}

Try calling MDNS.close() before MDNS.begin() to release the underlying UDP socket.

If I remember correctly (might be on an older core though), when you disconnect Wi-Fi, the mDNS responder thinks it’s still on and running and won’t start a new session.

Thanks @J-M-L I'm trying that now. No better.

Here is the record from my logging app when running 90%: - very consistent

IP address TALKTALKCC34C4 pinging target 192.168.1.23 Hourly data : Date, Time, %Uptime, Uptime, Downtime, DropOuts, Ping Deciles Q1, Q5 (average), Q9
25/06/2025	 01:00:00	     89 	 3092765 	 361012 	     12 	     31 	    105 	    188
25/06/2025	 02:00:01	     89 	 3097528 	 367007 	     12 	     29 	     97 	    190
25/06/2025	 03:00:05	     90 	 3129187 	 335009 	     12 	     28 	    102 	    194
25/06/2025	 04:00:04	     90 	 3113939 	 343006 	     12 	     28 	    107 	    200

and with "100%" selected, showing irregular %uptime and LOTS of drop outs

IP address TALKTALKCC34C4 pinging target 192.168.1.23 Hourly data : Date, Time, %Uptime, Uptime, Downtime, DropOuts, Ping Deciles Q1, Q5 (average), Q9
26/06/2025	 20:00:01	     92 	 2576959 	 207059 	     67 	     22 	     87 	    186
26/06/2025	 21:00:03	     95 	 2758541 	 130003 	     59 	     18 	     89 	    188
26/06/2025	 22:00:00	     85 	 2022569 	 348048 	    101 	     22 	     71 	    175

hum — looks like something’s off under load. This seems to indicate a network congestion or resource exhaustion either on the ESP8266 itself (CPU, RAM, Wi-Fi driver queue limits?) or in your Wi-Fi network’s multicast/broadcast handling under load.

Could you try logging a bit more from your Arduino code?

something like this (typed this roughly from memory so double-check the includes if needed).

add

extern "C" {
  #include "lwip/tcp.h"
  #include "lwip/udp.h"
}

and a function

void logStatus() {
  struct tcp_pcb *tcpPcb;
  struct udp_pcb *udpPcb;
  uint16_t tcpCount = 0;
  uint16_t udpCount = 0;

  for (tcpPcb = tcp_active_pcbs; tcpPcb != NULL; tcpPcb = tcpPcb->next) tcpCount++;
  for (udpPcb = udp_pcbs; udpPcb != NULL; udpPcb = udpPcb->next) udpCount++;

  Serial.printf("Active TCP connections: %d\n", tcpCount);
  Serial.printf("Active UDP sockets: %d\n", udpCount);
  Serial.printf("Free heap: %d bytes\n", ESP.getFreeHeap());
}

and in your loop add a call to logStatus() like every second.

may be you'll see some rogue sockets or heap issue if there is a memory leak.

(The ESP8266’s Wi-Fi and mDNS stacks were notoriously fragile under load - I don't use 8266 anymore and moved to ESP32s which I found more capable / stable)

Compilation error: 'tcp_active_pcbs' was not declared in this scope

sorry Jackson I'm not familiar with these libraries and googles made no sense to me.

Light Weight IP stack..
used in the cores..
esp8266 core..
lwip faq..

never toyed with a esp8266..
reboot routers, check firewalls..
if these are local computer names, could be a mast browser issue, dup name or mac..

good luck.. ~q

also not sure if it's there for esp8266..
maybe crank up the core debug level..

~q

Sorry, I’m just on my phone, so can’t check in details easily.
The includes are from the underlying TCP code.

the lwip tcp.h doesnt have an entry for
tcp_active_pcbs
presently I'm seeing this

2025/06/29 06:32:54: 3: both off
Active UDP sockets: 3
Free heap: 48936 bytes
wifi disconnected
2025/06/29 06:32:56: 1: X on 

Active UDP sockets: 2
Free heap: 50120 bytes

but it hasnt shown the "not allowed" as yet. Generating a log file.

I've been googling for this but not found anything that makes sense to me.

Surely the "not allowed" message that you refer to in the title is due to a digitalRead() of these two pins both yielding a LOW.:

and that is dependent on how the switch is wired/positioned.

It is not obvious from the supplied code how that relates to an mDNS issue as you appear to have concluded.

Well I'm hanging my head in shame! Of course you are right, just because the message followed the mDNS message doesnt mean that is the source.

However I cant understand how the disallowed state can occur. Here is the schematic, and a pic

  default:
      {
        Serial.println("not allowed \n");

Have you printed out the value of swState? Might not be 0, might be some other number that is not 1, 2, or 3, depending on how addition and multiplication of a bool variable is implemented.

Doubt it would be causing a problem, but it is very odd to be setting the value of the global variable swState in the readState() function, then using that for the return value of the function which is then saved into the same swState variable.

int readState() {  //read 2 way switch state
  newX = digitalRead(sX);
  newY = digitalRead(sY);
  swState = newX + 2 * newY;  //possible states are: XY 01, 11, 10
  return (swState);
}
  MDNS.update();
  //read 2 way switch state
  swState = readState();

The wiring looks OK from the picture assuming the black wire makes a good contact with ground and there are no shorts on the underside of the board.

You are using a int function readState() to return a global variable and the calling statement also sets the same global variable. It is odd but I don't think it is wrong but anyway this would be nicer:

instead of this:

 //read 2 way switch state
  swState = readState();

just this:

 //read 2 way switch state
 readState();

EDIT
as @david_2018 more or less said as I was busy typing this !

Are compiler warnings activated ?

@david_2018 @6v6gt I've changed the code to reflect what you have both said in regard to global & boolean variables. I checked the circuit and cant see ANY way that a code of 00 could occur. So maybe this error in the code.
Hopefully the new code for reading the switch state will be more robust - I've put it here to save you time looking, I'd appreciate your fedback

int readState() {  //read 2 way switch state
  int locState;
  bool newX = digitalRead(sX);
  bool newY = digitalRead(sY);
  locState = newY;  //possible states are: XY 01, 11, 10
  locState *= 2;
  locState += newX;
  return (locState);
}
/*
ping responder on NodeMCU ESp8266: switch on d2, BLUE LED to ground on d1 via 1k: needs pull-down on pin d8 or wont boot.
wifi doesnt turn back on very quickly compared to esp32 "restart"
very quick response to ping to URL, sometimes slower via mdns
added simple static web page
NB some data pins will prevent upload if connected.
AMICA type needs pull-down on D8 to program
1p c/off c/o switch connected D5, D6
ternary operator example:  largest = ((a > b) ? a : b);
*/

#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>       //support for multicast to assign name to ip address
#include <ESP8266WebServer.h>  //to create a web page response so a browser can see the unit
#include "creds.h"             // my wifi credentials
#include "webpage.h"           //simple web page to display

extern "C" {
#include "lwip/tcp.h"
#include "lwip/udp.h"
}


ESP8266WebServer server(80);  //create instance of server: need web page to give name on port scanner

constexpr int sX = D5;    //
constexpr int sY = D6;    //allow about 20% down time say 5 min intervals
constexpr int bLED = D7;  //blue LED to show wifi state

bool changed;     // flags if switch state has changed
int swState = 0;  //state = sX + 2* sY;  state 0 - off; state 1: on; state 3 timed downtimes;
int oldState;
int wifiState = 0;
unsigned long previousMillis = 0;  // will store last time LED was updated
const long onTime = 270;           // wifi on time
const long offTime = 30;           // wifi off time (seconds)
unsigned long changeTime;

int readState() {  //read 2 way switch state
  int locState;
  bool newX = digitalRead(sX);
  bool newY = digitalRead(sY);
  locState = newY;  //possible states are: XY 01, 11, 10
  locState *= 2;
  locState += newX;
  return (locState);
}

void flashLed(int rate) {  //indicate wifi connecting
  digitalWrite(bLED, 1);
  delay(rate);
  digitalWrite(bLED, 0);
  delay(rate);
}

bool connectWiFi(int rate, String message) {  //this is deliberately blocking code.
  bool success = 0;
  WiFi.begin(ssid, password);
  Serial.print(message);
  while (WiFi.status() != WL_CONNECTED) {
    flashLed(rate);  //fast flash to show we are in the loop and trying to connect
    Serial.print("w");
  }
  success = 1;
  Serial.println(" connected.");
  digitalWrite(bLED, 1);
  // Initialize mDNS
  MDNS.close();  //ensure to release the underlying UDP socket.
  if (!MDNS.begin("responder")) {
    Serial.println("Error setting up MDNS responder!");
  }
  Serial.println("mDNS responder started");
  return (success);
}

//Handles http request
void handleRoot() {
  String s = MAIN_page;
  server.send(200, "text/html", s);
}

void logStatus() {
  struct tcp_pcb *tcpPcb;
  struct udp_pcb *udpPcb;
  uint16_t tcpCount = 0;
  uint16_t udpCount = 0;
  //for (tcpPcb = tcp_active_pcbs; tcpPcb != NULL; tcpPcb = tcpPcb->next) tcpCount++;
  for (udpPcb = udp_pcbs; udpPcb != NULL; udpPcb = udpPcb->next) udpCount++;

  //Serial.printf("Active TCP connections: %d\n", tcpCount);
  Serial.printf("Active UDP sockets: %d\n", udpCount);
  Serial.printf("Free heap: %d bytes\n", ESP.getFreeHeap());
}

void setup() {
  Serial.begin(115200);
  delay(5000);                                          //allow me time to clear serial monitor
  Serial.println("\n\n\n\n serial comms established");  //space after reset "junk"
  pinMode(sX, INPUT_PULLUP);
  pinMode(sY, INPUT_PULLUP);
  pinMode(bLED, OUTPUT);
  connectWiFi(200, "Connecting to WiFi network: ");
  Serial.print("Local IP: ");
  Serial.print(WiFi.localIP());
  Serial.print("  Signal strength (RSSI) : ");
  Serial.println(WiFi.RSSI());
  server.on("/", handleRoot);  //Associate handler function to path
  server.begin();              //Start server
  Serial.println("HTTP server started; setup complete");
  oldState = 4;  //force to process current switch state - max is 3
}

void loop() {
  server.handleClient();
  MDNS.update();

  //read 2 way switch state
  swState = readState();
  //Serial.println(swState);

  changed = ((swState != oldState) ? 1 : 0);  //conditional ternary operator
  // if (swState != oldState) changed = 1;  else changed = 0;
  //now handle the states
  switch (swState) {
    case 3:
      {
        if (changed) {
          Serial.println("State 3 : both off, WiFI going down");
          logStatus();
          WiFi.disconnect();
          Serial.println("wifi disconnected");
          wifiState = 0;
          digitalWrite(bLED, 0);
        }
      }
      break;
    case 1:
      {
        if (changed) {
          Serial.println("State 1: X on \n");
          logStatus();
          wifiState = connectWiFi(200, "State 1: connecting WiFi: ");
        }
      }
      break;
    case 2:
      {
        changeTime = (wifiState) ? (1000 * onTime) : (1000 * offTime);
        unsigned long currentMillis = millis();
        //Serial.printf("State 2: wifiState is: %i  changeTime is %i \n", wifiState, changeTime);  //prints every second
        if (currentMillis - previousMillis >= changeTime) {
          logStatus();
          if (wifiState) {
            Serial.println("State 2: Interrupting connection to WiFi \n");
            WiFi.disconnect();
            digitalWrite(bLED, 0);
            wifiState = 0;
          } else {
            wifiState = connectWiFi(200, "State 2: connecting WiFi: ");  //flash rate, message
          }
          previousMillis = currentMillis;
        }
      }
      break;

    default:
      {
        Serial.println("Switch state 0 not allowed \n");
      }
  }
  oldState = swState;  //
  delay(1000);         //no need to debounce the switch
}

It looks OK to me but it is also difficult to understand why it failed previously based on your wiring and code. Some sort of code corruption, memory problem is also a possible explanation.

I'd update this part to give some more information.

 default:
      {
        Serial.print("Switch state not allowed = ");
        Serial.print( swState ) ;
        Serial.println( "\n" ) ;
      }