diff --git a/dns-sd.go b/dns-sd.go index a07e269..7a2db38 100644 --- a/dns-sd.go +++ b/dns-sd.go @@ -206,6 +206,7 @@ func answerTo(records, knowns []dns.RR, question dns.Question) (answers, extras } // Returns any services from the msg that matches the provided search type. +// This includes unannouncements func servicesFromRecords(msg *dns.Msg) (services []*Service) { // TODO: Support meta-queries var ( @@ -222,23 +223,35 @@ func servicesFromRecords(msg *dns.Msg) (services []*Service) { // Note that stable sort is necessary to preserve order of A and AAAA records slices.SortStableFunc(answers, byRecordType) + // Create a svc record if it doesn't exist + ensureSvc := func(name string) *Service { + if svc = m[name]; svc != nil { + return svc + } + svc, err := parseServicePath(name) + if err != nil { + return nil + } + m[name] = svc + return svc + } + for _, answer := range answers { switch rr := answer.(type) { // Phase 1: create services case *dns.SRV: // pointer to service path, e.g. `My Printer._http._tcp.` - if svc, _ = parseServicePath(rr.Hdr.Name); svc == nil { + if svc = ensureSvc(rr.Hdr.Name); svc == nil { continue } svc.Hostname = rr.Target svc.Port = rr.Port svc.ttl = time.Second * time.Duration(rr.Hdr.Ttl) - m[rr.Hdr.Name] = svc // Phase 2: populate subtypes and text case *dns.PTR: - if svc = m[rr.Ptr]; svc == nil { + if svc = ensureSvc(rr.Ptr); svc == nil { continue } // parse type from query, e.g. `_printer._sub._http._tcp.local.` diff --git a/service.go b/service.go index d8cc4da..c14b3f8 100644 --- a/service.go +++ b/service.go @@ -118,6 +118,7 @@ func (s *Service) String() string { return fmt.Sprintf("%v.%v.%v", s.Name, s.Type.Name, s.Type.Domain) } +// Checks that the name and type are valid. The rest can be nullish when unannouncing. func (s *Service) Validate() error { if err := s.Type.Validate(); err != nil { return err @@ -125,9 +126,6 @@ func (s *Service) Validate() error { if s.Name == "" { return errors.New("no name specified") } - if s.Hostname == "" { - return errors.New("no hostname specified") - } return nil }