mdns

package module
v0.0.0-...-0a72d1e Latest Latest
Warning

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

Go to latest
Published: Apr 18, 2026 License: MIT Imports: 15 Imported by: 0

README

mDNS

mDNS implementation with service discovery and advertisement.

Features

  • Service discovery (one-shot and continuous queries)
  • Service advertisement with conflict probing
  • Exponential backoff announcements
  • Goodbye packets on shutdown
  • IPv4/IPv6 dual-stack support

Usage

go get github.com/cyberxnomad/mdns

See examples for more usage examples.

Query
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()

ch, err := mdns.Query(ctx, []mdns.Question{{Type: "_http._tcp"}})
if err != nil {
    log.Fatal(err)
}

for entry := range ch {
    fmt.Printf("%s at %s:%d\n", entry.Instance, entry.Host, entry.Port)
}
Respond
type myService struct{}

func (s *myService) Hostname() string        { return "my-device" }
func (s *myService) Port() uint16            { return 8080 }
func (s *myService) IPAddrs() []net.IPAddr   { return nil }
func (s *myService) Text() map[string]string { return map[string]string{"v": "1.0"} }

func main() {
    r := mdns.NewResponder()
    r.Serve()
    defer r.Shutdown()

    r.Register(mdns.Service{
        Instance: "My Server",
        Type:     "_http._tcp",
    }, &myService{})

    // ...
}

Status

API is not yet stable. Some features are incomplete:

  • TC (truncated) bit is not supported
  • Simultaneous probe tiebreaking is not implemented
  • Known-Answer Suppression only covers PTR records
  • Cache is not implemented
  • Logging is not yet implemented

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT

Documentation

Index

Constants

Variables

View Source
var (
	ErrNoEligibleIface    = errors.New("no eligible network interfaces found for mDNS")
	ErrFQDNLen            = errors.New("FQDN length exceeds 255 bytes")
	ErrDomainRequired     = errors.New("domain is required")
	ErrResponderNotServed = errors.New("responder not served")
	ErrResponderServed    = errors.New("responder already served")
	ErrServiceNotFound    = errors.New("service not registered")
	ErrServiceRegistered  = errors.New("service already registered")
	ErrServiceConflict    = errors.New("service name conflict detected")
)
View Source
var TypeEnumQuestion = Question{
	Type:   "_services._dns-sd._udp",
	Domain: "local",
	Record: TypePTR,
}

TypeEnumQuestion is a convenient predefined question for service type enumeration. It queries for "_services._dns-sd._udp.local." to discover all available service types.

Functions

func Query

func Query(ctx context.Context, questions []Question, options ...QueryOption) (<-chan *ServiceEntry, error)

Query performs an mDNS query and returns a channel of discovered services.

The query runs asynchronously. Results are streamed to the returned channel as they are received. The channel is closed when the query completes, the context is canceled, or an error occurs.

For continuous queries, the channel remains open and receives updates until the context is canceled.

Types

type AttrsProvider

type AttrsProvider interface {
	// Hostname returns the local hostname (without the ".local" suffix).
	Hostname() string

	// Port returns the service port number.
	Port() uint16

	// IPAddrs returns the IP addresses of the host.
	IPAddrs() []net.IPAddr

	// Text returns the TXT record key-value pairs.
	Text() map[string]string
}

AttrsProvider supplies runtime attributes for a registered service. These values may change over time and are queried when constructing responses.

type InterfaceFilter

type InterfaceFilter func(iface net.Interface) bool

InterfaceFilter is a function type that filters network interfaces. It returns true if the interface should be used, false otherwise.

type NetworkStack

type NetworkStack uint

NetworkStack defines bitmask for supported IP protocols.

const (
	IPv4 NetworkStack = 1 << iota
	IPv6
)

type QueryOption

type QueryOption func(q *querier)

QueryOption configures a querier instance.

func QueryWithContinuous

func QueryWithContinuous(enable bool) QueryOption

QueryWithContinuous enables or disables continuous querying mode.

If enabled, multicast responses are forcibly enabled (RFC6762 Section 5.2).

func QueryWithInterfaceFilter

func QueryWithInterfaceFilter(filter InterfaceFilter) QueryOption

QueryWithInterfaceFilter sets a filter function to select network interfaces.

func QueryWithMulticastResponse

func QueryWithMulticastResponse(enable bool) QueryOption

QueryWithMulticastResponse enables or disables multicast responses.

If false, the QU bit is set to request unicast responses.

func QueryWithNetwork

func QueryWithNetwork(network NetworkStack) QueryOption

QueryWithNetwork sets the IP protocol stack to use.

type Question

type Question struct {
	// Instance name (optional, used for specific instance query).
	// e.g. "My Web Server"
	Instance string

	// Service type.
	// e.g. "_http._tcp"
	Type string

	// Domain name.
	// Default to "local" if empty.
	Domain string

	// Record type to query (PTR, SRV, TXT, etc.).
	// Default to TypePTR if 0.
	Record RecordType
}

