Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
99b00b6a5e | ||
|
|
1e9769cdd7 | ||
|
|
0dd7934405 | ||
|
|
8606b4dd8d | ||
|
|
075a699aae | ||
|
|
0a50f374db | ||
|
|
4949721c0b | ||
|
|
00ce889a8b |
@@ -503,6 +503,10 @@ func buildZip(target target) {
|
||||
|
||||
build(target, tags)
|
||||
|
||||
if goos == "windows" {
|
||||
windowsCodesign(target.BinaryName())
|
||||
}
|
||||
|
||||
for i := range target.archiveFiles {
|
||||
target.archiveFiles[i].src = strings.Replace(target.archiveFiles[i].src, "{{binary}}", target.BinaryName(), 1)
|
||||
target.archiveFiles[i].dst = strings.Replace(target.archiveFiles[i].dst, "{{binary}}", target.BinaryName(), 1)
|
||||
@@ -1092,6 +1096,43 @@ func macosCodesign(file string) {
|
||||
}
|
||||
}
|
||||
|
||||
func windowsCodesign(file string) {
|
||||
st := "signtool.exe"
|
||||
|
||||
if path := os.Getenv("CODESIGN_SIGNTOOL"); path != "" {
|
||||
st = path
|
||||
}
|
||||
|
||||
for i, algo := range []string{"sha1", "sha256"} {
|
||||
args := []string{"sign", "/fd", algo}
|
||||
if f := os.Getenv("CODESIGN_CERTIFICATE_FILE"); f != "" {
|
||||
args = append(args, "/f", f)
|
||||
}
|
||||
if p := os.Getenv("CODESIGN_CERTIFICATE_PASSWORD"); p != "" {
|
||||
args = append(args, "/p", p)
|
||||
}
|
||||
if tr := os.Getenv("CODESIGN_TIMESTAMP_SERVER"); tr != "" {
|
||||
switch algo {
|
||||
case "sha256":
|
||||
args = append(args, "/tr", tr, "/td", algo)
|
||||
default:
|
||||
args = append(args, "/t", tr)
|
||||
}
|
||||
}
|
||||
if i > 0 {
|
||||
args = append(args, "/as")
|
||||
}
|
||||
args = append(args, file)
|
||||
|
||||
bs, err := runError(st, args...)
|
||||
if err != nil {
|
||||
log.Println("Codesign: signing failed:", string(bs))
|
||||
return
|
||||
}
|
||||
log.Println("Codesign: successfully signed", file, "using", algo)
|
||||
}
|
||||
}
|
||||
|
||||
func metalint() {
|
||||
lazyRebuildAssets()
|
||||
runPrint("go", "test", "-run", "Metalint", "./meta")
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
|
||||
"github.com/rcrowley/go-metrics"
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/connections"
|
||||
"github.com/syncthing/syncthing/lib/db"
|
||||
"github.com/syncthing/syncthing/lib/discover"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
@@ -98,7 +99,7 @@ type modelIntf interface {
|
||||
ScanFolders() map[string]error
|
||||
ScanFolderSubdirs(folder string, subs []string) error
|
||||
BringToFront(folder, file string)
|
||||
ConnectedTo(deviceID protocol.DeviceID) bool
|
||||
Connection(deviceID protocol.DeviceID) (connections.Connection, bool)
|
||||
GlobalSize(folder string) db.Counts
|
||||
LocalSize(folder string) db.Counts
|
||||
CurrentSequence(folder string) (int64, bool)
|
||||
@@ -1259,7 +1260,7 @@ func (s *apiService) getPeerCompletion(w http.ResponseWriter, r *http.Request) {
|
||||
for _, folder := range s.cfg.Folders() {
|
||||
for _, device := range folder.DeviceIDs() {
|
||||
deviceStr := device.String()
|
||||
if s.model.ConnectedTo(device) {
|
||||
if _, ok := s.model.Connection(device); ok {
|
||||
tot[deviceStr] += s.model.Completion(device, folder.ID).CompletionPct
|
||||
} else {
|
||||
tot[deviceStr] = 0
|
||||
|
||||
+3
-10
@@ -87,13 +87,6 @@ const (
|
||||
maxSystemLog = 250
|
||||
)
|
||||
|
||||
// The discovery results are sorted by their source priority.
|
||||
const (
|
||||
ipv6LocalDiscoveryPriority = iota
|
||||
ipv4LocalDiscoveryPriority
|
||||
globalDiscoveryPriority
|
||||
)
|
||||
|
||||
func init() {
|
||||
if Version != "unknown-dev" {
|
||||
// If not a generic dev build, version string should come from git describe
|
||||
@@ -824,7 +817,7 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
||||
// Each global discovery server gets its results cached for five
|
||||
// minutes, and is not asked again for a minute when it's returned
|
||||
// unsuccessfully.
|
||||
cachedDiscovery.Add(gd, 5*time.Minute, time.Minute, globalDiscoveryPriority)
|
||||
cachedDiscovery.Add(gd, 5*time.Minute, time.Minute)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -834,14 +827,14 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
||||
if err != nil {
|
||||
l.Warnln("IPv4 local discovery:", err)
|
||||
} else {
|
||||
cachedDiscovery.Add(bcd, 0, 0, ipv4LocalDiscoveryPriority)
|
||||
cachedDiscovery.Add(bcd, 0, 0)
|
||||
}
|
||||
// v6 multicasts
|
||||
mcd, err := discover.NewLocal(myID, cfg.Options().LocalAnnMCAddr, connectionsService)
|
||||
if err != nil {
|
||||
l.Warnln("IPv6 local discovery:", err)
|
||||
} else {
|
||||
cachedDiscovery.Add(mcd, 0, 0, ipv6LocalDiscoveryPriority)
|
||||
cachedDiscovery.Add(mcd, 0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ func (m *mockedCachingMux) Cache() map[protocol.DeviceID]discover.CacheEntry {
|
||||
|
||||
// from events.CachingMux
|
||||
|
||||
func (m *mockedCachingMux) Add(finder discover.Finder, cacheTime, negCacheTime time.Duration, priority int) {
|
||||
func (m *mockedCachingMux) Add(finder discover.Finder, cacheTime, negCacheTime time.Duration) {
|
||||
}
|
||||
|
||||
func (m *mockedCachingMux) ChildErrors() map[string]error {
|
||||
|
||||
@@ -9,6 +9,7 @@ package main
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/connections"
|
||||
"github.com/syncthing/syncthing/lib/db"
|
||||
"github.com/syncthing/syncthing/lib/model"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
@@ -91,8 +92,8 @@ func (m *mockedModel) ScanFolderSubdirs(folder string, subs []string) error {
|
||||
|
||||
func (m *mockedModel) BringToFront(folder, file string) {}
|
||||
|
||||
func (m *mockedModel) ConnectedTo(deviceID protocol.DeviceID) bool {
|
||||
return false
|
||||
func (m *mockedModel) Connection(deviceID protocol.DeviceID) (connections.Connection, bool) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (m *mockedModel) GlobalSize(folder string) db.Counts {
|
||||
|
||||
@@ -198,7 +198,7 @@ func (c *folderSummaryService) sendSummary(folder string) {
|
||||
// We already know about ourselves.
|
||||
continue
|
||||
}
|
||||
if !c.model.ConnectedTo(devCfg.DeviceID) {
|
||||
if _, ok := c.model.Connection(devCfg.DeviceID); !ok {
|
||||
// We're not interested in disconnected devices.
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -100,6 +100,10 @@ func (kcpDialerFactory) Priority() int {
|
||||
return kcpPriority
|
||||
}
|
||||
|
||||
func (kcpDialerFactory) AlwaysWAN() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (kcpDialerFactory) Enabled(cfg config.Configuration) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// Copyright (C) 2017 The Syncthing Authors.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
package connections
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
)
|
||||
|
||||
func TestIsLANHost(t *testing.T) {
|
||||
cases := []struct {
|
||||
addr string
|
||||
lan bool
|
||||
}{
|
||||
// loopback
|
||||
{"127.0.0.1:22000", true},
|
||||
{"127.0.0.1", true},
|
||||
// local nets
|
||||
{"10.20.30.40:22000", true},
|
||||
{"10.20.30.40", true},
|
||||
// neither
|
||||
{"192.0.2.1:22000", false},
|
||||
{"192.0.2.1", false},
|
||||
// doesn't resolve
|
||||
{"[banana::phone]:hello", false},
|
||||
{"„‹›fl´fi·‰ˇ¨Á˝", false},
|
||||
}
|
||||
|
||||
cfg := config.Wrap("/dev/null", config.Configuration{
|
||||
Options: config.OptionsConfiguration{
|
||||
AlwaysLocalNets: []string{"10.20.30.0/24"},
|
||||
},
|
||||
})
|
||||
s := &Service{cfg: cfg}
|
||||
|
||||
for _, tc := range cases {
|
||||
res := s.isLANHost(tc.addr)
|
||||
if res != tc.lan {
|
||||
t.Errorf("isLANHost(%q) => %v, expected %v", tc.addr, res, tc.lan)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -64,10 +64,6 @@ func (d *relayDialer) Dial(id protocol.DeviceID, uri *url.URL) (internalConn, er
|
||||
return internalConn{tc, connTypeRelayClient, relayPriority}, nil
|
||||
}
|
||||
|
||||
func (relayDialer) Priority() int {
|
||||
return relayPriority
|
||||
}
|
||||
|
||||
func (d *relayDialer) RedialFrequency() time.Duration {
|
||||
return time.Duration(d.cfg.Options().RelayReconnectIntervalM) * time.Minute
|
||||
}
|
||||
@@ -85,6 +81,10 @@ func (relayDialerFactory) Priority() int {
|
||||
return relayPriority
|
||||
}
|
||||
|
||||
func (relayDialerFactory) AlwaysWAN() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (relayDialerFactory) Enabled(cfg config.Configuration) bool {
|
||||
return cfg.Options.RelaysEnabled
|
||||
}
|
||||
|
||||
+53
-39
@@ -89,9 +89,6 @@ type Service struct {
|
||||
listeners map[string]genericListener
|
||||
listenerTokens map[string]suture.ServiceToken
|
||||
listenerSupervisor *suture.Supervisor
|
||||
|
||||
curConMut sync.Mutex
|
||||
currentConnection map[protocol.DeviceID]completeConn
|
||||
}
|
||||
|
||||
func NewService(cfg *config.Wrapper, myID protocol.DeviceID, mdl Model, tlsCfg *tls.Config, discoverer discover.Finder,
|
||||
@@ -129,9 +126,6 @@ func NewService(cfg *config.Wrapper, myID protocol.DeviceID, mdl Model, tlsCfg *
|
||||
FailureThreshold: 2,
|
||||
FailureBackoff: 600 * time.Second,
|
||||
}),
|
||||
|
||||
curConMut: sync.NewMutex(),
|
||||
currentConnection: make(map[protocol.DeviceID]completeConn),
|
||||
}
|
||||
cfg.Subscribe(service)
|
||||
|
||||
@@ -228,15 +222,11 @@ next:
|
||||
|
||||
// If we have a relay connection, and the new incoming connection is
|
||||
// not a relay connection, we should drop that, and prefer this one.
|
||||
connected := s.model.ConnectedTo(remoteID)
|
||||
s.curConMut.Lock()
|
||||
ct, ok := s.currentConnection[remoteID]
|
||||
s.curConMut.Unlock()
|
||||
priorityKnown := ok && connected
|
||||
ct, connected := s.model.Connection(remoteID)
|
||||
|
||||
// Lower priority is better, just like nice etc.
|
||||
if priorityKnown && ct.internalConn.priority > c.priority {
|
||||
l.Debugln("Switching connections", remoteID)
|
||||
if connected && ct.Priority() > c.priority {
|
||||
l.Debugf("Switching connections %s (existing: %s new: %s)", remoteID, ct, c)
|
||||
} else if connected {
|
||||
// We should not already be connected to the other party. TODO: This
|
||||
// could use some better handling. If the old connection is dead but
|
||||
@@ -244,7 +234,7 @@ next:
|
||||
// this one. But in case we are two devices connecting to each other
|
||||
// in parallel we don't want to do that or we end up with no
|
||||
// connections still established...
|
||||
l.Infof("Connected to already connected device (%s)", remoteID)
|
||||
l.Infof("Connected to already connected device %s (existing: %s new: %s)", remoteID, ct, c)
|
||||
c.Close()
|
||||
continue
|
||||
}
|
||||
@@ -284,9 +274,6 @@ next:
|
||||
l.Infof("Established secure connection to %s at %s (%s)", remoteID, name, tlsCipherSuiteNames[c.ConnectionState().CipherSuite])
|
||||
|
||||
s.model.AddConnection(modelConn, hello)
|
||||
s.curConMut.Lock()
|
||||
s.currentConnection[remoteID] = modelConn
|
||||
s.curConMut.Unlock()
|
||||
continue next
|
||||
}
|
||||
}
|
||||
@@ -329,19 +316,13 @@ func (s *Service) connect() {
|
||||
continue
|
||||
}
|
||||
|
||||
connected := s.model.ConnectedTo(deviceID)
|
||||
s.curConMut.Lock()
|
||||
ct, ok := s.currentConnection[deviceID]
|
||||
s.curConMut.Unlock()
|
||||
priorityKnown := ok && connected
|
||||
ct, connected := s.model.Connection(deviceID)
|
||||
|
||||
if priorityKnown && ct.internalConn.priority == bestDialerPrio {
|
||||
if connected && ct.Priority() == bestDialerPrio {
|
||||
// Things are already as good as they can get.
|
||||
continue
|
||||
}
|
||||
|
||||
l.Debugln("Reconnect loop for", deviceID)
|
||||
|
||||
var addrs []string
|
||||
for _, addr := range deviceCfg.Addresses {
|
||||
if addr == "dynamic" {
|
||||
@@ -355,6 +336,10 @@ func (s *Service) connect() {
|
||||
}
|
||||
}
|
||||
|
||||
addrs = util.UniqueStrings(addrs)
|
||||
|
||||
l.Debugln("Reconnect loop for", deviceID, addrs)
|
||||
|
||||
seen = append(seen, addrs...)
|
||||
|
||||
dialTargets := make([]dialTarget, 0)
|
||||
@@ -392,19 +377,28 @@ func (s *Service) connect() {
|
||||
continue
|
||||
}
|
||||
|
||||
prio := dialerFactory.Priority()
|
||||
priority := dialerFactory.Priority()
|
||||
|
||||
if priorityKnown && prio >= ct.internalConn.priority {
|
||||
l.Debugf("Not dialing using %s as priority is less than current connection (%d >= %d)", dialerFactory, dialerFactory.Priority(), ct.internalConn.priority)
|
||||
if connected && priority >= ct.Priority() {
|
||||
l.Debugf("Not dialing using %s as priority is less than current connection (%d >= %d)", dialerFactory, dialerFactory.Priority(), ct.Priority())
|
||||
continue
|
||||
}
|
||||
|
||||
dialer := dialerFactory.New(s.cfg, s.tlsCfg)
|
||||
nextDial[addr] = now.Add(dialer.RedialFrequency())
|
||||
|
||||
// For LAN addresses, increase the priority so that we
|
||||
// try these first.
|
||||
switch {
|
||||
case dialerFactory.AlwaysWAN():
|
||||
// Do nothing.
|
||||
case s.isLANHost(uri.Host):
|
||||
priority -= 1
|
||||
}
|
||||
|
||||
dialTargets = append(dialTargets, dialTarget{
|
||||
dialer: dialer,
|
||||
priority: prio,
|
||||
priority: priority,
|
||||
deviceID: deviceID,
|
||||
uri: uri,
|
||||
})
|
||||
@@ -429,13 +423,37 @@ func (s *Service) connect() {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) isLANHost(host string) bool {
|
||||
// Probably we are called with an ip:port combo which we can resolve as
|
||||
// a TCP address.
|
||||
if addr, err := net.ResolveTCPAddr("tcp", host); err == nil {
|
||||
return s.isLAN(addr)
|
||||
}
|
||||
// ... but this function looks general enough that someone might try
|
||||
// with just an IP as well in the future so lets allow that.
|
||||
if addr, err := net.ResolveIPAddr("ip", host); err == nil {
|
||||
return s.isLAN(addr)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *Service) isLAN(addr net.Addr) bool {
|
||||
tcpaddr, ok := addr.(*net.TCPAddr)
|
||||
if !ok {
|
||||
var ip net.IP
|
||||
|
||||
switch addr := addr.(type) {
|
||||
case *net.IPAddr:
|
||||
ip = addr.IP
|
||||
case *net.TCPAddr:
|
||||
ip = addr.IP
|
||||
case *net.UDPAddr:
|
||||
ip = addr.IP
|
||||
default:
|
||||
// From the standard library, just Unix sockets.
|
||||
// If you invent your own, handle it.
|
||||
return false
|
||||
}
|
||||
|
||||
if tcpaddr.IP.IsLoopback() {
|
||||
if ip.IsLoopback() {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -445,14 +463,14 @@ func (s *Service) isLAN(addr net.Addr) bool {
|
||||
l.Debugln("Network", lan, "is malformed:", err)
|
||||
continue
|
||||
}
|
||||
if ipnet.Contains(tcpaddr.IP) {
|
||||
if ipnet.Contains(ip) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
lans, _ := osutil.GetLans()
|
||||
for _, lan := range lans {
|
||||
if lan.Contains(tcpaddr.IP) {
|
||||
if lan.Contains(ip) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -492,9 +510,6 @@ func (s *Service) CommitConfiguration(from, to config.Configuration) bool {
|
||||
|
||||
for _, dev := range from.Devices {
|
||||
if !newDevices[dev.DeviceID] {
|
||||
s.curConMut.Lock()
|
||||
delete(s.currentConnection, dev.DeviceID)
|
||||
s.curConMut.Unlock()
|
||||
warningLimitersMut.Lock()
|
||||
delete(warningLimiters, dev.DeviceID)
|
||||
warningLimitersMut.Unlock()
|
||||
@@ -776,12 +791,11 @@ func dialParallel(deviceID protocol.DeviceID, dialTargets []dialTarget) (interna
|
||||
conn.Close()
|
||||
}
|
||||
}(deviceID, prio)
|
||||
return conn, ok
|
||||
} else {
|
||||
// Failed to connect, report that fact.
|
||||
l.Debugln("failed to connect to", deviceID, prio)
|
||||
}
|
||||
|
||||
return conn, ok
|
||||
}
|
||||
return internalConn{}, false
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ type Connection interface {
|
||||
Type() string
|
||||
Transport() string
|
||||
RemoteAddr() net.Addr
|
||||
Priority() int
|
||||
}
|
||||
|
||||
// completeConn is the aggregation of an internalConn and the
|
||||
@@ -92,6 +93,10 @@ func (c internalConn) Type() string {
|
||||
return c.connType.String()
|
||||
}
|
||||
|
||||
func (c internalConn) Priority() int {
|
||||
return c.priority
|
||||
}
|
||||
|
||||
func (c internalConn) Transport() string {
|
||||
transport := c.connType.Transport()
|
||||
host, _, err := net.SplitHostPort(c.LocalAddr().String())
|
||||
@@ -115,6 +120,7 @@ func (c internalConn) String() string {
|
||||
type dialerFactory interface {
|
||||
New(*config.Wrapper, *tls.Config) genericDialer
|
||||
Priority() int
|
||||
AlwaysWAN() bool
|
||||
Enabled(config.Configuration) bool
|
||||
String() string
|
||||
}
|
||||
@@ -152,7 +158,7 @@ type genericListener interface {
|
||||
type Model interface {
|
||||
protocol.Model
|
||||
AddConnection(conn Connection, hello protocol.HelloResult)
|
||||
ConnectedTo(remoteID protocol.DeviceID) bool
|
||||
Connection(remoteID protocol.DeviceID) (Connection, bool)
|
||||
OnHello(protocol.DeviceID, net.Addr, protocol.HelloResult) error
|
||||
GetHello(protocol.DeviceID) protocol.HelloIntf
|
||||
}
|
||||
|
||||
@@ -73,6 +73,10 @@ func (tcpDialerFactory) Priority() int {
|
||||
return tcpPriority
|
||||
}
|
||||
|
||||
func (tcpDialerFactory) AlwaysWAN() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (tcpDialerFactory) Enabled(cfg config.Configuration) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
+7
-53
@@ -7,7 +7,6 @@
|
||||
package discover
|
||||
|
||||
import (
|
||||
"sort"
|
||||
stdsync "sync"
|
||||
"time"
|
||||
|
||||
@@ -25,7 +24,7 @@ import (
|
||||
// or negative).
|
||||
type CachingMux interface {
|
||||
FinderService
|
||||
Add(finder Finder, cacheTime, negCacheTime time.Duration, priority int)
|
||||
Add(finder Finder, cacheTime, negCacheTime time.Duration)
|
||||
ChildErrors() map[string]error
|
||||
}
|
||||
|
||||
@@ -41,14 +40,6 @@ type cachedFinder struct {
|
||||
Finder
|
||||
cacheTime time.Duration
|
||||
negCacheTime time.Duration
|
||||
priority int
|
||||
}
|
||||
|
||||
// A prioritizedAddress is what we use to sort addresses returned from
|
||||
// different sources with different priorities.
|
||||
type prioritizedAddress struct {
|
||||
priority int
|
||||
addr string
|
||||
}
|
||||
|
||||
// An error may implement cachedError, in which case it will be interrogated
|
||||
@@ -66,9 +57,9 @@ func NewCachingMux() CachingMux {
|
||||
}
|
||||
|
||||
// Add registers a new Finder, with associated cache timeouts.
|
||||
func (m *cachingMux) Add(finder Finder, cacheTime, negCacheTime time.Duration, priority int) {
|
||||
func (m *cachingMux) Add(finder Finder, cacheTime, negCacheTime time.Duration) {
|
||||
m.mut.Lock()
|
||||
m.finders = append(m.finders, cachedFinder{finder, cacheTime, negCacheTime, priority})
|
||||
m.finders = append(m.finders, cachedFinder{finder, cacheTime, negCacheTime})
|
||||
m.caches = append(m.caches, newCache())
|
||||
m.mut.Unlock()
|
||||
|
||||
@@ -80,8 +71,6 @@ func (m *cachingMux) Add(finder Finder, cacheTime, negCacheTime time.Duration, p
|
||||
// Lookup attempts to resolve the device ID using any of the added Finders,
|
||||
// while obeying the cache settings.
|
||||
func (m *cachingMux) Lookup(deviceID protocol.DeviceID) (addresses []string, err error) {
|
||||
var paddresses []prioritizedAddress
|
||||
|
||||
m.mut.RLock()
|
||||
for i, finder := range m.finders {
|
||||
if cacheEntry, ok := m.caches[i].Get(deviceID); ok {
|
||||
@@ -91,9 +80,7 @@ func (m *cachingMux) Lookup(deviceID protocol.DeviceID) (addresses []string, err
|
||||
// It's a positive, valid entry. Use it.
|
||||
l.Debugln("cached discovery entry for", deviceID, "at", finder)
|
||||
l.Debugln(" cache:", cacheEntry)
|
||||
for _, addr := range cacheEntry.Addresses {
|
||||
paddresses = append(paddresses, prioritizedAddress{finder.priority, addr})
|
||||
}
|
||||
addresses = append(addresses, cacheEntry.Addresses...)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -112,9 +99,7 @@ func (m *cachingMux) Lookup(deviceID protocol.DeviceID) (addresses []string, err
|
||||
if addrs, err := finder.Lookup(deviceID); err == nil {
|
||||
l.Debugln("lookup for", deviceID, "at", finder)
|
||||
l.Debugln(" addresses:", addrs)
|
||||
for _, addr := range addrs {
|
||||
paddresses = append(paddresses, prioritizedAddress{finder.priority, addr})
|
||||
}
|
||||
addresses = append(addresses, addrs...)
|
||||
m.caches[i].Set(deviceID, CacheEntry{
|
||||
Addresses: addrs,
|
||||
when: time.Now(),
|
||||
@@ -134,10 +119,11 @@ func (m *cachingMux) Lookup(deviceID protocol.DeviceID) (addresses []string, err
|
||||
}
|
||||
m.mut.RUnlock()
|
||||
|
||||
addresses = uniqueSortedAddrs(paddresses)
|
||||
l.Debugln("lookup results for", deviceID)
|
||||
l.Debugln(" addresses: ", addresses)
|
||||
|
||||
addresses = util.UniqueStrings(addresses)
|
||||
|
||||
return addresses, nil
|
||||
}
|
||||
|
||||
@@ -239,35 +225,3 @@ func (c *cache) Cache() map[protocol.DeviceID]CacheEntry {
|
||||
c.mut.Unlock()
|
||||
return m
|
||||
}
|
||||
|
||||
func uniqueSortedAddrs(ss []prioritizedAddress) []string {
|
||||
// We sort the addresses by priority, then filter them based on seen
|
||||
// (first time seen is the on kept, so we retain priority).
|
||||
sort.Sort(prioritizedAddressList(ss))
|
||||
filtered := make([]string, 0, len(ss))
|
||||
seen := make(map[string]struct{}, len(ss))
|
||||
for _, s := range ss {
|
||||
if _, ok := seen[s.addr]; !ok {
|
||||
filtered = append(filtered, s.addr)
|
||||
seen[s.addr] = struct{}{}
|
||||
}
|
||||
}
|
||||
return filtered
|
||||
}
|
||||
|
||||
type prioritizedAddressList []prioritizedAddress
|
||||
|
||||
func (l prioritizedAddressList) Len() int {
|
||||
return len(l)
|
||||
}
|
||||
|
||||
func (l prioritizedAddressList) Swap(a, b int) {
|
||||
l[a], l[b] = l[b], l[a]
|
||||
}
|
||||
|
||||
func (l prioritizedAddressList) Less(a, b int) bool {
|
||||
if l[a].priority != l[b].priority {
|
||||
return l[a].priority < l[b].priority
|
||||
}
|
||||
return l[a].addr < l[b].addr
|
||||
}
|
||||
|
||||
@@ -15,19 +15,18 @@ import (
|
||||
)
|
||||
|
||||
func TestCacheUnique(t *testing.T) {
|
||||
addresses0 := []string{"tcp://192.0.2.44:22000", "tcp://192.0.2.42:22000"} // prio 0
|
||||
addresses1 := []string{"tcp://192.0.2.43:22000", "tcp://192.0.2.42:22000"} // prio 1
|
||||
addresses0 := []string{"tcp://192.0.2.44:22000", "tcp://192.0.2.42:22000"}
|
||||
addresses1 := []string{"tcp://192.0.2.43:22000", "tcp://192.0.2.42:22000"}
|
||||
|
||||
// what we expect from just addresses0
|
||||
addresses0Sorted := []string{"tcp://192.0.2.42:22000", "tcp://192.0.2.44:22000"}
|
||||
|
||||
// what we expect from addresses0+addresses1
|
||||
totalSorted := []string{
|
||||
// first prio 0, sorted
|
||||
"tcp://192.0.2.42:22000", "tcp://192.0.2.44:22000",
|
||||
// then prio 1
|
||||
"tcp://192.0.2.43:22000",
|
||||
"tcp://192.0.2.42:22000",
|
||||
// no duplicate .42
|
||||
"tcp://192.0.2.43:22000",
|
||||
"tcp://192.0.2.44:22000",
|
||||
}
|
||||
|
||||
c := NewCachingMux()
|
||||
@@ -38,7 +37,7 @@ func TestCacheUnique(t *testing.T) {
|
||||
// cache.
|
||||
|
||||
f1 := &fakeDiscovery{addresses0}
|
||||
c.Add(f1, time.Minute, 0, 0)
|
||||
c.Add(f1, time.Minute, 0)
|
||||
|
||||
addr, err := c.Lookup(protocol.LocalDeviceID)
|
||||
if err != nil {
|
||||
@@ -52,7 +51,7 @@ func TestCacheUnique(t *testing.T) {
|
||||
// duplicate or otherwise mess up the responses now.
|
||||
|
||||
f2 := &fakeDiscovery{addresses1}
|
||||
c.Add(f2, time.Minute, 0, 1)
|
||||
c.Add(f2, time.Minute, 0)
|
||||
|
||||
addr, err = c.Lookup(protocol.LocalDeviceID)
|
||||
if err != nil {
|
||||
@@ -92,7 +91,7 @@ func TestCacheSlowLookup(t *testing.T) {
|
||||
|
||||
started := make(chan struct{})
|
||||
f1 := &slowDiscovery{time.Second, started}
|
||||
c.Add(f1, time.Minute, 0, 0)
|
||||
c.Add(f1, time.Minute, 0)
|
||||
|
||||
// Start a lookup, which will take at least a second
|
||||
|
||||
|
||||
@@ -50,8 +50,6 @@ func (f *folder) DelayScan(next time.Duration) {
|
||||
f.scan.Delay(next)
|
||||
}
|
||||
|
||||
func (f *folder) IndexUpdated() {}
|
||||
|
||||
func (f *folder) IgnoresUpdated() {
|
||||
if f.FSWatcherEnabled {
|
||||
f.scheduleWatchRestart()
|
||||
|
||||
+6
-7
@@ -47,9 +47,8 @@ const (
|
||||
type service interface {
|
||||
BringToFront(string)
|
||||
DelayScan(d time.Duration)
|
||||
IndexUpdated() // Remote index was updated notification
|
||||
IgnoresUpdated() // ignore matcher was updated notification
|
||||
SchedulePull()
|
||||
IgnoresUpdated() // ignore matcher was updated notification
|
||||
SchedulePull() // something relevant changed, we should try a pull
|
||||
Jobs() ([]string, []string) // In progress, Queued
|
||||
Scan(subs []string) error
|
||||
Serve()
|
||||
@@ -1331,15 +1330,15 @@ func (cf cFiler) CurrentFile(file string) (protocol.FileInfo, bool) {
|
||||
return cf.m.CurrentFolderFile(cf.r, file)
|
||||
}
|
||||
|
||||
// ConnectedTo returns true if we are connected to the named device.
|
||||
func (m *Model) ConnectedTo(deviceID protocol.DeviceID) bool {
|
||||
// Connection returns the current connection for device, and a boolean wether a connection was found.
|
||||
func (m *Model) Connection(deviceID protocol.DeviceID) (connections.Connection, bool) {
|
||||
m.pmut.RLock()
|
||||
_, ok := m.conn[deviceID]
|
||||
cn, ok := m.conn[deviceID]
|
||||
m.pmut.RUnlock()
|
||||
if ok {
|
||||
m.deviceWasSeen(deviceID)
|
||||
}
|
||||
return ok
|
||||
return cn, ok
|
||||
}
|
||||
|
||||
func (m *Model) GetIgnores(folder string) ([]string, []string, error) {
|
||||
|
||||
@@ -311,6 +311,9 @@ func (f *fakeConnection) Type() string {
|
||||
func (f *fakeConnection) Transport() string {
|
||||
return "fake"
|
||||
}
|
||||
func (f *fakeConnection) Priority() int {
|
||||
return 9000
|
||||
}
|
||||
|
||||
func (f *fakeConnection) DownloadProgress(folder string, updates []protocol.FileDownloadProgressUpdate) {
|
||||
f.downloadProgressMessages = append(f.downloadProgressMessages, downloadProgressMessage{
|
||||
|
||||
@@ -399,7 +399,7 @@ func (f *sendReceiveFolder) pullerIteration(ignores *ignore.Matcher, ignoresChan
|
||||
|
||||
devices := folderFiles.Availability(file.Name)
|
||||
for _, dev := range devices {
|
||||
if f.model.ConnectedTo(dev) {
|
||||
if _, ok := f.model.Connection(dev); ok {
|
||||
f.queue.Push(file.Name, file.Size, file.ModTime())
|
||||
changed++
|
||||
return true
|
||||
@@ -1728,7 +1728,7 @@ func (f *sendReceiveFolder) basePause() time.Duration {
|
||||
|
||||
func (f *sendReceiveFolder) IgnoresUpdated() {
|
||||
f.folder.IgnoresUpdated()
|
||||
f.IndexUpdated()
|
||||
f.SchedulePull()
|
||||
}
|
||||
|
||||
// A []fileError is sent as part of an event and will be JSON serialized.
|
||||
|
||||
+3
-1
@@ -7,6 +7,9 @@ import (
|
||||
)
|
||||
|
||||
type FilteredConn struct {
|
||||
// Alignment
|
||||
deadline atomic.Value
|
||||
|
||||
source *PacketFilter
|
||||
priority int
|
||||
|
||||
@@ -14,7 +17,6 @@ type FilteredConn struct {
|
||||
|
||||
filter Filter
|
||||
|
||||
deadline atomic.Value
|
||||
closed chan struct{}
|
||||
}
|
||||
|
||||
|
||||
+4
-3
@@ -26,13 +26,14 @@ func NewPacketFilter(conn net.PacketConn) *PacketFilter {
|
||||
|
||||
// PacketFilter embeds a net.PacketConn to perform the filtering.
|
||||
type PacketFilter struct {
|
||||
// Alignment
|
||||
dropped uint64
|
||||
overflow uint64
|
||||
|
||||
net.PacketConn
|
||||
|
||||
conns []*FilteredConn
|
||||
mut sync.Mutex
|
||||
|
||||
dropped uint64
|
||||
overflow uint64
|
||||
}
|
||||
|
||||
// NewConn returns a new net.PacketConn object which filters packets based
|
||||
|
||||
Vendored
+2
-2
@@ -29,7 +29,7 @@
|
||||
"importpath": "github.com/AudriusButkevicius/pfilter",
|
||||
"repository": "https://github.com/AudriusButkevicius/pfilter",
|
||||
"vcs": "git",
|
||||
"revision": "09b3cfdd04de89f0196caecb0b335d7149a6593a",
|
||||
"revision": "56143fe9cebe95636de1275acf30fcca36a1383d",
|
||||
"branch": "master",
|
||||
"notests": true
|
||||
},
|
||||
@@ -679,4 +679,4 @@
|
||||
"notests": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user