brutella / dnssd Goto Github PK
View Code? Open in Web Editor NEWThis library implements Multicast DNS (mDNS) and DNS-Based Service Discovery (DNS-SD) for Zero Configuration Networking in Go.
License: MIT License
This library implements Multicast DNS (mDNS) and DNS-Based Service Discovery (DNS-SD) for Zero Configuration Networking in Go.
License: MIT License
github.com/brutella/dnssd v1.1.1
MacOS 10.14.6 (Mojave)
go version go1.14.1 darwin/amd64
I've been successfully using the library for some time, but in the last few days, my program has been crashing at unpredictable times with the following panic stack trace.
Here's how I start the responder:
cfg := dnssd.Config{
Name: serviceName,
Type: "_osc._udp",
Port: int(oscListenPort),
}
var service dnssd.Service
if service, err = dnssd.NewService(cfg); err != nil {
return
}
var responder dnssd.Responder
if responder, err = dnssd.NewResponder(); err != nil {
return
}
if _, err = responder.Add(service); err != nil {
return
}
go func() {
ctx, cancel := context.WithCancel(context.Background())
responderCancel = cancel
defer cancel()
if err = responder.Respond(ctx); err != nil {
return
}
}()
How can I help get more useful debugging info so you can help diagnose?
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x13a6946]
goroutine 3864 [running]:
github.com/brutella/dnssd.probeAtInterface(0x164fd40, 0xc001bb5880, 0x1650e40, 0xc0009cd440, 0xc00ad31670, 0xe, 0x158de5c, 0x9, 0x158c55e, 0x5, ...)
/Users/tynor/go/pkg/mod/github.com/brutella/[email protected]/probe.go:178 +0x8f6
github.com/brutella/dnssd.probe(0x164fd40, 0xc001bb5880, 0x1650e40, 0xc0009cd440, 0xc00ad31670, 0xe, 0x158de5c, 0x9, 0x158c55e, 0x5, ...)
/Users/tynor/go/pkg/mod/github.com/brutella/[email protected]/probe.go:114 +0x337
github.com/brutella/dnssd.probeService(0x164fd40, 0xc001bb5880, 0x1650e40, 0xc0009cd440, 0xc00ad31670, 0xe, 0x158de5c, 0x9, 0x158c55e, 0x5, ...)
/Users/tynor/go/pkg/mod/github.com/brutella/[email protected]/probe.go:61 +0x35b
github.com/brutella/dnssd.ReprobeService(0x164fd40, 0xc001bb5880, 0xc00ad31670, 0xe, 0x158de5c, 0x9, 0x158c55e, 0x5, 0xc001cf7c40, 0x37, ...)
/Users/tynor/go/pkg/mod/github.com/brutella/[email protected]/probe.go:49 +0x14c
github.com/brutella/dnssd.(*responder).reprobe(0xc00b050e80, 0xc000010b28)
/Users/tynor/go/pkg/mod/github.com/brutella/[email protected]/responder.go:348 +0x13b
created by github.com/brutella/dnssd.(*responder).respond
/Users/tynor/go/pkg/mod/github.com/brutella/[email protected]/responder.go:248 +0x474
I realized that the browsing query wasn't send on all my network interfaces, but multiple times on the same interface:
DEBUG 2021/01/29 11:05:39.304802 Send browsing query at docker0
DEBUG 2021/01/29 11:05:39.304884 Send browsing query at docker0
DEBUG 2021/01/29 11:05:39.304929 Send browsing query at veth8e256c1
DEBUG 2021/01/29 11:05:39.304990 Send browsing query at veth8e256c1
DEBUG 2021/01/29 11:05:39.305033 Send browsing query at vethb987ea9
The reason of this behaviour is because of Implicit memory aliasing in for loop
see here
Such issues can easily be found by a linter like golangci-lint.
Running the linter locally found more critical entries:
browse.go:60:31: G601: Implicit memory aliasing in for loop. (gosec)
q := &Query{msg: m, iface: &iface}
^
mdns.go:130:33: G601: Implicit memory aliasing in for loop. (gosec)
if err := connIPv4.JoinGroup(&iface, &net.UDPAddr{IP: IPv4LinkLocalMulticast}); err != nil {
^
mdns.go:146:33: G601: Implicit memory aliasing in for loop. (gosec)
if err := connIPv6.JoinGroup(&iface, &net.UDPAddr{IP: IPv6LinkLocalMulticast}); err != nil {
^
probe.go:33:7: G404: Use of weak random number generator (math/rand instead of crypto/rand) (gosec)
r := rand.New(rand.NewSource(time.Now().UnixNano()))
^
resolve.go:41:31: G601: Implicit memory aliasing in for loop. (gosec)
q := &Query{msg: m, iface: &iface}
^
responder.go:64:14: G404: Use of weak random number generator (math/rand instead of crypto/rand) (gosec)
random: rand.New(rand.NewSource(time.Now().UnixNano())),
^
I would like to fix the points and add the golangci-lint linter in the refactoring
branch. Are you fine with that?
The loopback network interface is currently ignored.
I tried the browse example to test out lookup of all services.
Using just _tcp
yields no results. Compare that to avahi-browse _tcp
wich yields a lot of results
./browse -Type _tcp
Browsing for _tcp.local.
DATE: –––Wed Mar 1 2023–––
16:08:35.855 ...STARTING...
Timestamp A/R if Domain Service Type Service Name
^C
However I get results with a broader query
./browse -Type _googlecast._tcp
Browsing for _googlecast._tcp.local.
DATE: –––Wed Mar 1 2023–––
16:09:43.070 ...STARTING...
Timestamp A/R if Domain Service Type Service Name
16:09:43.164 Add wlp0s20f3 local _googlecast._tcp Google-Nest-Mini-6147e2ff355612c5da0029f5a82002a2 ([192.168.1.26])
16:09:43.165 Add wlp0s20f3 local _googlecast._tcp M65Q7-H1-a4cbf4829ec90c72e9f4e42c2b2ca294 ([192.168.1.103])
^C
Attempting to create a simple service following the sample in HAP,
goroutine 7 [running]:
github.com/brutella/dnssd.(*Service).IPsAtInterface(0xc0000916b8, 0x0)
C:/Users/rober/go/pkg/mod/github.com/brutella/[email protected]/service.go:154 +0x3d
github.com/brutella/dnssd.A({{0xc0000299b0, 0xa}, {0x99a57d, 0x9}, {0x998f38, 0x5}, {0xc0000299c0, 0xc}, 0xc0001c2f00, 0x0, ...}, ...)
[signal C:/Users/rober/go/pkg/mod/github.com/brutella/[email protected]/dns.go:116 +0x39
github.com/brutella/dnssd.containsConflictingAnswers(0xc0002581f8, 0xc000006820)
C:/Users/rober/go/pkg/mod/github.com/brutella/[email protected]/responder.go:465 +0xbb
github.com/brutella/dnssd.findConflicts(0xc0002581f8, {0xc000208050, 0x1, 0x1?})
C:/Users/rober/go/pkg/mod/github.com/brutella/[email protected]/responder.go:446 +0x9b
github.com/brutella/dnssd.(*responder).handleRequest(0xc0001c4700, 0xc0002581f8)
C:/Users/rober/go/pkg/mod/github.com/brutella/[email protected]/responder.go:238 +0x195
github.com/brutella/dnssd.(*responder).respond(0xc0001c4700, {0xa3df30, 0xc0001d8300})
C:/Users/rober/go/pkg/mod/github.com/brutella/[email protected]/responder.go:203 +0x1d4
github.com/brutella/dnssd.(*responder).Respond(0xc0001c4700, {0xa3df30, 0xc0001d8300})
C:/Users/rober/go/pkg/mod/github.com/brutella/[email protected]/responder.go:113 +0x3ef
github.com/brutella/hap.(*Server).listenAndServe.func1()
C:/Users/rober/go/pkg/mod/github.com/brutella/[email protected]/server.go:205 +0x37
created by github.com/brutella/hap.(*Server).listenAndServe
C:/Users/rober/go/pkg/mod/github.com/brutella/[email protected]/server.go:204 +0x465
Process finished with the exit code 2
The HAP server announces correctly on DNSSD and no panic occurs.
Looking into this further, it's failing because the iface
parameter being passed to the A()
and AAAA()
is nil
which causes those functions to fail.
It's nil
because the implementation of payloadHandler.ReadFrom
which is used internally by mdnsConn.readInto
, doesn't set the cm
parameter (leaving it nil
), which the rest of the dnssd
stack fails to deal with correctly.
A()
and AAAA()
methods deal with a possibly nil
interface (iface
) argument.iface
parameter of the dnssd.request
struct from being nil
in the first place.I've tested the first of these two options and DNSSD then exhibits the correct behaviour (and I will submit an MR for this) however the second possible fix might be the better solution (though both can be implemented together to be suitable defensive).
For additional reference, my network configuration which exposes this issue is (Public IPs and MACs redacted):
Ethernet adapter Ethernet:
Connection-specific DNS Suffix . : xxxx.local
Description . . . . . . . . . . . : Intel(R) Ethernet Connection I217-V
Physical Address. . . . . . . . . : XX-XX-XX-XX-XX-XX
DHCP Enabled. . . . . . . . . . . : Yes
Autoconfiguration Enabled . . . . : Yes
IPv6 Address. . . . . . . . . . . : xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx(Preferred)
Temporary IPv6 Address. . . . . . : xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx(Deprecated)
Temporary IPv6 Address. . . . . . : xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx(Preferred)
Link-local IPv6 Address . . . . . : xxxx::xxxx:xxxx:xxxx:xxxx%X(Preferred)
IPv4 Address. . . . . . . . . . . : 10.4.1.2(Preferred)
Subnet Mask . . . . . . . . . . . : 255.255.0.0
Lease Obtained. . . . . . . . . . : 14 May 2022 08:20:32
Lease Expires . . . . . . . . . . : 16 May 2022 11:01:35
Default Gateway . . . . . . . . . : xxxx::xxxx:xxxx:xxxx:xxxx%X
10.4.0.1
DHCP Server . . . . . . . . . . . : 10.4.0.1
DHCPv6 IAID . . . . . . . . . . . : 213671924
DHCPv6 Client DUID. . . . . . . . : XX-XX-XX-XX-XX-XX-XX-XX-XX-XX-XX-XX-XX-XX
DNS Servers . . . . . . . . . . . : 10.4.0.1
Primary WINS Server . . . . . . . : 10.4.1.1
NetBIOS over Tcpip. . . . . . . . : Enabled
Unknown adapter Private Internet Access:
Media State . . . . . . . . . . . : Media disconnected
Connection-specific DNS Suffix . :
Description . . . . . . . . . . . : Private Internet Access Network Adapter
Physical Address. . . . . . . . . : XX-XX-XX-XX-XX-XX
DHCP Enabled. . . . . . . . . . . : Yes
Autoconfiguration Enabled . . . . : Yes
Wireless LAN adapter WiFi:
Media State . . . . . . . . . . . : Media disconnected
Connection-specific DNS Suffix . : xxxx.local
Description . . . . . . . . . . . : Broadcom 802.11ac Network Adapter
Physical Address. . . . . . . . . : XX-XX-XX-XX-XX-XX
DHCP Enabled. . . . . . . . . . . : Yes
Autoconfiguration Enabled . . . . : Yes
Wireless LAN adapter Local Area Connection* 1:
Media State . . . . . . . . . . . : Media disconnected
Connection-specific DNS Suffix . :
Description . . . . . . . . . . . : Microsoft Wi-Fi Direct Virtual Adapter
Physical Address. . . . . . . . . : XX-XX-XX-XX-XX-XX
DHCP Enabled. . . . . . . . . . . : Yes
Autoconfiguration Enabled . . . . : Yes
Wireless LAN adapter Local Area Connection* 2:
Media State . . . . . . . . . . . : Media disconnected
Connection-specific DNS Suffix . :
Description . . . . . . . . . . . : Microsoft Wi-Fi Direct Virtual Adapter #2
Physical Address. . . . . . . . . : XX-XX-XX-XX-XX-XX
DHCP Enabled. . . . . . . . . . . : No
Autoconfiguration Enabled . . . . : Yes
Ethernet adapter Bluetooth Network Connection:
Media State . . . . . . . . . . . : Media disconnected
Connection-specific DNS Suffix . :
Description . . . . . . . . . . . : Bluetooth Device (Personal Area Network)
Physical Address. . . . . . . . . : XX-XX-XX-XX-XX-XX
DHCP Enabled. . . . . . . . . . . : Yes
Autoconfiguration Enabled . . . . : Yes
Ethernet adapter vEthernet (WSL):
Connection-specific DNS Suffix . :
Description . . . . . . . . . . . : Hyper-V Virtual Ethernet Adapter
Physical Address. . . . . . . . . : XX-XX-XX-XX-XX-XX
DHCP Enabled. . . . . . . . . . . : No
Autoconfiguration Enabled . . . . : Yes
Link-local IPv6 Address . . . . . : xxxx::xxxx:xxxx:xxxx:xxxx%X(Preferred)
IPv4 Address. . . . . . . . . . . : 172.29.112.1(Preferred)
Subnet Mask . . . . . . . . . . . : 255.255.240.0
Default Gateway . . . . . . . . . :
DHCPv6 IAID . . . . . . . . . . . : 721425757
DHCPv6 Client DUID. . . . . . . . : XX-XX-XX-XX-XX-XX-XX-XX-XX-XX-XX-XX-XX-XX
NetBIOS over Tcpip. . . . . . . . : Enabled
I use this package to manage some hardware , my source is her https://github.com/ErwanMAS/godfrey4home/blob/master/src/homekit-switch.go .
After registration , and a long time .
When i restart , the bridge , my iphone can not reconnect to the hk bridge .
I ran some tcpdump on 5353 , and i saw that the phone always made a query on _hap._tcp.local. PTR .
The mdns hc bridge provide by /brutella/hc/ , does not reply , with a answer .
If i comment this line , i have what i think the good behavior, the bridge reply with a response to himself .
Line 437 in 61d1bc6
I think the object req.msg.Answer , must not store answers from his own local services .
I am trying to update my code to use the new 1.2.0 version of the library (was using 1.1.1). browse.go
has changed to use BrowseEntry
's instead of Service
objects. I can't find a way to get the Hostname and Port of the browsed service in my addFunc
. None of the relevant example cmd programs (e.g., cmd/browse
, cmd/resolve
) appear to print hostname or port for the discovered services.
Help?
I'm using dnssd in a project of mine and I run my tests with the race detector. This surfaced a race in dnssd:
==================
WARNING: DATA RACE
Write at 0x00c00029e0b7 by goroutine 31:
github.com/brutella/dnssd.(*mdnsConn).readInto.func3()
/home/daenney/Development/go/pkg/mod/github.com/brutella/[email protected]/mdns.go:260 +0x63
Previous read at 0x00c00029e0b7 by goroutine 29:
github.com/brutella/dnssd.(*mdnsConn).readInto.func1()
/home/daenney/Development/go/pkg/mod/github.com/brutella/[email protected]/mdns.go:188 +0x7f
Goroutine 31 (running) created at:
github.com/brutella/dnssd.(*mdnsConn).readInto()
/home/daenney/Development/go/pkg/mod/github.com/brutella/[email protected]/mdns.go:258 +0xc7
github.com/brutella/dnssd.(*mdnsConn).Drain()
/home/daenney/Development/go/pkg/mod/github.com/brutella/[email protected]/mdns.go:178 +0x1e3
github.com/brutella/dnssd.probeAtInterface()
/home/daenney/Development/go/pkg/mod/github.com/brutella/[email protected]/probe.go:163 +0x9fa
github.com/brutella/dnssd.probe()
/home/daenney/Development/go/pkg/mod/github.com/brutella/[email protected]/probe.go:114 +0x441
github.com/brutella/dnssd.probeService()
/home/daenney/Development/go/pkg/mod/github.com/brutella/[email protected]/probe.go:61 +0x3ae
github.com/brutella/dnssd.ProbeService()
/home/daenney/Development/go/pkg/mod/github.com/brutella/[email protected]/probe.go:38 +0x43d
github.com/brutella/dnssd.(*responder).register()
/home/daenney/Development/go/pkg/mod/github.com/brutella/[email protected]/responder.go:185 +0x481
github.com/brutella/dnssd.(*responder).Respond()
/home/daenney/Development/go/pkg/mod/github.com/brutella/[email protected]/responder.go:104 +0x20b
github.com/hemtjanst/fargton/bridge.(*Server).Start.func4()
/home/daenney/Development/github.com/hemtjanst/fargton/bridge/server.go:226 +0x6e
Goroutine 29 (running) created at:
github.com/brutella/dnssd.(*mdnsConn).readInto()
/home/daenney/Development/go/pkg/mod/github.com/brutella/[email protected]/mdns.go:185 +0x13a
github.com/brutella/dnssd.(*mdnsConn).Drain()
/home/daenney/Development/go/pkg/mod/github.com/brutella/[email protected]/mdns.go:178 +0x1e3
github.com/brutella/dnssd.probeAtInterface()
/home/daenney/Development/go/pkg/mod/github.com/brutella/[email protected]/probe.go:163 +0x9fa
github.com/brutella/dnssd.probe()
/home/daenney/Development/go/pkg/mod/github.com/brutella/[email protected]/probe.go:114 +0x441
github.com/brutella/dnssd.probeService()
/home/daenney/Development/go/pkg/mod/github.com/brutella/[email protected]/probe.go:61 +0x3ae
github.com/brutella/dnssd.ProbeService()
/home/daenney/Development/go/pkg/mod/github.com/brutella/[email protected]/probe.go:38 +0x43d
github.com/brutella/dnssd.(*responder).register()
/home/daenney/Development/go/pkg/mod/github.com/brutella/[email protected]/responder.go:185 +0x481
github.com/brutella/dnssd.(*responder).Respond()
/home/daenney/Development/go/pkg/mod/github.com/brutella/[email protected]/responder.go:104 +0x20b
github.com/hemtjanst/fargton/bridge.(*Server).Start.func4()
/home/daenney/Development/github.com/hemtjanst/fargton/bridge/server.go:226 +0x6e
==================
This happens b/c the isReading
var in readInto
needs a lock around it to ensure it can safely be modified.
linux% go get github.com/brutella/hklight
linux% $GOPATH/bin/hklight
The service appears, but after two minutes, is removed:
osx% dns-sd -B _hap._tcp
Browsing for _hap._tcp
DATE: ---Wed 22 Nov 2017---
21:57:49.094 ...STARTING...
Timestamp A/R Flags if Domain Service Type Instance Name
21:57:49.095 Add 2 5 local. _hap._tcp. Personal_Light_Bulb
21:59:47.216 Rmv 0 5 local. _hap._tcp. Personal_Light_Bulb
If you run tcpdump and run browse.go
,
you can see lookup packets but no answer.
osx% tcpdump -n -p -v -i en4 port 5353
osx% go get -d github.com/brutella/dnssd
osx% cd $GOPATH/src/github.com/brutella/dnssd/_cmd
osx% go run browse.go
tcpdump: listening on en4, link-type EN10MB (Ethernet), capture size 262144 bytes
22:00:27.957981 IP (tos 0x0, ttl 1, id 7291, offset 0, flags [none], proto UDP (17), length 61)
192.168.1.40.5353 > 224.0.0.251.5353: 0 PTR (QM)? _hap._tcp.local. (33)
Hi, I've contributed to oleksandr/bonjour and it's fork grandcat/zeroconf in the past. Happy to see another dnssd library with a clean approach and conformance tests.
Does dnssd support known-answer suppression? I added it to grandcat/zeroconf earlier this year after noticing a lot of unnecessary bonjour traffic on the network.
I am using your hc project in my choria.io project to do some IoT work and really loving it.
Unfortunately though due to this line:
Line 46 in 5bf037f
Even when hc
is not enabled a mdns listener is started and active and talking to the network, this is not desired as I tend to run my software on very large server estates - 10s of thousands of nodes - all of them joining mDNS is a bit of a surprise :) I'd like to enable it only when configured to be enabled.
Investigating further I cannot see anywhere where this DefaultResponder
is used in hc
or dnssd
, would it be possible to either remove this line if its unused or turn it into something thats lazy started only when needed?
I can send a PR with your guidance @brutella
thanks
Unfortunately setting a control message is not supported for windows, see here: https://github.com/golang/net/blob/master/ipv6/control_windows.go
So a Request
struct will never have a iface
. It will always be nil
:
Line 222 in 0d9d12f
This leads to a nil pointer exception at:
Line 72 in 0d9d12f
And it will never notify about any service because the ifaceIPs
dictionary is always empty for windows:
Line 79 in 0d9d12f
Hello,
First of all thank you for the library.
I had couple of issues:
How can I publish service on selected interface only? Providing config.Ifaces
seems not working.
Here is the testing code:
package main
import (
"context"
"fmt"
"os"
"os/signal"
"time"
slog "log"
"github.com/brutella/dnssd"
)
func main() {
// log.Debug.Enable()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go startDNSSDServer(ctx)
time.Sleep(time.Second)
go queryDNSSD(ctx)
go func() {
stop := make(chan os.Signal, 1)
signal.Notify(stop, os.Interrupt)
select {
case <-stop:
cancel()
}
}()
<-ctx.Done()
}
func queryDNSSD(ctx context.Context) {
service := "_service_type._tcp.local."
slog.Printf("Lookup %s\n", service)
addFn := func(e dnssd.BrowseEntry) {
slog.Printf(
"%s can be reached at %s %v\n",
e.ServiceInstanceName(),
e.IPs,
e.Text)
}
if err := dnssd.LookupType(ctx, service, addFn, func(dnssd.BrowseEntry) {}); err != nil {
fmt.Println(err)
return
}
}
func startDNSSDServer(ctx context.Context) {
txtRecord := map[string]string{
"txtvers": "1",
"data": "some-data",
}
config := dnssd.Config{
Name: "my_service",
Type: "_service_type._tcp",
Domain: "local",
Port: 1337,
Text: txtRecord,
Ifaces: []string{"en0"},
// IPs: []net.IP{net.ParseIP("192.168.228.92")},
}
service, err := dnssd.NewService(config)
if err != nil {
slog.Fatal(err)
}
responder, err := dnssd.NewResponder()
if err != nil {
slog.Fatal(err)
}
_, err = responder.Add(service)
if err != nil {
slog.Fatal(err)
}
slog.Println("Starting dnssd server")
err = responder.Respond(ctx)
if err != nil {
slog.Fatal(err)
}
}
This outputs:
$ go run main.go
2022/04/01 12:21:33 Starting dnssd server
2022/04/01 12:21:34 Lookup _service_type._tcp.local.
2022/04/01 12:21:34 my_service._service_type._tcp.local. can be reached at [127.0.0.1 ::1 fe80::1] map[data:some-data txtvers:1]
2022/04/01 12:21:34 my_service._service_type._tcp.local. can be reached at [192.168.228.92 fe80::107e:be39:9b23:64e5] map[data:some-data txtvers:1]
2022/04/01 12:21:34 my_service._service_type._tcp.local. can be reached at [fe80::f483:f4ff:fe0f:6312] map[data:some-data txtvers:1]
2022/04/01 12:21:34 my_service._service_type._tcp.local. can be reached at [fe80::278d:3c6:4662:f2b2] map[data:some-data txtvers:1]
2022/04/01 12:21:34 my_service._service_type._tcp.local. can be reached at [fe80::503:1e69:3b2e:b7a4] map[data:some-data txtvers:1]
As you can see from output, it includes multiple interfaces.
Second issue I had is related to TXT records. In the same file if you remove time.Sleep()
before querying data, the results do not include TXT record. Might be related to #16.
Output:
$ go run main.go
2022/04/01 12:29:14 Lookup _service_type._tcp.local.
2022/04/01 12:29:14 Starting dnssd server
2022/04/01 12:29:14 my_service._service_type._tcp.local. can be reached at [192.168.228.92 fe80::107e:be39:9b23:64e5] map[]
2022/04/01 12:29:14 my_service._service_type._tcp.local. can be reached at [127.0.0.1 ::1 fe80::1] map[data:some-data txtvers:1]
2022/04/01 12:29:15 my_service._service_type._tcp.local. can be reached at [fe80::f483:f4ff:fe0f:6312] map[data:some-data txtvers:1]
2022/04/01 12:29:15 my_service._service_type._tcp.local. can be reached at [fe80::278d:3c6:4662:f2b2] map[data:some-data txtvers:1]
2022/04/01 12:29:15 my_service._service_type._tcp.local. can be reached at [fe80::503:1e69:3b2e:b7a4] map[data:some-data txtvers:1]
Registering a service with a fixed IP address might not work as expected because the IP address is announced on all multicast network interfaces. But the IP address might not be accessible from all network interfaces.
Instead a fixed IP address should be specified for a specific network interface.
Is this expected behavior ?
Edit: When i run cmd/register on another device then this service is detected by cmd/browse
I am see periodic high cpu usage of my HimeKit app and I am try to detect what wrong.
As show pprof/profile
info - 36% cpu time spend on call net.InterfaceByIndex():
As I am see from sources https://github.com/brutella/dnssd/blob/master/mdns.go#L233 - net.InterfaceByIndex() called on each udp packet received.
May be cache interfaces info instead of get this info from system on every incoming udp packet?
Sometimes DHCP or manual changes can cause a computer's IP address to change. It looks like dnssd currently caches the IPs in the Service's IfaceIPs. This means the incorrect IP will be included in mdns responses.
Services should be renounced after a new network interface is active.
Currently there is no way to tell if a network interface is operational.
net.FlagUp
only tells that a network interface is configured and up.
Also a network interface can have a valid IP address even though for example no ethernet cable is attached.
Wait until net.FlagRunning
is added to Go.
golang/go#29991
Unicast responses are not received when listing to the multicast link local address.
Thanks for your great work with this project.
We are currently facing the issue that for IPv6 link local the interface name is needed to establish a connection.
You implemented this feature in your refactoring
branch along with other fixes like e45ff4e.
Now i wonder if there is a reason why the branch was not merged into master. On a first glance it works stable. Are there some open issues? Do you think the refactoring
branch can be used in production?
I'm using this patch to be able to set a hostname for the register
example:
diff --git a/_cmd/register.go b/_cmd/register.go
index d866c64..9d49ad3 100644
--- a/_cmd/register.go
+++ b/_cmd/register.go
@@ -15,6 +15,7 @@ import (
var instanceFlag = flag.String("Name", "Service", "Service name")
var serviceFlag = flag.String("Type", "_asdf._tcp.", "Service type")
var domainFlag = flag.String("Domain", "local.", "domain")
+var hostFlag = flag.String("Host", "", "hostname")
var portFlag = flag.Int("Port", 12345, "Port")
var timeFormat = "15:04:05.000"
@@ -39,7 +40,7 @@ func main() {
if resp, err := dnssd.NewResponder(); err != nil {
fmt.Println(err)
} else {
- srv := dnssd.NewService(*instanceFlag, *serviceFlag, *domainFlag, "", nil, *portFlag)
+ srv := dnssd.NewService(*instanceFlag, *serviceFlag, *domainFlag, *hostFlag, nil, *portFlag)
go func() {
stop := make(chan os.Signal, 1)
If I don't specify a hostname, everything works as expected:
./register 2>&1 | grep -v DEBUG 130 ↵
Registering Service Service._asdf._tcp.local. port 12345
DATE: –––Thu Mar 22 2018–––
18:20:53.110 ...STARTING...
;; flags:; QUERY: 2, ANSWER: 0, AUTHORITY: 2, ADDITIONAL: 0
;; QUESTION SECTION:
;Service._asdf._tcp.local. CLASS32769 ANY
;tmm1-imac.local. CLASS32769 ANY
;; AUTHORITY SECTION:
Service._asdf._tcp.local. 120 IN SRV 0 0 12345 tmm1-imac.local.
tmm1-imac.local. 120 IN A 10.0.1.240
;; flags:; QUERY: 2, ANSWER: 0, AUTHORITY: 2, ADDITIONAL: 0
;; QUESTION SECTION:
;Service._asdf._tcp.local. CLASS32769 ANY
;tmm1-imac.local. CLASS32769 ANY
;; AUTHORITY SECTION:
Service._asdf._tcp.local. 120 IN SRV 0 0 12345 tmm1-imac.local.
tmm1-imac.local. 120 IN A 10.0.1.240
;; flags:; QUERY: 2, ANSWER: 0, AUTHORITY: 2, ADDITIONAL: 0
;; QUESTION SECTION:
;Service._asdf._tcp.local. CLASS32769 ANY
;tmm1-imac.local. CLASS32769 ANY
;; AUTHORITY SECTION:
Service._asdf._tcp.local. 120 IN SRV 0 0 12345 tmm1-imac.local.
tmm1-imac.local. 120 IN A 10.0.1.240
18:20:53.987 Got a reply for service Service._asdf._tcp.local.: Name now registered and active
But if I pass in a hostname, it appends a number to the end and keep incrementing it forever:
Registering Service Service._asdf._tcp.local. port 12345
DATE: –––Thu Mar 22 2018–––
18:21:09.860 ...STARTING...
;; flags:; QUERY: 2, ANSWER: 0, AUTHORITY: 7, ADDITIONAL: 0
;; QUESTION SECTION:
;Service._asdf._tcp.local. CLASS32769 ANY
;unknown.local. CLASS32769 ANY
;; AUTHORITY SECTION:
Service._asdf._tcp.local. 120 IN SRV 0 0 12345 unknown.local.
unknown.local. 120 IN A 10.0.1.240
unknown.local. 120 IN AAAA fe80::2b8:2527:4334:98b4
unknown.local. 120 IN AAAA fe80::4aa:883:df8b:110c
unknown.local. 120 IN AAAA fe80::d8d2:50ff:fea2:33f8
unknown.local. 120 IN AAAA fe80::cfa4:720:c5b6:d2f4
unknown.local. 120 IN AAAA fe80::121a:1fda:9977:8b89
;; flags:; QUERY: 2, ANSWER: 0, AUTHORITY: 7, ADDITIONAL: 0
;; QUESTION SECTION:
;Service._asdf._tcp.local. CLASS32769 ANY
;unknown.local. CLASS32769 ANY
;; AUTHORITY SECTION:
Service._asdf._tcp.local. 120 IN SRV 0 0 12345 unknown.local.
unknown.local. 120 IN A 10.0.1.240
unknown.local. 120 IN AAAA fe80::2b8:2527:4334:98b4
unknown.local. 120 IN AAAA fe80::4aa:883:df8b:110c
unknown.local. 120 IN AAAA fe80::d8d2:50ff:fea2:33f8
unknown.local. 120 IN AAAA fe80::cfa4:720:c5b6:d2f4
unknown.local. 120 IN AAAA fe80::121a:1fda:9977:8b89
;; flags:; QUERY: 2, ANSWER: 0, AUTHORITY: 7, ADDITIONAL: 0
;; QUESTION SECTION:
;Service._asdf._tcp.local. CLASS32769 ANY
;unknown-2.local. CLASS32769 ANY
;; AUTHORITY SECTION:
Service._asdf._tcp.local. 120 IN SRV 0 0 12345 unknown-2.local.
unknown-2.local. 120 IN A 10.0.1.240
unknown-2.local. 120 IN AAAA fe80::2b8:2527:4334:98b4
unknown-2.local. 120 IN AAAA fe80::4aa:883:df8b:110c
unknown-2.local. 120 IN AAAA fe80::d8d2:50ff:fea2:33f8
unknown-2.local. 120 IN AAAA fe80::cfa4:720:c5b6:d2f4
unknown-2.local. 120 IN AAAA fe80::121a:1fda:9977:8b89
;; flags:; QUERY: 2, ANSWER: 0, AUTHORITY: 7, ADDITIONAL: 0
;; QUESTION SECTION:
;Service._asdf._tcp.local. CLASS32769 ANY
;unknown-2.local. CLASS32769 ANY
;; AUTHORITY SECTION:
Service._asdf._tcp.local. 120 IN SRV 0 0 12345 unknown-2.local.
unknown-2.local. 120 IN A 10.0.1.240
unknown-2.local. 120 IN AAAA fe80::2b8:2527:4334:98b4
unknown-2.local. 120 IN AAAA fe80::4aa:883:df8b:110c
unknown-2.local. 120 IN AAAA fe80::d8d2:50ff:fea2:33f8
unknown-2.local. 120 IN AAAA fe80::cfa4:720:c5b6:d2f4
unknown-2.local. 120 IN AAAA fe80::121a:1fda:9977:8b89
;; flags:; QUERY: 2, ANSWER: 0, AUTHORITY: 7, ADDITIONAL: 0
;; QUESTION SECTION:
;Service._asdf._tcp.local. CLASS32769 ANY
;unknown-3.local. CLASS32769 ANY
;; AUTHORITY SECTION:
Service._asdf._tcp.local. 120 IN SRV 0 0 12345 unknown-3.local.
unknown-3.local. 120 IN A 10.0.1.240
unknown-3.local. 120 IN AAAA fe80::2b8:2527:4334:98b4
unknown-3.local. 120 IN AAAA fe80::4aa:883:df8b:110c
unknown-3.local. 120 IN AAAA fe80::d8d2:50ff:fea2:33f8
unknown-3.local. 120 IN AAAA fe80::cfa4:720:c5b6:d2f4
unknown-3.local. 120 IN AAAA fe80::121a:1fda:9977:8b89
;; flags:; QUERY: 2, ANSWER: 0, AUTHORITY: 7, ADDITIONAL: 0
;; QUESTION SECTION:
;Service._asdf._tcp.local. CLASS32769 ANY
;unknown-3.local. CLASS32769 ANY
;; AUTHORITY SECTION:
Service._asdf._tcp.local. 120 IN SRV 0 0 12345 unknown-3.local.
unknown-3.local. 120 IN A 10.0.1.240
unknown-3.local. 120 IN AAAA fe80::2b8:2527:4334:98b4
unknown-3.local. 120 IN AAAA fe80::4aa:883:df8b:110c
unknown-3.local. 120 IN AAAA fe80::d8d2:50ff:fea2:33f8
unknown-3.local. 120 IN AAAA fe80::cfa4:720:c5b6:d2f4
unknown-3.local. 120 IN AAAA fe80::121a:1fda:9977:8b89
;; flags:; QUERY: 2, ANSWER: 0, AUTHORITY: 7, ADDITIONAL: 0
;; QUESTION SECTION:
;Service._asdf._tcp.local. CLASS32769 ANY
;unknown-4.local. CLASS32769 ANY
;; AUTHORITY SECTION:
Service._asdf._tcp.local. 120 IN SRV 0 0 12345 unknown-4.local.
unknown-4.local. 120 IN A 10.0.1.240
unknown-4.local. 120 IN AAAA fe80::2b8:2527:4334:98b4
unknown-4.local. 120 IN AAAA fe80::4aa:883:df8b:110c
unknown-4.local. 120 IN AAAA fe80::d8d2:50ff:fea2:33f8
unknown-4.local. 120 IN AAAA fe80::cfa4:720:c5b6:d2f4
unknown-4.local. 120 IN AAAA fe80::121a:1fda:9977:8b89
;; flags:; QUERY: 2, ANSWER: 0, AUTHORITY: 7, ADDITIONAL: 0
;; QUESTION SECTION:
;Service._asdf._tcp.local. CLASS32769 ANY
;unknown-4.local. CLASS32769 ANY
;; AUTHORITY SECTION:
Service._asdf._tcp.local. 120 IN SRV 0 0 12345 unknown-4.local.
unknown-4.local. 120 IN A 10.0.1.240
unknown-4.local. 120 IN AAAA fe80::2b8:2527:4334:98b4
unknown-4.local. 120 IN AAAA fe80::4aa:883:df8b:110c
unknown-4.local. 120 IN AAAA fe80::d8d2:50ff:fea2:33f8
unknown-4.local. 120 IN AAAA fe80::cfa4:720:c5b6:d2f4
unknown-4.local. 120 IN AAAA fe80::121a:1fda:9977:8b89
;; flags:; QUERY: 2, ANSWER: 0, AUTHORITY: 7, ADDITIONAL: 0
;; QUESTION SECTION:
;Service._asdf._tcp.local. CLASS32769 ANY
;unknown-5.local. CLASS32769 ANY
;; AUTHORITY SECTION:
Service._asdf._tcp.local. 120 IN SRV 0 0 12345 unknown-5.local.
unknown-5.local. 120 IN A 10.0.1.240
unknown-5.local. 120 IN AAAA fe80::2b8:2527:4334:98b4
unknown-5.local. 120 IN AAAA fe80::4aa:883:df8b:110c
unknown-5.local. 120 IN AAAA fe80::d8d2:50ff:fea2:33f8
unknown-5.local. 120 IN AAAA fe80::cfa4:720:c5b6:d2f4
unknown-5.local. 120 IN AAAA fe80::121a:1fda:9977:8b89
;; flags:; QUERY: 2, ANSWER: 0, AUTHORITY: 7, ADDITIONAL: 0
;; QUESTION SECTION:
;Service._asdf._tcp.local. CLASS32769 ANY
;unknown-5.local. CLASS32769 ANY
;; AUTHORITY SECTION:
Service._asdf._tcp.local. 120 IN SRV 0 0 12345 unknown-5.local.
unknown-5.local. 120 IN A 10.0.1.240
unknown-5.local. 120 IN AAAA fe80::2b8:2527:4334:98b4
unknown-5.local. 120 IN AAAA fe80::4aa:883:df8b:110c
unknown-5.local. 120 IN AAAA fe80::d8d2:50ff:fea2:33f8
unknown-5.local. 120 IN AAAA fe80::cfa4:720:c5b6:d2f4
unknown-5.local. 120 IN AAAA fe80::121a:1fda:9977:8b89
^C
I'm using the example code here and trying to register a Record:
https://github.com/brutella/dnssd/tree/v1.2.4/cmd/register
I've adjusted:
cfg := dnssd.Config{
Name: *instanceFlag,
Type: *serviceFlag,
Domain: *domainFlag,
Port: *portFlag,
Ifaces: ifaces,
IPs: []net.IP{net.ParseIP("127.0.0.1")}, //hardcoded just for a test (although docs say this is deprecated)
}
Trying to get a test.local to resolve to 127.0.0.1 (or whatever IP I like).
$ dns-sd -B. --> this does detect the Service
Timestamp A/R Flags if Domain Service Type Instance Name
13:30:38.961 Add 3 6 local. _http._tcp. test
$ dns-sd -G v4 test.local --> this does not show any entries. Where as other mDNS devices on my network pop up such as Octopi.local and my printer.
$ ping test.local
ping: cannot resolve test.local: Unknown host
When I try this with the dns-sd -P "test" _http._tcp local 8888 test.local 127.0.0.1. --> this works and I see the A record when I packet sniff and also name resolution works.
Just curious what I am doing wrong, or need example code to make it happen :)
Thanks!
I'm trying to send out a unicast QU for service discovery at startup of my application. I can't find a way to use the library to do that. LookupType() does not expose a way to set the unicast bit and unconditionally sends out a QM query.
I tried to copy and paste the browse.go functions into my app and adapt them, but got stuck since I can't create a Query struct (all fields are unexported) and I can't find a public constructor function.
Ideas?
(if you agree that this is a reasonable use case and adding a call to setQuestionUnicast() in lookupType is the fix, I could create a pull request. Perhaps create a new func LookupTypeUnicast() that passes in a boolean to tell lookupType() to set the bit?)
Currently when sending probe and announcement messages, all A (ip v4) and AAAA (ip v6) records from all network interfaces are included.
We should also provide an option to advertise on specific network interfaces only.
i'm try to resolve onetime some record via dnssd.LookupInstance, but it stuck.
Can you provide example? Or does it work?
Browsing services with multiple dots in their domain name fails to read A records.
Consider the following answer:
****** ;; opcode: QUERY, status: NOERROR, id: 0
;; flags: qr aa; QUERY: 0, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 4
;; ANSWER SECTION:
_raop._tcp.local. 4500 IN PTR CEDD39ACA62E\@Corpisone._raop._tcp.local.
;; ADDITIONAL SECTION:
CEDD39ACA62E\@Corpisone._raop._tcp.local. 4500 CLASS32769 TXT "sf=0x4" "fv=76400.10" "am=ShairportSync" "vs=105.1" "tp=TCP,UDP" "vn=65537" "ss=16" "sr=44100" "da=true" "sv=false" "et=0,1" "ek=1" "cn=0,1" "ch=2" "txtvers=1" "pw=false"
CEDD39ACA62E\@Corpisone._raop._tcp.local. 4500 CLASS32769 SRV 0 0 5000 airport.corpisone.container.local.
airport.corpisone.container.local. 120 CLASS32769 A 10.0.4.18
airport.corpisone.container.local. 120 CLASS32769 NSEC airport.corpisone.container.local. A
While parsing the srv record:
Line 63 in 7335cb4
ParseHostName will apparently fail to set the hostname
Line 175 in 7335cb4
In turn, when parsing the A record, it will fail to recognize the entry as valid:
Line 70 in 7335cb4
... ultimately not listing the service IP.
The above works well if the service name contains just one level (eg: "foobar.local.")
Maybe I'm missing something here - plus I'm not familiar with the spec...
What are your thoughts?
Thanks.
#35 fix code not int tag v1.2.3, can you release new tag for that?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.