dnssd: github.com/andrewtj/dnssd Index | Examples | Files

package dnssd

import "github.com/andrewtj/dnssd"

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.

1. http://support.apple.com/kb/dl999
2. https://developer.apple.com/bonjour/
3. http://opensource.apple.com/tarballs/mDNSResponder/
4. 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

Examples

Package Files

browse.go dnssd.go errors.go os_unix.go poller.go queryrecord.go register.go resolve.go

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.

type BrowseCallbackFunc Uses

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.

Code:

if err != nil {
    // op is now inactive
    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)

type BrowseOp Uses

type BrowseOp struct {
    // contains filtered or unexported fields
}

BrowseOp represents a query for services of a particular type.

Code:

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()

Code:

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()

func NewBrowseOp Uses

func NewBrowseOp(serviceType string, f BrowseCallbackFunc) *BrowseOp

NewBrowseOp creates a new BrowseOp with the given service type and call back set.

func StartBrowseOp Uses

func StartBrowseOp(serviceType string, f BrowseCallbackFunc) (*BrowseOp, error)

StartBrowseOp returns the equivalent of calling NewBrowseOp and Start().

func (*BrowseOp) Active Uses

func (o *BrowseOp) Active() bool

Active indicates whether an operation is active

func (*BrowseOp) Domain Uses

func (o *BrowseOp) Domain() string

Domain returns the domain associated with the op.

func (*BrowseOp) InterfaceIndex Uses

func (o *BrowseOp) InterfaceIndex() int

InterfaceIndex returns the interface index the op is tied to.

func (*BrowseOp) SetCallback Uses

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) SetDomain Uses

func (o *BrowseOp) SetDomain(s string) error

SetDomain sets the domain associated with the op.

func (*BrowseOp) SetInterfaceIndex Uses

func (o *BrowseOp) SetInterfaceIndex(i int) error

SetInterfaceIndex sets the interface index the op is tied to.

func (*BrowseOp) SetType Uses

func (o *BrowseOp) SetType(s string) error

SetType sets the service type associated with the op.

func (*BrowseOp) Start Uses

func (o *BrowseOp) Start() error

Start begins the browse query.

func (*BrowseOp) Stop Uses

func (o *BrowseOp) Stop()

Stop stops the operation.

func (*BrowseOp) Type Uses

func (o *BrowseOp) Type() string

Type returns the service type associated with the op.

type Error Uses

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.

func (Error) Desc Uses

func (e Error) Desc() string

Desc returns a string describing the error.

func (Error) Error Uses

func (e Error) Error() string

func (Error) Num Uses

func (e Error) Num() int32

Num returns an error number.

type QueryCallbackFunc Uses

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.

Code:

if err != nil {
    // op is now inactive
    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)

Code:

// Demonstrates constructing a resource record and unpacking it using
// Miek Gieben's dns package (https://github.com/miekg/dns/).

if err != nil {
    // op is now inactive
    log.Printf("Query operation failed: %s", err)
    return
}

buf := make([]byte, len(fullname)+1+2+2+4+2+len(rdata))
off, err := dns.PackDomainName(fullname, buf, 0, nil, false)
if err != nil {
    log.Fatalf("Error packing domain: %s", err)
}
buf = buf[:off]
buf = append(buf, byte(rrtype>>8), byte(rrtype))
buf = append(buf, byte(rrclass>>8), byte(rrclass))
buf = append(buf, byte(ttl>>24), byte(ttl>>16), byte(ttl>>8), byte(ttl))
buf = append(buf, byte(len(rdata)>>8), byte(len(rdata)))
buf = append(buf, rdata...)
rr, off, err := dns.UnpackRR(buf, 0)
if err != nil {
    log.Fatalf("Error unpacking rr: %s", err)
}

change := "removed"
if add {
    change = "added"
}

log.Printf("Query operation on interface %d %s:\n%s", interfaceIndex, change, rr.String())

type QueryOp Uses

type QueryOp struct {
    // contains filtered or unexported fields
}

QueryOp represents a query for a specific name, class and type.

Code:

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()

func NewQueryOp Uses

func NewQueryOp(interfaceIndex int, name string, rrtype, rrclass uint16, f QueryCallbackFunc) *QueryOp

NewQueryOp creates a new QueryOp with the associated parameters set.

func StartQueryOp Uses

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 Uses

func (o *QueryOp) Active() bool

Active indicates whether an operation is active

func (*QueryOp) Class Uses

func (o *QueryOp) Class() uint16

Class returns the DNS Resource Record Class for the operation.

func (*QueryOp) InterfaceIndex Uses

func (o *QueryOp) InterfaceIndex() int

InterfaceIndex returns the interface index the op is tied to.

func (*QueryOp) Name Uses

func (o *QueryOp) Name() string

Name returns the domain name for the operation.

func (*QueryOp) SetCallback Uses

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) SetClass Uses

func (o *QueryOp) SetClass(c uint16) error

SetClass sets the DNS Resource Record Class for the operation.

func (*QueryOp) SetInterfaceIndex Uses

func (o *QueryOp) SetInterfaceIndex(i int) error

SetInterfaceIndex sets the interface index the op is tied to.

func (*QueryOp) SetName Uses

func (o *QueryOp) SetName(n string) error

SetName sets the domain name for the operation.

func (*QueryOp) SetType Uses

func (o *QueryOp) SetType(t uint16) error

SetType sets the DNS Resource Record Type for the operation.

func (*QueryOp) Start Uses

func (o *QueryOp) Start() error

Start begins the query operation.

func (*QueryOp) Stop Uses

func (o *QueryOp) Stop()

Stop stops the operation.

func (*QueryOp) Type Uses

func (o *QueryOp) Type() uint16

