Compare commits

..

24 Commits

Author SHA1 Message Date
Jakob Borg
c07b39e58b Stress test the HTTP(S) server 2014-09-17 17:11:53 +02:00
Jakob Borg
384c543ab9 Ignore patterns should be case insensitive on OS X and Windows 2014-09-16 23:16:39 +02:00
Jakob Borg
592b13d7db Merge branch 'integration-tests'
* integration-tests:
  Script cleanups
  Fail integration tests early
  Improve integration tests
  Add integration test HTTPS certificates
  Upgrade integration test configs
2014-09-16 22:59:42 +02:00
Jakob Borg
6fdba3c02e Script cleanups 2014-09-16 23:26:52 +02:00
Jakob Borg
cbf758ead9 Fail integration tests early 2014-09-16 23:22:03 +02:00
Jakob Borg
d1ad778a64 Improve integration tests 2014-09-16 23:14:19 +02:00
Jakob Borg
ce5ad296ae Add integration test HTTPS certificates 2014-09-16 23:08:24 +02:00
Jakob Borg
797e105786 Upgrade integration test configs 2014-09-16 23:03:18 +02:00
Jakob Borg
d17d80747e Update dependencies (fixes #692) 2014-09-15 18:15:16 +02:00
Jakob Borg
55ea207a55 Merge branch 'new-tls'
* new-tls:
  Cleanups and tweaks
  Add redirection middleware
  Add DowngradingListener

Conflicts:
	auto/gui.files.go
2014-09-15 00:19:07 +02:00
Jakob Borg
6384d1e5a3 Cleanups and tweaks 2014-09-15 00:18:05 +02:00
Jakob Borg
aba01cdace Print error on monitor restart failure 2014-09-14 23:19:28 +02:00
Jakob Borg
517b7a14b4 Merge branch 'pr/683'
* pr/683:
  Restart monitor as part of the upgrade process (fixes #682)
2014-09-14 23:18:48 +02:00
Jakob Borg
2927de7cf9 More than a year ago might as well be never (fixes #690) 2014-09-14 23:16:15 +02:00
Jakob Borg
6471ba70e4 Merge pull request #686 from AudriusButkevicius/auth
Send the real hash as part of the config (fixes #681)
2014-09-14 10:50:17 +02:00
Jakob Borg
9f9de01c51 Merge pull request #685 from AudriusButkevicius/preview
Add usage reporting preview (closes #395)
2014-09-14 10:43:22 +02:00
Audrius Butkevicius
3662decb8b Add redirection middleware 2014-09-13 22:10:55 +01:00
Audrius Butkevicius
583bcfb3c7 Add DowngradingListener
"Inspired" by https://github.com/BenLubar/Rnoadm/maybetls
but avoids pulling the whole game as a dependency, and has the API slightly changed,
as it makes no sense to have non-tcp TLS listeners.
2014-09-13 22:10:47 +01:00
Audrius Butkevicius
c45e3fa4d5 Require username and password for authentication 2014-09-13 22:06:25 +01:00
Audrius Butkevicius
24cbcef620 Send the real hash as part of the config (fixes #681) 2014-09-13 21:52:20 +01:00
Audrius Butkevicius
e2a520ff49 Add usage reporting preview (closes #395) 2014-09-13 21:40:13 +01:00
Audrius Butkevicius
a5e3317e28 Restart monitor as part of the upgrade process (fixes #682) 2014-09-13 15:32:47 +01:00
Jakob Borg
5638c4ba87 Woops (fixup of previous) 2014-09-13 15:11:47 +02:00
Jakob Borg
bf7a128142 Smarter limit on size of pull block queue 2014-09-13 10:57:36 +02:00
47 changed files with 960 additions and 254 deletions

4
Godeps/Godeps.json generated
View File

@@ -37,7 +37,7 @@
},
{
"ImportPath": "github.com/bkaradzic/go-lz4",
"Rev": "77e2ba877bde9da31213bec75dbbe197fa507c21"
"Rev": "93a831dcee242be64a9cc9803dda84af25932de7"
},
{
"ImportPath": "github.com/calmh/xdr",
@@ -49,7 +49,7 @@
},
{
"ImportPath": "github.com/syndtr/goleveldb/leveldb",
"Rev": "457e6f75905f7c1316afd8c43ad323f4c32b31c2"
"Rev": "9bca75c48d6c31becfbb127702b425e7226052e3"
},
{
"ImportPath": "github.com/vitrun/qart/coding",

View File

@@ -72,10 +72,18 @@ func main() {
if *decompress {
data, _ = ioutil.ReadAll(input)
data, _ = lz4.Decode(nil, data)
data, err = lz4.Decode(nil, data)
if err != nil {
fmt.Println("Failed to decode:", err)
return
}
} else {
data, _ = ioutil.ReadAll(input)
data, _ = lz4.Encode(nil, data)
data, err = lz4.Encode(nil, data)
if err != nil {
fmt.Println("Failed to encode:", err)
return
}
}
err = ioutil.WriteFile(args[1], data, 0644)

View File

@@ -121,7 +121,7 @@ func Encode(dst, src []byte) ([]byte, error) {
)
for {
if int(e.pos)+4 >= len(e.src) {
if int(e.pos)+12 >= len(e.src) {
e.writeLiterals(uint32(len(e.src))-e.anchor, 0, e.anchor)
return e.dst[:e.dpos], nil
}
@@ -158,7 +158,7 @@ func Encode(dst, src []byte) ([]byte, error) {
ref += minMatch
e.anchor = e.pos
for int(e.pos) < len(e.src) && e.src[e.pos] == e.src[ref] {
for int(e.pos) < len(e.src)-5 && e.src[e.pos] == e.src[ref] {
e.pos++
ref++
}

View File

@@ -13,8 +13,8 @@ import (
"github.com/syndtr/goleveldb/leveldb/util"
)
// The LLRB implementation were taken from https://github.com/petar/GoLLRB,
// which conatins the following header:
// The LLRB implementation were taken from https://github.com/petar/GoLLRB.
// Which contains the following header:
//
// Copyright 2010 Petar Maymounkov. All rights reserved.
// Use of this source code is governed by a BSD-style

View File

@@ -1579,8 +1579,8 @@ func TestDb_BloomFilter(t *testing.T) {
const (
n = 10000
indexOverheat = 19898
filterOverheat = 19799
indexOverhead = 19898
filterOverhead = 19799
)
// Populate multiple layers
@@ -1605,7 +1605,7 @@ func TestDb_BloomFilter(t *testing.T) {
cnt := int(h.stor.ReadCounter())
t.Logf("lookup of %d present keys yield %d sstable I/O reads", n, cnt)
if min, max := n+indexOverheat+filterOverheat, n+indexOverheat+filterOverheat+2*n/100; cnt < min || cnt > max {
if min, max := n+indexOverhead+filterOverhead, n+indexOverhead+filterOverhead+2*n/100; cnt < min || cnt > max {
t.Errorf("num of sstable I/O reads of present keys not in range of %d - %d, got %d", min, max, cnt)
}
@@ -1616,7 +1616,7 @@ func TestDb_BloomFilter(t *testing.T) {
}
cnt = int(h.stor.ReadCounter())
t.Logf("lookup of %d missing keys yield %d sstable I/O reads", n, cnt)
if max := 3*n/100 + indexOverheat + filterOverheat; cnt > max {
if max := 3*n/100 + indexOverhead + filterOverhead; cnt > max {
t.Errorf("num of sstable I/O reads of missing keys was more than %d, got %d", max, cnt)
}

View File

@@ -40,18 +40,17 @@ var _ = testutil.Defer(func() {
})
Describe("read test", func() {
testutil.AllKeyValueTesting(nil, func(kv testutil.KeyValue) testutil.DB {
testutil.AllKeyValueTesting(nil, nil, func(kv testutil.KeyValue) testutil.DB {
// Building the DB.
db := newTestingDB(o, nil, nil)
kv.IterateShuffled(nil, func(i int, key, value []byte) {
err := db.TestPut(key, value)
Expect(err).NotTo(HaveOccurred())
})
testutil.Defer("teardown", func() {
db.TestClose()
})
return db
}, func(db testutil.DB) {
db.(*testingDB).TestClose()
})
})
})

View File

@@ -129,7 +129,7 @@ var _ = testutil.Defer(func() {
}
return db
})
}, nil, nil)
})
})
})

View File

@@ -59,7 +59,7 @@ var _ = testutil.Defer(func() {
// Make block.
br := Build(kv, restartInterval)
// Do testing.
testutil.KeyValueTesting(nil, br, kv.Clone())
testutil.KeyValueTesting(nil, kv.Clone(), br, nil, nil)
}
Describe(Text(), Test)

View File

@@ -104,11 +104,11 @@ var _ = testutil.Defer(func() {
if body != nil {
body(db.(tableWrapper).Reader)
}
testutil.KeyValueTesting(nil, db, *kv)
testutil.KeyValueTesting(nil, *kv, db, nil, nil)
}
}
testutil.AllKeyValueTesting(nil, Build)
testutil.AllKeyValueTesting(nil, Build, nil, nil)
Describe("with one key per block", Test(testutil.KeyValue_Generate(nil, 9, 1, 10, 512, 512), func(r *Reader) {
It("should have correct blocks number", func() {
indexBlock, err := r.readBlock(r.indexBH, true)

View File

@@ -16,13 +16,22 @@ import (
"github.com/syndtr/goleveldb/leveldb/util"
)
func KeyValueTesting(rnd *rand.Rand, p DB, kv KeyValue) {
func KeyValueTesting(rnd *rand.Rand, kv KeyValue, p DB, setup func(KeyValue) DB, teardown func(DB)) {
if rnd == nil {
rnd = NewRand()
}
if db, ok := p.(Find); ok {
It("Should find all keys with Find", func() {
if p == nil {
BeforeEach(func() {
p = setup(kv)
})
AfterEach(func() {
teardown(p)
})
}
It("Should find all keys with Find", func() {
if db, ok := p.(Find); ok {
ShuffledIndex(nil, kv.Len(), 1, func(i int) {
key_, key, value := kv.IndexInexact(i)
@@ -38,9 +47,11 @@ func KeyValueTesting(rnd *rand.Rand, p DB, kv KeyValue) {
Expect(rkey).Should(Equal(key))
Expect(rvalue).Should(Equal(value), "Value for key %q (%q)", key_, key)
})
})
}
})
It("Should return error if the key is not present", func() {
It("Should return error if the key is not present", func() {
if db, ok := p.(Find); ok {
var key []byte
if kv.Len() > 0 {
key_, _ := kv.Index(kv.Len() - 1)
@@ -49,11 +60,11 @@ func KeyValueTesting(rnd *rand.Rand, p DB, kv KeyValue) {
rkey, _, err := db.TestFind(key)
Expect(err).Should(HaveOccurred(), "Find for key %q yield key %q", key, rkey)
Expect(err).Should(Equal(util.ErrNotFound))
})
}
}
})
if db, ok := p.(Get); ok {
It("Should only find exact key with Get", func() {
It("Should only find exact key with Get", func() {
if db, ok := p.(Get); ok {
ShuffledIndex(nil, kv.Len(), 1, func(i int) {
key_, key, value := kv.IndexInexact(i)
@@ -69,11 +80,11 @@ func KeyValueTesting(rnd *rand.Rand, p DB, kv KeyValue) {
Expect(err).Should(Equal(util.ErrNotFound))
}
})
})
}
}
})
if db, ok := p.(NewIterator); ok {
TestIter := func(r *util.Range, _kv KeyValue) {
TestIter := func(r *util.Range, _kv KeyValue) {
if db, ok := p.(NewIterator); ok {
iter := db.TestNewIterator(r)
Expect(iter.Error()).ShouldNot(HaveOccurred())
@@ -84,45 +95,48 @@ func KeyValueTesting(rnd *rand.Rand, p DB, kv KeyValue) {
DoIteratorTesting(&t)
}
}
It("Should iterates and seeks correctly", func(done Done) {
TestIter(nil, kv.Clone())
done <- true
}, 3.0)
It("Should iterates and seeks correctly", func(done Done) {
TestIter(nil, kv.Clone())
done <- true
}, 3.0)
RandomIndex(rnd, kv.Len(), kv.Len(), func(i int) {
type slice struct {
r *util.Range
start, limit int
}
RandomIndex(rnd, kv.Len(), kv.Len(), func(i int) {
type slice struct {
r *util.Range
start, limit int
}
key_, _, _ := kv.IndexInexact(i)
for _, x := range []slice{
{&util.Range{Start: key_, Limit: nil}, i, kv.Len()},
{&util.Range{Start: nil, Limit: key_}, 0, i},
} {
It(fmt.Sprintf("Should iterates and seeks correctly of a slice %d .. %d", x.start, x.limit), func(done Done) {
TestIter(x.r, kv.Slice(x.start, x.limit))
done <- true
}, 3.0)
}
})
RandomRange(rnd, kv.Len(), kv.Len(), func(start, limit int) {
It(fmt.Sprintf("Should iterates and seeks correctly of a slice %d .. %d", start, limit), func(done Done) {
r := kv.Range(start, limit)
TestIter(&r, kv.Slice(start, limit))
key_, _, _ := kv.IndexInexact(i)
for _, x := range []slice{
{&util.Range{Start: key_, Limit: nil}, i, kv.Len()},
{&util.Range{Start: nil, Limit: key_}, 0, i},
} {
It(fmt.Sprintf("Should iterates and seeks correctly of a slice %d .. %d", x.start, x.limit), func(done Done) {
TestIter(x.r, kv.Slice(x.start, x.limit))
done <- true
}, 3.0)
})
}
}
})
RandomRange(rnd, kv.Len(), kv.Len(), func(start, limit int) {
It(fmt.Sprintf("Should iterates and seeks correctly of a slice %d .. %d", start, limit), func(done Done) {
r := kv.Range(start, limit)
TestIter(&r, kv.Slice(start, limit))
done <- true
}, 3.0)
})
}
func AllKeyValueTesting(rnd *rand.Rand, body func(kv KeyValue) DB) {
func AllKeyValueTesting(rnd *rand.Rand, body, setup func(KeyValue) DB, teardown func(DB)) {
Test := func(kv *KeyValue) func() {
return func() {
db := body(*kv)
KeyValueTesting(rnd, db, *kv)
var p DB
if body != nil {
p = body(*kv)
}
KeyValueTesting(rnd, *kv, p, setup, teardown)
}
}

View File

File diff suppressed because one or more lines are too long

View File

@@ -45,10 +45,6 @@ var (
eventSub *events.BufferedSubscription
)
const (
unchangedPassword = "--password-unchanged--"
)
func init() {
l.AddHandler(logger.LevelWarn, showGuiError)
sub := events.Default.Subscribe(events.AllEvents)
@@ -56,33 +52,28 @@ func init() {
}
func startGUI(cfg config.GUIConfiguration, assetDir string, m *model.Model) error {
var listener net.Listener
var err error
if cfg.UseTLS {
cert, err := loadCert(confDir, "https-")
if err != nil {
l.Infoln("Loading HTTPS certificate:", err)
l.Infoln("Creating new HTTPS certificate")
newCertificate(confDir, "https-")
cert, err = loadCert(confDir, "https-")
}
if err != nil {
return err
}
tlsCfg := &tls.Config{
Certificates: []tls.Certificate{cert},
ServerName: "syncthing",
}
listener, err = tls.Listen("tcp", cfg.Address, tlsCfg)
if err != nil {
return err
}
} else {
listener, err = net.Listen("tcp", cfg.Address)
if err != nil {
return err
}
cert, err := loadCert(confDir, "https-")
if err != nil {
l.Infoln("Loading HTTPS certificate:", err)
l.Infoln("Creating new HTTPS certificate")
newCertificate(confDir, "https-")
cert, err = loadCert(confDir, "https-")
}
if err != nil {
return err
}
tlsCfg := &tls.Config{
Certificates: []tls.Certificate{cert},
ServerName: "syncthing",
}
rawListener, err := net.Listen("tcp", cfg.Address)
if err != nil {
return err
}
listener := &DowngradingListener{rawListener, tlsCfg}
// The GET handlers
getRestMux := http.NewServeMux()
@@ -140,10 +131,15 @@ func startGUI(cfg config.GUIConfiguration, assetDir string, m *model.Model) erro
handler = withVersionMiddleware(handler)
// Wrap everything in basic auth, if user/password is set.
if len(cfg.User) > 0 {
if len(cfg.User) > 0 && len(cfg.Password) > 0 {
handler = basicAuthAndSessionMiddleware(cfg, handler)
}
// Redirect to HTTPS if we are supposed to
if cfg.UseTLS {
handler = redirectToHTTPSMiddleware(handler)
}
go http.Serve(listener, handler)
return nil
}
@@ -161,6 +157,23 @@ func getPostHandler(get, post http.Handler) http.Handler {
})
}
func redirectToHTTPSMiddleware(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Add a generous access-control-allow-origin header since we may be
// redirecting REST requests over protocols
w.Header().Add("Access-Control-Allow-Origin", "*")
if r.TLS == nil {
// Redirect HTTP requests to HTTPS
r.URL.Host = r.Host
r.URL.Scheme = "https"
http.Redirect(w, r, r.URL.String(), http.StatusFound)
} else {
h.ServeHTTP(w, r)
}
})
}
func noCacheMiddleware(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Cache-Control", "no-cache")
@@ -255,7 +268,7 @@ func restGetNeed(m *model.Model, w http.ResponseWriter, r *http.Request) {
var qs = r.URL.Query()
var repo = qs.Get("repo")
files := m.NeedFilesRepo(repo)
files := m.NeedFilesRepoLimited(repo, 100, 2500) // max 100 files or 2500 blocks
w.Header().Set("Content-Type", "application/json; charset=utf-8")
json.NewEncoder(w).Encode(files)
@@ -274,12 +287,8 @@ func restGetNodeStats(m *model.Model, w http.ResponseWriter, r *http.Request) {
}
func restGetConfig(w http.ResponseWriter, r *http.Request) {
encCfg := cfg
if encCfg.GUI.Password != "" {
encCfg.GUI.Password = unchangedPassword
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
json.NewEncoder(w).Encode(encCfg)
json.NewEncoder(w).Encode(cfg)
}
func restPostConfig(m *model.Model, w http.ResponseWriter, r *http.Request) {
@@ -290,18 +299,16 @@ func restPostConfig(m *model.Model, w http.ResponseWriter, r *http.Request) {
http.Error(w, err.Error(), 500)
return
} else {
if newCfg.GUI.Password == "" {
// Leave it empty
} else if newCfg.GUI.Password == unchangedPassword {
newCfg.GUI.Password = cfg.GUI.Password
} else {
hash, err := bcrypt.GenerateFromPassword([]byte(newCfg.GUI.Password), 0)
if err != nil {
l.Warnln("bcrypting password:", err)
http.Error(w, err.Error(), 500)
return
} else {
newCfg.GUI.Password = string(hash)
if newCfg.GUI.Password != cfg.GUI.Password {
if newCfg.GUI.Password != "" {
hash, err := bcrypt.GenerateFromPassword([]byte(newCfg.GUI.Password), 0)
if err != nil {
l.Warnln("bcrypting password:", err)
http.Error(w, err.Error(), 500)
return
} else {
newCfg.GUI.Password = string(hash)
}
}
}
@@ -541,7 +548,9 @@ func restPostUpgrade(w http.ResponseWriter, r *http.Request) {
return
}
restPostRestart(w, r)
flushResponse(`{"ok": "restarting"}`, w)
l.Infoln("Upgrading")
stop <- exitUpgrading
}
}

View File

@@ -56,6 +56,7 @@ const (
exitError = 1
exitNoUpgradeAvailable = 2
exitRestarting = 3
exitUpgrading = 4
)
var l = logger.DefaultLogger

View File

@@ -91,6 +91,21 @@ func monitorMain() {
if err == nil {
// Successfull exit indicates an intentional shutdown
return
} else if exiterr, ok := err.(*exec.ExitError); ok {
if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
switch status.ExitStatus() {
case exitUpgrading:
// Restart the monitor process to release the .old
// binary as part of the upgrade process.
l.Infoln("Restarting monitor...")
os.Setenv("STNORESTART", "")
err := exec.Command(args[0], args[1:]...).Start()
if err != nil {
l.Warnln("restart:", err)
}
return
}
}
}
}

View File

@@ -5,6 +5,7 @@
package main
import (
"bufio"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
@@ -13,8 +14,10 @@ import (
"crypto/x509/pkix"
"encoding/binary"
"encoding/pem"
"io"
"math/big"
mr "math/rand"
"net"
"os"
"path/filepath"
"time"
@@ -73,3 +76,40 @@ func newCertificate(dir string, prefix string) {
pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
keyOut.Close()
}
type DowngradingListener struct {
net.Listener
TLSConfig *tls.Config
}
type WrappedConnection struct {
io.Reader
net.Conn
}
func (l *DowngradingListener) Accept() (net.Conn, error) {
conn, err := l.Listener.Accept()
if err != nil {
return nil, err
}
br := bufio.NewReader(conn)
bs, err := br.Peek(1)
if err != nil {
conn.Close()
return nil, err
}
wrapper := &WrappedConnection{br, conn}
// 0x16 is the first byte of a TLS handshake
if bs[0] == 0x16 {
return tls.Server(wrapper, l.TLSConfig), nil
}
return wrapper, nil
}
func (c *WrappedConnection) Read(b []byte) (n int, err error) {
return c.Reader.Read(b)
}

View File

@@ -20,15 +20,22 @@ const (
func Convert(pattern string, flags int) (*regexp.Regexp, error) {
any := "."
if runtime.GOOS == "windows" {
flags |= FNM_NOESCAPE
switch runtime.GOOS {
case "windows":
flags |= FNM_NOESCAPE | FNM_CASEFOLD
pattern = filepath.FromSlash(pattern)
if flags&FNM_PATHNAME != 0 {
any = "[^\\\\]"
}
} else if flags&FNM_PATHNAME != 0 {
any = "[^/]"
case "darwin":
flags |= FNM_CASEFOLD
fallthrough
default:
if flags&FNM_PATHNAME != 0 {
any = "[^/]"
}
}
if flags&FNM_NOESCAPE != 0 {
pattern = strings.Replace(pattern, "\\", "\\\\", -1)
} else {

View File

@@ -50,12 +50,17 @@ var testcases = []testcase{
{"**/foo.txt", "bar/baz/foo.txt", 0, true},
{"**/foo.txt", "bar/baz/foo.txt", FNM_PATHNAME, true},
{"foo.txt", "foo.TXT", 0, false},
{"foo.txt", "foo.TXT", FNM_CASEFOLD, true},
}
func TestMatch(t *testing.T) {
if runtime.GOOS != "windows" {
switch runtime.GOOS {
case "windows":
testcases = append(testcases, testcase{"foo.txt", "foo.TXT", 0, true})
case "darwin":
testcases = append(testcases, testcase{"foo.txt", "foo.TXT", 0, true})
fallthrough
default:
testcases = append(testcases, testcase{"f\\[ab\\]o.txt", "f[ab]o.txt", 0, true})
testcases = append(testcases, testcase{"foo\\.txt", "foo.txt", 0, true})
testcases = append(testcases, testcase{"foo\\*.txt", "foo*.txt", 0, true})

View File

@@ -153,13 +153,17 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http, $translate, $loca
return;
}
console.log('UIOnline');
$scope.init();
online = true;
restarting = false;
$('#networkError').modal('hide');
$('#restarting').modal('hide');
$('#shutdown').modal('hide');
if (restarting){
document.location.reload(true);
} else {
console.log('UIOnline');
$scope.init();
online = true;
restarting = false;
$('#networkError').modal('hide');
$('#restarting').modal('hide');
$('#shutdown').modal('hide');
}
});
$scope.$on('UIOffline', function (event, arg) {
@@ -371,6 +375,10 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http, $translate, $loca
var refreshNodeStats = debounce(function () {
$http.get(urlbase+"/stats/node").success(function (data) {
$scope.stats = data;
for (var node in $scope.stats) {
$scope.stats[node].LastSeen = new Date($scope.stats[node].LastSeen);
$scope.stats[node].LastSeenDays = (new Date() - $scope.stats[node].LastSeen) / 1000 / 86400;
}
console.log("refreshNodeStats", data);
});
}, 500);
@@ -581,7 +589,7 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http, $translate, $loca
setTimeout(function(){
window.location.protocol = protocol;
}, 1000);
}, 2500);
$scope.protocolChanged = false;
}
@@ -839,6 +847,13 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http, $translate, $loca
cfg.APIKey = randomString(30, 32);
};
$scope.showURPreview = function () {
$('#settings').modal('hide');
$('#urPreview').modal().on('hidden.bs.modal', function () {
$('#settings').modal();
});
}
$scope.acceptUR = function () {
$scope.config.Options.URAccepted = 1000; // Larger than the largest existing report version
$scope.saveConfig();

View File

@@ -266,8 +266,8 @@
</tr>
<tr ng-if="!connections[nodeCfg.NodeID]">
<th><span class="glyphicon glyphicon-eye-open"></span>&emsp;<span translate>Last seen</span></th>
<td translate ng-if="stats[nodeCfg.NodeID].LastSeen.indexOf('1970') > -1" class="text-right">Never</td>
<td ng-if="stats[nodeCfg.NodeID].LastSeen.indexOf('1970') < 0" class="text-right">{{stats[nodeCfg.NodeID].LastSeen | date:"yyyy-MM-dd HH:mm"}}</td>
<td translate ng-if="!stats[nodeCfg.NodeID].LastSeenDays || stats[nodeCfg.NodeID].LastSeenDays >= 365" class="text-right">Never</td>
<td ng-if="stats[nodeCfg.NodeID].LastSeenDays < 365" class="text-right">{{stats[nodeCfg.NodeID].LastSeen | date:"yyyy-MM-dd HH:mm"}}</td>
</tr>
</tbody>
</table>
@@ -614,7 +614,7 @@
<div class="form-group">
<div class="checkbox">
<label>
<span translate>Anonymous Usage Reporting</span> <input id="UREnabled" type="checkbox" ng-model="tmpOptions.UREnabled">
<span translate>Anonymous Usage Reporting</span> <input id="UREnabled" type="checkbox" ng-model="tmpOptions.UREnabled"> (<a translate ng-click="showURPreview()" href="#">Preview</a>)
</label>
</div>
</div>
@@ -661,6 +661,26 @@
</div>
</div>
<!-- Usage report preview modal -->
<div id="urPreview" class="modal fade" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header alert alert-success">
<h4 translate class="modal-title">Anonymous Usage Reporting</h4>
</div>
<div class="modal-body">
<p translate>The encrypted usage report is sent daily. It is used to track common platforms, repo sizes and app versions. If the reported data set is changed you will be prompted with this dialog again.</p>
<p translate translate-value-url="https://data.syncthing.net">The aggregated statistics are publicly available at {%url%}.</p>
<pre><small>{{reportData | json}}</small></pre>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-success btn-sm" data-dismiss="modal"><span class="glyphicon glyphicon-ok"></span>&emsp;<span translate>OK</span></button>
</div>
</div>
</div>
</div>
<!-- Needed files modal -->
<modal id="needed" large="yes" status="info" icon="cloud-download" close="yes" title="Out of Sync Items">

View File

@@ -64,6 +64,7 @@
"Path to the repository on the local computer. Will be created if it does not exist. The tilde character (~) can be used as a shortcut for": "Path to the repository on the local computer. Will be created if it does not exist. The tilde character (~) can be used as a shortcut for",
"Path where versions should be stored (leave empty for the default .stversions folder in the repository).": "Path where versions should be stored (leave empty for the default .stversions folder in the repository).",
"Please wait": "Please wait",
"Preview": "Preview",
"Preview Usage Report": "Preview Usage Report",
"RAM Utilization": "RAM Utilization",
"Reconnect Interval (s)": "Reconnect Interval (s)",

View File

@@ -7,6 +7,7 @@ package ignore_test
import (
"bytes"
"path/filepath"
"runtime"
"testing"
"github.com/syncthing/syncthing/ignore"
@@ -106,3 +107,29 @@ func TestBadPatterns(t *testing.T) {
}
}
}
func TestCaseSensitivity(t *testing.T) {
ign, _ := ignore.Parse(bytes.NewBufferString("test"), ".stignore")
match := []string{"test"}
dontMatch := []string{"foo"}
switch runtime.GOOS {
case "darwin", "windows":
match = append(match, "TEST", "Test", "tESt")
default:
dontMatch = append(dontMatch, "TEST", "Test", "tESt")
}
for _, tc := range match {
if !ign.Match(tc) {
t.Errorf("Incorrect match for %q: should be matched", tc)
}
}
for _, tc := range dontMatch {
if ign.Match(tc) {
t.Errorf("Incorrect match for %q: should not be matched", tc)
}
}
}

View File

@@ -2,7 +2,7 @@
set -euo pipefail
IFS=$'\n\t'
go test -tags integration -v
./test-http.sh
./test-merge.sh
./test-delupd.sh
go test -tags integration -v

View File

@@ -13,30 +13,44 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"log"
mr "math/rand"
"net/http"
"os"
"os/exec"
"path/filepath"
"runtime"
"time"
)
const (
id1 = "I6KAH76-66SLLLB-5PFXSOA-UFJCDZC-YAOMLEK-CP2GB32-BV5RQST-3PSROAU"
id2 = "JMFJCXB-GZDE4BN-OCJE3VF-65GYZNU-AIVJRET-3J6HMRQ-AUQIGJO-FKNHMQU"
apiKey = "abc123"
)
var env = []string{
"HOME=.",
"STTRACE=model",
"STGUIAPIKEY=" + apiKey,
}
type syncthingProcess struct {
log string
argv []string
port int
log string
argv []string
port int
apiKey string
csrfToken string
cmd *exec.Cmd
logfd *os.File
}
func (p *syncthingProcess) start() error {
func (p *syncthingProcess) start() (string, error) {
if p.logfd == nil {
logfd, err := os.Create(p.log)
if err != nil {
return err
return "", err
}
p.logfd = logfd
}
@@ -48,23 +62,47 @@ func (p *syncthingProcess) start() error {
err := cmd.Start()
if err != nil {
return err
return "", err
}
p.cmd = cmd
return nil
for {
ver, err := p.version()
if err == nil {
return ver, nil
}
time.Sleep(250 * time.Millisecond)
}
}
func (p *syncthingProcess) stop() {
if runtime.GOOS != "windows" {
p.cmd.Process.Signal(os.Interrupt)
} else {
p.cmd.Process.Kill()
}
p.cmd.Process.Signal(os.Interrupt)
p.cmd.Wait()
}
func (p *syncthingProcess) get(path string) (*http.Response, error) {
client := &http.Client{
Timeout: 2 * time.Second,
}
req, err := http.NewRequest("GET", fmt.Sprintf("http://127.0.0.1:%d%s", p.port, path), nil)
if err != nil {
return nil, err
}
if p.apiKey != "" {
req.Header.Add("X-API-Key", p.apiKey)
}
if p.csrfToken != "" {
req.Header.Add("X-CSRF-Token", p.csrfToken)
}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
return resp, nil
}
func (p *syncthingProcess) peerCompletion() (map[string]int, error) {
resp, err := http.Get(fmt.Sprintf("http://127.0.0.1:%d/rest/debug/peerCompletion", p.port))
resp, err := p.get("/rest/debug/peerCompletion")
if err != nil {
return nil, err
}
@@ -75,6 +113,19 @@ func (p *syncthingProcess) peerCompletion() (map[string]int, error) {
return comp, err
}
func (p *syncthingProcess) version() (string, error) {
resp, err := p.get("/rest/version")
if err != nil {
return "", err
}
bs, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
return "", err
}
return string(bs), nil
}
type fileGenerator struct {
files int
maxexp int
@@ -202,7 +253,7 @@ func compareDirectories(dirs ...string) error {
type fileInfo struct {
name string
mode os.FileMode
mod time.Time
mod int64
hash [16]byte
}
@@ -228,7 +279,7 @@ func startWalker(dir string, res chan<- fileInfo, abort <-chan struct{}) {
f = fileInfo{
name: rn,
mode: info.Mode(),
mod: info.ModTime(),
mod: info.ModTime().Unix(),
}
sum, err := md5file(path)
if err != nil {

View File

@@ -0,0 +1,23 @@
-----BEGIN CERTIFICATE-----
MIID5TCCAk+gAwIBAgIIHozuBlC9RPswCwYJKoZIhvcNAQELMBQxEjAQBgNVBAMT
CXN5bmN0aGluZzAeFw0xNDA5MTUwNTE0MDBaFw00OTEyMzEyMzU5NTlaMBQxEjAQ
BgNVBAMTCXN5bmN0aGluZzCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGB
ALxVRAh6EWr1Vum1EDafEGNTxWYcsMFssl4lc18cgQ5SRFtdkDi2IxELqiAPT0K9
11DkD563o7MIdCvB/XCA2hEaapfKKMiba/yH6tSnE7Fud5Wq8AtsAZV5weCjhGrc
s2YL8Nm57tiJC4W0K7txB8Ob5Q9gxvSpzLak2eh/fqhNoO6DxvUF/iE3VsdhKbKb
epXsTEvR1T3Qx0MUam7Dkz1eT4kXpwPGwLKfXY+BOxybxHAKM12qKV4R5Ebs/JZB
5GajZqd6XpwgldIg7KHWpWWSSjH4ojnP4XmEy5WZA33t0o+xkrg+EcQbzSEFhRMD
KT7fKT9+Evf+xB0j8FJ1+kL2ajTVfOPx3Fyg+YAPK9OVI6fr9OMJD6pLxZMLaRi9
R8IHEgOLo4vLRNLCmJWVIqfMtUlsVkXLM+alDo0maPUesPDTXeCuMG9TpDyHFQI5
6H4OYD3/9DOEOYMXXCCpPqpjk0CpS4GAtI6qXFG3dUY3EdfOcrKvnKi/DoRrpdzp
7wIDAQABoz8wPTAOBgNVHQ8BAf8EBAMCAKAwHQYDVR0lBBYwFAYIKwYBBQUHAwEG
CCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwCwYJKoZIhvcNAQELA4IBgQB4MajA42Wp
L1xFMb4Ba7+aW3o3j0N7wqJjHuU5HtbpwdYgv3tgmn+Ju6rvy6BwAQt8OsVNbai9
ptwsHbR6epoXPzAGyqY/9A74PJr6GraYJS148zuEgCir2Q0TfzbPtd4rDYN3LE81
STwtBvcaQsuAukQbeTQJkayobLQH8ve34BVX43XHUchEPLeZqAec5/btVyR9xwWz
rwJyEfCtx1/YxkPRBPs1cBQOK0Edn9nBKF114ogpWKlKt1Ou1HZzsMS2usWPdme1
IATpCR9i5/ZRIC7vhSK3se7IRaMrmOXc0kpgmbi9pr+Tg2sgJSC1Bvyfh3ReC53F
R6WJrmqut+SqCJlefQh+6On4MaW9hnrv62OTkyBKZZ3ogCQ+FMNFs+jRJHpdtxs4
ZVkuv1NZu8nB7NsY8i6vHKkOE6XCejg6HZL4R70iXoDDgo9E6A8TwTN7TZz7SdWh
+Bh3GGJAMubzuHysmEkKBSYHYlrW8GuUwCbLCl+HcQnfOtN7ffJwJb4=
-----END CERTIFICATE-----

View File

@@ -0,0 +1,39 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

View File

@@ -0,0 +1,23 @@
-----BEGIN CERTIFICATE-----
MIID5TCCAk+gAwIBAgIIORN2TOZWOjwwCwYJKoZIhvcNAQELMBQxEjAQBgNVBAMT
CXN5bmN0aGluZzAeFw0xNDA5MTUwNTE0MDJaFw00OTEyMzEyMzU5NTlaMBQxEjAQ
BgNVBAMTCXN5bmN0aGluZzCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGB
ANizpGVpWvlhkwRddVkVHo68JFSRG74ostSECMUGZTt3vpoUFuCYBUsh138KOPUH
qN59mlgGoCbvH0RVN54UDTjw32n3r5c/Pzm+ky842O1gkrexizxrODtVL/SQnp35
nPsiU86GUZ8IJIfiqYmcjd+exHmi3iU0f+m39pHQuxjeHpSNBJ9VsV30pCouFcSu
i2PI1VEsPWG/w9gL19al7JcOPhxrLQBcUzG8rTnXTFq0cxGaZre4NsVacQPC2IcE
Jdis6M6b/eTCbHquPSVs+gd9NT8ubJy6CzX5w3FGODTsQAtW1lpI7qgOQ3DRT6+n
LY3SP792le1ZEs/C0wd/xIP0gkM+PD6ZW070xmdDTbgSj48JvJIn1Xo3+XVTSVJ0
bzEbGMfGwxstZR+d/vIH1XX8gu8M9reJsT1InTLvGvJDuiZjp1aHUo8z4E6ZPKRb
I/d7h/V4nZmBaCZYjht5hxR4e3jcpzaEBq4Foh4/0e/iLnZn8JxgejDys2NqqUTx
8wIDAQABoz8wPTAOBgNVHQ8BAf8EBAMCAKAwHQYDVR0lBBYwFAYIKwYBBQUHAwEG
CCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwCwYJKoZIhvcNAQELA4IBgQANaMq2yf7A
R5r2ac1+MCwzgLSBFTMrdfperjhEvkkyC7ln73qU6FhJzbccU3NCR1pI6052X5sM
68wFBf/opIEFJLm/KRmfAlNQ1I02a0gCmmpm8stjtfynC6Iu7fKdWjytZRfXY6F7
bXCNoUlbQmePHOawIS26JP3QMauhnetRPUJt72/Yt+HFgt2cEdazzuWpbs/JVp1T
UFI/GvVTKkAgDWcb93mm1dKkHd8pOA0ATURnV+zyfOOky85Gky3++WOMre6Cb9rQ
PlooY9tQGvvuBqc17yY/RPcOBMtpUna6SKw+gW9D67fIjp529lIhcmInh1nuBjHS
EbSIxeQBGlYQKHcMfOW2HQrax0QSsMT39ppIHuiJ7ZHBO26HhtdnryhJNMiSpEs3
BK2/kGZev8CQCJrNTXCRMEPLhDHMKhHGHTSMkYJnAVEsKtzY9yFqfL7LiFA6k2Lu
CPNNZ5Ftb1RpEV2rkiNK2Le/oqg15c3la+UbTy+rfMzjLvkV33kFYcQ=
-----END CERTIFICATE-----

View File

@@ -0,0 +1,39 @@
-----BEGIN RSA PRIVATE KEY-----
MIIG5QIBAAKCAYEA2LOkZWla+WGTBF11WRUejrwkVJEbviiy1IQIxQZlO3e+mhQW
4JgFSyHXfwo49Qeo3n2aWAagJu8fRFU3nhQNOPDfafevlz8/Ob6TLzjY7WCSt7GL
PGs4O1Uv9JCenfmc+yJTzoZRnwgkh+KpiZyN357EeaLeJTR/6bf2kdC7GN4elI0E
n1WxXfSkKi4VxK6LY8jVUSw9Yb/D2AvX1qXslw4+HGstAFxTMbytOddMWrRzEZpm
t7g2xVpxA8LYhwQl2Kzozpv95MJseq49JWz6B301Py5snLoLNfnDcUY4NOxAC1bW
WkjuqA5DcNFPr6ctjdI/v3aV7VkSz8LTB3/Eg/SCQz48PplbTvTGZ0NNuBKPjwm8
kifVejf5dVNJUnRvMRsYx8bDGy1lH53+8gfVdfyC7wz2t4mxPUidMu8a8kO6JmOn
VodSjzPgTpk8pFsj93uH9XidmYFoJliOG3mHFHh7eNynNoQGrgWiHj/R7+Iudmfw
nGB6MPKzY2qpRPHzAgMBAAECggGBAL698Rhqke8smdGfyejtlAYjSP8+8uKAxFgX
F/kE1hpwHk9VG4X5ib9GPH7QKq5TXarpd++/dTyQAj+NmvUDxVe3fY+yutYwj6Bu
RPOt4BOhi8Mw/dPitI5VP27P1S5MRocvAgGpbTLEYhNRydUc/iw1fc9rMoohGe5J
RTm4Ntd+vAAZ2FW/ge2nptCR3AtRb9QXNNzMSgM+Xk5Orl97kTKtELLHC8djfL8s
ynU9MzIr35VBCOTxuxQftZaP7TN6y46obQFTpwNhX2ouXT5CH4QzGOLebo3Af2gT
3CWFtW+o6ISKJyEsGUOsxuxCKWJX3X3FNQ4TeQm38hzV9ocZOfOXq7vQMTdkB8SP
Y9LNFzaQwGAzBsBiY8aeDSWZ3TCOI+HyDIhkSjWE7ybYkcFcUv8z2yuB/gspIEgW
VhYwBoorrIZYRQXVwrWd9SKzlt/nmLOuEQWLBifEt31zmMzJhZZkUaYEssyfBvhh
/zi3BMbngkDhr2g+G6bQznwsoAQv8QKBwQDvgIdlWJbUTrfB5HBzAsW6z44phyBj
utDlhyaflAHs4BOPYPkpeeYrn/LvhhwTyhR2nIbbKCpzorjnm9LvxLu0t96SD22p
qnYJ5M7dMj6tfN7CYLqRSUkrDFm8MLDrOEjqFPriyYoITQNjbVFHwPv0k4yem8y2
RoCfM0iU9mS9q+9sKcVN7HBY5dR9KDf+k6fljYE+bETcTrTkDiacxhJhPO/PKmp2
0YvgQzb9MJaKIhZ+ovy0/0YtA9F8ZGonmf8CgcEA56ELGwfPYALv/IczCgUsheWX
S4OO4Lukv5LtgqHylvog+ZeSGxNh6wDgDhVK5XIuzVW3GiTC8sxaynsSvpyGMSeS
V7Crs85VqMryw20Con3NVttELslsYQ46ljtNNP4yFOdKIPMFrP8x7EwegqNHZ976
1/fGI9h7CMrYbUU5sndducUZoVDU79shRILJ/+Z+UZvsaMznqPCiHo1w22WPxW2W
Eo9zNnZ9t7L+jybevro0NVlKPMrHg/ZQf1WTfeANAoHAGdc1RJMFWwzPOMVL+KzA
5sIEJajlrrz2Uv19BlSyzHr0wVCGMZpsYiKU1JEUsHHqOU30Ius3gVh6OMsQPDxu
wDXidsHhZB/3MmQUibslFhTV+AT1vD06/sELYYmjXQ2qmE8BLrzt/q1Ig07FKUfC
J4ZP8sD+mmAK+qJO33uiLPDDGVl8Z0bubDkH7yUKvZXy1Iqq+jA2UcrQK5b3RYz9
aK5pdWGvMPi07dJyuWinpWm+IZW2TFUKnkq+LHytE27DAoHBAN4ZvKVhmsZMasOw
/A66oVOOr8EX19PD+Zg8kYO2N//uvdm2LcHKlxSY1T6LyjIyh5AahaUK5Oedbd1D
n9ioC8BsWlW9MRcLXXWpjJg5GdKnYFLNkxZty39Q/np5SHHs4CbNFHZ9sM6OMNeM
saDAYcLGu66Ehjhu5qKqplY4j7eB35w203msIVIQw1iHNJws7qjgIxLmj6edfUZg
h3vIadB8YO9RH790ZN3VQ2QOeH1X3KHfCWE7a44sjElczD1hrQKBwQDnnERBvdNS
47FYK+OZ88eLMedXxFuWF2PRntnSvhHohY5FcqBEh1QXbrEldS5bj+lJwk29Skqd
u+qfOKtG0VwzZcn9Rq/PG8D8cO3WwOYP+/Y1CFpDSQavVgzGgpt6DMv6lMDWD/LT
H4s6kiSfcjVm7T9FeMUKHTFbE8A0VAXMsFyasRfycdaCKfmnSpI3mMXppM26pb4C
Z/gKcbosQm2MANDrvUwnIaFeghRUtDRP3KK9kEQJX1xP6TcMxiMH58k=
-----END RSA PRIVATE KEY-----

View File

@@ -1,27 +1,27 @@
<configuration version="2">
<repository id="default" directory="s1" ro="false" ignorePerms="false">
<configuration version="4">
<repository id="default" directory="s1" ro="false" rescanIntervalS="10" ignorePerms="false">
<node id="I6KAH76-66SLLLB-5PFXSOA-UFJCDZC-YAOMLEK-CP2GB32-BV5RQST-3PSROAU"></node>
<node id="JMFJCXB-GZDE4BN-OCJE3VF-65GYZNU-AIVJRET-3J6HMRQ-AUQIGJO-FKNHMQU"></node>
<node id="373HSRP-QLPNLIE-JYKZVQF-P4PKZ63-R2ZE6K3-YD442U2-JHBGBQG-WWXAHAU"></node>
<versioning></versioning>
</repository>
<repository id="s12" directory="s12-1" ro="false" ignorePerms="false">
<repository id="s12" directory="s12-1" ro="false" rescanIntervalS="10" ignorePerms="false">
<node id="I6KAH76-66SLLLB-5PFXSOA-UFJCDZC-YAOMLEK-CP2GB32-BV5RQST-3PSROAU"></node>
<node id="JMFJCXB-GZDE4BN-OCJE3VF-65GYZNU-AIVJRET-3J6HMRQ-AUQIGJO-FKNHMQU"></node>
<versioning></versioning>
</repository>
<node id="EJHMPAQ-OGCVORE-ISB4IS3-SYYVJXF-TKJGLTU-66DIQPF-GJ5D2GX-GQ3OWQK" name="s4" compression="true">
<address>127.0.0.1:22004</address>
</node>
<node id="I6KAH76-66SLLLB-5PFXSOA-UFJCDZC-YAOMLEK-CP2GB32-BV5RQST-3PSROAU" name="s1" compression="true">
<address>127.0.0.1:22001</address>
</node>
<node id="JMFJCXB-GZDE4BN-OCJE3VF-65GYZNU-AIVJRET-3J6HMRQ-AUQIGJO-FKNHMQU" name="s2">
<node id="JMFJCXB-GZDE4BN-OCJE3VF-65GYZNU-AIVJRET-3J6HMRQ-AUQIGJO-FKNHMQU" name="s2" compression="true">
<address>127.0.0.1:22002</address>
</node>
<node id="373HSRP-QLPNLIE-JYKZVQF-P4PKZ63-R2ZE6K3-YD442U2-JHBGBQG-WWXAHAU" name="s3">
<node id="373HSRP-QLPNLIE-JYKZVQF-P4PKZ63-R2ZE6K3-YD442U2-JHBGBQG-WWXAHAU" name="s3" compression="true">
<address>127.0.0.1:22003</address>
</node>
<node id="EJHMPAQ-OGCVORE-ISB4IS3-SYYVJXF-TKJGLTU-66DIQPF-GJ5D2GX-GQ3OWQK" name="s4">
<address>127.0.0.1:22004</address>
</node>
<gui enabled="true" tls="false">
<address>127.0.0.1:8081</address>
<user>testuser</user>
@@ -34,13 +34,16 @@
<globalAnnounceEnabled>false</globalAnnounceEnabled>
<localAnnounceEnabled>true</localAnnounceEnabled>
<localAnnouncePort>21025</localAnnouncePort>
<localAnnounceMCAddr>[ff32::5222]:21026</localAnnounceMCAddr>
<parallelRequests>16</parallelRequests>
<maxSendKbps>0</maxSendKbps>
<rescanIntervalS>10</rescanIntervalS>
<maxRecvKbps>0</maxRecvKbps>
<reconnectionIntervalS>5</reconnectionIntervalS>
<maxChangeKbps>10000</maxChangeKbps>
<startBrowser>false</startBrowser>
<upnpEnabled>true</upnpEnabled>
<upnpLeaseMinutes>0</upnpLeaseMinutes>
<upnpRenewalMinutes>30</upnpRenewalMinutes>
<urAccepted>-1</urAccepted>
<restartOnWakeup>true</restartOnWakeup>
</options>
</configuration>

View File

@@ -0,0 +1,23 @@
-----BEGIN CERTIFICATE-----
MIID5TCCAk+gAwIBAgIIBYqoKiSgB+owCwYJKoZIhvcNAQELMBQxEjAQBgNVBAMT
CXN5bmN0aGluZzAeFw0xNDA5MTQyMjIzMzVaFw00OTEyMzEyMzU5NTlaMBQxEjAQ
BgNVBAMTCXN5bmN0aGluZzCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGB
AKZK/sjb6ZuVVHPvo77Cp5E8LfiznfoIWJRoX/MczE99iDyFZm1Wf9GFT8WhXICM
C2kgGbr/gAxhkeEcZ500vhA2C+aois1DGcb+vNY53I0qp3vSUl4ow55R0xJ4UjpJ
nJWF8p9iPDMwMP6WQ/E/ekKRKCOt0TFj4xqtiSt0pxPLeHfKVpWXxqIVDhnsoGQ+
NWuUjM3FkmEmhp5DdRtwskiZZYz1zCgoHkFzKt/+IxjCuzbO0+Ti8R3b/d0A+WLN
LHr0SjatajLbHebA+9c3ts6t3V5YzcMqDJ4MyxFtRoXFJjEbcM9IqKQE8t8TIhv8
a302yRikJ2uPx+fXJGospnmWCbaK2rViPbvICSgvSBA3As0f3yPzXsEt+aW5NmDV
fLBX1DU7Ow6oBqZTlI+STrzZR1qfvIuweIWoPqnPNd4sxuoxAK50ViUKdOtSYL/a
F0eM3bqbp2ozhct+Bfmqu2oI/RHXe+RUfAXrlFQ8p6jcISW2ip+oiBtR4GZkncI9
YQIDAQABoz8wPTAOBgNVHQ8BAf8EBAMCAKAwHQYDVR0lBBYwFAYIKwYBBQUHAwEG
CCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwCwYJKoZIhvcNAQELA4IBgQBsYc5XVQy5
aJVdwx+mAKiuCs5ZCvV4H4VWY9XUwEJuUUD3yXw2xyzuQl5+lOxfiQcaudhVwARC
Dao75MUctXmx1YU+J5G31cGdC9kbxWuo1xypkK+2Zl+Kwh65aod3OkHVz9oNkKpf
JnXbdph4UiFJzijSruXDDaerrQdABUvlusPozZn8vMwZ21Ls/eNIOJvA0S2d2jep
fvmu7yQPejDp7zcgPdmneuZqmUyXLxxFopYqHqFQVM8f+Y8iZ8HnMiAJgLKQcmro
pp1z/NY0Xr0pLyBY5d/sO+tZmQkyUEWegHtEtQQOO+x8BWinDEAurej/YvZTWTmN
+YoUvGdKyV6XfC6WPFcUDFHY4KPSqS3xoLmoVV4xNjJU3aG/xL4uDencNZR/UFNw
wKsdvm9SX4TpSLlQa0wu1iNv7QyeR4ZKgaBNSwp2rxpatOi7TTs9KRPfjLFLpYAg
bIons/a890SIxpuneuhQZkH63t930EXIZ+9GkU0aUs7MFg5cCmwmlvE=
-----END CERTIFICATE-----

View File

@@ -0,0 +1,39 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

View File

@@ -1,30 +1,27 @@
<configuration version="2">
<repository id="default" directory="s2" ro="false" ignorePerms="false">
<node id="I6KAH7666SLLL5PFXSOAUFJCDZYAOMLEKCP2GB3BV5RQST3PSROA"></node>
<node id="JMFJCXBGZDE4BOCJE3VF65GYZNAIVJRET3J6HMRAUQIGJOFKNHMQ"></node>
<node id="373HSRPQLPNLIJYKZVQFP4PKZ6R2ZE6K3YD442UJHBGBQGWWXAHA"></node>
<configuration version="4">
<repository id="default" directory="s2" ro="false" rescanIntervalS="15" ignorePerms="false">
<node id="I6KAH76-66SLLLB-5PFXSOA-UFJCDZC-YAOMLEK-CP2GB32-BV5RQST-3PSROAU"></node>
<node id="JMFJCXB-GZDE4BN-OCJE3VF-65GYZNU-AIVJRET-3J6HMRQ-AUQIGJO-FKNHMQU"></node>
<node id="373HSRP-QLPNLIE-JYKZVQF-P4PKZ63-R2ZE6K3-YD442U2-JHBGBQG-WWXAHAU"></node>
<versioning></versioning>
<syncorder></syncorder>
</repository>
<repository id="s12" directory="s12-2" ro="false" ignorePerms="false">
<node id="I6KAH7666SLLL5PFXSOAUFJCDZYAOMLEKCP2GB3BV5RQST3PSROA"></node>
<node id="JMFJCXBGZDE4BOCJE3VF65GYZNAIVJRET3J6HMRAUQIGJOFKNHMQ"></node>
<repository id="s12" directory="s12-2" ro="false" rescanIntervalS="15" ignorePerms="false">
<node id="I6KAH76-66SLLLB-5PFXSOA-UFJCDZC-YAOMLEK-CP2GB32-BV5RQST-3PSROAU"></node>
<node id="JMFJCXB-GZDE4BN-OCJE3VF-65GYZNU-AIVJRET-3J6HMRQ-AUQIGJO-FKNHMQU"></node>
<versioning></versioning>
<syncorder></syncorder>
</repository>
<repository id="s23" directory="s23-2" ro="false" ignorePerms="false">
<node id="JMFJCXBGZDE4BOCJE3VF65GYZNAIVJRET3J6HMRAUQIGJOFKNHMQ"></node>
<node id="373HSRPQLPNLIJYKZVQFP4PKZ6R2ZE6K3YD442UJHBGBQGWWXAHA"></node>
<repository id="s23" directory="s23-2" ro="false" rescanIntervalS="15" ignorePerms="false">
<node id="JMFJCXB-GZDE4BN-OCJE3VF-65GYZNU-AIVJRET-3J6HMRQ-AUQIGJO-FKNHMQU"></node>
<node id="373HSRP-QLPNLIE-JYKZVQF-P4PKZ63-R2ZE6K3-YD442U2-JHBGBQG-WWXAHAU"></node>
<versioning></versioning>
<syncorder></syncorder>
</repository>
<node id="I6KAH7666SLLL5PFXSOAUFJCDZYAOMLEKCP2GB3BV5RQST3PSROA" name="s1" compression="true">
<node id="I6KAH76-66SLLLB-5PFXSOA-UFJCDZC-YAOMLEK-CP2GB32-BV5RQST-3PSROAU" name="s1" compression="true">
<address>127.0.0.1:22001</address>
</node>
<node id="JMFJCXBGZDE4BOCJE3VF65GYZNAIVJRET3J6HMRAUQIGJOFKNHMQ" name="s2" compression="true">
<node id="JMFJCXB-GZDE4BN-OCJE3VF-65GYZNU-AIVJRET-3J6HMRQ-AUQIGJO-FKNHMQU" name="s2" compression="true">
<address>127.0.0.1:22002</address>
</node>
<node id="373HSRPQLPNLIJYKZVQFP4PKZ6R2ZE6K3YD442UJHBGBQGWWXAHA" name="s3">
<node id="373HSRP-QLPNLIE-JYKZVQF-P4PKZ63-R2ZE6K3-YD442U2-JHBGBQG-WWXAHAU" name="s3" compression="true">
<address>127.0.0.1:22003</address>
</node>
<gui enabled="true" tls="false">
@@ -33,17 +30,20 @@
</gui>
<options>
<listenAddress>127.0.0.1:22002</listenAddress>
<globalAnnounceServer>announce.syncthing.net:22025</globalAnnounceServer>
<globalAnnounceServer>announce.syncthing.net:22026</globalAnnounceServer>
<globalAnnounceEnabled>false</globalAnnounceEnabled>
<localAnnounceEnabled>true</localAnnounceEnabled>
<localAnnouncePort>21025</localAnnouncePort>
<localAnnounceMCAddr>[ff32::5222]:21026</localAnnounceMCAddr>
<parallelRequests>16</parallelRequests>
<maxSendKbps>0</maxSendKbps>
<rescanIntervalS>15</rescanIntervalS>
<maxRecvKbps>0</maxRecvKbps>
<reconnectionIntervalS>5</reconnectionIntervalS>
<maxChangeKbps>10000</maxChangeKbps>
<startBrowser>false</startBrowser>
<upnpEnabled>true</upnpEnabled>
<upnpLeaseMinutes>0</upnpLeaseMinutes>
<upnpRenewalMinutes>30</upnpRenewalMinutes>
<urAccepted>-1</urAccepted>
<restartOnWakeup>true</restartOnWakeup>
</options>
</configuration>

View File

@@ -0,0 +1,23 @@
-----BEGIN CERTIFICATE-----
MIID5TCCAk+gAwIBAgIIX9LzFBcO3tkwCwYJKoZIhvcNAQELMBQxEjAQBgNVBAMT
CXN5bmN0aGluZzAeFw0xNDA5MTQyMjIzMzNaFw00OTEyMzEyMzU5NTlaMBQxEjAQ
BgNVBAMTCXN5bmN0aGluZzCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGB
AJ4ZRlf2aaI6iU6xFhFhJJ4mvLTWiA4/HS3IsFAz5qvfJUr39/G51xTE/mSwFQIq
GI87C+0EOFDHwo1gIoB6d7+Ggws/1kYs6oWlhi5zZp/gRp+HkQLmy1Qv1KyCrOzP
LWChAgWzbSN9vQ9ZH/LluWfmdpChaqIiSNRGE+Ks7j1hm1ge9Hs9TzVuSH0EUAVo
OPOCY90OMA6e8bVXRCFET1qcS/jvqgVZKJ/LtD2mDn0S+tXW+bfnIaVJ+RJ8+89O
L8AL+iufth56K81CG8AP+Czz/su1xMXsS56tLF4SjuqciqqtSCH4IJidi3i2kqCP
FiGn8xHUfGZ1FfNW5dc6bMWAAUlE04G5w5vsAD0hpw/m2vGKjI6fT9qHt86emvz/
uYd2WupaEvcdevvrN5tJZLBE2aFybokDszl+ATEtTkZbvPOC2cKyAENSte6SfvZW
Ht/mvD0W6MP1oztRFRQASYG4OsvcP/4JNczRTWYNJpwVWHuQXl0DnCppYuF+QQWm
LwIDAQABoz8wPTAOBgNVHQ8BAf8EBAMCAKAwHQYDVR0lBBYwFAYIKwYBBQUHAwEG
CCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwCwYJKoZIhvcNAQELA4IBgQCQoYkLnqVN
b1BQKHox4lkQRrbhUNIOjtCo4NxvOA5Vzu4s6b4pk8Twj332Zk6sIJHkELaTZRgR
U5PzLhwvzIakpdPpH5ovQ3FTtJi6n06n61pKyXs84obXa8HR4zekRoDQHDY4FzOl
th2KOTDEya3kKfdYfApiRyVsgf2UGww8kRJuFMepVL2c52raZAJb2I26YJUTRTrV
Vuy0i0U0Up9jODBrlsvqzdVj0Yt1+8W1LR/RO5zECE8qa4HbyvW+ZRxdL76zcIGi
RiUmJH4jWw4BYg/ydvVm0ozPDlNo7NNh53tENTposIb4hj2tDOsmCZq97yHGeAL1
H/YOiKBt7nKwsLbs+AuIAzdgNggSHu/nTvieAPRKakKFqcs6vEKPr4Hlaxq2mKBM
byE+V0cwSz3jkHb51bHLTOnaGWShTTspzAeOf/U2aUJKATjdOVYS380OYuNFopob
Alm1GEriC4feATVvLuOr7hZuZx0Gg6HEFFaBRRV99P7Zv/Rh6JJJKTs=
-----END CERTIFICATE-----

View File

@@ -0,0 +1,39 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

View File

@@ -1,26 +1,24 @@
<configuration version="2">
<repository id="s23" directory="s23-3" ro="false" ignorePerms="false">
<configuration version="4">
<repository id="s23" directory="s23-3" ro="false" rescanIntervalS="20" ignorePerms="false">
<node id="JMFJCXB-GZDE4BN-OCJE3VF-65GYZNU-AIVJRET-3J6HMRQ-AUQIGJO-FKNHMQU"></node>
<node id="373HSRP-QLPNLIE-JYKZVQF-P4PKZ63-R2ZE6K3-YD442U2-JHBGBQG-WWXAHAU"></node>
<versioning></versioning>
<syncorder></syncorder>
</repository>
<repository id="default" directory="s3" ro="false" ignorePerms="false">
<repository id="default" directory="s3" ro="false" rescanIntervalS="20" ignorePerms="false">
<node id="I6KAH76-66SLLLB-5PFXSOA-UFJCDZC-YAOMLEK-CP2GB32-BV5RQST-3PSROAU"></node>
<node id="JMFJCXB-GZDE4BN-OCJE3VF-65GYZNU-AIVJRET-3J6HMRQ-AUQIGJO-FKNHMQU"></node>
<node id="373HSRP-QLPNLIE-JYKZVQF-P4PKZ63-R2ZE6K3-YD442U2-JHBGBQG-WWXAHAU"></node>
<versioning type="simple">
<param key="keep" val="5"></param>
</versioning>
<syncorder></syncorder>
</repository>
<node id="I6KAH76-66SLLLB-5PFXSOA-UFJCDZC-YAOMLEK-CP2GB32-BV5RQST-3PSROAU" name="s1">
<node id="I6KAH76-66SLLLB-5PFXSOA-UFJCDZC-YAOMLEK-CP2GB32-BV5RQST-3PSROAU" name="s1" compression="true">
<address>127.0.0.1:22001</address>
</node>
<node id="JMFJCXB-GZDE4BN-OCJE3VF-65GYZNU-AIVJRET-3J6HMRQ-AUQIGJO-FKNHMQU" name="s2">
<node id="JMFJCXB-GZDE4BN-OCJE3VF-65GYZNU-AIVJRET-3J6HMRQ-AUQIGJO-FKNHMQU" name="s2" compression="true">
<address>127.0.0.1:22002</address>
</node>
<node id="373HSRP-QLPNLIE-JYKZVQF-P4PKZ63-R2ZE6K3-YD442U2-JHBGBQG-WWXAHAU" name="s3">
<node id="373HSRP-QLPNLIE-JYKZVQF-P4PKZ63-R2ZE6K3-YD442U2-JHBGBQG-WWXAHAU" name="s3" compression="true">
<address>127.0.0.1:22003</address>
</node>
<gui enabled="true" tls="false">
@@ -29,17 +27,20 @@
</gui>
<options>
<listenAddress>127.0.0.1:22003</listenAddress>
<globalAnnounceServer>announce.syncthing.net:22025</globalAnnounceServer>
<globalAnnounceServer>announce.syncthing.net:22026</globalAnnounceServer>
<globalAnnounceEnabled>false</globalAnnounceEnabled>
<localAnnounceEnabled>true</localAnnounceEnabled>
<localAnnounceEnabled>false</localAnnounceEnabled>
<localAnnouncePort>21025</localAnnouncePort>
<localAnnounceMCAddr>[ff32::5222]:21026</localAnnounceMCAddr>
<parallelRequests>16</parallelRequests>
<maxSendKbps>0</maxSendKbps>
<rescanIntervalS>20</rescanIntervalS>
<maxRecvKbps>0</maxRecvKbps>
<reconnectionIntervalS>5</reconnectionIntervalS>
<maxChangeKbps>10000</maxChangeKbps>
<startBrowser>false</startBrowser>
<upnpEnabled>true</upnpEnabled>
<upnpEnabled>false</upnpEnabled>
<upnpLeaseMinutes>0</upnpLeaseMinutes>
<upnpRenewalMinutes>30</upnpRenewalMinutes>
<urAccepted>-1</urAccepted>
<restartOnWakeup>true</restartOnWakeup>
</options>
</configuration>

View File

@@ -0,0 +1,23 @@
-----BEGIN CERTIFICATE-----
MIID5TCCAk+gAwIBAgIIdbrEV5+jpE0wCwYJKoZIhvcNAQELMBQxEjAQBgNVBAMT
CXN5bmN0aGluZzAeFw0xNDA5MTQyMjI0MDdaFw00OTEyMzEyMzU5NTlaMBQxEjAQ
BgNVBAMTCXN5bmN0aGluZzCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGB
ALEhr4uC9J4vwDSXQCviKfJBln+LhQhHn8xBEi4xqedmYbXkesIZfCBf6t7DIgdN
whPkcJb74tbiMqEyEIVFHRbdlyFRaDLfvCoV3f7OU36EoChDsAQ+LCHza39pWcsq
uGXBk6xsuMAgPubPr4tYbUW+bgrC5owK1Ny1341TOwcxpXw3XzaRNqwMgKVPUfB4
jfr9vf59OgQb+kElWyVMCbuHHEGVLYUmIa1tjFOul6HgUEfbTKvyjeXkJKKMnMXX
rERdp3kq/nIkKzhpqu0X6L6vnG4vQ+7hvs5NIhyjSgMVXr7dMlxWYoIEbGyR9ZXD
Yr3vL/3EAoTOA0OuBV5OHHb+wQGK8eeiKzlheXF7nAeIpitH7/sih3I7Yk+bdsGY
HlWkOkGt1xQh/d9BDCm3+MPhIZRlF/m1QYha8ofLIbk8vLpJZSpY/2q8qV7xCKKd
0b4E/x+ee7KDdBxsH4XzqZAMW/9zFQEu8VxQSPp2Wfwda+gKmWB3XzRrNdyqbtcg
zQIDAQABoz8wPTAOBgNVHQ8BAf8EBAMCAKAwHQYDVR0lBBYwFAYIKwYBBQUHAwEG
CCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwCwYJKoZIhvcNAQELA4IBgQBHlkaRKtXm
pb882RdvFMXLuChuqhDjf8cciWaqaN7N0f3u9JetO+3MGOLsSrv5EBVNFYVqGzwc
otapi3w3CJ1Cu/bRSl88A1TlLIzjet6R6/gbcRmshW7KgZa2yfeDiIOZw4O5SQvX
SFvJNqViotMj3XgAE8iNo2pyEkQk4l/HHEf8/ALYSlU9O4SVr7kw0udoZOIrlx2a
EvQXsXf/kJDeBJ2TNDZ0p4gow8kacsxmKt/uoKDBGiRyUdeC9Au0qa2LNgc9yO0z
dzaBTpDT5kuuFBjul7GFsqvSoQx+DXcvj1URBsaGMKUHJXpdbSpIBmiWv+tdSdw5
qipizzSBMpKOofCtkPn7eCGumCp0oxk1EHMAyMD0eLFy+v+rEBBpld40J0CB28MT
6r5rUkH77aKRXSLeO0hGRuiuKPtJLG+P9n8/q4SwZZ42LF3XpeE35l8noG7KFnXl
lkbbdLZR5FaFwRbosB07LE9UkjYrWokHw4PGab1H/pkcYazBhXDREVU=
-----END CERTIFICATE-----

View File

@@ -0,0 +1,39 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

View File

@@ -1,40 +1,48 @@
<configuration version="2">
<repository id="unique" directory="s4" ro="false">
<node id="I6KAH7666SLLL5PFXSOAUFJCDZYAOMLEKCP2GB3BV5RQST3PSROA" name="s1"></node>
<node id="JMFJCXBGZDE4BOCJE3VF65GYZNAIVJRET3J6HMRAUQIGJOFKNHMQ" name="s2"></node>
<node id="373HSRPQLPNLIJYKZVQFP4PKZ6R2ZE6K3YD442UJHBGBQGWWXAHA" name="s3"></node>
<node id="EJHMPAQOGCVORISB4IS3SYYVJXTKJGLTU66DIQPGJ5D2GXGQ3OWQ" name="s4"></node>
<configuration version="4">
<repository id="unique" directory="s4" ro="false" rescanIntervalS="60" ignorePerms="false">
<node id="EJHMPAQ-OGCVORE-ISB4IS3-SYYVJXF-TKJGLTU-66DIQPF-GJ5D2GX-GQ3OWQK"></node>
<node id="I6KAH76-66SLLLB-5PFXSOA-UFJCDZC-YAOMLEK-CP2GB32-BV5RQST-3PSROAU"></node>
<node id="JMFJCXB-GZDE4BN-OCJE3VF-65GYZNU-AIVJRET-3J6HMRQ-AUQIGJO-FKNHMQU"></node>
<node id="373HSRP-QLPNLIE-JYKZVQF-P4PKZ63-R2ZE6K3-YD442U2-JHBGBQG-WWXAHAU"></node>
<versioning></versioning>
</repository>
<repository id="default" directory="s4d" ro="false">
<node id="I6KAH7666SLLL5PFXSOAUFJCDZYAOMLEKCP2GB3BV5RQST3PSROA" name="s1"></node>
<repository id="default" directory="s4d" ro="false" rescanIntervalS="60" ignorePerms="false">
<node id="EJHMPAQ-OGCVORE-ISB4IS3-SYYVJXF-TKJGLTU-66DIQPF-GJ5D2GX-GQ3OWQK"></node>
<node id="I6KAH76-66SLLLB-5PFXSOA-UFJCDZC-YAOMLEK-CP2GB32-BV5RQST-3PSROAU"></node>
<versioning></versioning>
</repository>
<node id="I6KAH7666SLLL5PFXSOAUFJCDZYAOMLEKCP2GB3BV5RQST3PSROA" name="s1">
<node id="I6KAH76-66SLLLB-5PFXSOA-UFJCDZC-YAOMLEK-CP2GB32-BV5RQST-3PSROAU" name="s1" compression="true">
<address>127.0.0.1:22001</address>
</node>
<node id="JMFJCXBGZDE4BOCJE3VF65GYZNAIVJRET3J6HMRAUQIGJOFKNHMQ" name="s2">
<node id="JMFJCXB-GZDE4BN-OCJE3VF-65GYZNU-AIVJRET-3J6HMRQ-AUQIGJO-FKNHMQU" name="s2" compression="true">
<address>127.0.0.1:22002</address>
</node>
<node id="373HSRPQLPNLIJYKZVQFP4PKZ6R2ZE6K3YD442UJHBGBQGWWXAHA" name="s3">
<node id="373HSRP-QLPNLIE-JYKZVQF-P4PKZ63-R2ZE6K3-YD442U2-JHBGBQG-WWXAHAU" name="s3" compression="true">
<address>127.0.0.1:22003</address>
</node>
<node id="EJHMPAQOGCVORISB4IS3SYYVJXTKJGLTU66DIQPGJ5D2GXGQ3OWQ" name="s4">
<node id="EJHMPAQ-OGCVORE-ISB4IS3-SYYVJXF-TKJGLTU-66DIQPF-GJ5D2GX-GQ3OWQK" name="s4" compression="true">
<address>dynamic</address>
</node>
<gui enabled="true">
<gui enabled="true" tls="false">
<address>127.0.0.1:8084</address>
<apikey>abc123</apikey>
<apikey>abc123</apikey>
</gui>
<options>
<listenAddress>:22004</listenAddress>
<globalAnnounceServer>announce.syncthing.net:22025</globalAnnounceServer>
<globalAnnounceServer>announce.syncthing.net:22026</globalAnnounceServer>
<globalAnnounceEnabled>false</globalAnnounceEnabled>
<localAnnounceEnabled>true</localAnnounceEnabled>
<localAnnounceEnabled>false</localAnnounceEnabled>
<localAnnouncePort>21025</localAnnouncePort>
<localAnnounceMCAddr>[ff32::5222]:21026</localAnnounceMCAddr>
<parallelRequests>16</parallelRequests>
<maxSendKbps>0</maxSendKbps>
<rescanIntervalS>60</rescanIntervalS>
<maxRecvKbps>0</maxRecvKbps>
<reconnectionIntervalS>10</reconnectionIntervalS>
<maxChangeKbps>10000</maxChangeKbps>
<startBrowser>false</startBrowser>
<upnpEnabled>false</upnpEnabled>
<upnpLeaseMinutes>0</upnpLeaseMinutes>
<upnpRenewalMinutes>30</upnpRenewalMinutes>
<urAccepted>-1</urAccepted>
<restartOnWakeup>true</restartOnWakeup>
</options>
</configuration>

View File

@@ -0,0 +1,23 @@
-----BEGIN CERTIFICATE-----
MIID5TCCAk+gAwIBAgIISAohRYcPi4cwCwYJKoZIhvcNAQELMBQxEjAQBgNVBAMT
CXN5bmN0aGluZzAeFw0xNDA5MTQyMjI0MTBaFw00OTEyMzEyMzU5NTlaMBQxEjAQ
BgNVBAMTCXN5bmN0aGluZzCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGB
ANqeoSRjMEnjCOTO6yAaAl3XeV3nAYlC1MK2qPPIBo4NuY8ilEXM0Q7BL1ux8f+k
V7VPRL2QBizRai7/DqdsXdVQGPY38p4MKpIyp/PXQcPxLyIgZXPE8OQqX9sBltKV
Xjbe9aJbiGnFrLeQye10DBkq+2UXCMeNX06KjVPaxNf7O4fdowgfYu28QsyMb1lw
g72ve501lKvtjEobBN2+NAxm1vBKLVU9onbU6ewGZBMHtap9qE+gDulkS419U62p
79HG/xvBcazWIGSWw9AsHNO6GOtvsjb1U2m2KUHqFAIKmmNPuiy/RupXHoHpgiec
r+sZHx3OFL66gdnZWNRTMcDUrpflD8f/Mp6gba2+1CM2RB3bIzNaEiYbgippH5FM
/Hpa9q931+Rucll+NMwPb3ORTG8XSAB7DoNqudixid1S+Grc1bqF2dq9ZzJUwIqH
uJBtshb1U/p8t7I1pEOTGnWs1b/tasDOIHiHx1AWCKa8mMLzqqx6d9IuzUI5vcql
xwIDAQABoz8wPTAOBgNVHQ8BAf8EBAMCAKAwHQYDVR0lBBYwFAYIKwYBBQUHAwEG
CCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwCwYJKoZIhvcNAQELA4IBgQCYFBRPZqpc
1+A7CpfcYezH4/9Cd9yUMeYBFebGnB9NEsp6Q/BaLAHBaeDfxjed45etOH3WaYBJ
IUru+bAuk8xKitYmpXi4AByPmYp3pI1gsldqYSZWS6ivpdGD/t4Yd6nOxNZokOOq
Ygxdg7WCu1d5fgvReZ3GbBlRn6+uym7ZZuTcpgOqbdeMY3EFKwoBR5LtW9iaDeZ5
gQXvTRk276TgFZuh9GPYv4iD3F3iAlDHdA8sQz4mUnYHxYrWoSViy7TOPZbB/NP0
eAN5d4s1BhESNzDX3ODR47VL7IyZtVqbNURPdw0BVMnC7m1iKTsSAsh+b4zShNqg
RNjBtv3Kew5BKP79qUZL5v/WSBgIl1RIko/jp+RwlghoFJGl5ku2A0syZLgUBor1
VaTfL9Uv/fSYUscBnAd/2Yt+Gxm3Ng48I24FkXdL4ZWVP76+63ugoEGvgAiRTHBC
Lls7vBQS7a/3TVayhogADkUo6XgZE/FfNTqLeLKoljBLLyYs3CIHE8s=
-----END CERTIFICATE-----

View File

@@ -0,0 +1,39 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

View File

@@ -0,0 +1,102 @@
// Copyright (C) 2014 Jakob Borg and Contributors (see the CONTRIBUTORS file).
// All rights reserved. Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
// +build integration
package integration_test
import (
"bytes"
"crypto/tls"
"errors"
"io/ioutil"
"log"
"net/http"
"os"
"sync"
"testing"
"time"
)
func TestStressHTTP(t *testing.T) {
log.Println("Cleaning...")
err := removeAll("s2", "h2/index")
if err != nil {
t.Fatal(err)
}
os.Setenv("STNORESTART", "1")
log.Println("Starting up...")
sender := syncthingProcess{ // id1
log: "2.out",
argv: []string{"-home", "h2"},
port: 8082,
apiKey: apiKey,
}
ver, err := sender.start()
if err != nil {
t.Fatal(err)
}
log.Println(ver)
tc := &tls.Config{InsecureSkipVerify: true}
tr := &http.Transport{
TLSClientConfig: tc,
}
client := &http.Client{
Transport: tr,
Timeout: 2 * time.Second,
}
var wg sync.WaitGroup
t0 := time.Now()
var counter int
var lock sync.Mutex
errChan := make(chan error, 2)
for i := 0; i < 50; i++ {
i := i
wg.Add(1)
go func() {
for time.Since(t0).Seconds() < 30 {
proto := "http"
if i%2 == 0 {
proto = "https"
}
resp, err := client.Get(proto + "://localhost:8082/")
if err != nil {
errChan <- err
return
}
bs, _ := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if !bytes.Contains(bs, []byte("</html>")) {
log.Printf("%s", bs)
errChan <- errors.New("Incorrect response")
return
}
lock.Lock()
counter++
lock.Unlock()
}
wg.Done()
}()
}
go func() {
wg.Wait()
errChan <- nil
}()
err = <-errChan
t.Logf("%.01f reqs/sec", float64(counter)/time.Since(t0).Seconds())
sender.stop()
if err != nil {
t.Error(err)
}
}

View File

@@ -13,17 +13,6 @@ import (
"time"
)
const (
apiKey = "abc123" // Used when talking to the processes under test
id1 = "I6KAH76-66SLLLB-5PFXSOA-UFJCDZC-YAOMLEK-CP2GB32-BV5RQST-3PSROAU"
id2 = "JMFJCXB-GZDE4BN-OCJE3VF-65GYZNU-AIVJRET-3J6HMRQ-AUQIGJO-FKNHMQU"
)
var env = []string{
"HOME=.",
"STTRACE=model",
}
func TestRestartReceiverDuringTransfer(t *testing.T) {
testRestartDuringTransfer(t, false, true, 0, 0)
}
@@ -33,48 +22,50 @@ func TestRestartSenderDuringTransfer(t *testing.T) {
}
func TestRestartSenderAndReceiverDuringTransfer(t *testing.T) {
// // Give the receiver some time to rot with needed files but
// // without any peer. This triggers
// // https://github.com/syncthing/syncthing/issues/463
// Give the receiver some time to rot with needed files but
// without any peer. This triggers
// https://github.com/syncthing/syncthing/issues/463
testRestartDuringTransfer(t, true, true, 10*time.Second, 0)
}
func testRestartDuringTransfer(t *testing.T, restartSender, restartReceiver bool, senderDelay, receiverDelay time.Duration) {
log.Println("Cleaning...")
err := removeAll("s1", "s2", "f1/index", "f2/index")
err := removeAll("s1", "s2", "h1/index", "h2/index")
if err != nil {
t.Fatal(err)
}
log.Println("Generating files...")
err = generateFiles("s1", 1000, 20, "../bin/syncthing")
err = generateFiles("s1", 1000, 22, "../bin/syncthing")
if err != nil {
t.Fatal(err)
}
log.Println("Starting up...")
sender := syncthingProcess{ // id1
log: "1.out",
argv: []string{"-home", "f1"},
port: 8081,
log: "1.out",
argv: []string{"-home", "h1"},
port: 8081,
apiKey: apiKey,
}
err = sender.start()
ver, err := sender.start()
if err != nil {
t.Fatal(err)
}
log.Println(ver)
receiver := syncthingProcess{ // id2
log: "2.out",
argv: []string{"-home", "f2"},
port: 8082,
log: "2.out",
argv: []string{"-home", "h2"},
port: 8082,
apiKey: apiKey,
}
err = receiver.start()
ver, err = receiver.start()
if err != nil {
sender.stop()
t.Fatal(err)
}
// Give them time to start up
time.Sleep(1 * time.Second)
log.Println(ver)
var prevComp int
for {
@@ -130,8 +121,6 @@ func testRestartDuringTransfer(t *testing.T, restartSender, restartReceiver bool
prevComp = curComp
}
time.Sleep(1 * time.Second)
}
sender.stop()

View File

@@ -1,4 +1,6 @@
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'
# Copyright (C) 2014 Jakob Borg and other contributors. All rights reserved.
# Use of this source code is governed by an MIT-style license that can be
@@ -23,7 +25,7 @@ start() {
stop() {
for i in 1 2 3 ; do
curl -HX-API-Key:abc123 -X POST "http://127.0.0.1:808$i/rest/shutdown"
curl -s -o /dev/null -HX-API-Key:abc123 -X POST "http://127.0.0.1:808$i/rest/shutdown"
done
exit $1
}
@@ -96,11 +98,13 @@ alterFiles() {
if [[ $nfiles -ge 300 ]] ; then
todelete=$(( $nfiles - 300 ))
echo " $i: deleting $todelete files..."
set +o pipefail
find . -type f \
| grep -v large \
| sort -k 1.16 \
| head -n "$todelete" \
| xargs rm -f
set -o pipefail
fi
# Create some new files and alter existing ones
@@ -119,11 +123,11 @@ alterFiles() {
pkill -CONT syncthing
echo "Restarting instance 2"
curl -HX-API-Key:abc123 -X POST "http://127.0.0.1:8082/rest/restart"
curl -s -o /dev/null -HX-API-Key:abc123 -X POST "http://127.0.0.1:8082/rest/restart"
}
rm -rf h?/*.idx.gz h?/index
chmod -R u+w s? s??-?
chmod -R u+w s? s??-? || true
rm -rf s? s??-?
mkdir s1 s2 s3 s12-1 s12-2 s23-2 s23-3

View File

@@ -1,4 +1,6 @@
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'
# Copyright (C) 2014 Jakob Borg and other contributors. All rights reserved.
# Use of this source code is governed by an MIT-style license that can be
@@ -21,7 +23,7 @@ start() {
stop() {
echo "Stopping..."
for i in 1 2 ; do
curl -HX-API-Key:abc123 -X POST "http://127.0.0.1:808$i/rest/shutdown"
curl -s -o /dev/null -HX-API-Key:abc123 -X POST "http://127.0.0.1:808$i/rest/shutdown"
done
}
@@ -29,7 +31,7 @@ setup() {
echo "Setting up dirs..."
mkdir -p s1
pushd s1 >/dev/null
rm -r */*[02468] 2>/dev/null
rm -r */*[02468] 2>/dev/null || true
rm -rf *2
for ((i = 0; i < 500; i++)) ; do
mkdir -p "$RANDOM/$RANDOM"
@@ -75,7 +77,7 @@ testConvergence() {
fi
}
chmod -R +w s? s??-?
chmod -R +w s? s??-? || true
rm -rf s? s??-?
rm -rf f?/*.idx.gz f?/index

View File

@@ -1,4 +1,6 @@
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'
# Copyright (C) 2014 Jakob Borg and other contributors. All rights reserved.
# Use of this source code is governed by an MIT-style license that can be
@@ -19,7 +21,7 @@ echo Building
go build http.go
echo Starting
chmod -R +w s1 s2
chmod -R +w s1 s2 || true
rm -rf s1 s2 h1/index h2/index
syncthing -home h1 > 1.out 2>&1 &
syncthing -home h2 > 2.out 2>&1 &

View File

@@ -1,4 +1,6 @@
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'
# Copyright (C) 2014 Jakob Borg and other contributors. All rights reserved.
# Use of this source code is governed by an MIT-style license that can be
@@ -23,7 +25,7 @@ start() {
stop() {
for i in 1 2 3 4 ; do
curl -HX-API-Key:abc123 -X POST "http://127.0.0.1:808$i/rest/shutdown"
curl -s -o /dev/null -HX-API-Key:abc123 -X POST "http://127.0.0.1:808$i/rest/shutdown"
done
exit $1
}
@@ -114,7 +116,7 @@ alterFiles() {
}
rm -rf h?/*.idx.gz h?/index
chmod -R +w s? s??-? s4d
chmod -R +w s? s??-? s4d || true
rm -rf s? s??-? s4d
echo "Setting up files..."

View File

@@ -324,15 +324,19 @@ func (m *Model) NeedSize(repo string) (files int, bytes int64) {
return
}
// NeedFiles returns the list of currently needed files
func (m *Model) NeedFilesRepo(repo string) []protocol.FileInfo {
// NeedFiles returns the list of currently needed files, stopping at maxFiles
// files or maxBlocks blocks. Limits <= 0 are ignored.
func (m *Model) NeedFilesRepoLimited(repo string, maxFiles, maxBlocks int) []protocol.FileInfo {
m.rmut.RLock()
defer m.rmut.RUnlock()
nblocks := 0
if rf, ok := m.repoFiles[repo]; ok {
fs := make([]protocol.FileInfo, 0, indexBatchSize)
fs := make([]protocol.FileInfo, 0, maxFiles)
rf.WithNeed(protocol.LocalNodeID, func(f protocol.FileIntf) bool {
fs = append(fs, f.(protocol.FileInfo))
return len(fs) < indexBatchSize
fi := f.(protocol.FileInfo)
fs = append(fs, fi)
nblocks += len(fi.Blocks)
return (maxFiles <= 0 || len(fs) < maxFiles) && (maxBlocks <= 0 || nblocks < maxBlocks)
})
return fs
}

View File

@@ -61,6 +61,11 @@ type openFile struct {
type activityMap map[protocol.NodeID]int
// Queue about this many blocks each puller iteration. More blocks means
// longer iterations and better efficiency; fewer blocks reduce memory
// consumption. 1000 blocks ~= 1000 * 128 KiB ~= 125 MiB of data.
const pullIterationBlocks = 1000
func (m activityMap) leastBusyNode(availability []protocol.NodeID, isValid func(protocol.NodeID) bool) protocol.NodeID {
var low int = 2<<30 - 1
var selected protocol.NodeID
@@ -702,7 +707,7 @@ func (p *puller) queueNeededBlocks(prevVer uint64) (uint64, int) {
queued := 0
files := make([]protocol.FileInfo, 0, indexBatchSize)
for _, f := range p.model.NeedFilesRepo(p.repoCfg.ID) {
for _, f := range p.model.NeedFilesRepoLimited(p.repoCfg.ID, indexBatchSize, pullIterationBlocks) {
if _, ok := p.openFiles[f.Name]; ok {
continue
}