{"id":27974268,"url":"https://github.com/openprinting/go-avahi","last_synced_at":"2025-05-08T00:13:35.576Z","repository":{"id":253003594,"uuid":"842135538","full_name":"OpenPrinting/go-avahi","owner":"OpenPrinting","description":"Golang (cgo) binding for Avahi (Multicast DNS and Device Discovery, mDNS/DNS-SD)","archived":false,"fork":false,"pushed_at":"2025-05-03T15:20:48.000Z","size":125,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-08T00:13:24.768Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/OpenPrinting.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-08-13T18:35:23.000Z","updated_at":"2025-05-03T15:20:51.000Z","dependencies_parsed_at":"2024-08-20T15:13:39.555Z","dependency_job_id":"e5f48058-3f9f-4fe6-91b6-b15587799e96","html_url":"https://github.com/OpenPrinting/go-avahi","commit_stats":null,"previous_names":["alexpevzner/go-avahi","openprinting/go-avahi"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenPrinting%2Fgo-avahi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenPrinting%2Fgo-avahi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenPrinting%2Fgo-avahi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenPrinting%2Fgo-avahi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/OpenPrinting","download_url":"https://codeload.github.com/OpenPrinting/go-avahi/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252973674,"owners_count":21834108,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-05-08T00:13:34.984Z","updated_at":"2025-05-08T00:13:35.558Z","avatar_url":"https://github.com/OpenPrinting.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Golang (cgo) binding for Avahi\n\n[![godoc.org](https://godoc.org/github.com/OpenPrinting/go-avahi?status.svg)](https://godoc.org/github.com/OpenPrinting/go-avahi)\n![GitHub](https://img.shields.io/github/license/OpenPrinting/go-avahi)\n[![Go Report Card](https://goreportcard.com/badge/github.com/OpenPrinting/go-avahi)](https://goreportcard.com/report/github.com/OpenPrinting/go-avahi)\n\n```\nimport \"github.com/OpenPrinting/go-avahi\"\n```\n\nPackage avahi provides a fairly complete CGo-based Golang binding for\nAvahi client.\n\nPackage reference:\n\n  - https://pkg.go.dev/github.com/OpenPrinting/go-avahi\n\n# Introduction\n\nAvahi is the standard implementation of Multicast DNS and DNS-SD for Linux, and\nlikely for some BSD systems as well. This technology is essential for automatic\nnetwork configuration, service discovery on local networks, and driverless\nprinting and scanning. It also can be useful for the peer services discovery\nin a cloud.\n\nPlease notice, there is an alternative Avahi binding in pure Go:\n\n  - GitHub project: https://github.com/holoplot/go-avahi\n  - The documentation: https://pkg.go.dev/github.com/holoplot/go-avahi\n\nThis package has the following key differences:\n\n  - This is CGo binding, not pure Go\n  - It uses native/stdlib types, where appropriate. For example,\n    IP addresses returned as [netip.AddrPort]\n  - It uses a single channel for all events reported by an object,\n    so add/remove events cannot be reordered\n  - It survives Avahi restart\n  - Integer values, like various flags, DNS class and type and\n    so own, have their own type, not a generic int16/int32\n  - And the last but not least, it attempts to fill the gaps\n    in Avahi documentation, which is not very detailed\n\nThere is also DNS implementation on pure Go:\n\n  - https://pkg.go.dev/github.com/brutella/dnssd\n\nThis library is comprehensive, high-quality, and quite popular. It is possible\n(and not very difficult) to implement MDNS/DNS-SD directly on top of it,\nallowing the entire protocol to run within the user process without relying on\na system daemon like Avahi.\n\nThere are several existing implementations; however, I don't have experience\nwith them, so I can't provide a review.\n\nOne inherent disadvantage of all these implementations is that they do not work\nwith local services operating via the loopback network interface. MDNS is a\nmulticast-based protocol, and the loopback interface does not support\nmulticasting. System daemons like Avahi do not actually use multicasting for\nloopback services; instead, they emulate the publishing and discovery\nfunctionality for those services. An in-process implementation cannot achieve\nthis.\n\n# Avahi documentation\n\n[Avahi API documentation](https://avahi.org/doxygen/html/), to be\nhonest, is not easy to read. It lacks significant details and hard to\nunderstand unless you have a lot of a-priory knowledge in the subject.\n\nAmong other things, this package attempts to fill this gap. As its\nexported objects map very closely to the native C API objects (except\nGo vs C naming conventions and using channels instead of callbacks),\n[the package reference](https://godoc.org/github.com/OpenPrinting/go-avahi)\nmay be useful as a generic Avahi API reference, regardless of\nprogramming language you use.\n\nSo even if you are the C or Python programmer, you may find package\nreference useful for you.\n\n# Build requirements\n\nThis package requires Go 1.18 or newer. This is an easy requirement,\nbecause Go 1.18 was released at March 2022, so must distros should\nbe up to date.\n\nAs it is CGo binding, it requires avahi-devel (or avahi-client, the\nexact name may depend on your distro) package to be installed. On\nmost Linux distros it is an easy to achieve.\n\nYou will need also a working C compiler. This is easy in a case of\nnative build, but in a case of cross-compiling may require some\nadditional effort.\n\nThis package was developed and tested at Fedora 40, but expected\nto work at all other distros.\n\n# Runtime requirements\n\nThis package requires a working Avahi daemon and libavahi-client dynamic\nlibraries installed on a system. In most cases it should work out of\nbox.\n\n# An Example\n\nThe following simple example demonstrates usage of the API provided by\nthis package. This simple program scans local network for available network\nprinters and outputs found devices.\n\n```\n// github.com/OpenPrinting/go-avahi example\n\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"time\"\n\n\t\"github.com/OpenPrinting/go-avahi\"\n)\n\n// checkErr terminates a program if err is not nil.\nfunc checkErr(err error, format string, args ...any) {\n\tif err != nil {\n\t\tmsg := fmt.Sprintf(format, args...)\n\t\tfmt.Printf(\"%s: %s\\n\", msg, err)\n\t\tos.Exit(1)\n\t}\n}\n\n// The main function.\nfunc main() {\n\t// Create a Client with enabled workarounds for Avahi bugs\n\tclnt, err := avahi.NewClient(avahi.ClientLoopbackWorkarounds)\n\tcheckErr(err, \"avahi.NewClient\")\n\n\tdefer clnt.Close()\n\n\t// Create context with timeout\n\tctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)\n\tdefer cancel()\n\n\t// Create poller to simplify event loop.\n\tpoller := avahi.NewPoller()\n\n\t// Create ServiceBrowsers for a variety of printer types\n\tsvctypes := []string{\n\t\t\"_printer._tcp\",        // LPD protocol\n\t\t\"_pdl-datastream._tcp\", // HP JetDirect\n\t\t\"_ipp._tcp\",            // IPP over HTTPS\n\t\t\"_ipps._tcp\",           // IPP over HTTPS\n\t}\n\n\tfor _, svctype := range svctypes {\n\t\tbrowser, err := avahi.NewServiceBrowser(\n\t\t\tclnt,\n\t\t\tavahi.IfIndexUnspec,\n\t\t\tavahi.ProtocolUnspec,\n\t\t\tsvctype,\n\t\t\t\"\",\n\t\t\tavahi.LookupUseMulticast)\n\n\t\tcheckErr(err, \"browse %q\", svctype)\n\t\tpoller.AddServiceBrowser(browser)\n\t}\n\n\t// Wait for Browser events. Create resolvers on a fly.\n\t//\n\t// Here we use asynchronous API, so we can start resolvers\n\t// early to run in background.\n\t//\n\t// Run until we found/resolve all we expect or timeout occurs.\n\twanted := make(map[string]struct{})\n\tfor _, svctype := range svctypes {\n\t\twanted[svctype] = struct{}{}\n\t}\n\n\tfor ctx.Err() == nil \u0026\u0026 len(wanted) \u003e 0 {\n\t\tevnt, _ := poller.Poll(ctx)\n\n\t\tswitch evnt := evnt.(type) {\n\t\tcase *avahi.ServiceBrowserEvent:\n\t\t\tswitch evnt.Event {\n\t\t\tcase avahi.BrowserNew:\n\t\t\t\tresolver, err := avahi.NewServiceResolver(\n\t\t\t\t\tclnt,\n\t\t\t\t\tevnt.IfIdx,\n\t\t\t\t\tevnt.Proto,\n\t\t\t\t\tevnt.InstanceName,\n\t\t\t\t\tevnt.SvcType,\n\t\t\t\t\tevnt.Domain,\n\t\t\t\t\tavahi.ProtocolUnspec,\n\t\t\t\t\tavahi.LookupUseMulticast)\n\n\t\t\t\tcheckErr(err, \"resolve %q\", evnt.InstanceName)\n\t\t\t\tpoller.AddServiceResolver(resolver)\n\t\t\t\twanted[evnt.InstanceName] = struct{}{}\n\n\t\t\tcase avahi.BrowserAllForNow:\n\t\t\t\tdelete(wanted, evnt.SvcType)\n\n\t\t\tcase avahi.BrowserFailure:\n\t\t\t\terr = evnt.Err\n\t\t\t\tcheckErr(err, \"browse %q\", evnt.SvcType)\n\t\t\t}\n\n\t\tcase *avahi.ServiceResolverEvent:\n\t\t\tswitch evnt.Event {\n\t\t\tcase avahi.ResolverFound:\n\t\t\t\tfmt.Printf(\"Found new device:\\n\"+\n\t\t\t\t\t\"  Name:       %s:\\n\"+\n\t\t\t\t\t\"  Type:       %s\\n\"+\n\t\t\t\t\t\"  IP address: %s:%d\\n\",\n\t\t\t\t\tevnt.InstanceName,\n\t\t\t\t\tevnt.SvcType,\n\t\t\t\t\tevnt.Addr,\n\t\t\t\t\tevnt.Port)\n\n\t\t\t\tdelete(wanted, evnt.InstanceName)\n\n\t\t\tcase avahi.ResolverFailure:\n\t\t\t\terr = evnt.Err\n\t\t\t\tcheckErr(err, \"resolve %q\", evnt.InstanceName)\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n\u003c!-- vim:ts=8:sw=4:et:textwidth=72\n--\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenprinting%2Fgo-avahi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopenprinting%2Fgo-avahi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenprinting%2Fgo-avahi/lists"}