Type returns the DNS Resource Record Type for the operation.

type RegisterCallbackFunc Uses

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.

Code:

if err != nil {
    // op is now inactive
    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)
}

type RegisterOp Uses

type RegisterOp struct {
    // contains filtered or unexported fields
}

RegisterOp represents a service registration operation.

Code:

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()

Code:

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()

func NewProxyRegisterOp Uses

func NewProxyRegisterOp(name, serviceType, host string, port int, f RegisterCallbackFunc) *RegisterOp

NewProxyRegisterOp creates a new RegisterOp with the given parameters set.

func NewRegisterOp Uses

func NewRegisterOp(name, serviceType string, port int, f RegisterCallbackFunc) *RegisterOp

NewRegisterOp creates a new RegisterOp with the given parameters set.

func StartProxyRegisterOp Uses

func StartProxyRegisterOp(name, serviceType, host string, port int, f RegisterCallbackFunc) (*RegisterOp, error)

StartProxyRegisterOp returns the equivalent of calling NewProxyRegisterOp and Start().

func StartRegisterOp Uses

func StartRegisterOp(name, serviceType string, port int, f RegisterCallbackFunc) (*RegisterOp, error)

StartRegisterOp returns the equivalent of calling NewRegisterOp and Start().

func (*RegisterOp) Active Uses

func (o *RegisterOp) Active() bool

Active indicates whether an operation is active

func (*RegisterOp) DeleteTXTPair Uses

func (o *RegisterOp) DeleteTXTPair(key string) error

DeleteTXTPair deletes the TXT string with the provided key.

func (*RegisterOp) Domain Uses

func (o *RegisterOp) Domain() string

Domain returns the domain associated with the op.

func (*RegisterOp) Host Uses

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 Uses

func (o *RegisterOp) InterfaceIndex() int

InterfaceIndex returns the interface index the op is tied to.

func (*RegisterOp) Name Uses

func (o *RegisterOp) Name() string

Name returns the name of the service.

func (*RegisterOp) NoAutoRename Uses

func (o *RegisterOp) NoAutoRename() bool

NoAutoRename indicates how service-name conflicts will be handled.

func (*RegisterOp) Port Uses

func (o *RegisterOp) Port() int

Port returns the port the service is available from.

func (*RegisterOp) SetCallback Uses

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 Uses

func (o *RegisterOp) SetDomain(s string) error

SetDomain sets the domain associated with the op.

func (*RegisterOp) SetHost Uses

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 Uses

func (o *RegisterOp) SetInterfaceIndex(i int) error

SetInterfaceIndex sets the interface index the op is tied to.

func (*RegisterOp) SetName Uses

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 Uses

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 Uses

func (o *RegisterOp) SetPort(p int) error

SetPort sets the port the service is available from.

func (*RegisterOp) SetTXTPair Uses

func (o *RegisterOp) SetTXTPair(key, value string) error

SetTXTPair creates or updates a TXT string with the provided value.

func (*RegisterOp) SetType Uses

func (o *RegisterOp) SetType(s string) error

SetType sets the service type associated with the op.

func (*RegisterOp) Start Uses

func (o *RegisterOp) Start() error

Start begins advertising the service.

func (*RegisterOp) Stop Uses

func (o *RegisterOp) Stop()

Stop stops the operation.

func (*RegisterOp) Type Uses

func (o *RegisterOp) Type() string

Type returns the service type associated with the op.

type ResolveCallbackFunc Uses

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.

Code:

if err != nil {
    // op is now inactive
    log.Printf("Resolve operation failed: %s", err)
    return
}
log.Printf("Resolved service to host %s port %d with meta info: %v", host, port, txt)

type ResolveOp Uses

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.

Code:

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()

func NewResolveOp Uses

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 Uses

func StartResolveOp(interfaceIndex int, name, serviceType, domain string, f ResolveCallbackFunc) (*ResolveOp, error)

StartResolveOp returns the equivalent of calling NewResolveOp and Start.

func (*ResolveOp) Active Uses

func (o *ResolveOp) Active() bool

Active indicates whether an operation is active

func (*ResolveOp) Domain Uses

func (o *ResolveOp) Domain() string

Domain returns the domain associated with the op.

func (*ResolveOp) InterfaceIndex Uses

func (o *ResolveOp) InterfaceIndex() int

InterfaceIndex returns the interface index the op is tied to.

func (*ResolveOp) Name Uses

func (o *ResolveOp) Name() string

Name returns the name of the service.

func (*ResolveOp) SetCallback Uses

func (o *ResolveOp) SetCallback(f ResolveCallbackFunc) error

SetCallback sets the function to call when a service is resolved or an error occurs.

func (*ResolveOp) SetDomain Uses

func (o *ResolveOp) SetDomain(s string) error

SetDomain sets the domain associated with the op.

func (*ResolveOp) SetInterfaceIndex Uses

func (o *ResolveOp) SetInterfaceIndex(i int) error

SetInterfaceIndex sets the interface index the op is tied to.

func (*ResolveOp) SetName Uses

func (o *ResolveOp) SetName(n string) error

SetName set's the name of the service.

func (*ResolveOp) SetType Uses

func (o *ResolveOp) SetType(s string) error

SetType sets the service type associated with the op.

func (*ResolveOp) Start Uses

func (o *ResolveOp) Start() error

Start begins the resolve operation. Resolve operations should be stopped as soon as they are no longer needed.

func (*ResolveOp) Stop Uses

func (o *ResolveOp) Stop()

Stop stops the operation.

func (*ResolveOp) Type Uses

func (o *ResolveOp) Type() string

Type returns the service type associated with the op.

Package dnssd imports 7 packages (graph) and is imported by 3 packages. Updated 2016-12-22. Refresh now. Tools for package owners.