mdns.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. package mdns
  2. import (
  3. "context"
  4. "log"
  5. "net"
  6. "strings"
  7. "time"
  8. "github.com/grandcat/zeroconf"
  9. )
  10. type MDNSHost struct {
  11. MDNS *zeroconf.Server
  12. Host *NetworkHost
  13. }
  14. type NetworkHost struct {
  15. HostName string
  16. Port int
  17. IPv4 []net.IP
  18. Domain string
  19. Model string
  20. UUID string
  21. Vendor string
  22. BuildVersion string
  23. MinorVersion string
  24. }
  25. func NewMDNS(config NetworkHost) (*MDNSHost, error) {
  26. //Register the mds services
  27. //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)
  28. 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)
  29. if err != nil {
  30. return &MDNSHost{}, err
  31. }
  32. return &MDNSHost{
  33. MDNS: server,
  34. Host: &config,
  35. }, nil
  36. }
  37. func (m *MDNSHost) Close() {
  38. if m != nil {
  39. m.MDNS.Shutdown()
  40. }
  41. }
  42. //Scan with given timeout and domain filter. Use m.Host.Domain for scanning similar typed devices
  43. func (m *MDNSHost) Scan(timeout int, domainFilter string) []*NetworkHost {
  44. // Discover all services on the network (e.g. _workstation._tcp)
  45. resolver, err := zeroconf.NewResolver(nil)
  46. if err != nil {
  47. log.Fatalln("Failed to initialize resolver:", err.Error())
  48. }
  49. entries := make(chan *zeroconf.ServiceEntry)
  50. //Create go routine to wait for the resolver
  51. discoveredHost := []*NetworkHost{}
  52. go func(results <-chan *zeroconf.ServiceEntry) {
  53. for entry := range results {
  54. if domainFilter == "" {
  55. //This is a ArOZ Online Host
  56. //Split the required information out of the text element
  57. TEXT := entry.Text
  58. properties := map[string]string{}
  59. for _, v := range TEXT {
  60. kv := strings.Split(v, "=")
  61. if len(kv) == 2 {
  62. properties[kv[0]] = kv[1]
  63. }
  64. }
  65. //log.Println(properties)
  66. discoveredHost = append(discoveredHost, &NetworkHost{
  67. HostName: entry.HostName,
  68. Port: entry.Port,
  69. IPv4: entry.AddrIPv4,
  70. Domain: properties["domain"],
  71. Model: properties["model"],
  72. UUID: properties["uuid"],
  73. Vendor: properties["vendor"],
  74. BuildVersion: properties["version_build"],
  75. MinorVersion: properties["version_minor"],
  76. })
  77. } else {
  78. if stringInSlice("domain="+domainFilter, entry.Text) {
  79. //This is a ArOZ Online Host
  80. //Split the required information out of the text element
  81. TEXT := entry.Text
  82. properties := map[string]string{}
  83. for _, v := range TEXT {
  84. kv := strings.Split(v, "=")
  85. if len(kv) == 2 {
  86. properties[kv[0]] = kv[1]
  87. }
  88. }
  89. //log.Println(properties)
  90. discoveredHost = append(discoveredHost, &NetworkHost{
  91. HostName: entry.HostName,
  92. Port: entry.Port,
  93. IPv4: entry.AddrIPv4,
  94. Domain: properties["domain"],
  95. Model: properties["model"],
  96. UUID: properties["uuid"],
  97. Vendor: properties["vendor"],
  98. BuildVersion: properties["version_build"],
  99. MinorVersion: properties["version_minor"],
  100. })
  101. }
  102. }
  103. }
  104. }(entries)
  105. //Resolve each of the mDNS and pipe it back to the log functions
  106. ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(timeout))
  107. defer cancel()
  108. err = resolver.Browse(ctx, "_http._tcp", "local.", entries)
  109. if err != nil {
  110. log.Fatalln("Failed to browse:", err.Error())
  111. }
  112. <-ctx.Done()
  113. return discoveredHost
  114. }