cbrand / micropython-mdns

MDNS implementation for MicroPython with Service Discovery
MIT License
53 stars 12 forks source link

Not functioning on Pico W #5

Closed twitch0001 closed 2 years ago

twitch0001 commented 2 years ago

Hello! I'm currently trying to use this library with my Pico W to advertise its web server to the LAN. Unfortunately while trying to discover the device using Zeroconf and Android DNS-SD it seems that they both have issues with parsing the packets from the Pico.

I have compiled my own version of micropython in order to disable the MDNS port from being used and I have made several attempts to rewrite the serialisation code with no success (likely because of my limited DNS knowledge lol). I do understand this report is slightly ambiguous, therefore I have attached both the code I am using, and the debug logs from zeroconf while trying to discover the service to support any debugging of such issues

Pico W Code & Zeroconf Log: https://gist.github.com/twitch0001/801619733a543917a54ff9fdb7924d2a

I will attempt to provide more information as I debug this more :)

Many thanks, twitch

ZanderBrown commented 2 years ago

With avahi I see

server.c: Packet too short or invalid while reading response record. (Maybe a UTF-8 problem?)

Interestingly avahi can resolve the (blah.local) hostname, just can't list services

cbrand commented 2 years ago

I had the time to take a look into this and could reproduce the issue on my esp32. It seems that there is an issue with PTR record serialization which strangely enough works with wireshark and mdnsresponder but not with zeroconf and other tools.

The latest changes on the code base fixes the issue for me. I published the changes in version 1.2.0. It is a bit hacky but does the job both in Wireshark / MDNSResponder as well as zeroconf.

@twitch0001 can you test it with the newly published code to see if this fixes it for you too? @ZanderBrown please double check it on your end too

cbrand commented 2 years ago

@twitch0001 Needed to slightly adjust your example script for it to work for me to make the host name not changing on every request:

import network

import time
import socket
import uasyncio as asyncio
import usocket

from machine import Pin

from config import SSID, PASSWORD
from mdns_client import Client
from mdns_client.responder import Responder, generate_random_postfix

nic = network.WLAN(network.STA_IF)  # Client

nic.active(True)
nic.connect(SSID, PASSWORD)
while nic.isconnected() is False:
    time.sleep(0.5)

print("Connected to WIFI!")

async def serve_client(reader, writer):
    writer.write("HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n")
    writer.write("<h1>test response</h1>")
    await writer.drain()
    await writer.wait_closed()
    print("disconnected")

async def setup_mdns():
    local_ip = nic.ifconfig()[0]
    print(f"Setting up MDNS on local ip: {local_ip}")
    client = Client(local_ip)
    host = "pico-{}".format(generate_random_postfix())
    responder = Responder(
        client,
        own_ip=lambda: local_ip,
        host=lambda: host,
    )
    responder.debug = True
    responder.advertise("_myawesomeservice", "_tcp", port=1234)

async def run():
    await setup_mdns()
    await asyncio.create_task(asyncio.start_server(serve_client, "0.0.0.0", 1234)) # open port 1234 

    while True:
        await asyncio.sleep(3)

asyncio.run(run())
twitch0001 commented 2 years ago

Thank you very much! I can confirm after testing that the new version works perfectly, and zeroconf is able to recognise the responses from the Pico.

I appreciate the fix :)

ZanderBrown commented 2 years ago

With a freshly upip'd install on a clean device, I still see the same result

Connected to WIFI!
Setting up MDNS on local ip: 192.168.0.139
MDNS Responder: Answering service record query with services _myawesomeservice._tcp.local
MDNS Responder: Answering service record query with services _myawesomeservice._tcp.local
MDNS Responder: Answering service record query with services _myawesomeservice._tcp.local
MDNS Responder: Answering service record query with services _myawesomeservice._tcp.local
server.c: Packet too short or invalid while reading response record. (Maybe a UTF-8 problem?)
server.c: Packet too short or invalid while reading response record. (Maybe a UTF-8 problem?)
server.c: Packet too short or invalid while reading response record. (Maybe a UTF-8 problem?)
server.c: Packet too short or invalid while reading response record. (Maybe a UTF-8 problem?)
cbrand commented 2 years ago

Hm seems to be a different problem then. Let me create an own issue for this and close this issue.

ondrej1024 commented 1 year ago

I have compiled my own version of micropython in order to disable the MDNS port from being used

@twitch0001 How did you do that? What files need to be tweaked to disable the MDNS port in the MP Pico build? Thanks

ingles98 commented 1 year ago

I have compiled my own version of micropython in order to disable the MDNS port from being used

@twitch0001 How did you do that? What files need to be tweaked to disable the MDNS port in the MP Pico build? Thanks

same here, been trying to get this to work on my Pico as well...

ondrej1024 commented 1 year ago

I cannot find any documentation regarding mDNS and RPi Pico. Also there doesn't seem to be any reference to mDNS in the source code of the Pico version of MP.

I have also asked for information here but no answer yet. So need to continue digging for infos.

twitch0001 commented 1 year ago

While there is no documentation on MDNS for the RP2 build of micropython, the LWIP options for RP2 have set MDNS to enabled by default and this will bind to the MDNS port. Source here

The way I disabled this was to follow the micropython build instructions and edit that line to 0. However a better way of doing this is to use custom build configs and use those to build a version of micropython as seen here.

ondrej1024 commented 1 year ago

@twitch0001 : Thanks a lot for the info. Now I found the LWIP_MDNS_RESPONDER option. So setting this to 0 should free the MDNS port, which then allows to run themicropython-mdns service.

However it seems that the default setting of this option set to 1 just occupies the port but does not respond to any external MDNS requests. A port scan of the Pico does not reveal any open ports, an MDNS discovery does not find the Pico in the local network and a ping to {hostname}.local does not get a response. :roll_eyes:

twitch0001 commented 1 year ago

I believe that it is used for the network.hostname (which replaced the hostname kwarg in network.WLAN.config).

I've not tested whether this feature works on RP2 but yes, it will just bind to the port regardless of whether the hostname is set.

ingles98 commented 1 year ago

@twitch0001 : Thanks a lot for the info. Now I found the LWIP_MDNS_RESPONDER option. So setting this to 0 should free the MDNS port, which then allows to run themicropython-mdns service.

However it seems that the default setting of this option set to 1 just occupies the port but does not respond to any external MDNS requests. A port scan of the Pico does not reveal any open ports, an MDNS discovery does not find the Pico in the local network and a ping to {hostname}.local does not get a response. 🙄

I changed the port in the constants to something else, work for me as I am only trying to query and announce my Pico 's