1
1
package zeroconf
2
2
3
3
import (
4
- "errors"
5
4
"fmt"
6
5
"log"
7
6
"math/rand"
@@ -75,8 +74,7 @@ func Register(instance, service, domain string, port int, text []string, ifaces
75
74
}
76
75
77
76
s .service = entry
78
- go s .mainloop ()
79
- go s .probe ()
77
+ s .start ()
80
78
81
79
return s , nil
82
80
}
@@ -132,8 +130,7 @@ func RegisterProxy(instance, service, domain string, port int, host string, ips
132
130
}
133
131
134
132
s .service = entry
135
- go s .mainloop ()
136
- go s .probe ()
133
+ s .start ()
137
134
138
135
return s , nil
139
136
}
@@ -151,7 +148,7 @@ type Server struct {
151
148
152
149
shouldShutdown chan struct {}
153
150
shutdownLock sync.Mutex
154
- shutdownEnd sync.WaitGroup
151
+ refCount sync.WaitGroup
155
152
isShutdown bool
156
153
ttl uint32
157
154
}
@@ -182,19 +179,17 @@ func newServer(ifaces []net.Interface) (*Server, error) {
182
179
return s , nil
183
180
}
184
181
185
- // Start listeners and waits for the shutdown signal from exit channel
186
- func (s * Server ) mainloop () {
182
+ func (s * Server ) start () {
187
183
if s .ipv4conn != nil {
184
+ s .refCount .Add (1 )
188
185
go s .recv4 (s .ipv4conn )
189
186
}
190
187
if s .ipv6conn != nil {
188
+ s .refCount .Add (1 )
191
189
go s .recv6 (s .ipv6conn )
192
190
}
193
- }
194
-
195
- // Shutdown closes all udp connections and unregisters the service
196
- func (s * Server ) Shutdown () {
197
- s .shutdown ()
191
+ s .refCount .Add (1 )
192
+ go s .probe ()
198
193
}
199
194
200
195
// SetText updates and announces the TXT records
@@ -208,15 +203,17 @@ func (s *Server) TTL(ttl uint32) {
208
203
s .ttl = ttl
209
204
}
210
205
211
- // Shutdown server will close currently open connections & channel
212
- func (s * Server ) shutdown () error {
206
+ // Shutdown closes all udp connections and unregisters the service
207
+ func (s * Server ) Shutdown () {
213
208
s .shutdownLock .Lock ()
214
209
defer s .shutdownLock .Unlock ()
215
210
if s .isShutdown {
216
- return errors . New ( "server is already shutdown" )
211
+ return
217
212
}
218
213
219
- err := s .unregister ()
214
+ if err := s .unregister (); err != nil {
215
+ log .Printf ("failed to unregister: %s" , err )
216
+ }
220
217
221
218
close (s .shouldShutdown )
222
219
@@ -228,20 +225,17 @@ func (s *Server) shutdown() error {
228
225
}
229
226
230
227
// Wait for connection and routines to be closed
231
- s .shutdownEnd .Wait ()
228
+ s .refCount .Wait ()
232
229
s .isShutdown = true
233
-
234
- return err
235
230
}
236
231
237
- // recv is a long running routine to receive packets from an interface
232
+ // recv4 is a long running routine to receive packets from an interface
238
233
func (s * Server ) recv4 (c * ipv4.PacketConn ) {
234
+ defer s .refCount .Done ()
239
235
if c == nil {
240
236
return
241
237
}
242
238
buf := make ([]byte , 65536 )
243
- s .shutdownEnd .Add (1 )
244
- defer s .shutdownEnd .Done ()
245
239
for {
246
240
select {
247
241
case <- s .shouldShutdown :
@@ -260,14 +254,13 @@ func (s *Server) recv4(c *ipv4.PacketConn) {
260
254
}
261
255
}
262
256
263
- // recv is a long running routine to receive packets from an interface
257
+ // recv6 is a long running routine to receive packets from an interface
264
258
func (s * Server ) recv6 (c * ipv6.PacketConn ) {
259
+ defer s .refCount .Done ()
265
260
if c == nil {
266
261
return
267
262
}
268
263
buf := make ([]byte , 65536 )
269
- s .shutdownEnd .Add (1 )
270
- defer s .shutdownEnd .Done ()
271
264
for {
272
265
select {
273
266
case <- s .shouldShutdown :
@@ -528,6 +521,8 @@ func (s *Server) serviceTypeName(resp *dns.Msg, ttl uint32) {
528
521
// Perform probing & announcement
529
522
//TODO: implement a proper probing & conflict resolution
530
523
func (s * Server ) probe () {
524
+ defer s .refCount .Done ()
525
+
531
526
q := new (dns.Msg )
532
527
q .SetQuestion (s .service .ServiceInstanceName (), dns .TypePTR )
533
528
q .RecursionDesired = false
@@ -555,16 +550,25 @@ func (s *Server) probe() {
555
550
}
556
551
q .Ns = []dns.RR {srv , txt }
557
552
558
- randomizer := rand .New (rand .NewSource (time .Now ().UnixNano ()))
559
-
560
553
// Wait for a random duration uniformly distributed between 0 and 250 ms
561
554
// before sending the first probe packet.
562
- time .Sleep (time .Duration (randomizer .Intn (250 )) * time .Millisecond )
555
+ timer := time .NewTimer (time .Duration (rand .Intn (250 )) * time .Millisecond )
556
+ defer timer .Stop ()
557
+ select {
558
+ case <- timer .C :
559
+ case <- s .shouldShutdown :
560
+ return
561
+ }
563
562
for i := 0 ; i < 3 ; i ++ {
564
563
if err := s .multicastResponse (q , 0 ); err != nil {
565
564
log .Println ("[ERR] zeroconf: failed to send probe:" , err .Error ())
566
565
}
567
- time .Sleep (250 * time .Millisecond )
566
+ timer .Reset (250 * time .Millisecond )
567
+ select {
568
+ case <- timer .C :
569
+ case <- s .shouldShutdown :
570
+ return
571
+ }
568
572
}
569
573
570
574
// From RFC6762
@@ -573,7 +577,7 @@ func (s *Server) probe() {
573
577
// packet loss, a responder MAY send up to eight unsolicited responses,
574
578
// provided that the interval between unsolicited responses increases by
575
579
// at least a factor of two with every response sent.
576
- timeout := 1 * time .Second
580
+ timeout := time .Second
577
581
for i := 0 ; i < multicastRepetitions ; i ++ {
578
582
for _ , intf := range s .ifaces {
579
583
resp := new (dns.Msg )
@@ -587,7 +591,12 @@ func (s *Server) probe() {
587
591
log .Println ("[ERR] zeroconf: failed to send announcement:" , err .Error ())
588
592
}
589
593
}
590
- time .Sleep (timeout )
594
+ timer .Reset (timeout )
595
+ select {
596
+ case <- timer .C :
597
+ case <- s .shouldShutdown :
598
+ return
599
+ }
591
600
timeout *= 2
592
601
}
593
602
}
@@ -719,7 +728,7 @@ func (s *Server) unicastResponse(resp *dns.Msg, ifIndex int, from net.Addr) erro
719
728
}
720
729
}
721
730
722
- // multicastResponse us used to send a multicast response packet
731
+ // multicastResponse is used to send a multicast response packet
723
732
func (s * Server ) multicastResponse (msg * dns.Msg , ifIndex int ) error {
724
733
buf , err := msg .Pack ()
725
734
if err != nil {
0 commit comments