Question defines the parameters for an mDNS query request.

type RecordType

type RecordType uint16

type Responder

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

Responder is an mDNS responder that advertises services and answers queries.

func NewResponder

func NewResponder(options ...ResponderOption) *Responder

NewResponder creates a new mDNS Responder with the given options.

func (*Responder) Register

func (r *Responder) Register(svc Service, provider AttrsProvider) error

Register adds a service to be advertised via mDNS. It performs conflict probing before announcing the service.

Returns `ErrResponderNotServed` if the Responder is not running. Returns `ErrServiceRegistered` if the service is already registered. Returns `ErrServiceConflict` if a name conflict is detected during probing.

func (*Responder) Serve

func (r *Responder) Serve() error

Serve starts the mDNS responder, binding to network interfaces and listening for queries.

Returns `ErrResponderServed` if the responder is already running.

func (*Responder) Shutdown

func (r *Responder) Shutdown() error

Shutdown stops the mDNS responder, sends Goodbye packets for all services, and closes all network connections.

Returns `ErrResponderNotServed` if the responder is not running.

func (*Responder) Unregister

func (r *Responder) Unregister(svc Service) error

Unregister stops advertising a service and sends a Goodbye announcement.

Returns `ErrResponderNotServed` if the Responder is not running. Returns `ErrServiceNotFound` if the service is not registered.

func (*Responder) Update

func (r *Responder) Update(svc Service, provider AttrsProvider) error

Update refreshes the runtime attributes of a registered service.

It stops any ongoing announcements, updates the service's attributes and TTL, and restarts the announcement process if the service was actively announcing. If the service had finished announcing, a single announcement is sent.

Note: The service identity (Instance, Type, Domain) cannot be changed. To change the identity, Unregister the old service and Register a new one.

Returns `ErrResponderNotServed` if the Responder is not running. Returns `ErrServiceNotFound` if the service is not registered.

type ResponderOption

type ResponderOption func(*Responder)

ResponderOption configures a Responder instance.

func ResponderWithAnnounceCount

func ResponderWithAnnounceCount(count int) ResponderOption

ResponderWithAnnounceCount sets the number of announcement packets to send. The value is clamped between 2 and 8 per RFC6762 Section 8.3.

func ResponderWithInterfaceFilter

func ResponderWithInterfaceFilter(filter InterfaceFilter) ResponderOption

ResponderWithInterfaceFilter sets a filter function to select which network interfaces to use. Only interfaces for which the filter returns true will be used.

func ResponderWithNetwork

func ResponderWithNetwork(network NetworkStack) ResponderOption

ResponderWithNetwork sets the IP protocol stack to use (IPv4, IPv6, or both).

func ResponderWithProbeRetryCount

func ResponderWithProbeRetryCount(count int) ResponderOption

ResponderWithProbeRetryCount sets the number of probe packets to send. Default is 3.

func ResponderWithProbeWaitTime

func ResponderWithProbeWaitTime(waitTime time.Duration) ResponderOption

ResponderWithProbeWaitTime sets the time to wait between probe packets. Default is 250ms (RFC6762 Section 8.1).

type Service

type Service struct {
	// Instance is the user-friendly name of the service instance.
	// e.g., "My Web Server"
	Instance string

	// Type is the service type in the format "_application._protocol".
	// e.g., "_http._tcp"
	Type string

	// Domain is the DNS domain for the service.
	// Default to "local" if empty.
	Domain string

	// TTL is the time-to-live for advertised records in seconds.
	// Default to 120 if 0.
	TTL uint32
}

Service represents a service to be advertised via mDNS.

type ServiceEntry

type ServiceEntry struct {
	// Name is the fully qualified domain name (FQDN) of the service instance.
	// Format: "<Instance>.<Type>.<Domain>."
	// e.g. "My Web Server._http._tcp.local."
	Name string

	// Instance is the user-friendly name of the service instance.
	// e.g. "My Web Server"
	Instance string

	// Type is the service type in the format "_application._protocol".
	// e.g. "_http._tcp"
	Type string

	// Domain is the DNS domain for the service.
	// e.g. "local"
	Domain string

	// Host is the hostname of the device providing the service.
	// e.g. "macbook.local."
	Host string

	// Port is the port number on which the service is available.
	Port uint16

	// IPAddrs contains the IP addresses of the host.
	// Including both IPv4 and IPv6.
	IPAddrs []net.IPAddr

	// Text contains the TXT record key-value pairs.
	Text map[string]string

	// TTL is the time-to-live in seconds from the original resource record.
	TTL uint32

	// Expiry is the expiration time calculated from TTL.
	Expiry time.Time
}

ServiceEntry represents a discovered mDNS service instance.

Directories

Path Synopsis
examples
instance_query command
responder command
type_enumerate command

Jump to

Keyboard shortcuts

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