-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdiscovery.go
125 lines (107 loc) · 2.5 KB
/
discovery.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package main
import (
"io/ioutil"
"log"
"net"
"reflect"
"time"
"github.com/hashicorp/mdns"
)
const (
QUERY_INTERVAL = 11 // in seconds
QUERY_TIMEOUT = 10 // in seconds
// Used to query all peers for their services
// https://github.com/libp2p/specs/blob/master/discovery/mdns.md#dns-service-discovery
MDNS_META_QUERY = "_services._dns-sd._udp"
DEFAULT_DOMAIN = "local"
)
type ServiceEntry = mdns.ServiceEntry // type alias
type Discovery struct {
Params *mdns.QueryParam
Entries []ServiceEntry
entriesCh chan *mdns.ServiceEntry
timer *time.Ticker
stop chan struct{}
}
var discoveries []*Discovery
var interfaces []*net.Interface
var domains []string
var discoveryLogger *log.Logger
func InitDiscovery(ifaces []string, domains []string) {
if len(ifaces) == 0 {
interfaces = GetInterfaces()
} else {
interfaces = GetInterfacesByName(ifaces)
}
domains = domains
discoveries = make([]*Discovery, 0)
discoveryLogger = log.New(ioutil.Discard, "", 0)
for _, itf := range interfaces {
for _, domain := range domains {
discovery := NewDiscovery(MDNS_META_QUERY, domain, itf)
discoveries = append(discoveries, discovery)
discovery.Start()
}
}
}
func NewDiscovery(service string, domain string, iface *net.Interface) *Discovery {
entriesCh := make(chan *mdns.ServiceEntry, 10)
entries := make([]ServiceEntry, 0)
return &Discovery{
Entries: entries,
entriesCh: entriesCh,
Params: &mdns.QueryParam{
Service: service,
Domain: domain,
Timeout: QUERY_TIMEOUT * time.Second,
Entries: entriesCh,
Interface: iface,
WantUnicastResponse: false,
DisableIPv4: false,
DisableIPv6: false,
Logger: discoveryLogger,
},
}
}
func (d *Discovery) Start() {
d.timer = time.NewTicker(QUERY_INTERVAL * time.Second)
d.stop = make(chan struct{})
go d.Run()
}
func (d *Discovery) Stop() {
close(d.stop)
}
func (d *Discovery) Run() {
defer d.timer.Stop()
// Running the queries at interval in it's own goroutine
go func() {
mdns.Query(d.Params)
for {
select {
case <-d.stop:
return
case <-d.timer.C:
mdns.Query(d.Params)
}
}
}()
for {
select {
case <-d.stop:
return
case <-d.entriesCh:
for entry := range d.entriesCh {
found := false
for _, existing := range d.Entries {
if reflect.DeepEqual(entry, existing) {
found = true
break
}
}
if !found {
d.Entries = append(d.Entries, *entry)
}
}
}
}
}