dnssd

package module
v0.0.0-...-242ed8d Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 22, 2016 License: MIT Imports: 7 Imported by: 2

README

dnssd

This package broke with Go 1.6

This is an MIT licensed Go wrapper for Apple's C DNS Service Discovery API.

Please see godoc via the web or godoc github.com/andrewtj/dnssd for further information.

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.

  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

Constants

View Source
const InterfaceIndexAny = 0

InterfaceIndexAny is the default for all operations.

View Source
const InterfaceIndexLocalOnly = int(^uint(0) >> 1)

InterfaceIndexLocalOnly limits the scope of the operation to the local machine.

Variables

View Source
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.

View Source
var ErrMissingCallback = errors.New("no callback set")

ErrMissingCallback is returned when an operation is started without setting a callback.

View Source
var ErrStarted = errors.New("already started")

ErrStarted is returned when trying to mutate an active operation or when starting a started operation.

View Source
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.

View Source
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) Domain

func (o *BrowseOp) Domain() string

Domain returns the domain associated with the op.

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

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

SetDomain sets the domain associated with the op.

func (*BrowseOp) SetInterfaceIndex

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

SetInterfaceIndex sets the interface index the op is tied to.

func (*BrowseOp) SetType

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

SetType sets the service type associated with the op.

func (*BrowseOp) Start

func (o *BrowseOp) Start() error

Start begins the browse query.

func (*BrowseOp) Stop

func (o *BrowseOp) Stop()

Stop stops the operation.

func (*BrowseOp) Type

func (o *BrowseOp) Type() string

Type returns the service type associated with the op.

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.

func (Error) Desc

func (e Error) Desc() string

Desc returns a string describing the error.

func (Error) Error

func (e Error) Error() string

func (Error) Num

func (e Error) Num() int32

Num returns an error number.

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

func (o *QueryOp) Class() uint16

Class returns the DNS Resource Record Class for the operation.

func (*QueryOp) InterfaceIndex

func (o *QueryOp) InterfaceIndex() int

InterfaceIndex returns the interface index the op is tied to.

func (*QueryOp) Name

func (o *QueryOp) Name() string

Name returns the domain name for the operation.

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

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

SetClass sets the DNS Resource Record Class for the operation.

func (*QueryOp) SetInterfaceIndex

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

SetInterfaceIndex sets the interface index the op is tied to.

func (*QueryOp) SetName

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

SetName sets the domain name for the operation.

func (*QueryOp) SetType

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

SetType sets the DNS Resource Record Type for the operation.

func (*QueryOp) Start

func (o *QueryOp) Start() error

Start begins the query operation.

func (*QueryOp) Stop

func (o *QueryOp) Stop()

Stop stops the operation.

func (*QueryOp) Type

func (o *QueryOp) Type() uint16

Type returns the DNS Resource Record Type for the operation.

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

func (o *RegisterOp) Name() string

Name returns the name of the service.

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

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

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

func (o *RegisterOp) Start() error

Start begins advertising the service.

func (*RegisterOp) Stop

func (o *RegisterOp) Stop()

Stop stops the operation.

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

func (o *ResolveOp) Domain() string

Domain returns the domain associated with the op.

func (*ResolveOp) InterfaceIndex

func (o *ResolveOp) InterfaceIndex() int

InterfaceIndex returns the interface index the op is tied to.

func (*ResolveOp) Name

func (o *ResolveOp) Name() string

Name returns the name of the service.

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

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

SetDomain sets the domain associated with the op.

func (*ResolveOp) SetInterfaceIndex

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

SetInterfaceIndex sets the interface index the op is tied to.

func (*ResolveOp) SetName

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

SetName set's the name of the service.

func (*ResolveOp) SetType

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

SetType sets the service type associated with the op.

func (*ResolveOp) Start

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

func (o *ResolveOp) Stop()

Stop stops the operation.

func (*ResolveOp) Type

func (o *ResolveOp) Type() string

Type returns the service type associated with the op.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL