Documentation ¶
Overview ¶
Package dnssd implements a wrapper for Apple's C DNS Service Discovery API.
This package broke with Go 1.6: https://github.com/andrewtj/dnssd/issues/5
The DNS Service Discovery API is part of the Apple Bonjour zero configuration networking stack. The API allows for network services to be registered, browsed and resolved without configuration via multicast DNS in the ".local" domain and with additional configuration in unicast DNS domains. A service consists of a name, type, host, port and a set of key-value pairs containing meta information.
Bonjour is bundled with OS X and available for Windows via Bonjour Print Services for Windows¹, the Bonjour SDK for Windows² or bundled with iTunes. For other POSIX platforms Apple offer mDNSResponder³ as open-source, however the Avahi⁴ project is the de facto choice on most Linux and BSD systems. Although Avahi has a different API, it does offer a compatibility shim which covers a subset of the DNS Service Discovery API, and which this package largely sticks to.
- http://support.apple.com/kb/dl999
- https://developer.apple.com/bonjour/
- http://opensource.apple.com/tarballs/mDNSResponder/
- http://www.avahi.org/
The DNS Service Discovery API is wrapped as follows:
DNSServiceRegister() -> RegisterOp DNSServiceBrowse() -> BrowseOp DNSServiceResolve() -> ResolveOp DNSServiceQueryRecord() -> QueryOp
All operations require a callback be set. RegisterOp, BrowseOp and ResolveOp require a service type be set. QueryOp requires name, class and type be set. If an InterfaceIndex is not set the default value of InterfaceIndexAny is used which applies the operation to all network interfaces. For operations that take a domain, if no domain is set or the domain is set to an empty string the operation applies to all applicable DNS-SD domains.
If a service is registered with an empty string as it's name, the local computer name (or hostname) will be substitued. If no host is specified a hostname for the local machine will be used. By default services will be renamed with a numeric suffix if a name collision occurs.
Callbacks are executed in serial. If an error is supplied to a callback the operation will no longer be active and other arguments must be ignored.
Index ¶
- Constants
- Variables
- type BrowseCallbackFunc
- type BrowseOp
- func (o *BrowseOp) Active() bool
- func (o *BrowseOp) Domain() string
- func (o *BrowseOp) InterfaceIndex() int
- func (o *BrowseOp) SetCallback(f BrowseCallbackFunc) error
- func (o *BrowseOp) SetDomain(s string) error
- func (o *BrowseOp) SetInterfaceIndex(i int) error
- func (o *BrowseOp) SetType(s string) error
- func (o *BrowseOp) Start() error
- func (o *BrowseOp) Stop()
- func (o *BrowseOp) Type() string
- type Error
- type QueryCallbackFunc
- type QueryOp
- func (o *QueryOp) Active() bool
- func (o *QueryOp) Class() uint16
- func (o *QueryOp) InterfaceIndex() int
- func (o *QueryOp) Name() string
- func (o *QueryOp) SetCallback(f QueryCallbackFunc) error
- func (o *QueryOp) SetClass(c uint16) error
- func (o *QueryOp) SetInterfaceIndex(i int) error
- func (o *QueryOp) SetName(n string) error
- func (o *QueryOp) SetType(t uint16) error
- func (o *QueryOp) Start() error
- func (o *QueryOp) Stop()
- func (o *QueryOp) Type() uint16
- type RegisterCallbackFunc
- type RegisterOp
- func NewProxyRegisterOp(name, serviceType, host string, port int, f RegisterCallbackFunc) *RegisterOp
- func NewRegisterOp(name, serviceType string, port int, f RegisterCallbackFunc) *RegisterOp
- func StartProxyRegisterOp(name, serviceType, host string, port int, f RegisterCallbackFunc) (*RegisterOp, error)
- func StartRegisterOp(name, serviceType string, port int, f RegisterCallbackFunc) (*RegisterOp, error)
- func (o *RegisterOp) Active() bool
- func (o *RegisterOp) DeleteTXTPair(key string) error
- func (o *RegisterOp) Domain() string
- func (o *RegisterOp) Host() string
- func (o *RegisterOp) InterfaceIndex() int
- func (o *RegisterOp) Name() string
- func (o *RegisterOp) NoAutoRename() bool
- func (o *RegisterOp) Port() int
- func (o *RegisterOp) SetCallback(f RegisterCallbackFunc) error
- func (o *RegisterOp) SetDomain(s string) error
- func (o *RegisterOp) SetHost(h string) error
- func (o *RegisterOp) SetInterfaceIndex(i int) error
- func (o *RegisterOp) SetName(n string) error
- func (o *RegisterOp) SetNoAutoRename(e bool) error
- func (o *RegisterOp) SetPort(p int) error
- func (o *RegisterOp) SetTXTPair(key, value string) error
- func (o *RegisterOp) SetType(s string) error
- func (o *RegisterOp) Start() error
- func (o *RegisterOp) Stop()
- func (o *RegisterOp) Type() string
- type ResolveCallbackFunc
- type ResolveOp
- func (o *ResolveOp) Active() bool
- func (o *ResolveOp) Domain() string
- func (o *ResolveOp) InterfaceIndex() int
- func (o *ResolveOp) Name() string
- func (o *ResolveOp) SetCallback(f ResolveCallbackFunc) error
- func (o *ResolveOp) SetDomain(s string) error
- func (o *ResolveOp) SetInterfaceIndex(i int) error
- func (o *ResolveOp) SetName(n string) error
- func (o *ResolveOp) SetType(s string) error
- func (o *ResolveOp) Start() error
- func (o *ResolveOp) Stop()
- func (o *ResolveOp) Type() string
Examples ¶
Constants ¶
const InterfaceIndexAny = 0
InterfaceIndexAny is the default for all operations.
const InterfaceIndexLocalOnly = int(^uint(0) >> 1)
InterfaceIndexLocalOnly limits the scope of the operation to the local machine.
Variables ¶
var ( ErrUnknown = Error{-65537, "Unknown"} ErrNoSuchName = Error{-65538, "No Such Name"} ErrNoMemory = Error{-65539, "No Memory"} ErrBadParam = Error{-65540, "Bad Param"} ErrBadReference = Error{-65541, "Bad Reference"} ErrBadState = Error{-65542, "Bad State"} ErrBadFlags = Error{-65543, "Bad Flags"} ErrUnsupported = Error{-65544, "Unsupported"} ErrNotInitialized = Error{-65545, "Not Initialized"} ErrAlreadyRegistered = Error{-65547, "Already Registered"} ErrNameConflict = Error{-65548, "Name Conflict"} ErrInvalid = Error{-65549, "Invalid"} ErrFirewall = Error{-65550, "Firewall"} ErrIncompatible = Error{-65551, "Incompatible"} ErrBadInterfaceIndex = Error{-65552, "Bad Interface Index"} ErrRefused = Error{-65553, "Refused"} ErrNoSuchRecord = Error{-65554, "No Such Record"} ErrNoAuth = Error{-65555, "No Auth"} ErrNoSuchKey = Error{-65556, "No Such Key"} ErrNATTraversal = Error{-65557, "NAT Traversal"} ErrDoubleNAT = Error{-65558, "Double NAT"} ErrBadTime = Error{-65559, "Bad Time"} ErrBadSig = Error{-65560, "Bad Sig"} ErrBadKey = Error{-65561, "Bad Key"} ErrTransient = Error{-65562, "Transient"} ErrServiceNotRunning = Error{-65563, "Service Not Running"} ErrNATPortMappingUnsupported = Error{-65564, "NAT Port Mapping Unsupported"} ErrNATPortMappingDisabled = Error{-65565, "NAT Port Mapping Disabled"} ErrNoRouter = Error{-65566, "No Router"} ErrPollingMode = Error{-65567, "Polling Mode"} ErrTimeout = Error{-65568, "Timeout"} )
Errors returned by the underlying C API.
var ErrMissingCallback = errors.New("no callback set")
ErrMissingCallback is returned when an operation is started without setting a callback.
var ErrStarted = errors.New("already started")
ErrStarted is returned when trying to mutate an active operation or when starting a started operation.
var ErrTXTLen = errors.New("TXT size may not exceed 65535 bytes")
ErrTXTLen is returned when setting a TXT pair that would exceed the 65,535 byte TXT record limit.
var ErrTXTStringLen = errors.New("TXT string may not exceed 255 bytes")
ErrTXTStringLen is returned when setting a TXT pair that would exceed the 255 byte string limit.
Functions ¶
This section is empty.
Types ¶
type BrowseCallbackFunc ¶
type BrowseCallbackFunc func(op *BrowseOp, err error, add bool, interfaceIndex int, name string, serviceType string, domain string)
BrowseCallbackFunc is called when an error occurs or a service is lost or found.
type BrowseOp ¶
type BrowseOp struct {
// contains filtered or unexported fields
}
BrowseOp represents a query for services of a particular type.
Example ¶
package main import ( "log" "github.com/andrewtj/dnssd" ) func ExampleBrowseCallbackFunc(op *dnssd.BrowseOp, err error, add bool, interfaceIndex int, name string, serviceType string, domain string) { if err != nil { log.Printf("Browse operation failed: %s", err) return } change := "lost" if add { change = "found" } log.Printf("Browse operation %s %s service “%s” in %s on interface %d", change, serviceType, name, domain, interfaceIndex) } func main() { op, err := dnssd.StartBrowseOp("_http._tcp", ExampleBrowseCallbackFunc) if err != nil { // op is now inactive log.Printf("Browse operation failed: %s", err) return } // later... op.Stop() }
Output:
Example (Domain) ¶
package main import ( "log" "github.com/andrewtj/dnssd" ) func ExampleBrowseCallbackFunc(op *dnssd.BrowseOp, err error, add bool, interfaceIndex int, name string, serviceType string, domain string) { if err != nil { log.Printf("Browse operation failed: %s", err) return } change := "lost" if add { change = "found" } log.Printf("Browse operation %s %s service “%s” in %s on interface %d", change, serviceType, name, domain, interfaceIndex) } func main() { op := dnssd.NewBrowseOp("_http._tcp", ExampleBrowseCallbackFunc) op.SetDomain("dns-sd.org") if err := op.Start(); err != nil { log.Printf("Failed to start browse operation: %s", err) return } // later... op.Stop() }
Output:
func NewBrowseOp ¶
func NewBrowseOp(serviceType string, f BrowseCallbackFunc) *BrowseOp
NewBrowseOp creates a new BrowseOp with the given service type and call back set.
func StartBrowseOp ¶
func StartBrowseOp(serviceType string, f BrowseCallbackFunc) (*BrowseOp, error)
StartBrowseOp returns the equivalent of calling NewBrowseOp and Start().
func (*BrowseOp) Active ¶
func (o *BrowseOp) Active() bool
Active indicates whether an operation is active
func (*BrowseOp) InterfaceIndex ¶
func (o *BrowseOp) InterfaceIndex() int
InterfaceIndex returns the interface index the op is tied to.
func (*BrowseOp) SetCallback ¶
func (o *BrowseOp) SetCallback(f BrowseCallbackFunc) error
SetCallback sets the function to call when an error occurs or a service is lost or found.
func (*BrowseOp) SetInterfaceIndex ¶
SetInterfaceIndex sets the interface index the op is tied to.
type Error ¶
type Error struct {
// contains filtered or unexported fields
}
Error structs meet the error interface and are returned when errors occur in the underlying C API.
type QueryCallbackFunc ¶
type QueryCallbackFunc func(op *QueryOp, err error, add bool, interfaceIndex int, fullname string, rrtype, rrclass uint16, rdata []byte, ttl uint32)
QueryCallbackFunc is called when an error occurs or a record is added or removed. Results may be cached for ttl seconds. After ttl seconds the result should be discarded. Alternatively the operation may be left running in which case the result can be considered valid until a callback indicates otherwise.
type QueryOp ¶
type QueryOp struct {
// contains filtered or unexported fields
}
QueryOp represents a query for a specific name, class and type.
Example ¶
package main import ( "log" "github.com/andrewtj/dnssd" ) func ExampleQueryCallbackFunc(op *dnssd.QueryOp, err error, add bool, interfaceIndex int, fullname string, rrtype, rrclass uint16, rdata []byte, ttl uint32) { if err != nil { log.Printf("Query operation failed: %s", err) return } change := "removed" if add { change = "added" } log.Printf("Query operation %s %s/%d/%d/%v (TTL: %d) on interface %d", change, fullname, rrtype, rrclass, rdata, ttl, interfaceIndex) } func main() { op := dnssd.NewQueryOp(0, "golang.org.", 1, 1, ExampleQueryCallbackFunc) if err := op.Start(); err != nil { log.Printf("Failed to start query operation: %s", err) return } // later op.Stop() }
Output:
func NewQueryOp ¶
func NewQueryOp(interfaceIndex int, name string, rrtype, rrclass uint16, f QueryCallbackFunc) *QueryOp
NewQueryOp creates a new QueryOp with the associated parameters set.
func StartQueryOp ¶
func StartQueryOp(interfaceIndex int, name string, rrtype, rrclass uint16, f QueryCallbackFunc) (*QueryOp, error)
StartQueryOp returns the equivalent of calling NewQueryOp and Start.
func (*QueryOp) Active ¶
func (o *QueryOp) Active() bool
Active indicates whether an operation is active
func (*QueryOp) InterfaceIndex ¶
func (o *QueryOp) InterfaceIndex() int
InterfaceIndex returns the interface index the op is tied to.
func (*QueryOp) SetCallback ¶
func (o *QueryOp) SetCallback(f QueryCallbackFunc) error
SetCallback sets the function to call when an error occurs or a record is added or removed.
func (*QueryOp) SetInterfaceIndex ¶
SetInterfaceIndex sets the interface index the op is tied to.
type RegisterCallbackFunc ¶
type RegisterCallbackFunc func(op *RegisterOp, err error, add bool, name, serviceType, domain string)
RegisterCallbackFunc is called when a name is registered or deregistered in a given domain, or when an error occurs.
type RegisterOp ¶
type RegisterOp struct {
// contains filtered or unexported fields
}
RegisterOp represents a service registration operation.
Example ¶
package main import ( "fmt" "log" "net" "net/http" "github.com/andrewtj/dnssd" ) func ExampleRegisterCallbackFunc(op *dnssd.RegisterOp, err error, add bool, name, serviceType, domain string) { if err != nil { log.Printf("Service registration failed: %s", err) return } if add { log.Printf("Service registered as “%s“ in %s", name, domain) } else { log.Printf("Service “%s” removed from %s", name, domain) } } func main() { listener, err := net.Listen("tcp", ":0") if err != nil { log.Printf("Listen failed: %s", err) return } port := listener.Addr().(*net.TCPAddr).Port op, err := dnssd.StartRegisterOp("", "_http._tcp", port, ExampleRegisterCallbackFunc) if err != nil { log.Printf("Failed to register service: %s", err) return } http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, %s", r.RemoteAddr) }) http.Serve(listener, nil) // later... op.Stop() }
Output:
Example (Proxy) ¶
package main import ( "log" "github.com/andrewtj/dnssd" ) func ExampleRegisterCallbackFunc(op *dnssd.RegisterOp, err error, add bool, name, serviceType, domain string) { if err != nil { log.Printf("Service registration failed: %s", err) return } if add { log.Printf("Service registered as “%s“ in %s", name, domain) } else { log.Printf("Service “%s” removed from %s", name, domain) } } func main() { op := dnssd.NewProxyRegisterOp("dnssd godoc", "_http._tcp", "godoc.org", 80, ExampleRegisterCallbackFunc) if err := op.SetTXTPair("path", "/github.com/andrewtj/dnssd"); err != nil { log.Printf("Failed to set key-value pair: %s", err) return } if err := op.Start(); err != nil { log.Printf("Failed to register service: %s", err) return } // later... op.Stop() }
Output:
func NewProxyRegisterOp ¶
func NewProxyRegisterOp(name, serviceType, host string, port int, f RegisterCallbackFunc) *RegisterOp
NewProxyRegisterOp creates a new RegisterOp with the given parameters set.
func NewRegisterOp ¶
func NewRegisterOp(name, serviceType string, port int, f RegisterCallbackFunc) *RegisterOp
NewRegisterOp creates a new RegisterOp with the given parameters set.
func StartProxyRegisterOp ¶
func StartProxyRegisterOp(name, serviceType, host string, port int, f RegisterCallbackFunc) (*RegisterOp, error)
StartProxyRegisterOp returns the equivalent of calling NewProxyRegisterOp and Start().
func StartRegisterOp ¶
func StartRegisterOp(name, serviceType string, port int, f RegisterCallbackFunc) (*RegisterOp, error)
StartRegisterOp returns the equivalent of calling NewRegisterOp and Start().
func (*RegisterOp) Active ¶
func (o *RegisterOp) Active() bool
Active indicates whether an operation is active
func (*RegisterOp) DeleteTXTPair ¶
func (o *RegisterOp) DeleteTXTPair(key string) error
DeleteTXTPair deletes the TXT string with the provided key.
func (*RegisterOp) Domain ¶
func (o *RegisterOp) Domain() string
Domain returns the domain associated with the op.
func (*RegisterOp) Host ¶
func (o *RegisterOp) Host() string
Host returns the hostname of the service. An empty string will result in the local machine's hostname being used.
func (*RegisterOp) InterfaceIndex ¶
func (o *RegisterOp) InterfaceIndex() int
InterfaceIndex returns the interface index the op is tied to.
func (*RegisterOp) NoAutoRename ¶
func (o *RegisterOp) NoAutoRename() bool
NoAutoRename indicates how service-name conflicts will be handled.
func (*RegisterOp) Port ¶
func (o *RegisterOp) Port() int
Port returns the port the service is available from.
func (*RegisterOp) SetCallback ¶
func (o *RegisterOp) SetCallback(f RegisterCallbackFunc) error
SetCallback sets the function to call when a name is registered or deregistered in a given domain, or when an error occurs.
func (*RegisterOp) SetDomain ¶
func (o *RegisterOp) SetDomain(s string) error
SetDomain sets the domain associated with the op.
func (*RegisterOp) SetHost ¶
func (o *RegisterOp) SetHost(h string) error
SetHost sets the hostname of the service. An empty string will result in the local machine's hostname being used.
func (*RegisterOp) SetInterfaceIndex ¶
SetInterfaceIndex sets the interface index the op is tied to.
func (*RegisterOp) SetName ¶
func (o *RegisterOp) SetName(n string) error
SetName sets the name of the service. A service name can not exceed 63 bytes.
func (*RegisterOp) SetNoAutoRename ¶
func (o *RegisterOp) SetNoAutoRename(e bool) error
SetNoAutoRename sets how service-name conflicts will be handled. If set to the default, false, conflicts will be handled automatically be renaming the service (eg: "My Service" will be become "My Service 2" or similar). If set to true the operations callback will be invoked with an error.
func (*RegisterOp) SetPort ¶
func (o *RegisterOp) SetPort(p int) error
SetPort sets the port the service is available from.
func (*RegisterOp) SetTXTPair ¶
func (o *RegisterOp) SetTXTPair(key, value string) error
SetTXTPair creates or updates a TXT string with the provided value.
func (*RegisterOp) SetType ¶
func (o *RegisterOp) SetType(s string) error
SetType sets the service type associated with the op.
func (*RegisterOp) Type ¶
func (o *RegisterOp) Type() string
Type returns the service type associated with the op.
type ResolveCallbackFunc ¶
type ResolveCallbackFunc func(op *ResolveOp, err error, host string, port int, txt map[string]string)
ResolveCallbackFunc is called when a service is resolved or an error occurs.
type ResolveOp ¶
type ResolveOp struct {
// contains filtered or unexported fields
}
ResolveOp represents an operation that resolves a service instance to a host, port and TXT map containing meta data.
Example ¶
package main import ( "log" "github.com/andrewtj/dnssd" ) func ExampleResolveCallbackFunc(op *dnssd.ResolveOp, err error, host string, port int, txt map[string]string) { if err != nil { log.Printf("Resolve operation failed: %s", err) return } log.Printf("Resolved service to host %s port %d with meta info: %v", host, port, txt) } func main() { op, err := dnssd.StartResolveOp(0, " * DNS Service Discovery", "_http._tcp", "dns-sd.org", ExampleResolveCallbackFunc) if err != nil { log.Printf("Failed to start resolve operation: %s", err) return } // later... op.Stop() }
Output:
func NewResolveOp ¶
func NewResolveOp(interfaceIndex int, name, serviceType, domain string, f ResolveCallbackFunc) *ResolveOp
NewResolveOp creates a new ResolveOp with the associated parameters set. It should be called with the parameters supplied to the callback of a browse operation.
func StartResolveOp ¶
func StartResolveOp(interfaceIndex int, name, serviceType, domain string, f ResolveCallbackFunc) (*ResolveOp, error)
StartResolveOp returns the equivalent of calling NewResolveOp and Start.
func (*ResolveOp) Active ¶
func (o *ResolveOp) Active() bool
Active indicates whether an operation is active
func (*ResolveOp) InterfaceIndex ¶
func (o *ResolveOp) InterfaceIndex() int
InterfaceIndex returns the interface index the op is tied to.
func (*ResolveOp) SetCallback ¶
func (o *ResolveOp) SetCallback(f ResolveCallbackFunc) error
SetCallback sets the function to call when a service is resolved or an error occurs.
func (*ResolveOp) SetInterfaceIndex ¶
SetInterfaceIndex sets the interface index the op is tied to.