| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 | package mdnsimport (	"context"	"log"	"net"	"strings"	"time"	"github.com/grandcat/zeroconf")type MDNSHost struct {	MDNS *zeroconf.Server	Host *NetworkHost}type NetworkHost struct {	HostName     string	Port         int	IPv4         []net.IP	Domain       string	Model        string	UUID         string	Vendor       string	BuildVersion string	MinorVersion string}func NewMDNS(config NetworkHost) (*MDNSHost, error) {	//Register the mds services	//server, err := zeroconf.Register("ArOZ", "_http._tcp", "local.", *listen_port, []string{"version_build=" + build_version, "version_minor=" + internal_version, "vendor=" + deviceVendor, "model=" + deviceModel, "uuid=" + deviceUUID, "domain=aroz.online"}, nil)	server, err := zeroconf.Register(config.HostName, "_http._tcp", "local.", config.Port, []string{"version_build=" + config.BuildVersion, "version_minor=" + config.MinorVersion, "vendor=" + config.Vendor, "model=" + config.Model, "uuid=" + config.UUID, "domain=" + config.Domain}, nil)	if err != nil {		return &MDNSHost{}, err	}	return &MDNSHost{		MDNS: server,		Host: &config,	}, nil}func (m *MDNSHost) Close() {	if m != nil {		m.MDNS.Shutdown()	}}//Scan with given timeout and domain filter. Use m.Host.Domain for scanning similar typed devicesfunc (m *MDNSHost) Scan(timeout int, domainFilter string) []*NetworkHost {	// Discover all services on the network (e.g. _workstation._tcp)	resolver, err := zeroconf.NewResolver(nil)	if err != nil {		log.Fatalln("Failed to initialize resolver:", err.Error())	}	entries := make(chan *zeroconf.ServiceEntry)	//Create go routine  to wait for the resolver	discoveredHost := []*NetworkHost{}	go func(results <-chan *zeroconf.ServiceEntry) {		for entry := range results {			if domainFilter == "" {				//This is a ArOZ Online Host				//Split the required information out of the text element				TEXT := entry.Text				properties := map[string]string{}				for _, v := range TEXT {					kv := strings.Split(v, "=")					if len(kv) == 2 {						properties[kv[0]] = kv[1]					}				}				//log.Println(properties)				discoveredHost = append(discoveredHost, &NetworkHost{					HostName:     entry.HostName,					Port:         entry.Port,					IPv4:         entry.AddrIPv4,					Domain:       properties["domain"],					Model:        properties["model"],					UUID:         properties["uuid"],					Vendor:       properties["vendor"],					BuildVersion: properties["version_build"],					MinorVersion: properties["version_minor"],				})			} else {				if stringInSlice("domain="+domainFilter, entry.Text) {					//This is a ArOZ Online Host					//Split the required information out of the text element					TEXT := entry.Text					properties := map[string]string{}					for _, v := range TEXT {						kv := strings.Split(v, "=")						if len(kv) == 2 {							properties[kv[0]] = kv[1]						}					}					//log.Println(properties)					discoveredHost = append(discoveredHost, &NetworkHost{						HostName:     entry.HostName,						Port:         entry.Port,						IPv4:         entry.AddrIPv4,						Domain:       properties["domain"],						Model:        properties["model"],						UUID:         properties["uuid"],						Vendor:       properties["vendor"],						BuildVersion: properties["version_build"],						MinorVersion: properties["version_minor"],					})				}			}		}	}(entries)	//Resolve each of the mDNS and pipe it back to the log functions	ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(timeout))	defer cancel()	err = resolver.Browse(ctx, "_http._tcp", "local.", entries)	if err != nil {		log.Fatalln("Failed to browse:", err.Error())	}	<-ctx.Done()	return discoveredHost}
 |