holoplot / go-avahi Goto Github PK
View Code? Open in Web Editor NEWGolang bindings for the Avahi mDNS daemon
License: MIT License
Golang bindings for the Avahi mDNS daemon
License: MIT License
hi,
it seems that the avahi Server signal handler in https://github.com/holoplot/go-avahi/blob/master/server.go#L50 will check for the closure of the dbus Signal channel, but if it is closed, it simply continues the loop. the loop isn't cleaned up until an explicit Server.Close().
this leads to the inner signal handler spinning tightly on select if one did not call Close on dbus connection loss. how are users of this library expected to handle bus loss? for now my best guess is that a caller needs to register their own Signal channel to the dbus Conn and wait for it to close, and then Close the avahi Server. is that right? this seems like a big footgun.
in the following example we spin forever inside of ServerNew's anonymous function, unless you uncomment the two lines in the select{} with the explicit Server.Close() triggered by the dbus.Signal channel closure.
package main
import (
"log"
"github.com/godbus/dbus/v5"
"github.com/holoplot/go-avahi"
)
func main() {
conn, err := dbus.SystemBus()
if err != nil {
log.Fatalf("Cannot get system bus: %v", err)
}
server, err := avahi.ServerNew(conn)
if err != nil {
log.Fatalf("Avahi new failed: %v", err)
}
host, err := server.GetHostName()
if err != nil {
log.Fatalf("GetHostName() failed: %v", err)
}
log.Println("GetHostName()", host)
// Register a DBus signal handler
sig := make(chan *dbus.Signal)
conn.Signal(sig)
// Terminate the dbus connection, or otherwise simulate loss of the bus (e.g., dbus restarted).
log.Println("Conn.Close():", conn.Close())
doit := true
for doit {
select {
case _, ok := <-sig:
if !ok {
//server.Close()
//doit = false
}
}
}
}
When executing the example from the README this error occurs:
2020/03/30 16:12:51 DomainBrowserNew() failed: Method "DomainBrowserNew" with signature "iisuu" on interface "org.freedesktop.Avahi.Server" doesn't exist
You changed the signature of func (c *Server) DomainBrowserNew(...)
in 3a2e610
Not sure if this was on purpose?!
Would you mind if we could restructure the project to fit to the very common Standard Go Project Layout?
I can create a PR, if it is fine with you
It seems that if avahi-daemon has been restarted and therefore service registration is lost, go-avahi does not currently handle such events. Am I right? And if yes, what is the most straightforward way to handle such event in order to update/re-add the service on avahi-daemon?
Hi,
Service.Port is defined as int16, but TCP port number can be larger that 32767. At this case, Service.Port becomes negative.
Please, redefine it as uint16 or int.
Hi,
I would like to write a go program which can search for multiple services in parallel (with the same service name as well as with different names). For that purpose I made some tests to get familiar with this library:
func searchService(sb *avahi.ServiceBrowser, srv *avahi.Server, t int) (avahi.Service, error) {
var s avahi.Service
for {
select {
case s = <-sb.AddChannel:
s, err := srv.ResolveService(s.Interface, s.Protocol, s.Name,
s.Type, s.Domain, avahi.ProtoUnspec, 0)
if err != nil {
return s, err
}
return s, err
case <-time.After(time.Duration(t) * time.Second):
err := errors.New("could not find instance or service")
return s, err
}
}
}
func main() {
serviceName := "_service1._tcp"
serviceName2 := "_service2._tcp"
conn, err := dbus.SystemBus()
if err != nil {
log.Fatalf("Cannot get system bus: %v", err)
}
server, err := avahi.ServerNew(conn)
if err != nil {
log.Fatalf("Avahi new failed: %v", err)
}
sb, err := server.ServiceBrowserNew(avahi.InterfaceUnspec, avahi.ProtoUnspec, serviceName, "local", 0)
if err != nil {
log.Fatalf("ServiceBrowserNew() failed: %v", err)
}
s, err := searchService(sb, server, 3)
if err != nil {
log.Fatalf("searchService() failed: %v", err)
}
fmt.Println(s)
sb2, err := server.ServiceBrowserNew(avahi.InterfaceUnspec, avahi.ProtoUnspec, serviceName2, "local", 0)
if err != nil {
log.Fatalf("ServiceBrowserNew() failed: %v", err)
}
fmt.Println("sb2 created!")
s2, err := searchService(sb2, server, 3)
if err != nil {
log.Fatalf("searchService() failed: %v", err)
}
fmt.Println(s2)
I got never the output "sb2 created". The second call of ServiceBrowserNew
stucks in c.mutex.Lock()
, because the go routine in ServerNew
hangs in obj.dispatchSignal(signal)
.
Is it not intended to have multiple ServiceBrowser per server?
Thank you in advance :)
On my Debian stretch system server.ServiceBrowserNew() does often not return, about 9 out of 10 times.
It blocks at err := c.object.Call(c.interfaceForMember("ServiceBrowserNew"), 0, iface, protocol, serviceType, domain, flags).Store(&o)
with c.mutex.Lock()
held.
Do you have an idea what could cause this?
I just realized that calling ServerNew
tries to add match with an invalid interface name 'org.freedesktop.Avahi.*'. I guess the * is not valid.
Lines 35 to 45 in c53ad34
Results from busctl monitor
:
Type=method_call Endian=l Flags=0 Version=1 Priority=0 Cookie=3
Sender=:1.981 Destination=org.freedesktop.DBus Path=/org/freedesktop/DBus Interface=org.freedesktop.DBus Member=AddMatch
UniqueName=:1.981
MESSAGE "s" {
STRING "type='signal',interface='org.freedesktop.Avahi.*'";
};
‣ Type=error Endian=l Flags=1 Version=1 Priority=0 Cookie=5 ReplyCookie=3
Sender=org.freedesktop.DBus Destination=:1.981
ErrorName=org.freedesktop.DBus.Error.MatchRuleInvalid ErrorMessage="Interface name 'org.freedesktop.Avahi.*' is invalid
"
MESSAGE "s" {
STRING "Interface name 'org.freedesktop.Avahi.*' is invalid
";
};
Any chance to upgrade the dbus v5 dependency to v5.0.4
and create a tag for go-avahi? e.g. v1.0.0
?
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.