Arduino
Arduino copied to clipboard
mDNS not working with WiFi.mode(WIFI_AP_STA) on current git
Basic Infos
- [X] This issue complies with the issue POLICY doc.
- [X] I have read the documentation at readthedocs and the issue is not addressed there.
- [X] I have tested that the issue is present in current master branch (aka latest git).
- [X] I have searched the issue tracker for a similar issue.
- [ ] If there is a stack dump, I have decoded it.
- [ ] I have filled out all fields below.
Platform
- Hardware: [ESP-12]
- Core Version: [current]
- Development Env: [Arduino IDE]
- Operating System: [Windows]
Problem Description
mDNS not working with WiFi.mode(WIFI_AP_STA) on current git, but working on v2.4.7
MCVE Sketch
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
void setup(void) {
Serial.begin(115200);
WiFi.mode(WIFI_AP_STA);
WiFi.softAP("SETUP777685", "admin678");
MDNS.begin("TestMDNS");
MDNS.addService("http", "tcp", 80);
MDNS.addServiceTxt("http", "tcp", "type", "smartctrl");
MDNS.addServiceTxt("http", "tcp", "id", "777685");
}
void loop(void) {
MDNS.update();
}
Seems to be a logical error when IP isSet() is false for the STA interface. But, logs do show that it finds the AP netif, and attempts to send the data https://github.com/esp8266/Arduino/blob/9d024d17fd18dffa569fa646b5326b5e8f58b0d5/libraries/ESP8266mDNS/src/LEAmDNS_Transfer.cpp#L124-L149
Adding -DDEBUG_ESP_PORT=Serial -DDEBUG_ESP_MDNS_RESPONDER
and the small patch, udpcontext is finally able to send out the data for the AP:
[MDNSResponder] _writeMDNSAnswer_A ((IP unset))
[MDNSResponder] _sendMDNSMessage_Multicast: FAILED!
[MDNSResponder] _sendMDNSMessage: FAILED!
[MDNSResponder] _updateProbeStatus: FAILED!
...
never sends the data
...
@@ -128,6 +128,10 @@ bool MDNSResponder::_sendMDNSMessage_Multicast(MDNSResponder::stcMDNSSendParamet
IPAddress fromIPAddress;
//fromIPAddress = _getResponseMulticastInterface();
fromIPAddress = pNetIf->ip_addr;
+ if (!fromIPAddress.isSet()) {
+ continue;
+ }
+
m_pUDPContext->setMulticastInterface(fromIPAddress);
[MDNSResponder] _writeMDNSAnswer_A (192.168.4.1)
[MDNSResponder] _updateProbeStatus: Announcing service TestMDNS.http.tcp (1)
...
data can be seen with the network inspector / bonjour http app
...
(obviously, diff is not a fix! just exploring the code)
@hreintke and/or me updated this part of this code (to make it interface-agnostic).
Usually when netif_is_up()
is true, the interface has a valid address and IPAddress::isSet()
should be true.
However if this test solves the issue (that I could not reproduce) then such patch is welcome.
@hreintke What do you think ?
@mcspr @d-a-v Can't reproduce either.
But, logs do show that it finds the AP netif, and attempts to send the data
Can you provide your logs so I can (perhaps) check what is happening.
and the small patch, udpcontext is finally able to send out the data for the AP:
Do you say here :
- The esp is connected to both AP & STA.
- The STA interface has
!fromIPAddress.isSet()
- There is no sending of mdns traffic on the AP interface ?
@mcspr @d-a-v Can't reproduce either.
But, logs do show that it finds the AP netif, and attempts to send the data
Can you provide your logs so I can (perhaps) check what is happening.
and the small patch, udpcontext is finally able to send out the data for the AP:
Do you say here :
- The esp is connected to both AP & STA.
- The STA interface has
!fromIPAddress.isSet()
- There is no sending of mdns traffic on the AP interface ?
Adding UDP debug logs as well, there's an endless stream of -4 (ERR_RTE) from the underlying udp sender (softAP network is the default 192.168.4.0/24, transfer.cpp logs modified to point to the currently used netif & ips)
[MDNSResponder] _sendHostProbe (TestMDNS, 16111)
[MDNSResponder] _sendMDNSMessage_Multicast: Will send '192.168.4.1' -> '224.0.0.251' (netif ap timeout 50 port 5353).
[MDNSResponder] _prepareMDNSMessage
[MDNSResponder] _prepareMDNSMessage: ID:0 QR:0 OP:0 AA:0 TC:0 RD:0 RA:0 R:0 QD:1 AN:0 NS:1 AR:0
[MDNSResponder] _writeMDNSQuestion
[MDNSResponder] _writeMDNSAnswer_A (192.168.4.1)
[MDNSResponder] _sendMDNSMessage_Multicast: Will send '(IP unset)' -> '224.0.0.251' (netif st timeout 50 port 5353).
[MDNSResponder] _prepareMDNSMessage
[MDNSResponder] _prepareMDNSMessage: ID:0 QR:0 OP:0 AA:0 TC:0 RD:0 RA:0 R:0 QD:1 AN:0 NS:1 AR:0
[MDNSResponder] _writeMDNSQuestion
[MDNSResponder] _writeMDNSAnswer_A ((IP unset))
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
[MDNSResponder] _sendMDNSMessage_Multicast: FAILED! (netif st from '(IP unset)' to '224.0.0.251'
[MDNSResponder] _sendMDNSMessage: FAILED!
[MDNSResponder] _updateProbeStatus: FAILED!
... repeat ad infinitum ...
Modifying the example above and adding a WiFi.begin
to connect to something, it does work after STA interface receives IP (10.0.0.0/24 in the logs):
connected with TESTTESTTEST, channel 1
dhcp client start...
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
:ust rc=-4
[MDNSResponder] _sendMDNSMessage_Multicast: FAILED! (netif st from '(IP unset)' to '224.0.0.251'
[MDNSResponder] _sendMDNSMessage: FAILED!
[MDNSResponder] _updateProbeStatus: FAILED!
ip:10.0.0.130,mask:255.255.255.0,gw:10.0.0.1
.[MDNSResponder] _sendHostProbe (TestMDNS, 4865)
[MDNSResponder] _sendMDNSMessage_Multicast: Will send '192.168.4.1' -> '224.0.0.251' (netif ap timeout 50 port 5353).
[MDNSResponder] _prepareMDNSMessage
[MDNSResponder] _prepareMDNSMessage: ID:0 QR:0 OP:0 AA:0 TC:0 RD:0 RA:0 R:0 QD:1 AN:0 NS:1 AR:0
[MDNSResponder] _writeMDNSQuestion
[MDNSResponder] _writeMDNSAnswer_A (192.168.4.1)
[MDNSResponder] _sendMDNSMessage_Multicast: Will send '10.0.0.130' -> '224.0.0.251' (netif st timeout 50 port 5353).
[MDNSResponder] _prepareMDNSMessage
[MDNSResponder] _prepareMDNSMessage: ID:0 QR:0 OP:0 AA:0 TC:0 RD:0 RA:0 R:0 QD:1 AN:0 NS:1 AR:0
[MDNSResponder] _writeMDNSQuestion
[MDNSResponder] _writeMDNSAnswer_A (10.0.0.130)
[MDNSResponder] _updateProbeStatus: Did sent host probe
[MDNSResponder] _sendServiceProbe (TestMDNS.http.tcp, 4931)
[MDNSResponder] _sendMDNSMessage_Multicast: Will send '192.168.4.1' -> '224.0.0.251' (netif ap timeout 50 port 5353).
[MDNSResponder] _prepareMDNSMessage
[MDNSResponder] _prepareMDNSMessage: ID:0 QR:0 OP:0 AA:0 TC:0 RD:0 RA:0 R:0 QD:1 AN:0 NS:2 AR:2
[MDNSResponder] _writeMDNSQuestion
[MDNSResponder] _writeMDNSAnswer_PTR_NAME
[MDNSResponder] _writeMDNSAnswer_SRV
[MDNSResponder] _writeMDNSAnswer_TXT
[MDNSResponder] _writeMDNSAnswer_A (192.168.4.1)
[MDNSResponder] _sendMDNSMessage_Multicast: Will send '10.0.0.130' -> '224.0.0.251' (netif st timeout 50 port 5353).
[MDNSResponder] _prepareMDNSMessage
[MDNSResponder] _prepareMDNSMessage: ID:0 QR:0 OP:0 AA:0 TC:0 RD:0 RA:0 R:0 QD:1 AN:0 NS:2 AR:2
[MDNSResponder] _writeMDNSQuestion
[MDNSResponder] _writeMDNSAnswer_PTR_NAME
[MDNSResponder] _writeMDNSAnswer_SRV
[MDNSResponder] _writeMDNSAnswer_TXT
[MDNSResponder] _writeMDNSAnswer_A (10.0.0.130)
[MDNSResponder] _updateProbeStatus: Did sent service probe (1)
_sendMDNSMessage_Multicast: Will send '(IP unset)' -> '224.0.0.251' (netif st timeout 50 port 5353). ... :ust rc=-4
udp_sendto()
== -4 is lwIP's ERR_RTE / Routing Problem
All this seems consistent (cannot route from invalid address), except that the source address should not be unset when the interface is up. We are speaking of the STA interface (netif st
). Maybe AP doesn't work because of a side effect of the following m_pUDPContext->setMulticastInterface(fromIPAddress);
where fromIPAddress
is unset.
The reason why the flag NETIF_FLAG_UP
is up for the STA interface has yet to be understood, but your patch @mcspr seems to be OK to work the issue around for wherever it is coming from.
There is no sending of mdns traffic on the AP interface ?
Only queries going on
6643 1147.360615 192.168.4.1 224.0.0.251 MDNS 104 Standard query 0x0000 ANY TestMDNS.local, "QU" question A 192.168.4.1
... repeating ...
Unless the loop is blocked via isSet() check or STA is connected so the bResult finally returns true, it never gets to these A record and the http service responses.
2071 148.562197 192.168.4.1 224.0.0.251 MDNS 122 Standard query response 0x0000 A, cache flush 192.168.4.1 PTR, cache flush TestMDNS.local
2076 148.864304 192.168.4.1 224.0.0.251 MDNS 238 Standard query response 0x0000 PTR _http._tcp.local PTR TestMDNS._http._tcp.local SRV, cache flush 0 0 80 TestMDNS.local TXT, cache flush A, cache flush 192.168.4.1
The reason why the flag NETIF_FLAG_UP is up for the STA interface has yet to be understood, but your patch @mcspr seems to be OK to work the issue around for wherever it is coming from.
We do change opmode though, so we do expect both up and link-up? The gist of the issue seems to be with the initial probe result never succeeding from the mdns lib pov, so it never wants to do anything else until it does. And it does seem reasonable to help it out and filter the invalid netif instead of failing everything, will update with a PR
We do change opmode though, so we do expect both up and link-up?
There are two interface "up" flags: LINK_UP
and UP
.
Per doc, the answer to the question raised there which is how an interface can be in the state "LINK_UP" while not "UP" is that it can happen after a dhcp request and before the answer to it. The interface becomes "UP" when the IP address is assigned.
LINK_UP
should happen when there is power and the interface is enabled (WiFi) and/or a "cable" is wired.
So it is strange that the IP address above is unset. Reproducing this bug should allow to dig into lwip2's code and track this bug down (having in mind that lwip2 logic is quite sensitive for general stability). It is anyway good to add your workaround @mcspr.
@d-a-v I agree with you on the workaround. I will submit a PR (today or tomorrow) where I also include some debug print so we still can see it happen when debugging.
The gist of the issue seems to be with the initial probe result never succeeding from the mdns lib pov, so it never wants to do anything else until it does.
I'll check this. Not sending a request should trigger a timeout and keep mdns working.
@d-a-v Have some trouble with my dev environment. PR will come what later.
I have bumped into this exact issue. The clients cannot associate with the SoftAP interface as long as ESP8266 isn't connected to an access point.
The issue isn't there when the ESP8266 connects to an access point. In that case the SoftAP works as intended.
Submitted a PR to solve the infinite sending of host probes.
To be decided/handled : When STA is connected after MDNS,begin() there is no trigger from LwipIntf::stateUpCB -> No probing/announcing started.
Also noticed in https://savannah.nongnu.org/bugs/?37068 and the associated https://git.savannah.nongnu.org/cgit/lwip.git/commit/?id=4e520cdd3009cf2e04c50c173737b379ff7d72a2, it seems UP is totally ok state to be in during DHCP initialization.
State callback needs to happen on IP change instead, not the interface status? If I understood correctly, only way to have a cb is to use EXT
callbacks and wait up for LWIP_NSC_IPV4_ADDRESS_CHANGED
(notably, git-grep
ing the source, lwip mdns impl does exactly that:). otherwise, it is simply checking for not-ipv4-any as was suggested earlier)