MDNS failure

    local ip, port = '224.0.0.251', 5353
    local udp = socket.udp()
    assert(udp:setsockname(ip, port))
    assert(udp:setoption('reuseaddr', true))
    assert(udp:setoption("ip-add-membership", {multiaddr = ip, interface = "0.0.0.0"}), "join multicast group")
    assert(udp:settimeout(0))

discovery thread encountered error: [string “mdns”]:240: Failed to UDP bind on addr: Broker Script: UDP bind failed (224.0.0.251:5353): Io(Os { code: 98, kind: AddrInUse, message: “Address already in use” })

Hey, @veonua

To query the service, I recommend you tweak the order of configurations a little bit:

    local ip, port = '*', 0
    local data = '...'
    local udp = socket.udp()
    
    -- socket config
    -- in addition to your current configurations
    assert(udp:setsockname(ip, port))
    assert(udp:setoption('broadcast', true))

    -- broadcast
    assert(udp:sendto(data, '224.0.0.251', 5353)
    local res = assert(udp:receivefrom())

discovery thread encountered error: [string “mdns”]:247: join multicast group

it seems like it’s impossible to join ‘*’, 0 this group

You should have a smooth execution if you update the multiaddr param of your socket’s config pointing to the multicast address you previously had, e.g.

local mc_addr = '224.0.0.251'
local addr, port = '*', 0
local udp = socket.udp()
...
...
udp:setoption("ip-add-membership", {multiaddr = '224.0.0.251', interface = "0.0.0.0"})

Also, it would be awesome if you could share with the community what are you developing, since, we’ve only covered implementations for Edge LAN Devices on top of SSDP + HTTP or JSON RPC.

can you please give a full example? from what you posted parameters are not really clear.

I am trying to run lua-mdns/mdns.lua at master · JaredSartin/lua-mdns · GitHub

Interesting… so, by tweaking just a bit the socket configuration and using the mdns_make_query function, I was able to track the mDNS query via wireshark.
image

And the code is this simple:

-- [[
--  Borrowed from the library you referred
--  ]]
local function mdns_make_query(service)
    -- header: transaction id, flags, qdcount, ancount, nscount, nrcount
    local data = '\000\000'..'\000\000'..'\000\001'..'\000\000'..'\000\000'..'\000\000'
    -- question section: qname, qtype, qclass
    for n in service:gmatch('([^%.]+)') do
        data = data..string.char(#n)..n
    end
    return data..string.char(0)..'\000\012'..'\000\001'
end

-- [[
--  Opens the UDP socket to query the network
-- ]]
local function mdns_query()
  local socket = require 'socket'
  local udp = assert(socket.udp())
  local service = 'erickv'

  assert(udp:setsockname("*", 0))
  assert(udp:settimeout(0.1))
  assert(udp:setoption("ip-add-membership", {multiaddr = '224.0.0.251', interface = "0.0.0.0"}))

  -- broadcast query
  assert(udp:sendto(
    mdns_make_query(service),
    '224.0.0.251', 5353))
end

So, you should be able to use that library by updating the interface to "0.0.0.0" instead of just the wildcard char.

I can see the udp packet sent but no response received

    while (os.time() - start < timeout) do
        local data, peeraddr, peerport = udp:receivefrom()
        print('data:', data, 'peeraddr:', peeraddr, 'peerport:', peerport)
        if data and (peerport == port) then
            log.info('mdns', 'received response from '..peeraddr)
        end
    end

you can see just before my request hub sends another mdns request “_hue._tcp.local” with port 5353<>5353

and I suppose the HUE request has a higher priority than mine and it could intercept the responses directed to my driver.

1 Like

This may be happening because you might be missing a query param and your query is being ignored.

Just as a reference, I programmed a dummy mDNS service deployed at an esp8266 board and I was able to read the response params accordingly.

2021-11-24T19:45:26.519872641+00:00
    PRINT 2021-11-23
    Hello from esp8266    <<< payload
    192.168.1.73          <<< address
    5353                  <<< port

So, I recommend you to stick to the documentation of the service you’re trying to consume/contact.

what do you mean by query parameter?
as you can see in the previous message the response is there.

I am not sure which of the implementations you have implemented, from the documentation you can see there are two options for a request/response

unicast request > unicast response
multicast request > unicast response
multicast request > multicast response

the Xiaomi uses the last one. And it works with all the mdns apps on my network including Google Local SDK.

This thread was useful to me when doing my first UDP edge driver. I did see what I think is a mistake in the code - the setsockname call is made BEFORE the setoption of “reusaddr” - in my testing you must set options that affect binding BEFORE you use setsockname (and I presume before setpeername). In addition there is a note in the “known issues” (at the time of this writing) of the following:

Calls to tcp.bind or udp.setsockname may only specify port 0 to be assigned a port randomly, unless you are binding to a multicast IP address and have already set the reuseaddr socket option to true .

In order for this to work you would have to set the option before calling setsockname. Just posting this because this thread was so useful and using this and the “known issue” got my udp multicast to work.