-
Notifications
You must be signed in to change notification settings - Fork 40
Expand file tree
/
Copy pathconfig.go
More file actions
316 lines (241 loc) · 8.22 KB
/
config.go
File metadata and controls
316 lines (241 loc) · 8.22 KB
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
// SPDX-FileCopyrightText: The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT
package mdns
import (
"errors"
"net"
"time"
"github.com/pion/logging"
"golang.org/x/net/dns/dnsmessage"
)
var (
errResponseTTLZero = errors.New("response TTL must be greater than 0")
errRefreshIntervalNonPositive = errors.New("refresh interval must be greater than 0")
)
const (
// DefaultAddressIPv4 is the default used by mDNS
// and in most cases should be the address that the
// ipv4.PacketConn passed to Server or NewServer is bound to.
DefaultAddressIPv4 = "224.0.0.0:5353"
// DefaultAddressIPv6 is the default IPv6 address used
// by mDNS and in most cases should be the address that
// the ipv6.PacketConn passed to Server or NewServer is bound to.
DefaultAddressIPv6 = "[FF02::]:5353"
)
// Config is used to configure a mDNS client or server.
type Config struct {
// Name is the name of the client/server used for logging purposes.
Name string
// QueryInterval controls how often we sends Queries until we
// get a response for the requested name.
QueryInterval time.Duration
// LocalNames are the names that we will generate answers for
// when we get questions.
LocalNames []string
// LocalAddress will override the published address with the given IP
// when set. Otherwise, the automatically determined address will be used.
LocalAddress net.IP
// LoggerFactory is used to create a logger for the server.
LoggerFactory logging.LoggerFactory
// IncludeLoopback will include loopback interfaces to be eligible for queries and answers.
IncludeLoopback bool
// Interfaces will override the interfaces used for queries and answers.
Interfaces []net.Interface
}
// ServerOption configures a Server.
type ServerOption interface {
applyServer(*serverConfig) error
}
// ClientOption configures a Client.
type ClientOption interface {
applyClient(*clientConfig) error
}
// clientConfig holds configuration for a future dedicated Client type.
// Currently used to demonstrate shared options between Server and Client.
type clientConfig struct {
name string
queryInterval time.Duration
loggerFactory logging.LoggerFactory
includeLoopback bool
interfaces []net.Interface
}
// nameOption sets the name for logging.
type nameOption string
// WithName sets the name used for logging purposes.
func WithName(name string) nameOption {
return nameOption(name)
}
func (o nameOption) applyServer(c *serverConfig) error {
c.name = string(o)
return nil
}
func (o nameOption) applyClient(c *clientConfig) error {
c.name = string(o)
return nil
}
// loggerFactoryOption sets the logger factory.
type loggerFactoryOption struct {
factory logging.LoggerFactory
}
// WithLoggerFactory sets the logger factory for creating loggers.
func WithLoggerFactory(factory logging.LoggerFactory) loggerFactoryOption {
return loggerFactoryOption{factory: factory}
}
func (o loggerFactoryOption) applyServer(c *serverConfig) error {
c.loggerFactory = o.factory
return nil
}
func (o loggerFactoryOption) applyClient(c *clientConfig) error {
c.loggerFactory = o.factory
return nil
}
// includeLoopbackOption sets whether to include loopback interfaces.
type includeLoopbackOption bool
// WithIncludeLoopback sets whether loopback interfaces should be included.
func WithIncludeLoopback(include bool) includeLoopbackOption {
return includeLoopbackOption(include)
}
func (o includeLoopbackOption) applyServer(c *serverConfig) error {
c.includeLoopback = bool(o)
return nil
}
func (o includeLoopbackOption) applyClient(c *clientConfig) error {
c.includeLoopback = bool(o)
return nil
}
// interfacesOption sets the interfaces to use.
type interfacesOption []net.Interface
// WithInterfaces sets the network interfaces to use.
// If not set, all suitable interfaces will be discovered automatically.
func WithInterfaces(ifaces ...net.Interface) interfacesOption {
return interfacesOption(ifaces)
}
func (o interfacesOption) applyServer(c *serverConfig) error {
c.interfaces = []net.Interface(o)
return nil
}
func (o interfacesOption) applyClient(c *clientConfig) error {
c.interfaces = []net.Interface(o)
return nil
}
// Server-only options
// localNamesOption sets the local names to respond to.
type localNamesOption []string
// WithLocalNames sets the names that the server will respond to.
// These are the mDNS names that this server will generate answers for.
func WithLocalNames(names ...string) localNamesOption {
return localNamesOption(names)
}
func (o localNamesOption) applyServer(c *serverConfig) error {
c.localNames = []string(o)
return nil
}
// localAddressOption sets the local address to publish.
type localAddressOption struct {
addr net.IP
}
// WithLocalAddress sets the IP address to publish in responses.
// If not set, the address will be automatically determined from the interface.
func WithLocalAddress(addr net.IP) localAddressOption {
return localAddressOption{addr: addr}
}
func (o localAddressOption) applyServer(c *serverConfig) error {
c.localAddress = o.addr
return nil
}
// recordTypesOption limits which record types are processed.
type recordTypesOption []dnsmessage.Type
// WithRecordTypes limits which DNS record types the server will process.
// By default (if not called), all record types are allowed - no filtering.
//
// For WebRTC/ICE usage (legacy behavior), restrict to address records:
//
// mdns.WithRecordTypes(dnsmessage.TypeA, dnsmessage.TypeAAAA)
func WithRecordTypes(types ...dnsmessage.Type) recordTypesOption {
return recordTypesOption(types)
}
func (o recordTypesOption) applyServer(c *serverConfig) error {
c.allowedRecordTypes = []dnsmessage.Type(o)
return nil
}
// serviceOption registers a DNS-SD service instance to advertise.
type serviceOption struct {
svc ServiceInstance
}
// WithService registers a DNS-SD service instance to be advertised.
// May be called multiple times to register multiple services.
//
// The Domain defaults to "local" if unset.
//
// Example:
//
// mdns.NewServer(v4, v6,
// mdns.WithLocalNames("myhost.local"),
// mdns.WithService(mdns.ServiceInstance{
// Instance: "My Web Server",
// Service: "_http._tcp",
// Port: 8080,
// }),
// )
func WithService(svc ServiceInstance) serviceOption {
return serviceOption{svc: svc}
}
func (o serviceOption) applyServer(cfg *serverConfig) error {
if err := validateInstanceName(o.svc.Instance); err != nil {
return err
}
if err := validateServiceName(o.svc.Service); err != nil {
return err
}
if err := validateTXTEntries(o.svc.Text); err != nil {
return err
}
// Default domain to "local".
if o.svc.Domain == "" {
o.svc.Domain = "local"
}
cfg.services = append(cfg.services, o.svc)
return nil
}
// responseTTLOption sets the TTL for DNS responses.
type responseTTLOption uint32
// WithResponseTTL sets the TTL (in seconds) for DNS response records.
// Default is 120 seconds per RFC 6762 recommendation.
func WithResponseTTL(seconds uint32) responseTTLOption {
return responseTTLOption(seconds)
}
func (o responseTTLOption) applyServer(c *serverConfig) error {
if o == 0 {
return errResponseTTLZero
}
c.responseTTL = uint32(o)
return nil
}
// cacheRefreshOption enables or disables proactive cache refresh.
type cacheRefreshOption bool
// WithCacheRefresh enables or disables proactive cache refresh per RFC 6762 §5.2.
// When enabled, actively-monitored records are re-queried at 80/85/90/95%
// of their TTL. Enabled by default in NewServer; disabled in the legacy
// Server constructor.
func WithCacheRefresh(enable bool) cacheRefreshOption {
return cacheRefreshOption(enable)
}
func (o cacheRefreshOption) applyServer(c *serverConfig) error {
c.cacheRefresh = bool(o)
return nil
}
// refreshIntervalOption sets the refresh check interval.
type refreshIntervalOption time.Duration
// WithRefreshInterval sets how often the cache refresh loop checks for
// records due for refresh. Default is 2 seconds. Must be greater than
// zero. Only effective when cache refresh is enabled.
func WithRefreshInterval(interval time.Duration) refreshIntervalOption {
return refreshIntervalOption(interval)
}
func (o refreshIntervalOption) applyServer(c *serverConfig) error {
if o <= 0 {
return errRefreshIntervalNonPositive
}
c.refreshCheckInterval = time.Duration(o)
return nil
}