diff --git a/lib/connections/service.go b/lib/connections/service.go index 6e97fd70..c197abf4 100644 --- a/lib/connections/service.go +++ b/lib/connections/service.go @@ -504,6 +504,13 @@ func (s *Service) CommitConfiguration(from, to config.Configuration) bool { s.listenersMut.Lock() seen := make(map[string]struct{}) for _, addr := range config.Wrap("", to).ListenAddresses() { + if addr == "" { + // We can get an empty address if there is an empty listener + // element in the config, indicating no listeners should be + // used. This is not an error. + continue + } + if _, ok := s.listeners[addr]; ok { seen[addr] = struct{}{} continue diff --git a/lib/discover/global.go b/lib/discover/global.go index 588fc94a..b38cc2f1 100644 --- a/lib/discover/global.go +++ b/lib/discover/global.go @@ -208,8 +208,10 @@ func (c *globalClient) sendAnnouncement(timer *time.Timer) { } if len(ann.Addresses) == 0 { - c.setError(errors.New("nothing to announce")) - l.Debugln("Nothing to announce") + // There are legitimate cases for not having anything to announce, + // yet still using global discovery for lookups. Do not error out + // here. + c.setError(nil) timer.Reset(announceErrorRetryInterval) return } diff --git a/lib/discover/global_test.go b/lib/discover/global_test.go index 8b0f0ac8..755aa8b7 100644 --- a/lib/discover/global_test.go +++ b/lib/discover/global_test.go @@ -214,7 +214,7 @@ func TestGlobalAnnounce(t *testing.T) { } if !strings.Contains(string(s.announce), "tcp://0.0.0.0:22000") { - t.Errorf("announce missing addresses address: %s", s.announce) + t.Errorf("announce missing address: %q", s.announce) } } diff --git a/lib/discover/local.go b/lib/discover/local.go index ed49902d..968545d7 100644 --- a/lib/discover/local.go +++ b/lib/discover/local.go @@ -112,24 +112,42 @@ func (c *localClient) Error() error { return c.beacon.Error() } -func (c *localClient) announcementPkt() Announce { - return Announce{ - ID: c.myID, - Addresses: c.addrList.AllAddresses(), - InstanceID: rand.Int63(), +// announcementPkt appends the local discovery packet to send to msg. Returns +// true if the packet should be sent, false if there is nothing useful to +// send. +func (c *localClient) announcementPkt(instanceID int64, msg []byte) ([]byte, bool) { + addrs := c.addrList.AllAddresses() + if len(addrs) == 0 { + // Nothing to announce + return msg, false } -} -func (c *localClient) sendLocalAnnouncements() { - msg := make([]byte, 4) + if cap(msg) >= 4 { + msg = msg[:4] + } else { + msg = make([]byte, 4) + } binary.BigEndian.PutUint32(msg, Magic) - var pkt = c.announcementPkt() + pkt := Announce{ + ID: c.myID, + Addresses: addrs, + InstanceID: instanceID, + } bs, _ := pkt.Marshal() msg = append(msg, bs...) + return msg, true +} + +func (c *localClient) sendLocalAnnouncements() { + var msg []byte + var ok bool + instanceID := rand.Int63() for { - c.beacon.Send(msg) + if msg, ok = c.announcementPkt(instanceID, msg[:0]); ok { + c.beacon.Send(msg) + } select { case <-c.localBcastTick: diff --git a/lib/discover/local_test.go b/lib/discover/local_test.go index e3534198..422e6ec9 100644 --- a/lib/discover/local_test.go +++ b/lib/discover/local_test.go @@ -7,13 +7,14 @@ package discover import ( + "bytes" "net" "testing" "github.com/syncthing/syncthing/lib/protocol" ) -func TestRandomLocalInstanceID(t *testing.T) { +func TestLocalInstanceID(t *testing.T) { c, err := NewLocal(protocol.LocalDeviceID, ":0", &fakeAddressLister{}) if err != nil { t.Fatal(err) @@ -23,9 +24,15 @@ func TestRandomLocalInstanceID(t *testing.T) { lc := c.(*localClient) - p0 := lc.announcementPkt() - p1 := lc.announcementPkt() - if p0.InstanceID == p1.InstanceID { + p0, ok := lc.announcementPkt(1, nil) + if !ok { + t.Fatal("unexpectedly not ok") + } + p1, ok := lc.announcementPkt(2, nil) + if !ok { + t.Fatal("unexpectedly not ok") + } + if bytes.Equal(p0, p1) { t.Error("each generated packet should have a new instance id") } }