浏览代码

all: Use protobuf to generate config structs (fixes #6734) (#6900)

Audrius Butkevicius 5 年之前
父节点
当前提交
d507d932b8
共有 84 个文件被更改,包括 3807 次插入542 次删除
  1. 1 0
      .gitignore
  2. 1 0
      build.go
  3. 1 1
      cmd/stcli/main.go
  4. 1 1
      cmd/stdiscosrv/database.go
  5. 1 1
      cmd/syncthing/main.go
  6. 1 0
      go.mod
  7. 0 4
      lib/api/mocked_config_test.go
  8. 0 7
      lib/config/authmode.go
  9. 69 0
      lib/config/authmode.pb.go
  10. 0 8
      lib/config/blockpullorder.go
  11. 70 0
      lib/config/blockpullorder.pb.go
  12. 14 26
      lib/config/config.go
  13. 151 0
      lib/config/config.pb.go
  14. 12 13
      lib/config/config_test.go
  15. 0 19
      lib/config/deviceconfiguration.go
  16. 213 0
      lib/config/deviceconfiguration.pb.go
  17. 13 64
      lib/config/folderconfiguration.go
  18. 401 0
      lib/config/folderconfiguration.pb.go
  19. 0 8
      lib/config/foldertype.go
  20. 69 0
      lib/config/foldertype.pb.go
  21. 0 16
      lib/config/guiconfiguration.go
  22. 187 0
      lib/config/guiconfiguration.pb.go
  23. 0 9
      lib/config/ldapconfiguration.go
  24. 138 0
      lib/config/ldapconfiguration.pb.go
  25. 0 8
      lib/config/ldaptransport.go
  26. 74 0
      lib/config/ldaptransport.pb.go
  27. 0 26
      lib/config/observed.go
  28. 175 0
      lib/config/observed.pb.go
  29. 0 57
      lib/config/optionsconfiguration.go
  30. 502 0
      lib/config/optionsconfiguration.pb.go
  31. 13 24
      lib/config/pullorder.go
  32. 87 0
      lib/config/pullorder.pb.go
  33. 0 5
      lib/config/size.go
  34. 101 0
      lib/config/size.pb.go
  35. 0 9
      lib/config/tuning.go
  36. 70 0
      lib/config/tuning.pb.go
  37. 0 7
      lib/config/versioningconfiguration.go
  38. 122 0
      lib/config/versioningconfiguration.pb.go
  39. 5 14
      lib/config/wrapper.go
  40. 4 2
      lib/connections/limiter.go
  41. 5 5
      lib/connections/limiter_test.go
  42. 1 1
      lib/connections/service.go
  43. 2 2
      lib/db/structs.go
  44. 1 1
      lib/discover/local.go
  45. 0 11
      lib/fs/copyrangemethod.go
  46. 87 0
      lib/fs/copyrangemethod.pb.go
  47. 0 7
      lib/fs/types.go
  48. 65 0
      lib/fs/types.pb.go
  49. 13 11
      lib/model/folder.go
  50. 1 1
      lib/model/folder_sendonly.go
  51. 10 10
      lib/model/folder_sendrecv.go
  52. 4 1
      lib/model/model.go
  53. 1 1
      lib/model/model_test.go
  54. 138 138
      lib/protocol/bep.pb.go
  55. 0 3
      lib/protocol/bep_extensions.go
  56. 1 1
      lib/protocol/deviceid_test.go
  57. 1 1
      lib/rc/rc.go
  58. 8 8
      lib/syncthing/utils.go
  59. 2 2
      lib/util/utils.go
  60. 2 1
      meta/gofmt_test.go
  61. 24 0
      proto/ext.proto
  62. 131 0
      proto/ext/ext.pb.go
  63. 55 0
      proto/generate.go
  64. 14 0
      proto/lib/config/authmode.proto
  65. 9 0
      proto/lib/config/blockpullorder.proto
  66. 23 0
      proto/lib/config/config.proto
  67. 27 0
      proto/lib/config/deviceconfiguration.proto
  68. 61 0
      proto/lib/config/folderconfiguration.proto
  69. 9 0
      proto/lib/config/foldertype.proto
  70. 23 0
      proto/lib/config/guiconfiguration.proto
  71. 17 0
      proto/lib/config/ldapconfiguration.proto
  72. 15 0
      proto/lib/config/ldaptransport.proto
  73. 20 0
      proto/lib/config/observed.proto
  74. 66 0
      proto/lib/config/optionsconfiguration.proto
  75. 16 0
      proto/lib/config/pullorder.proto
  76. 14 0
      proto/lib/config/size.proto
  77. 13 0
      proto/lib/config/tuning.proto
  78. 14 0
      proto/lib/config/versioningconfiguration.proto
  79. 12 0
      proto/lib/fs/copyrangemethod.proto
  80. 8 0
      proto/lib/fs/types.proto
  81. 0 0
      proto/lib/protocol/bep.proto
  82. 68 0
      proto/scripts/dump_tags.go
  83. 291 0
      proto/scripts/protoc_plugin.go
  84. 39 8
      proto/scripts/protofmt.go

+ 1 - 0
.gitignore

@@ -17,3 +17,4 @@ RELEASE
 deb
 deb
 *.bz2
 *.bz2
 /repos
 /repos
+/proto/scripts/protoc-gen-gosyncthing

+ 1 - 0
build.go

@@ -812,6 +812,7 @@ func proto() {
 		runPrintInDir(path, "git", "checkout", dep.commit)
 		runPrintInDir(path, "git", "checkout", dep.commit)
 	}
 	}
 	runPrint(goCmd, "generate", "github.com/syncthing/syncthing/lib/...", "github.com/syncthing/syncthing/cmd/stdiscosrv")
 	runPrint(goCmd, "generate", "github.com/syncthing/syncthing/lib/...", "github.com/syncthing/syncthing/cmd/stdiscosrv")
+	runPrint(goCmd, "generate", "proto/generate.go")
 }
 }
 
 
 func translate() {
 func translate() {

+ 1 - 1
cmd/stcli/main.go

@@ -85,7 +85,7 @@ func main() {
 		myID := protocol.NewDeviceID(cert.Certificate[0])
 		myID := protocol.NewDeviceID(cert.Certificate[0])
 
 
 		// Load the config
 		// Load the config
-		cfg, err := config.Load(locations.Get(locations.ConfigFile), myID, events.NoopLogger)
+		cfg, _, err := config.Load(locations.Get(locations.ConfigFile), myID, events.NoopLogger)
 		if err != nil {
 		if err != nil {
 			log.Fatalln(errors.Wrap(err, "loading config"))
 			log.Fatalln(errors.Wrap(err, "loading config"))
 		}
 		}

+ 1 - 1
cmd/stdiscosrv/database.go

@@ -4,7 +4,7 @@
 // License, v. 2.0. If a copy of the MPL was not distributed with this file,
 // 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/.
 // You can obtain one at https://mozilla.org/MPL/2.0/.
 
 
-//go:generate go run ../../script/protofmt.go database.proto
+//go:generate go run ../../proto/scripts/protofmt.go database.proto
 //go:generate protoc -I ../../ -I . --gogofast_out=. database.proto
 //go:generate protoc -I ../../ -I . --gogofast_out=. database.proto
 
 
 package main
 package main

+ 1 - 1
cmd/syncthing/main.go

@@ -748,7 +748,7 @@ func setupSignalHandling(app *syncthing.App) {
 
 
 func loadOrDefaultConfig(myID protocol.DeviceID, evLogger events.Logger) (config.Wrapper, error) {
 func loadOrDefaultConfig(myID protocol.DeviceID, evLogger events.Logger) (config.Wrapper, error) {
 	cfgFile := locations.Get(locations.ConfigFile)
 	cfgFile := locations.Get(locations.ConfigFile)
-	cfg, err := config.Load(cfgFile, myID, evLogger)
+	cfg, _, err := config.Load(cfgFile, myID, evLogger)
 
 
 	if err != nil {
 	if err != nil {
 		cfg, err = syncthing.DefaultConfig(cfgFile, myID, evLogger, noDefaultFolder)
 		cfg, err = syncthing.DefaultConfig(cfgFile, myID, evLogger, noDefaultFolder)

+ 1 - 0
go.mod

@@ -20,6 +20,7 @@ require (
 	github.com/gobwas/glob v0.2.3
 	github.com/gobwas/glob v0.2.3
 	github.com/gogo/protobuf v1.3.1
 	github.com/gogo/protobuf v1.3.1
 	github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9
 	github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9
+	github.com/golang/protobuf v1.4.2
 	github.com/greatroar/blobloom v0.3.0
 	github.com/greatroar/blobloom v0.3.0
 	github.com/jackpal/gateway v1.0.6
 	github.com/jackpal/gateway v1.0.6
 	github.com/jackpal/go-nat-pmp v1.0.2
 	github.com/jackpal/go-nat-pmp v1.0.2

+ 0 - 4
lib/api/mocked_config_test.go

@@ -74,10 +74,6 @@ func (c *mockedConfig) AddOrUpdatePendingDevice(device protocol.DeviceID, name,
 
 
 func (c *mockedConfig) AddOrUpdatePendingFolder(id, label string, device protocol.DeviceID) {}
 func (c *mockedConfig) AddOrUpdatePendingFolder(id, label string, device protocol.DeviceID) {}
 
 
-func (c *mockedConfig) MyName() string {
-	return ""
-}
-
 func (c *mockedConfig) ConfigPath() string {
 func (c *mockedConfig) ConfigPath() string {
 	return ""
 	return ""
 }
 }

+ 0 - 7
lib/config/authmode.go

@@ -6,13 +6,6 @@
 
 
 package config
 package config
 
 
-type AuthMode int
-
-const (
-	AuthModeStatic AuthMode = iota // default is static
-	AuthModeLDAP
-)
-
 func (t AuthMode) String() string {
 func (t AuthMode) String() string {
 	switch t {
 	switch t {
 	case AuthModeStatic:
 	case AuthModeStatic:

+ 69 - 0
lib/config/authmode.pb.go

@@ -0,0 +1,69 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: lib/config/authmode.proto
+
+package config
+
+import (
+	fmt "fmt"
+	_ "github.com/gogo/protobuf/gogoproto"
+	proto "github.com/gogo/protobuf/proto"
+	_ "github.com/syncthing/syncthing/proto/ext"
+	math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+type AuthMode int32
+
+const (
+	AuthModeStatic AuthMode = 0
+	AuthModeLDAP   AuthMode = 1
+)
+
+var AuthMode_name = map[int32]string{
+	0: "AUTH_MODE_STATIC",
+	1: "AUTH_MODE_LDAP",
+}
+
+var AuthMode_value = map[string]int32{
+	"AUTH_MODE_STATIC": 0,
+	"AUTH_MODE_LDAP":   1,
+}
+
+func (AuthMode) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_8e30b562e1bcea1e, []int{0}
+}
+
+func init() {
+	proto.RegisterEnum("config.AuthMode", AuthMode_name, AuthMode_value)
+}
+
+func init() { proto.RegisterFile("lib/config/authmode.proto", fileDescriptor_8e30b562e1bcea1e) }
+
+var fileDescriptor_8e30b562e1bcea1e = []byte{
+	// 230 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xcc, 0xc9, 0x4c, 0xd2,
+	0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0x4f, 0x2c, 0x2d, 0xc9, 0xc8, 0xcd, 0x4f, 0x49, 0xd5,
+	0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0x08, 0x4b, 0x29, 0x17, 0xa5, 0x16, 0xe4, 0x17,
+	0xeb, 0x83, 0x05, 0x93, 0x4a, 0xd3, 0xf4, 0xd3, 0xf3, 0xd3, 0xf3, 0xc1, 0x1c, 0x30, 0x0b, 0xa2,
+	0x58, 0x8a, 0x33, 0xb5, 0xa2, 0x04, 0xc2, 0xd4, 0x2a, 0xe0, 0xe2, 0x70, 0x2c, 0x2d, 0xc9, 0xf0,
+	0xcd, 0x4f, 0x49, 0x15, 0xd2, 0xe0, 0x12, 0x70, 0x0c, 0x0d, 0xf1, 0x88, 0xf7, 0xf5, 0x77, 0x71,
+	0x8d, 0x0f, 0x0e, 0x71, 0x0c, 0xf1, 0x74, 0x16, 0x60, 0x90, 0x12, 0xea, 0x9a, 0xab, 0xc0, 0x07,
+	0x53, 0x13, 0x5c, 0x92, 0x58, 0x92, 0x99, 0x2c, 0x64, 0xc2, 0xc5, 0x87, 0x50, 0xe9, 0xe3, 0xe2,
+	0x18, 0x20, 0xc0, 0x28, 0xa5, 0xd0, 0x35, 0x57, 0x81, 0x07, 0xa6, 0x0e, 0x24, 0x76, 0xa9, 0x4f,
+	0x15, 0x85, 0x2f, 0xc5, 0xb2, 0x62, 0x89, 0x1c, 0x83, 0x93, 0xfb, 0x89, 0x87, 0x72, 0x0c, 0x17,
+	0x1e, 0xca, 0x31, 0xbc, 0x78, 0x24, 0xc7, 0x30, 0xe1, 0xb1, 0x1c, 0xc3, 0x82, 0xc7, 0x72, 0x8c,
+	0x17, 0x1e, 0xcb, 0x31, 0xdc, 0x78, 0x2c, 0xc7, 0x10, 0xa5, 0x99, 0x9e, 0x59, 0x92, 0x51, 0x9a,
+	0xa4, 0x97, 0x9c, 0x9f, 0xab, 0x5f, 0x5c, 0x99, 0x97, 0x5c, 0x92, 0x91, 0x99, 0x97, 0x8e, 0xc4,
+	0x42, 0x84, 0x40, 0x12, 0x1b, 0xd8, 0x07, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x04, 0x8c,
+	0xb9, 0xb3, 0x16, 0x01, 0x00, 0x00,
+}

+ 0 - 8
lib/config/blockpullorder.go

@@ -6,14 +6,6 @@
 
 
 package config
 package config
 
 
-type BlockPullOrder int
-
-const (
-	BlockPullOrderStandard BlockPullOrder = iota // default is standard
-	BlockPullOrderRandom
-	BlockPullOrderInOrder
-)
-
 func (o BlockPullOrder) String() string {
 func (o BlockPullOrder) String() string {
 	switch o {
 	switch o {
 	case BlockPullOrderStandard:
 	case BlockPullOrderStandard:

+ 70 - 0
lib/config/blockpullorder.pb.go

@@ -0,0 +1,70 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: lib/config/blockpullorder.proto
+
+package config
+
+import (
+	fmt "fmt"
+	proto "github.com/gogo/protobuf/proto"
+	math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+type BlockPullOrder int32
+
+const (
+	BlockPullOrderStandard BlockPullOrder = 0
+	BlockPullOrderRandom   BlockPullOrder = 1
+	BlockPullOrderInOrder  BlockPullOrder = 2
+)
+
+var BlockPullOrder_name = map[int32]string{
+	0: "BLOCK_PULL_ORDER_STANDARD",
+	1: "BLOCK_PULL_ORDER_RANDOM",
+	2: "BLOCK_PULL_ORDER_IN_ORDER",
+}
+
+var BlockPullOrder_value = map[string]int32{
+	"BLOCK_PULL_ORDER_STANDARD": 0,
+	"BLOCK_PULL_ORDER_RANDOM":   1,
+	"BLOCK_PULL_ORDER_IN_ORDER": 2,
+}
+
+func (BlockPullOrder) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_3c46a5289006da6c, []int{0}
+}
+
+func init() {
+	proto.RegisterEnum("config.BlockPullOrder", BlockPullOrder_name, BlockPullOrder_value)
+}
+
+func init() { proto.RegisterFile("lib/config/blockpullorder.proto", fileDescriptor_3c46a5289006da6c) }
+
+var fileDescriptor_3c46a5289006da6c = []byte{
+	// 237 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xcf, 0xc9, 0x4c, 0xd2,
+	0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0x4f, 0xca, 0xc9, 0x4f, 0xce, 0x2e, 0x28, 0xcd, 0xc9,
+	0xc9, 0x2f, 0x4a, 0x49, 0x2d, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0x48, 0x6a,
+	0xed, 0x61, 0xe4, 0xe2, 0x73, 0x02, 0x29, 0x08, 0x28, 0xcd, 0xc9, 0xf1, 0x07, 0x29, 0x10, 0xb2,
+	0xe4, 0x92, 0x74, 0xf2, 0xf1, 0x77, 0xf6, 0x8e, 0x0f, 0x08, 0xf5, 0xf1, 0x89, 0xf7, 0x0f, 0x72,
+	0x71, 0x0d, 0x8a, 0x0f, 0x0e, 0x71, 0xf4, 0x73, 0x71, 0x0c, 0x72, 0x11, 0x60, 0x90, 0x92, 0xea,
+	0x9a, 0xab, 0x20, 0x86, 0xaa, 0x25, 0xb8, 0x24, 0x31, 0x2f, 0x25, 0xb1, 0x28, 0x45, 0xc8, 0x94,
+	0x4b, 0x1c, 0x43, 0x6b, 0x90, 0xa3, 0x9f, 0x8b, 0xbf, 0xaf, 0x00, 0xa3, 0x94, 0x44, 0xd7, 0x5c,
+	0x05, 0x11, 0x54, 0x8d, 0x41, 0x89, 0x79, 0x29, 0xf9, 0xb9, 0x42, 0x16, 0x58, 0x6c, 0xf4, 0xf4,
+	0x83, 0x30, 0x04, 0x98, 0xa4, 0x24, 0xbb, 0xe6, 0x2a, 0x88, 0xa2, 0x6a, 0xf4, 0xcc, 0x03, 0x53,
+	0x4e, 0xee, 0x27, 0x1e, 0xca, 0x31, 0x5c, 0x78, 0x28, 0xc7, 0xf0, 0xe2, 0x91, 0x1c, 0xc3, 0x84,
+	0xc7, 0x72, 0x0c, 0x0b, 0x1e, 0xcb, 0x31, 0x5e, 0x78, 0x2c, 0xc7, 0x70, 0xe3, 0xb1, 0x1c, 0x43,
+	0x94, 0x66, 0x7a, 0x66, 0x49, 0x46, 0x69, 0x92, 0x5e, 0x72, 0x7e, 0xae, 0x7e, 0x71, 0x65, 0x5e,
+	0x72, 0x49, 0x46, 0x66, 0x5e, 0x3a, 0x12, 0x0b, 0x11, 0x48, 0x49, 0x6c, 0xe0, 0x60, 0x31, 0x06,
+	0x04, 0x00, 0x00, 0xff, 0xff, 0x46, 0xfd, 0xeb, 0xcf, 0x39, 0x01, 0x00, 0x00,
+}

+ 14 - 26
lib/config/config.go

@@ -101,7 +101,6 @@ var (
 func New(myID protocol.DeviceID) Configuration {
 func New(myID protocol.DeviceID) Configuration {
 	var cfg Configuration
 	var cfg Configuration
 	cfg.Version = CurrentVersion
 	cfg.Version = CurrentVersion
-	cfg.OriginalVersion = CurrentVersion
 
 
 	cfg.Options.UnackedNotificationIDs = []string{"authenticationUserAndPassword"}
 	cfg.Options.UnackedNotificationIDs = []string{"authenticationUserAndPassword"}
 
 
@@ -144,22 +143,28 @@ func NewWithFreePorts(myID protocol.DeviceID) (Configuration, error) {
 	return cfg, nil
 	return cfg, nil
 }
 }
 
 
-func ReadXML(r io.Reader, myID protocol.DeviceID) (Configuration, error) {
-	var cfg Configuration
+type xmlConfiguration struct {
+	Configuration
+	XMLName xml.Name `xml:"configuration"`
+}
+
+func ReadXML(r io.Reader, myID protocol.DeviceID) (Configuration, int, error) {
+	var cfg xmlConfiguration
 
 
 	util.SetDefaults(&cfg)
 	util.SetDefaults(&cfg)
 	util.SetDefaults(&cfg.Options)
 	util.SetDefaults(&cfg.Options)
 	util.SetDefaults(&cfg.GUI)
 	util.SetDefaults(&cfg.GUI)
 
 
 	if err := xml.NewDecoder(r).Decode(&cfg); err != nil {
 	if err := xml.NewDecoder(r).Decode(&cfg); err != nil {
-		return Configuration{}, err
+		return Configuration{}, 0, err
 	}
 	}
-	cfg.OriginalVersion = cfg.Version
+
+	originalVersion := cfg.Version
 
 
 	if err := cfg.prepare(myID); err != nil {
 	if err := cfg.prepare(myID); err != nil {
-		return Configuration{}, err
+		return Configuration{}, originalVersion, err
 	}
 	}
-	return cfg, nil
+	return cfg.Configuration, originalVersion, nil
 }
 }
 
 
 func ReadJSON(r io.Reader, myID protocol.DeviceID) (Configuration, error) {
 func ReadJSON(r io.Reader, myID protocol.DeviceID) (Configuration, error) {
@@ -177,7 +182,6 @@ func ReadJSON(r io.Reader, myID protocol.DeviceID) (Configuration, error) {
 	if err := json.Unmarshal(bs, &cfg); err != nil {
 	if err := json.Unmarshal(bs, &cfg); err != nil {
 		return Configuration{}, err
 		return Configuration{}, err
 	}
 	}
-	cfg.OriginalVersion = cfg.Version
 
 
 	if err := cfg.prepare(myID); err != nil {
 	if err := cfg.prepare(myID); err != nil {
 		return Configuration{}, err
 		return Configuration{}, err
@@ -185,21 +189,6 @@ func ReadJSON(r io.Reader, myID protocol.DeviceID) (Configuration, error) {
 	return cfg, nil
 	return cfg, nil
 }
 }
 
 
-type Configuration struct {
-	Version        int                   `xml:"version,attr" json:"version"`
-	Folders        []FolderConfiguration `xml:"folder" json:"folders"`
-	Devices        []DeviceConfiguration `xml:"device" json:"devices"`
-	GUI            GUIConfiguration      `xml:"gui" json:"gui"`
-	LDAP           LDAPConfiguration     `xml:"ldap" json:"ldap"`
-	Options        OptionsConfiguration  `xml:"options" json:"options"`
-	IgnoredDevices []ObservedDevice      `xml:"remoteIgnoredDevice" json:"remoteIgnoredDevices"`
-	PendingDevices []ObservedDevice      `xml:"pendingDevice" json:"pendingDevices"`
-	XMLName        xml.Name              `xml:"configuration" json:"-"`
-
-	MyID            protocol.DeviceID `xml:"-" json:"-"` // Provided by the instantiator.
-	OriginalVersion int               `xml:"-" json:"-"` // The version we read from disk, before any conversion
-}
-
 func (cfg Configuration) Copy() Configuration {
 func (cfg Configuration) Copy() Configuration {
 	newCfg := cfg
 	newCfg := cfg
 
 
@@ -231,7 +220,8 @@ func (cfg Configuration) Copy() Configuration {
 func (cfg *Configuration) WriteXML(w io.Writer) error {
 func (cfg *Configuration) WriteXML(w io.Writer) error {
 	e := xml.NewEncoder(w)
 	e := xml.NewEncoder(w)
 	e.Indent("", "    ")
 	e.Indent("", "    ")
-	err := e.Encode(cfg)
+	xmlCfg := xmlConfiguration{Configuration: *cfg}
+	err := e.Encode(xmlCfg)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
@@ -242,8 +232,6 @@ func (cfg *Configuration) WriteXML(w io.Writer) error {
 func (cfg *Configuration) prepare(myID protocol.DeviceID) error {
 func (cfg *Configuration) prepare(myID protocol.DeviceID) error {
 	var myName string
 	var myName string
 
 
-	cfg.MyID = myID
-
 	// Ensure this device is present in the config
 	// Ensure this device is present in the config
 	for _, device := range cfg.Devices {
 	for _, device := range cfg.Devices {
 		if device.DeviceID == myID {
 		if device.DeviceID == myID {

+ 151 - 0
lib/config/config.pb.go

@@ -0,0 +1,151 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: lib/config/config.proto
+
+package config
+
+import (
+	fmt "fmt"
+	proto "github.com/gogo/protobuf/proto"
+	_ "github.com/syncthing/syncthing/proto/ext"
+	math "math"
+	math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+type Configuration struct {
+	Version        int                   `protobuf:"varint,1,opt,name=version,proto3,casttype=int" json:"version" xml:"version,attr"`
+	Folders        []FolderConfiguration `protobuf:"bytes,2,rep,name=folders,proto3" json:"folders" xml:"folder"`
+	Devices        []DeviceConfiguration `protobuf:"bytes,3,rep,name=devices,proto3" json:"devices" xml:"device"`
+	GUI            GUIConfiguration      `protobuf:"bytes,4,opt,name=gui,proto3" json:"gui" xml:"gui"`
+	LDAP           LDAPConfiguration     `protobuf:"bytes,5,opt,name=ldap,proto3" json:"ldap" xml:"ldap"`
+	Options        OptionsConfiguration  `protobuf:"bytes,6,opt,name=options,proto3" json:"options" xml:"options"`
+	IgnoredDevices []ObservedDevice      `protobuf:"bytes,7,rep,name=ignored_devices,json=ignoredDevices,proto3" json:"remoteIgnoredDevices" xml:"remoteIgnoredDevice"`
+	PendingDevices []ObservedDevice      `protobuf:"bytes,8,rep,name=pending_devices,json=pendingDevices,proto3" json:"pendingDevices" xml:"pendingDevice"`
+}
+
+func (m *Configuration) Reset()         { *m = Configuration{} }
+func (m *Configuration) String() string { return proto.CompactTextString(m) }
+func (*Configuration) ProtoMessage()    {}
+func (*Configuration) Descriptor() ([]byte, []int) {
+	return fileDescriptor_baadf209193dc627, []int{0}
+}
+func (m *Configuration) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Configuration.Unmarshal(m, b)
+}
+func (m *Configuration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Configuration.Marshal(b, m, deterministic)
+}
+func (m *Configuration) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Configuration.Merge(m, src)
+}
+func (m *Configuration) XXX_Size() int {
+	return xxx_messageInfo_Configuration.Size(m)
+}
+func (m *Configuration) XXX_DiscardUnknown() {
+	xxx_messageInfo_Configuration.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Configuration proto.InternalMessageInfo
+
+func init() {
+	proto.RegisterType((*Configuration)(nil), "config.Configuration")
+}
+
+func init() { proto.RegisterFile("lib/config/config.proto", fileDescriptor_baadf209193dc627) }
+
+var fileDescriptor_baadf209193dc627 = []byte{
+	// 544 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x93, 0x4f, 0x8b, 0xd3, 0x40,
+	0x18, 0xc6, 0x53, 0xdb, 0x6d, 0xdd, 0xec, 0x3f, 0xc8, 0x8a, 0xa6, 0x2a, 0x99, 0x3a, 0x54, 0xa9,
+	0xa2, 0x5d, 0x58, 0x2f, 0xe2, 0xcd, 0x5a, 0x2c, 0x05, 0x41, 0x19, 0x58, 0x51, 0x2f, 0xd2, 0x36,
+	0xb3, 0xe9, 0x40, 0x3b, 0x53, 0x92, 0xb4, 0xac, 0xdf, 0x42, 0xfc, 0x04, 0x5e, 0xfd, 0x06, 0x7e,
+	0x84, 0xbd, 0xb5, 0x47, 0x4f, 0x03, 0xbb, 0xbd, 0x48, 0x8e, 0x39, 0x7a, 0x92, 0xf9, 0xd7, 0x4d,
+	0x24, 0x7a, 0x6a, 0xde, 0xf7, 0x79, 0x9e, 0xdf, 0xfb, 0xf2, 0x36, 0xb1, 0x6f, 0x4d, 0xc8, 0xf0,
+	0x68, 0xc4, 0xe8, 0x29, 0x09, 0xf4, 0x4f, 0x7b, 0x16, 0xb2, 0x98, 0x39, 0x55, 0x55, 0xdd, 0x6e,
+	0x66, 0x0c, 0xa7, 0x6c, 0xe2, 0xe3, 0x50, 0x15, 0xf3, 0x70, 0x10, 0x13, 0x46, 0x95, 0x3b, 0xe7,
+	0xf2, 0xf1, 0x82, 0x8c, 0x70, 0x91, 0xeb, 0x5e, 0xc6, 0x15, 0xcc, 0x49, 0x91, 0x05, 0x66, 0x2c,
+	0x13, 0x7f, 0x30, 0x2b, 0xf2, 0xdc, 0xcf, 0x78, 0xd8, 0x4c, 0x08, 0x51, 0x91, 0xad, 0x9e, 0xb5,
+	0x0d, 0x23, 0x1c, 0x2e, 0xb0, 0xaf, 0xa5, 0x6d, 0x7c, 0x16, 0xab, 0x47, 0xf8, 0xa3, 0x6a, 0xef,
+	0xbd, 0xcc, 0xa6, 0x1d, 0x64, 0xd7, 0x16, 0x38, 0x8c, 0x08, 0xa3, 0x6e, 0xa9, 0x51, 0x6a, 0x6d,
+	0x75, 0x9e, 0x25, 0x1c, 0x98, 0x56, 0xca, 0x81, 0x73, 0x36, 0x9d, 0x3c, 0x87, 0xba, 0x7e, 0x3c,
+	0x88, 0xe3, 0x10, 0xfe, 0xe6, 0xa0, 0x4c, 0x68, 0x9c, 0x2c, 0x9b, 0xbb, 0xd9, 0x3e, 0x32, 0x29,
+	0xe7, 0x9d, 0x5d, 0x53, 0xc7, 0x8b, 0xdc, 0x6b, 0x8d, 0x72, 0x6b, 0xe7, 0xf8, 0x4e, 0x5b, 0x5f,
+	0xfb, 0x95, 0x6c, 0xe7, 0x36, 0xe8, 0x80, 0x73, 0x0e, 0x2c, 0x31, 0x54, 0x67, 0x52, 0x0e, 0x76,
+	0xe5, 0x50, 0x55, 0x43, 0x64, 0x04, 0xc1, 0x55, 0xe7, 0x8e, 0xdc, 0x72, 0x9e, 0xdb, 0x95, 0xed,
+	0x7f, 0x70, 0x75, 0x66, 0xc3, 0x55, 0x35, 0x44, 0x46, 0x70, 0x90, 0x5d, 0x0e, 0xe6, 0xc4, 0xad,
+	0x34, 0x4a, 0xad, 0x9d, 0x63, 0xd7, 0x30, 0x7b, 0x27, 0xfd, 0x3c, 0xf0, 0x81, 0x00, 0x5e, 0x72,
+	0x50, 0xee, 0x9d, 0xf4, 0x13, 0x0e, 0x44, 0x26, 0xe5, 0x60, 0x5b, 0x32, 0x83, 0x39, 0x81, 0x5f,
+	0x57, 0x4d, 0x21, 0x21, 0x21, 0x38, 0x1f, 0xec, 0x8a, 0xf8, 0x47, 0xdd, 0x2d, 0x09, 0xad, 0x1b,
+	0xe8, 0xeb, 0xee, 0x8b, 0xb7, 0x79, 0xea, 0x23, 0x4d, 0xad, 0x08, 0x29, 0xe1, 0x40, 0xc6, 0x52,
+	0x0e, 0x6c, 0xc9, 0x15, 0x85, 0x00, 0x4b, 0x15, 0x49, 0xcd, 0x79, 0x6f, 0xd7, 0xf4, 0x8b, 0xe0,
+	0x56, 0x25, 0xfd, 0xae, 0xa1, 0xbf, 0x51, 0xed, 0xfc, 0x80, 0x86, 0xb9, 0x83, 0x0e, 0xa5, 0x1c,
+	0xec, 0x49, 0xb6, 0xae, 0x21, 0x32, 0x8a, 0xf3, 0xbd, 0x64, 0x1f, 0x90, 0x80, 0xb2, 0x10, 0xfb,
+	0x9f, 0xcc, 0xa5, 0x6b, 0xf2, 0xd2, 0x37, 0x37, 0x23, 0xf4, 0xbb, 0xa5, 0x2e, 0xde, 0x19, 0x6b,
+	0xf8, 0x8d, 0x10, 0x4f, 0x59, 0x8c, 0xfb, 0x2a, 0xdc, 0xdd, 0x5c, 0xbc, 0x2e, 0x27, 0x15, 0x88,
+	0x30, 0x59, 0x36, 0x0f, 0x0b, 0xfa, 0xe9, 0xb2, 0x59, 0xc8, 0x42, 0xfb, 0x24, 0x57, 0x3b, 0xd4,
+	0x3e, 0x98, 0x61, 0xea, 0x13, 0x1a, 0x6c, 0x56, 0xbd, 0xfe, 0xdf, 0x55, 0x9f, 0xe8, 0x55, 0xf7,
+	0x75, 0xec, 0x6a, 0xc9, 0x43, 0xb9, 0x64, 0xae, 0x0d, 0xd1, 0x5f, 0xb6, 0x4e, 0xef, 0xfc, 0xc2,
+	0xb3, 0x56, 0x17, 0x9e, 0xf5, 0xeb, 0xd2, 0xb3, 0xbe, 0xac, 0x3d, 0xeb, 0xdb, 0xda, 0x2b, 0xad,
+	0xd6, 0x9e, 0xf5, 0x73, 0xed, 0x59, 0x1f, 0x1f, 0x06, 0x24, 0x1e, 0xcf, 0x87, 0xed, 0x11, 0x9b,
+	0x1e, 0x45, 0x9f, 0xe9, 0x28, 0x1e, 0x13, 0x1a, 0x64, 0x9e, 0xae, 0xbe, 0xce, 0x61, 0x55, 0x7e,
+	0x8a, 0x4f, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0xce, 0xc5, 0x80, 0x7a, 0x8d, 0x04, 0x00, 0x00,
+}
+
+func (m *Configuration) ProtoSize() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Version != 0 {
+		n += 1 + sovConfig(uint64(m.Version))
+	}
+	if len(m.Folders) > 0 {
+		for _, e := range m.Folders {
+			l = e.ProtoSize()
+			n += 1 + l + sovConfig(uint64(l))
+		}
+	}
+	if len(m.Devices) > 0 {
+		for _, e := range m.Devices {
+			l = e.ProtoSize()
+			n += 1 + l + sovConfig(uint64(l))
+		}
+	}
+	l = m.GUI.ProtoSize()
+	n += 1 + l + sovConfig(uint64(l))
+	l = m.LDAP.ProtoSize()
+	n += 1 + l + sovConfig(uint64(l))
+	l = m.Options.ProtoSize()
+	n += 1 + l + sovConfig(uint64(l))
+	if len(m.IgnoredDevices) > 0 {
+		for _, e := range m.IgnoredDevices {
+			l = e.ProtoSize()
+			n += 1 + l + sovConfig(uint64(l))
+		}
+	}
+	if len(m.PendingDevices) > 0 {
+		for _, e := range m.PendingDevices {
+			l = e.ProtoSize()
+			n += 1 + l + sovConfig(uint64(l))
+		}
+	}
+	return n
+}
+
+func sovConfig(x uint64) (n int) {
+	return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozConfig(x uint64) (n int) {
+	return sovConfig(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}

+ 12 - 13
lib/config/config_test.go

@@ -21,6 +21,7 @@ import (
 	"testing"
 	"testing"
 
 
 	"github.com/d4l3k/messagediff"
 	"github.com/d4l3k/messagediff"
+
 	"github.com/syncthing/syncthing/lib/events"
 	"github.com/syncthing/syncthing/lib/events"
 	"github.com/syncthing/syncthing/lib/fs"
 	"github.com/syncthing/syncthing/lib/fs"
 	"github.com/syncthing/syncthing/lib/protocol"
 	"github.com/syncthing/syncthing/lib/protocol"
@@ -523,9 +524,6 @@ func TestNewSaveLoad(t *testing.T) {
 	intCfg := New(device1)
 	intCfg := New(device1)
 	cfg := wrap(path, intCfg)
 	cfg := wrap(path, intCfg)
 
 
-	// To make the equality pass later
-	cfg.(*wrapper).cfg.XMLName.Local = "configuration"
-
 	if exists(path) {
 	if exists(path) {
 		t.Error(path, "exists")
 		t.Error(path, "exists")
 	}
 	}
@@ -614,14 +612,14 @@ func TestPullOrder(t *testing.T) {
 		name  string
 		name  string
 		order PullOrder
 		order PullOrder
 	}{
 	}{
-		{"f1", OrderRandom},        // empty value, default
-		{"f2", OrderRandom},        // explicit
-		{"f3", OrderAlphabetic},    // explicit
-		{"f4", OrderRandom},        // unknown value, default
-		{"f5", OrderSmallestFirst}, // explicit
-		{"f6", OrderLargestFirst},  // explicit
-		{"f7", OrderOldestFirst},   // explicit
-		{"f8", OrderNewestFirst},   // explicit
+		{"f1", PullOrderRandom},        // empty value, default
+		{"f2", PullOrderRandom},        // explicit
+		{"f3", PullOrderAlphabetic},    // explicit
+		{"f4", PullOrderRandom},        // unknown value, default
+		{"f5", PullOrderSmallestFirst}, // explicit
+		{"f6", PullOrderLargestFirst},  // explicit
+		{"f7", PullOrderOldestFirst},   // explicit
+		{"f8", PullOrderNewestFirst},   // explicit
 	}
 	}
 
 
 	// Verify values are deserialized correctly
 	// Verify values are deserialized correctly
@@ -640,7 +638,7 @@ func TestPullOrder(t *testing.T) {
 
 
 	t.Logf("%s", buf.Bytes())
 	t.Logf("%s", buf.Bytes())
 
 
-	cfg, err = ReadXML(buf, device1)
+	cfg, _, err = ReadXML(buf, device1)
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
@@ -1169,7 +1167,8 @@ func defaultConfigAsMap() map[string]interface{} {
 }
 }
 
 
 func load(path string, myID protocol.DeviceID) (Wrapper, error) {
 func load(path string, myID protocol.DeviceID) (Wrapper, error) {
-	return Load(path, myID, events.NoopLogger)
+	cfg, _, err := Load(path, myID, events.NoopLogger)
+	return cfg, err
 }
 }
 
 
 func wrap(path string, cfg Configuration) Wrapper {
 func wrap(path string, cfg Configuration) Wrapper {

+ 0 - 19
lib/config/deviceconfiguration.go

@@ -13,25 +13,6 @@ import (
 	"github.com/syncthing/syncthing/lib/util"
 	"github.com/syncthing/syncthing/lib/util"
 )
 )
 
 
-type DeviceConfiguration struct {
-	DeviceID                 protocol.DeviceID    `xml:"id,attr" json:"deviceID"`
-	Name                     string               `xml:"name,attr,omitempty" json:"name"`
-	Addresses                []string             `xml:"address,omitempty" json:"addresses" default:"dynamic"`
-	Compression              protocol.Compression `xml:"compression,attr" json:"compression"`
-	CertName                 string               `xml:"certName,attr,omitempty" json:"certName"`
-	Introducer               bool                 `xml:"introducer,attr" json:"introducer"`
-	SkipIntroductionRemovals bool                 `xml:"skipIntroductionRemovals,attr" json:"skipIntroductionRemovals"`
-	IntroducedBy             protocol.DeviceID    `xml:"introducedBy,attr" json:"introducedBy"`
-	Paused                   bool                 `xml:"paused" json:"paused"`
-	AllowedNetworks          []string             `xml:"allowedNetwork,omitempty" json:"allowedNetworks"`
-	AutoAcceptFolders        bool                 `xml:"autoAcceptFolders" json:"autoAcceptFolders"`
-	MaxSendKbps              int                  `xml:"maxSendKbps" json:"maxSendKbps"`
-	MaxRecvKbps              int                  `xml:"maxRecvKbps" json:"maxRecvKbps"`
-	IgnoredFolders           []ObservedFolder     `xml:"ignoredFolder" json:"ignoredFolders"`
-	PendingFolders           []ObservedFolder     `xml:"pendingFolder" json:"pendingFolders"`
-	MaxRequestKiB            int                  `xml:"maxRequestKiB" json:"maxRequestKiB"`
-}
-
 func NewDeviceConfiguration(id protocol.DeviceID, name string) DeviceConfiguration {
 func NewDeviceConfiguration(id protocol.DeviceID, name string) DeviceConfiguration {
 	d := DeviceConfiguration{
 	d := DeviceConfiguration{
 		DeviceID: id,
 		DeviceID: id,

+ 213 - 0
lib/config/deviceconfiguration.pb.go

@@ -0,0 +1,213 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: lib/config/deviceconfiguration.proto
+
+package config
+
+import (
+	fmt "fmt"
+	proto "github.com/gogo/protobuf/proto"
+	github_com_syncthing_syncthing_lib_protocol "github.com/syncthing/syncthing/lib/protocol"
+	protocol "github.com/syncthing/syncthing/lib/protocol"
+	_ "github.com/syncthing/syncthing/proto/ext"
+	math "math"
+	math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+type DeviceConfiguration struct {
+	DeviceID                 github_com_syncthing_syncthing_lib_protocol.DeviceID `protobuf:"bytes,1,opt,name=device_id,json=deviceId,proto3,customtype=github.com/syncthing/syncthing/lib/protocol.DeviceID" json:"deviceID" xml:"id,attr"`
+	Name                     string                                               `protobuf:"bytes,2,opt,name=name,proto3" json:"name" xml:"name,attr,omitempty"`
+	Addresses                []string                                             `protobuf:"bytes,3,rep,name=addresses,proto3" json:"addresses" xml:"address,omitempty" default:"dynamic"`
+	Compression              protocol.Compression                                 `protobuf:"varint,4,opt,name=compression,proto3,enum=protocol.Compression" json:"compression" xml:"compression,attr"`
+	CertName                 string                                               `protobuf:"bytes,5,opt,name=cert_name,json=certName,proto3" json:"certName" xml:"certName,attr,omitempty"`
+	Introducer               bool                                                 `protobuf:"varint,6,opt,name=introducer,proto3" json:"introducer" xml:"introducer,attr"`
+	SkipIntroductionRemovals bool                                                 `protobuf:"varint,7,opt,name=skip_introduction_removals,json=skipIntroductionRemovals,proto3" json:"skipIntroductionRemovals" xml:"skipIntroductionRemovals,attr"`
+	IntroducedBy             github_com_syncthing_syncthing_lib_protocol.DeviceID `protobuf:"bytes,8,opt,name=introduced_by,json=introducedBy,proto3,customtype=github.com/syncthing/syncthing/lib/protocol.DeviceID" json:"introducedBy" xml:"introducedBy,attr"`
+	Paused                   bool                                                 `protobuf:"varint,9,opt,name=paused,proto3" json:"paused" xml:"paused"`
+	AllowedNetworks          []string                                             `protobuf:"bytes,10,rep,name=allowed_networks,json=allowedNetworks,proto3" json:"allowedNetworks" xml:"allowedNetwork,omitempty"`
+	AutoAcceptFolders        bool                                                 `protobuf:"varint,11,opt,name=auto_accept_folders,json=autoAcceptFolders,proto3" json:"autoAcceptFolders" xml:"autoAcceptFolders"`
+	MaxSendKbps              int                                                  `protobuf:"varint,12,opt,name=max_send_kbps,json=maxSendKbps,proto3,casttype=int" json:"maxSendKbps" xml:"maxSendKbps"`
+	MaxRecvKbps              int                                                  `protobuf:"varint,13,opt,name=max_recv_kbps,json=maxRecvKbps,proto3,casttype=int" json:"maxRecvKbps" xml:"maxRecvKbps"`
+	IgnoredFolders           []ObservedFolder                                     `protobuf:"bytes,14,rep,name=ignored_folders,json=ignoredFolders,proto3" json:"ignoredFolders" xml:"ignoredFolder"`
+	PendingFolders           []ObservedFolder                                     `protobuf:"bytes,15,rep,name=pending_folders,json=pendingFolders,proto3" json:"pendingFolders" xml:"pendingFolder"`
+	MaxRequestKiB            int                                                  `protobuf:"varint,16,opt,name=max_request_kib,json=maxRequestKib,proto3,casttype=int" json:"maxRequestKiB" xml:"maxRequestKiB"`
+}
+
+func (m *DeviceConfiguration) Reset()         { *m = DeviceConfiguration{} }
+func (m *DeviceConfiguration) String() string { return proto.CompactTextString(m) }
+func (*DeviceConfiguration) ProtoMessage()    {}
+func (*DeviceConfiguration) Descriptor() ([]byte, []int) {
+	return fileDescriptor_744b782bd13071dd, []int{0}
+}
+func (m *DeviceConfiguration) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_DeviceConfiguration.Unmarshal(m, b)
+}
+func (m *DeviceConfiguration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_DeviceConfiguration.Marshal(b, m, deterministic)
+}
+func (m *DeviceConfiguration) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_DeviceConfiguration.Merge(m, src)
+}
+func (m *DeviceConfiguration) XXX_Size() int {
+	return xxx_messageInfo_DeviceConfiguration.Size(m)
+}
+func (m *DeviceConfiguration) XXX_DiscardUnknown() {
+	xxx_messageInfo_DeviceConfiguration.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_DeviceConfiguration proto.InternalMessageInfo
+
+func init() {
+	proto.RegisterType((*DeviceConfiguration)(nil), "config.DeviceConfiguration")
+}
+
+func init() {
+	proto.RegisterFile("lib/config/deviceconfiguration.proto", fileDescriptor_744b782bd13071dd)
+}
+
+var fileDescriptor_744b782bd13071dd = []byte{
+	// 900 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x55, 0x31, 0x6f, 0xdb, 0x46,
+	0x18, 0x15, 0xeb, 0xc4, 0xb6, 0xce, 0x96, 0x65, 0xd3, 0x88, 0xc3, 0x18, 0x88, 0x4e, 0x60, 0x35,
+	0x28, 0x68, 0x2a, 0x17, 0x6e, 0x27, 0xa3, 0x1d, 0xca, 0x04, 0x6d, 0x83, 0xa0, 0x49, 0x7b, 0xdd,
+	0xbc, 0xb0, 0x24, 0xef, 0xac, 0x1c, 0x2c, 0xf2, 0x58, 0xf2, 0xa4, 0x48, 0x40, 0x87, 0x8e, 0x1d,
+	0x3a, 0x14, 0x59, 0xbb, 0x14, 0x1d, 0x3a, 0xf4, 0x97, 0x04, 0xe8, 0x60, 0x8d, 0x45, 0x87, 0x03,
+	0x62, 0x2f, 0x05, 0x47, 0x8e, 0x99, 0x0a, 0xde, 0x51, 0x14, 0x49, 0x47, 0x45, 0x80, 0x6e, 0x77,
+	0xef, 0xbd, 0x7b, 0xef, 0xf8, 0x74, 0x1f, 0x04, 0x7a, 0x23, 0xea, 0x1e, 0x79, 0x2c, 0x38, 0xa3,
+	0xc3, 0x23, 0x4c, 0x26, 0xd4, 0x23, 0x6a, 0x33, 0x8e, 0x1c, 0x4e, 0x59, 0x30, 0x08, 0x23, 0xc6,
+	0x99, 0xbe, 0xae, 0xc0, 0xc3, 0x83, 0x4c, 0x2d, 0x21, 0x8f, 0x8d, 0x8e, 0x5c, 0x12, 0x2a, 0xfe,
+	0xf0, 0x4e, 0xc9, 0x85, 0xb9, 0x31, 0x89, 0x26, 0x04, 0xe7, 0x54, 0x93, 0x4c, 0xb9, 0x5a, 0x9a,
+	0x7f, 0xee, 0x80, 0xfd, 0x87, 0x32, 0xe3, 0x41, 0x39, 0x43, 0xff, 0x43, 0x03, 0x4d, 0x95, 0x6d,
+	0x53, 0x6c, 0x68, 0x5d, 0xad, 0xbf, 0x6d, 0xfd, 0xa4, 0xbd, 0x14, 0xb0, 0xf1, 0xb7, 0x80, 0x1f,
+	0x0d, 0x29, 0x7f, 0x36, 0x76, 0x07, 0x1e, 0xf3, 0x8f, 0xe2, 0x59, 0xe0, 0xf1, 0x67, 0x34, 0x18,
+	0x96, 0x56, 0xe5, 0x1b, 0x0d, 0x94, 0xfb, 0xa3, 0x87, 0x97, 0x02, 0x6e, 0x2e, 0xd6, 0x89, 0x80,
+	0x9b, 0x38, 0x5f, 0xa7, 0x02, 0xb6, 0xa6, 0xfe, 0xe8, 0xc4, 0xa4, 0xf8, 0xbe, 0xc3, 0x79, 0x64,
+	0x26, 0x17, 0xbd, 0x8d, 0x7c, 0x9d, 0x5e, 0xf4, 0x0a, 0xdd, 0x8f, 0xf3, 0x9e, 0xf6, 0x62, 0xde,
+	0x2b, 0x3c, 0xd0, 0x82, 0xc1, 0xfa, 0x57, 0xe0, 0x46, 0xe0, 0xf8, 0xc4, 0x78, 0xa7, 0xab, 0xf5,
+	0x9b, 0xd6, 0xc7, 0x89, 0x80, 0x72, 0x9f, 0x0a, 0x78, 0x47, 0x3a, 0x67, 0x1b, 0xe9, 0x77, 0x9f,
+	0xf9, 0x94, 0x13, 0x3f, 0xe4, 0xb3, 0x2c, 0x65, 0xff, 0x0d, 0x38, 0x92, 0x27, 0xf5, 0x29, 0x68,
+	0x3a, 0x18, 0x47, 0x24, 0x8e, 0x49, 0x6c, 0xac, 0x75, 0xd7, 0xfa, 0x4d, 0xeb, 0x34, 0x11, 0x70,
+	0x09, 0xa6, 0x02, 0xde, 0x93, 0xde, 0x39, 0x52, 0x72, 0xee, 0x62, 0x72, 0xe6, 0x8c, 0x47, 0xfc,
+	0xc4, 0xc4, 0xb3, 0xc0, 0xf1, 0xa9, 0x97, 0x65, 0xed, 0x5d, 0xd3, 0xbd, 0xbe, 0xe8, 0x6d, 0xe4,
+	0x02, 0xb4, 0xf4, 0xd5, 0x27, 0x60, 0xcb, 0x63, 0x7e, 0x98, 0xed, 0x28, 0x0b, 0x8c, 0x1b, 0x5d,
+	0xad, 0xbf, 0x73, 0x7c, 0x6b, 0x50, 0xd4, 0xf9, 0x60, 0x49, 0x5a, 0x9f, 0x24, 0x02, 0x96, 0xd5,
+	0xa9, 0x80, 0x07, 0xf2, 0x52, 0x25, 0xac, 0xe8, 0x74, 0xb7, 0x0e, 0xa2, 0xf2, 0x51, 0x9d, 0x80,
+	0xa6, 0x47, 0x22, 0x6e, 0xcb, 0x22, 0x6f, 0xca, 0x22, 0xbf, 0xc8, 0x7e, 0xa6, 0x0c, 0x7c, 0xa2,
+	0xca, 0xbc, 0xab, 0xbc, 0x73, 0xe0, 0x0d, 0x85, 0xde, 0x5e, 0xc1, 0xa1, 0xc2, 0x45, 0x3f, 0x05,
+	0x80, 0x06, 0x3c, 0x62, 0x78, 0xec, 0x91, 0xc8, 0x58, 0xef, 0x6a, 0xfd, 0x4d, 0xeb, 0x24, 0x11,
+	0xb0, 0x84, 0xa6, 0x02, 0xde, 0x52, 0x0f, 0xa2, 0x80, 0x8a, 0x8f, 0x68, 0xd7, 0x30, 0x54, 0x3a,
+	0xa7, 0xff, 0xa6, 0x81, 0xc3, 0xf8, 0x9c, 0x86, 0xf6, 0x02, 0xcb, 0x5e, 0xb2, 0x1d, 0x11, 0x9f,
+	0x4d, 0x9c, 0x51, 0x6c, 0x6c, 0xc8, 0x30, 0x9c, 0x08, 0x68, 0x64, 0xaa, 0x47, 0x25, 0x11, 0xca,
+	0x35, 0xa9, 0x80, 0xef, 0xca, 0xe8, 0x55, 0x82, 0xe2, 0x22, 0x77, 0xff, 0x53, 0x81, 0x56, 0x26,
+	0xe8, 0xbf, 0x6b, 0xa0, 0x55, 0xdc, 0x19, 0xdb, 0xee, 0xcc, 0xd8, 0x94, 0xc3, 0xf5, 0xc3, 0xff,
+	0x1a, 0xae, 0x44, 0xc0, 0xed, 0xa5, 0xab, 0x35, 0x4b, 0x05, 0xbc, 0x5d, 0xed, 0x10, 0x5b, 0xb3,
+	0xe2, 0xf2, 0x7b, 0xd7, 0xd0, 0x6c, 0xb8, 0x50, 0xc5, 0x41, 0x3f, 0x06, 0xeb, 0xa1, 0x33, 0x8e,
+	0x09, 0x36, 0x9a, 0xb2, 0xb8, 0xc3, 0x44, 0xc0, 0x1c, 0x49, 0x05, 0xdc, 0x96, 0xee, 0x6a, 0x6b,
+	0xa2, 0x1c, 0xd7, 0xbf, 0x07, 0xbb, 0xce, 0x68, 0xc4, 0x9e, 0x13, 0x6c, 0x07, 0x84, 0x3f, 0x67,
+	0xd1, 0x79, 0x6c, 0x00, 0x39, 0x3d, 0x5f, 0x27, 0x02, 0xb6, 0x73, 0xee, 0x49, 0x4e, 0xa5, 0x02,
+	0x76, 0xd4, 0x0c, 0x55, 0xf0, 0xea, 0x9b, 0x32, 0x56, 0x91, 0xa8, 0x6e, 0xa7, 0x7f, 0x0b, 0xf6,
+	0x9d, 0x31, 0x67, 0xb6, 0xe3, 0x79, 0x24, 0xe4, 0xf6, 0x19, 0x1b, 0x61, 0x12, 0xc5, 0xc6, 0x96,
+	0xbc, 0xfe, 0x07, 0x89, 0x80, 0x7b, 0x19, 0xfd, 0xa9, 0x64, 0x3f, 0x53, 0x64, 0xd1, 0xd3, 0x35,
+	0xc6, 0x44, 0xd7, 0xd5, 0xfa, 0x53, 0xd0, 0xf2, 0x9d, 0xa9, 0x1d, 0x93, 0x00, 0xdb, 0xe7, 0x6e,
+	0x18, 0x1b, 0xdb, 0x5d, 0xad, 0x7f, 0xd3, 0x7a, 0x2f, 0x9b, 0x43, 0xdf, 0x99, 0x7e, 0x43, 0x02,
+	0xfc, 0xd8, 0x0d, 0x33, 0xd7, 0x3d, 0xe9, 0x5a, 0xc2, 0xcc, 0xd7, 0x02, 0xae, 0xd1, 0x80, 0xa3,
+	0xb2, 0x70, 0x61, 0x18, 0x11, 0x6f, 0xa2, 0x0c, 0x5b, 0x15, 0x43, 0x44, 0xbc, 0x49, 0xdd, 0x70,
+	0x81, 0x55, 0x0c, 0x17, 0xa0, 0x1e, 0x80, 0x36, 0x1d, 0x06, 0x2c, 0x22, 0xb8, 0xf8, 0xfe, 0x9d,
+	0xee, 0x5a, 0x7f, 0xeb, 0xf8, 0x60, 0xa0, 0xfe, 0x0b, 0x06, 0x4f, 0xf3, 0xff, 0x02, 0xf5, 0x4d,
+	0xd6, 0xfb, 0xd9, 0xb3, 0x4b, 0x04, 0xdc, 0xc9, 0x8f, 0x2d, 0x8b, 0xd9, 0x57, 0x0f, 0xa8, 0x0c,
+	0x9b, 0xa8, 0x26, 0xcb, 0xf2, 0x42, 0x12, 0x60, 0x1a, 0x0c, 0x8b, 0xbc, 0xf6, 0xdb, 0xe5, 0xe5,
+	0xc7, 0xea, 0x79, 0x15, 0xd8, 0x44, 0x35, 0x99, 0xfe, 0x8b, 0x06, 0xda, 0xaa, 0xb1, 0xef, 0xc6,
+	0x24, 0xe6, 0xf6, 0x39, 0x75, 0x8d, 0x5d, 0xd9, 0x59, 0x7c, 0x29, 0x60, 0xeb, 0xcb, 0xac, 0x0a,
+	0xc9, 0x3c, 0xa6, 0x56, 0x22, 0x60, 0xcb, 0x2f, 0x03, 0x45, 0x48, 0x05, 0x5d, 0x14, 0x99, 0x5c,
+	0xf4, 0x6a, 0xf2, 0x3a, 0xf0, 0x62, 0xde, 0xab, 0x26, 0xa0, 0x0a, 0xef, 0x5a, 0x9f, 0xbf, 0x7c,
+	0xd5, 0x69, 0xcc, 0x5f, 0x75, 0x1a, 0xff, 0x5c, 0x76, 0x1a, 0x3f, 0x5f, 0x75, 0x1a, 0xbf, 0x5e,
+	0x75, 0xb4, 0xf9, 0x55, 0xa7, 0xf1, 0xd7, 0x55, 0xa7, 0x71, 0x7a, 0xef, 0x2d, 0x26, 0x5b, 0x95,
+	0xe6, 0xae, 0xcb, 0x09, 0xff, 0xf0, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x3c, 0x69, 0xcb, 0x9f,
+	0x0b, 0x08, 0x00, 0x00,
+}
+
+func (m *DeviceConfiguration) ProtoSize() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = m.DeviceID.ProtoSize()
+	n += 1 + l + sovDeviceconfiguration(uint64(l))
+	l = len(m.Name)
+	if l > 0 {
+		n += 1 + l + sovDeviceconfiguration(uint64(l))
+	}
+	if len(m.Addresses) > 0 {
+		for _, s := range m.Addresses {
+			l = len(s)
+			n += 1 + l + sovDeviceconfiguration(uint64(l))
+		}
+	}
+	if m.Compression != 0 {
+		n += 1 + sovDeviceconfiguration(uint64(m.Compression))
+	}
+	l = len(m.CertName)
+	if l > 0 {
+		n += 1 + l + sovDeviceconfiguration(uint64(l))
+	}
+	if m.Introducer {
+		n += 2
+	}
+	if m.SkipIntroductionRemovals {
+		n += 2
+	}
+	l = m.IntroducedBy.ProtoSize()
+	n += 1 + l + sovDeviceconfiguration(uint64(l))
+	if m.Paused {
+		n += 2
+	}
+	if len(m.AllowedNetworks) > 0 {
+		for _, s := range m.AllowedNetworks {
+			l = len(s)
+			n += 1 + l + sovDeviceconfiguration(uint64(l))
+		}
+	}
+	if m.AutoAcceptFolders {
+		n += 2
+	}
+	if m.MaxSendKbps != 0 {
+		n += 1 + sovDeviceconfiguration(uint64(m.MaxSendKbps))
+	}
+	if m.MaxRecvKbps != 0 {
+		n += 1 + sovDeviceconfiguration(uint64(m.MaxRecvKbps))
+	}
+	if len(m.IgnoredFolders) > 0 {
+		for _, e := range m.IgnoredFolders {
+			l = e.ProtoSize()
+			n += 1 + l + sovDeviceconfiguration(uint64(l))
+		}
+	}
+	if len(m.PendingFolders) > 0 {
+		for _, e := range m.PendingFolders {
+			l = e.ProtoSize()
+			n += 1 + l + sovDeviceconfiguration(uint64(l))
+		}
+	}
+	if m.MaxRequestKiB != 0 {
+		n += 2 + sovDeviceconfiguration(uint64(m.MaxRequestKiB))
+	}
+	return n
+}
+
+func sovDeviceconfiguration(x uint64) (n int) {
+	return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozDeviceconfiguration(x uint64) (n int) {
+	return sovDeviceconfiguration(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}

+ 13 - 64
lib/config/folderconfiguration.go

@@ -28,54 +28,6 @@ var (
 
 
 const DefaultMarkerName = ".stfolder"
 const DefaultMarkerName = ".stfolder"
 
 
-type FolderConfiguration struct {
-	ID                      string                      `xml:"id,attr" json:"id"`
-	Label                   string                      `xml:"label,attr" json:"label" restart:"false"`
-	FilesystemType          fs.FilesystemType           `xml:"filesystemType" json:"filesystemType"`
-	Path                    string                      `xml:"path,attr" json:"path"`
-	Type                    FolderType                  `xml:"type,attr" json:"type"`
-	Devices                 []FolderDeviceConfiguration `xml:"device" json:"devices"`
-	RescanIntervalS         int                         `xml:"rescanIntervalS,attr" json:"rescanIntervalS" default:"3600"`
-	FSWatcherEnabled        bool                        `xml:"fsWatcherEnabled,attr" json:"fsWatcherEnabled" default:"true"`
-	FSWatcherDelayS         int                         `xml:"fsWatcherDelayS,attr" json:"fsWatcherDelayS" default:"10"`
-	IgnorePerms             bool                        `xml:"ignorePerms,attr" json:"ignorePerms"`
-	AutoNormalize           bool                        `xml:"autoNormalize,attr" json:"autoNormalize" default:"true"`
-	MinDiskFree             Size                        `xml:"minDiskFree" json:"minDiskFree" default:"1%"`
-	Versioning              VersioningConfiguration     `xml:"versioning" json:"versioning"`
-	Copiers                 int                         `xml:"copiers" json:"copiers"` // This defines how many files are handled concurrently.
-	PullerMaxPendingKiB     int                         `xml:"pullerMaxPendingKiB" json:"pullerMaxPendingKiB"`
-	Hashers                 int                         `xml:"hashers" json:"hashers"` // Less than one sets the value to the number of cores. These are CPU bound due to hashing.
-	Order                   PullOrder                   `xml:"order" json:"order"`
-	IgnoreDelete            bool                        `xml:"ignoreDelete" json:"ignoreDelete"`
-	ScanProgressIntervalS   int                         `xml:"scanProgressIntervalS" json:"scanProgressIntervalS"` // Set to a negative value to disable. Value of 0 will get replaced with value of 2 (default value)
-	PullerPauseS            int                         `xml:"pullerPauseS" json:"pullerPauseS"`
-	MaxConflicts            int                         `xml:"maxConflicts" json:"maxConflicts" default:"-1"`
-	DisableSparseFiles      bool                        `xml:"disableSparseFiles" json:"disableSparseFiles"`
-	DisableTempIndexes      bool                        `xml:"disableTempIndexes" json:"disableTempIndexes"`
-	Paused                  bool                        `xml:"paused" json:"paused"`
-	WeakHashThresholdPct    int                         `xml:"weakHashThresholdPct" json:"weakHashThresholdPct"` // Use weak hash if more than X percent of the file has changed. Set to -1 to always use weak hash.
-	MarkerName              string                      `xml:"markerName" json:"markerName"`
-	CopyOwnershipFromParent bool                        `xml:"copyOwnershipFromParent" json:"copyOwnershipFromParent"`
-	RawModTimeWindowS       int                         `xml:"modTimeWindowS" json:"modTimeWindowS"`
-	MaxConcurrentWrites     int                         `xml:"maxConcurrentWrites" json:"maxConcurrentWrites" default:"2"`
-	DisableFsync            bool                        `xml:"disableFsync" json:"disableFsync"`
-	BlockPullOrder          BlockPullOrder              `xml:"blockPullOrder" json:"blockPullOrder"`
-	CopyRangeMethod         fs.CopyRangeMethod          `xml:"copyRangeMethod" json:"copyRangeMethod" default:"standard"`
-	CaseSensitiveFS         bool                        `xml:"caseSensitiveFS" json:"caseSensitiveFS"`
-	JunctionsAsDirs         bool                        `xml:"junctionsAsDirs" json:"junctionsAsDirs"`
-
-	cachedModTimeWindow time.Duration
-
-	DeprecatedReadOnly       bool    `xml:"ro,attr,omitempty" json:"-"`
-	DeprecatedMinDiskFreePct float64 `xml:"minDiskFreePct,omitempty" json:"-"`
-	DeprecatedPullers        int     `xml:"pullers,omitempty" json:"-"`
-}
-
-type FolderDeviceConfiguration struct {
-	DeviceID     protocol.DeviceID `xml:"id,attr" json:"deviceID"`
-	IntroducedBy protocol.DeviceID `xml:"introducedBy,attr" json:"introducedBy"`
-}
-
 func NewFolderConfiguration(myID protocol.DeviceID, id, label string, fsType fs.FilesystemType, path string) FolderConfiguration {
 func NewFolderConfiguration(myID protocol.DeviceID, id, label string, fsType fs.FilesystemType, path string) FolderConfiguration {
 	f := FolderConfiguration{
 	f := FolderConfiguration{
 		ID:             id,
 		ID:             id,
@@ -114,7 +66,19 @@ func (f FolderConfiguration) Filesystem() fs.Filesystem {
 }
 }
 
 
 func (f FolderConfiguration) ModTimeWindow() time.Duration {
 func (f FolderConfiguration) ModTimeWindow() time.Duration {
-	return f.cachedModTimeWindow
+	dur := time.Duration(f.RawModTimeWindowS) * time.Second
+	if f.RawModTimeWindowS < 1 && runtime.GOOS == "android" {
+		if usage, err := disk.Usage(f.Filesystem().URI()); err != nil {
+			dur = 2 * time.Second
+			l.Debugf(`Detecting FS at "%v" on android: Setting mtime window to 2s: err == "%v"`, f.Path, err)
+		} else if usage.Fstype == "" || strings.Contains(strings.ToLower(usage.Fstype), "fat") {
+			dur = 2 * time.Second
+			l.Debugf(`Detecting FS at "%v" on android: Setting mtime window to 2s: usage.Fstype == "%v"`, f.Path, usage.Fstype)
+		} else {
+			l.Debugf(`Detecting FS at %v on android: Leaving mtime window at 0: usage.Fstype == "%v"`, f.Path, usage.Fstype)
+		}
+	}
+	return dur
 }
 }
 
 
 func (f *FolderConfiguration) CreateMarker() error {
 func (f *FolderConfiguration) CreateMarker() error {
@@ -242,21 +206,6 @@ func (f *FolderConfiguration) prepare() {
 	if f.MarkerName == "" {
 	if f.MarkerName == "" {
 		f.MarkerName = DefaultMarkerName
 		f.MarkerName = DefaultMarkerName
 	}
 	}
-
-	switch {
-	case f.RawModTimeWindowS > 0:
-		f.cachedModTimeWindow = time.Duration(f.RawModTimeWindowS) * time.Second
-	case runtime.GOOS == "android":
-		if usage, err := disk.Usage(f.Filesystem().URI()); err != nil {
-			f.cachedModTimeWindow = 2 * time.Second
-			l.Debugf(`Detecting FS at "%v" on android: Setting mtime window to 2s: err == "%v"`, f.Path, err)
-		} else if usage.Fstype == "" || strings.Contains(strings.ToLower(usage.Fstype), "fat") {
-			f.cachedModTimeWindow = 2 * time.Second
-			l.Debugf(`Detecting FS at "%v" on android: Setting mtime window to 2s: usage.Fstype == "%v"`, f.Path, usage.Fstype)
-		} else {
-			l.Debugf(`Detecting FS at %v on android: Leaving mtime window at 0: usage.Fstype == "%v"`, f.Path, usage.Fstype)
-		}
-	}
 }
 }
 
 
 // RequiresRestartOnly returns a copy with only the attributes that require
 // RequiresRestartOnly returns a copy with only the attributes that require

+ 401 - 0
lib/config/folderconfiguration.pb.go

@@ -0,0 +1,401 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: lib/config/folderconfiguration.proto
+
+package config
+
+import (
+	fmt "fmt"
+	proto "github.com/gogo/protobuf/proto"
+	fs "github.com/syncthing/syncthing/lib/fs"
+	github_com_syncthing_syncthing_lib_protocol "github.com/syncthing/syncthing/lib/protocol"
+	_ "github.com/syncthing/syncthing/proto/ext"
+	math "math"
+	math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+type FolderDeviceConfiguration struct {
+	DeviceID     github_com_syncthing_syncthing_lib_protocol.DeviceID `protobuf:"bytes,1,opt,name=device_id,json=deviceId,proto3,customtype=github.com/syncthing/syncthing/lib/protocol.DeviceID" json:"deviceID" xml:"id,attr"`
+	IntroducedBy github_com_syncthing_syncthing_lib_protocol.DeviceID `protobuf:"bytes,2,opt,name=introduced_by,json=introducedBy,proto3,customtype=github.com/syncthing/syncthing/lib/protocol.DeviceID" json:"introducedBy" xml:"introducedBy,attr"`
+}
+
+func (m *FolderDeviceConfiguration) Reset()         { *m = FolderDeviceConfiguration{} }
+func (m *FolderDeviceConfiguration) String() string { return proto.CompactTextString(m) }
+func (*FolderDeviceConfiguration) ProtoMessage()    {}
+func (*FolderDeviceConfiguration) Descriptor() ([]byte, []int) {
+	return fileDescriptor_44a9785876ed3afa, []int{0}
+}
+func (m *FolderDeviceConfiguration) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_FolderDeviceConfiguration.Unmarshal(m, b)
+}
+func (m *FolderDeviceConfiguration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_FolderDeviceConfiguration.Marshal(b, m, deterministic)
+}
+func (m *FolderDeviceConfiguration) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_FolderDeviceConfiguration.Merge(m, src)
+}
+func (m *FolderDeviceConfiguration) XXX_Size() int {
+	return xxx_messageInfo_FolderDeviceConfiguration.Size(m)
+}
+func (m *FolderDeviceConfiguration) XXX_DiscardUnknown() {
+	xxx_messageInfo_FolderDeviceConfiguration.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_FolderDeviceConfiguration proto.InternalMessageInfo
+
+type FolderConfiguration struct {
+	ID                      string                      `protobuf:"bytes,1,opt,name=id,proto3" json:"id" xml:"id,attr"`
+	Label                   string                      `protobuf:"bytes,2,opt,name=label,proto3" json:"label" xml:"label,attr" restart:"false"`
+	FilesystemType          fs.FilesystemType           `protobuf:"varint,3,opt,name=filesystem_type,json=filesystemType,proto3,enum=fs.FilesystemType" json:"filesystemType" xml:"filesystemType"`
+	Path                    string                      `protobuf:"bytes,4,opt,name=path,proto3" json:"path" xml:"path,attr"`
+	Type                    FolderType                  `protobuf:"varint,5,opt,name=type,proto3,enum=config.FolderType" json:"type" xml:"type,attr"`
+	Devices                 []FolderDeviceConfiguration `protobuf:"bytes,6,rep,name=devices,proto3" json:"devices" xml:"device"`
+	RescanIntervalS         int                         `protobuf:"varint,7,opt,name=rescan_interval_s,json=rescanIntervalS,proto3,casttype=int" json:"rescanIntervalS" xml:"rescanIntervalS,attr" default:"3600"`
+	FSWatcherEnabled        bool                        `protobuf:"varint,8,opt,name=fs_watcher_enabled,json=fsWatcherEnabled,proto3" json:"fsWatcherEnabled" xml:"fsWatcherEnabled,attr" default:"true"`
+	FSWatcherDelayS         int                         `protobuf:"varint,9,opt,name=fs_watcher_delay_s,json=fsWatcherDelayS,proto3,casttype=int" json:"fsWatcherDelayS" xml:"fsWatcherDelayS,attr" default:"10"`
+	IgnorePerms             bool                        `protobuf:"varint,10,opt,name=ignore_perms,json=ignorePerms,proto3" json:"ignorePerms" xml:"ignorePerms,attr"`
+	AutoNormalize           bool                        `protobuf:"varint,11,opt,name=auto_normalize,json=autoNormalize,proto3" json:"autoNormalize" xml:"autoNormalize,attr" default:"true"`
+	MinDiskFree             Size                        `protobuf:"bytes,12,opt,name=min_disk_free,json=minDiskFree,proto3" json:"minDiskFree" xml:"minDiskFree"`
+	Versioning              VersioningConfiguration     `protobuf:"bytes,13,opt,name=versioning,proto3" json:"versioning" xml:"versioning"`
+	Copiers                 int                         `protobuf:"varint,14,opt,name=copiers,proto3,casttype=int" json:"copiers" xml:"copiers"`
+	PullerMaxPendingKiB     int                         `protobuf:"varint,15,opt,name=puller_max_pending_kib,json=pullerMaxPendingKib,proto3,casttype=int" json:"pullerMaxPendingKiB" xml:"pullerMaxPendingKiB"`
+	Hashers                 int                         `protobuf:"varint,16,opt,name=hashers,proto3,casttype=int" json:"hashers" xml:"hashers"`
+	Order                   PullOrder                   `protobuf:"varint,17,opt,name=order,proto3,enum=config.PullOrder" json:"order" xml:"order"`
+	IgnoreDelete            bool                        `protobuf:"varint,18,opt,name=ignore_delete,json=ignoreDelete,proto3" json:"ignoreDelete" xml:"ignoreDelete"`
+	ScanProgressIntervalS   int                         `protobuf:"varint,19,opt,name=scan_progress_interval_s,json=scanProgressIntervalS,proto3,casttype=int" json:"scanProgressIntervalS" xml:"scanProgressIntervalS"`
+	PullerPauseS            int                         `protobuf:"varint,20,opt,name=puller_pause_s,json=pullerPauseS,proto3,casttype=int" json:"pullerPauseS" xml:"pullerPauseS"`
+	MaxConflicts            int                         `protobuf:"varint,21,opt,name=max_conflicts,json=maxConflicts,proto3,casttype=int" json:"maxConflicts" xml:"maxConflicts" default:"-1"`
+	DisableSparseFiles      bool                        `protobuf:"varint,22,opt,name=disable_sparse_files,json=disableSparseFiles,proto3" json:"disableSparseFiles" xml:"disableSparseFiles"`
+	DisableTempIndexes      bool                        `protobuf:"varint,23,opt,name=disable_temp_indexes,json=disableTempIndexes,proto3" json:"disableTempIndexes" xml:"disableTempIndexes"`
+	Paused                  bool                        `protobuf:"varint,24,opt,name=paused,proto3" json:"paused" xml:"paused"`
+	WeakHashThresholdPct    int                         `protobuf:"varint,25,opt,name=weak_hash_threshold_pct,json=weakHashThresholdPct,proto3,casttype=int" json:"weakHashThresholdPct" xml:"weakHashThresholdPct"`
+	MarkerName              string                      `protobuf:"bytes,26,opt,name=marker_name,json=markerName,proto3" json:"markerName" xml:"markerName"`
+	CopyOwnershipFromParent bool                        `protobuf:"varint,27,opt,name=copy_ownership_from_parent,json=copyOwnershipFromParent,proto3" json:"copyOwnershipFromParent" xml:"copyOwnershipFromParent"`
+	RawModTimeWindowS       int                         `protobuf:"varint,28,opt,name=mod_time_window_s,json=modTimeWindowS,proto3,casttype=int" json:"modTimeWindowS" xml:"modTimeWindowS"`
+	MaxConcurrentWrites     int                         `protobuf:"varint,29,opt,name=max_concurrent_writes,json=maxConcurrentWrites,proto3,casttype=int" json:"maxConcurrentWrites" xml:"maxConcurrentWrites" default:"2"`
+	DisableFsync            bool                        `protobuf:"varint,30,opt,name=disable_fsync,json=disableFsync,proto3" json:"disableFsync" xml:"disableFsync"`
+	BlockPullOrder          BlockPullOrder              `protobuf:"varint,31,opt,name=block_pull_order,json=blockPullOrder,proto3,enum=config.BlockPullOrder" json:"blockPullOrder" xml:"blockPullOrder"`
+	CopyRangeMethod         fs.CopyRangeMethod          `protobuf:"varint,32,opt,name=copy_range_method,json=copyRangeMethod,proto3,enum=fs.CopyRangeMethod" json:"copyRangeMethod" xml:"copyRangeMethod" default:"standard"`
+	CaseSensitiveFS         bool                        `protobuf:"varint,33,opt,name=case_sensitive_fs,json=caseSensitiveFs,proto3" json:"caseSensitiveFS" xml:"caseSensitiveFS"`
+	JunctionsAsDirs         bool                        `protobuf:"varint,34,opt,name=follow_junctions,json=followJunctions,proto3" json:"junctionsAsDirs" xml:"junctionsAsDirs"`
+	// Legacy deprecated
+	DeprecatedReadOnly       bool    `protobuf:"varint,9000,opt,name=read_only,json=readOnly,proto3" json:"-" xml:"ro,attr,omitempty"`                       // Deprecated: Do not use.
+	DeprecatedMinDiskFreePct float64 `protobuf:"fixed64,9001,opt,name=min_disk_free_pct,json=minDiskFreePct,proto3" json:"-" xml:"minDiskFreePct,omitempty"` // Deprecated: Do not use.
+	DeprecatedPullers        int     `protobuf:"varint,9002,opt,name=pullers,proto3,casttype=int" json:"-" xml:"pullers,omitempty"`                          // Deprecated: Do not use.
+}
+
+func (m *FolderConfiguration) Reset()         { *m = FolderConfiguration{} }
+func (m *FolderConfiguration) String() string { return proto.CompactTextString(m) }
+func (*FolderConfiguration) ProtoMessage()    {}
+func (*FolderConfiguration) Descriptor() ([]byte, []int) {
+	return fileDescriptor_44a9785876ed3afa, []int{1}
+}
+func (m *FolderConfiguration) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_FolderConfiguration.Unmarshal(m, b)
+}
+func (m *FolderConfiguration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_FolderConfiguration.Marshal(b, m, deterministic)
+}
+func (m *FolderConfiguration) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_FolderConfiguration.Merge(m, src)
+}
+func (m *FolderConfiguration) XXX_Size() int {
+	return xxx_messageInfo_FolderConfiguration.Size(m)
+}
+func (m *FolderConfiguration) XXX_DiscardUnknown() {
+	xxx_messageInfo_FolderConfiguration.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_FolderConfiguration proto.InternalMessageInfo
+
+func init() {
+	proto.RegisterType((*FolderDeviceConfiguration)(nil), "config.FolderDeviceConfiguration")
+	proto.RegisterType((*FolderConfiguration)(nil), "config.FolderConfiguration")
+}
+
+func init() {
+	proto.RegisterFile("lib/config/folderconfiguration.proto", fileDescriptor_44a9785876ed3afa)
+}
+
+var fileDescriptor_44a9785876ed3afa = []byte{
+	// 1981 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x58, 0xcd, 0x8f, 0x1c, 0x47,
+	0x15, 0xdf, 0x5e, 0x7f, 0xed, 0xd6, 0x7e, 0x97, 0xbd, 0x76, 0x79, 0x9d, 0x6c, 0x6d, 0x9a, 0x21,
+	0x6c, 0xa2, 0x78, 0x6d, 0x6f, 0x10, 0x07, 0x2b, 0x09, 0x64, 0xbc, 0x59, 0x30, 0xc6, 0xf1, 0xa8,
+	0xd7, 0x60, 0x61, 0x90, 0x9a, 0x9e, 0xee, 0x9a, 0x99, 0xca, 0xf6, 0x17, 0x55, 0x3d, 0xde, 0x1d,
+	0x9f, 0xcc, 0x05, 0x81, 0xc8, 0x01, 0x2d, 0x07, 0xae, 0x48, 0x20, 0x04, 0xf9, 0x07, 0x90, 0xf8,
+	0x0b, 0x72, 0x41, 0x3b, 0x47, 0xc4, 0xa1, 0xa4, 0xac, 0x2f, 0x68, 0x6e, 0xf4, 0xd1, 0x27, 0x54,
+	0x55, 0xdd, 0x3d, 0xdd, 0x3d, 0x13, 0x84, 0x94, 0xdb, 0xd4, 0xef, 0xf7, 0xab, 0xf7, 0x5e, 0xbf,
+	0x7e, 0xef, 0x55, 0xf5, 0x80, 0x86, 0x4f, 0xdb, 0xb7, 0xdc, 0x28, 0xec, 0xd0, 0xee, 0xad, 0x4e,
+	0xe4, 0x7b, 0x84, 0xe9, 0x45, 0x9f, 0x39, 0x09, 0x8d, 0xc2, 0x9d, 0x98, 0x45, 0x49, 0x04, 0x2f,
+	0x6a, 0x70, 0xe3, 0xc6, 0x84, 0x3a, 0x19, 0xc4, 0x44, 0x8b, 0x36, 0xd6, 0x4b, 0x24, 0xa7, 0xcf,
+	0x73, 0x78, 0xa3, 0x04, 0xc7, 0x7d, 0xdf, 0x8f, 0x98, 0x47, 0x58, 0xc6, 0x6d, 0x97, 0xb8, 0x67,
+	0x84, 0x71, 0x1a, 0x85, 0x34, 0xec, 0x4e, 0x89, 0x60, 0x03, 0x97, 0x94, 0x6d, 0x3f, 0x72, 0x0f,
+	0xeb, 0xa6, 0xa0, 0x14, 0x74, 0xf8, 0x2d, 0x19, 0x10, 0xcf, 0xb0, 0xd7, 0x32, 0xcc, 0x8d, 0xe2,
+	0x01, 0x73, 0xc2, 0x2e, 0x09, 0x48, 0xd2, 0x8b, 0xbc, 0x8c, 0x9d, 0x27, 0xc7, 0x89, 0xfe, 0x69,
+	0xfe, 0x67, 0x16, 0x5c, 0xdf, 0x57, 0xcf, 0xb3, 0x47, 0x9e, 0x51, 0x97, 0xdc, 0x2b, 0x47, 0x00,
+	0x3f, 0x33, 0xc0, 0xbc, 0xa7, 0x70, 0x9b, 0x7a, 0xc8, 0xd8, 0x32, 0xb6, 0x17, 0x9b, 0x9f, 0x1a,
+	0x9f, 0x0b, 0x3c, 0xf3, 0x2f, 0x81, 0xbf, 0xd9, 0xa5, 0x49, 0xaf, 0xdf, 0xde, 0x71, 0xa3, 0xe0,
+	0x16, 0x1f, 0x84, 0x6e, 0xd2, 0xa3, 0x61, 0xb7, 0xf4, 0x4b, 0x86, 0xa0, 0x9c, 0xb8, 0x91, 0xbf,
+	0xa3, 0xad, 0xdf, 0xdf, 0x3b, 0x13, 0x78, 0x2e, 0xff, 0x3d, 0x12, 0x78, 0xce, 0xcb, 0x7e, 0xa7,
+	0x02, 0x2f, 0x1d, 0x07, 0xfe, 0x5d, 0x93, 0x7a, 0xef, 0x38, 0x49, 0xc2, 0xcc, 0xd1, 0x69, 0xe3,
+	0x52, 0xf6, 0x3b, 0x3d, 0x6d, 0x14, 0xba, 0x5f, 0x0d, 0x1b, 0xc6, 0xc9, 0xb0, 0x51, 0xd8, 0xb0,
+	0x72, 0xc6, 0x83, 0x7f, 0x36, 0xc0, 0x12, 0x0d, 0x13, 0x16, 0x79, 0x7d, 0x97, 0x78, 0x76, 0x7b,
+	0x80, 0x66, 0x55, 0xc0, 0x2f, 0xbe, 0x52, 0xc0, 0x23, 0x81, 0x17, 0xc7, 0x56, 0x9b, 0x83, 0x54,
+	0xe0, 0x6b, 0x3a, 0xd0, 0x12, 0x58, 0x84, 0xbc, 0x36, 0x81, 0xca, 0x80, 0xad, 0x8a, 0x05, 0xf3,
+	0x25, 0x06, 0x97, 0x75, 0xce, 0xab, 0xd9, 0xfe, 0x00, 0xcc, 0x66, 0x59, 0x9e, 0x6f, 0xee, 0x9c,
+	0x09, 0x3c, 0xab, 0xbc, 0xcf, 0x52, 0xef, 0x7f, 0x25, 0xe7, 0x64, 0xd8, 0x98, 0xbd, 0xbf, 0x67,
+	0xcd, 0x52, 0x0f, 0xfe, 0x10, 0x5c, 0xf0, 0x9d, 0x36, 0xf1, 0xd5, 0x73, 0xcf, 0x37, 0xbf, 0x3d,
+	0x12, 0x58, 0x03, 0xa9, 0xc0, 0x5b, 0x6a, 0xbf, 0x5a, 0x69, 0x13, 0x5b, 0x8c, 0xf0, 0xc4, 0x61,
+	0xc9, 0x5d, 0xb3, 0xe3, 0xf8, 0x9c, 0x48, 0x93, 0x60, 0x4c, 0xbf, 0x18, 0x36, 0x66, 0x2c, 0xbd,
+	0x19, 0x76, 0xc1, 0x4a, 0x87, 0xfa, 0x84, 0x0f, 0x78, 0x42, 0x02, 0x5b, 0x56, 0x19, 0x3a, 0xb7,
+	0x65, 0x6c, 0x2f, 0xef, 0xc2, 0x9d, 0x0e, 0xdf, 0xd9, 0x2f, 0xa8, 0xc7, 0x83, 0x98, 0x34, 0xdf,
+	0x1e, 0x09, 0xbc, 0xdc, 0xa9, 0x60, 0xa9, 0xc0, 0x57, 0x94, 0xf7, 0x2a, 0x6c, 0x5a, 0x35, 0x1d,
+	0x7c, 0x0f, 0x9c, 0x8f, 0x9d, 0xa4, 0x87, 0xce, 0xab, 0xf0, 0xb7, 0x47, 0x02, 0xab, 0x75, 0x2a,
+	0xf0, 0x8a, 0xda, 0x2f, 0x17, 0xc5, 0xf3, 0xcf, 0x17, 0x2b, 0x4b, 0xa9, 0x60, 0x0b, 0x9c, 0x57,
+	0xb1, 0x5d, 0xc8, 0x62, 0xd3, 0x2d, 0xb3, 0xa3, 0x13, 0xad, 0x62, 0x53, 0x16, 0x13, 0x1d, 0x91,
+	0xb6, 0x28, 0x17, 0x63, 0x8b, 0xc5, 0xca, 0x52, 0x2a, 0xf8, 0x53, 0x70, 0x49, 0x17, 0x17, 0x47,
+	0x17, 0xb7, 0xce, 0x6d, 0x2f, 0xec, 0xbe, 0x51, 0x35, 0x3a, 0xa5, 0x63, 0x9a, 0x58, 0xd6, 0xda,
+	0x48, 0xe0, 0x7c, 0x67, 0x2a, 0xf0, 0xa2, 0x72, 0xa5, 0xd7, 0xa6, 0x95, 0x13, 0xf0, 0x77, 0x06,
+	0x58, 0x63, 0x84, 0xbb, 0x4e, 0x68, 0xd3, 0x30, 0x21, 0xec, 0x99, 0xe3, 0xdb, 0x1c, 0x5d, 0xda,
+	0x32, 0xb6, 0x2f, 0x34, 0xbb, 0x23, 0x81, 0x57, 0x34, 0x79, 0x3f, 0xe3, 0x0e, 0x52, 0x81, 0xdf,
+	0x52, 0x96, 0x6a, 0x78, 0xf6, 0x3a, 0x3d, 0xd2, 0x71, 0xfa, 0x7e, 0x72, 0xd7, 0x7c, 0xf7, 0x5b,
+	0xb7, 0x6f, 0x9b, 0xaf, 0x04, 0x3e, 0x47, 0xc3, 0x64, 0x74, 0xda, 0xb8, 0x32, 0x4d, 0xfe, 0xea,
+	0xb4, 0x71, 0x5e, 0xea, 0xac, 0xba, 0x13, 0xf8, 0x77, 0x03, 0xc0, 0x0e, 0xb7, 0x8f, 0x9c, 0xc4,
+	0xed, 0x11, 0x66, 0x93, 0xd0, 0x69, 0xfb, 0xc4, 0x43, 0x73, 0x5b, 0xc6, 0xf6, 0x5c, 0xf3, 0x37,
+	0xc6, 0x99, 0xc0, 0xab, 0xfb, 0x07, 0x4f, 0x34, 0xfb, 0x91, 0x26, 0x47, 0x02, 0xaf, 0x76, 0x78,
+	0x15, 0x4b, 0x05, 0x7e, 0x5b, 0xbf, 0xf3, 0x1a, 0x51, 0x8f, 0x36, 0x61, 0x7d, 0x55, 0x7b, 0xeb,
+	0x53, 0x85, 0x32, 0x4e, 0xa9, 0x38, 0x19, 0x36, 0x26, 0xdc, 0x5a, 0x13, 0x4e, 0xe1, 0xdf, 0xaa,
+	0xc1, 0x7b, 0xc4, 0x77, 0x06, 0x36, 0x47, 0xf3, 0x2a, 0xa7, 0xbf, 0x96, 0xc1, 0xaf, 0x14, 0x56,
+	0xf6, 0x24, 0x79, 0x20, 0xf3, 0x5c, 0x98, 0xd1, 0x50, 0x2a, 0xf0, 0x37, 0xaa, 0xa1, 0x6b, 0xbc,
+	0x1e, 0xf9, 0x9d, 0x4a, 0x96, 0xa7, 0x89, 0x5f, 0x9d, 0x36, 0x66, 0xef, 0xdc, 0x3e, 0x19, 0x36,
+	0xea, 0x5e, 0xad, 0xba, 0x4f, 0xf8, 0x33, 0xb0, 0x48, 0xbb, 0x61, 0xc4, 0x88, 0x1d, 0x13, 0x16,
+	0x70, 0x04, 0x54, 0xbe, 0xdf, 0x1f, 0x09, 0xbc, 0xa0, 0xf1, 0x96, 0x84, 0x53, 0x81, 0xaf, 0xea,
+	0x39, 0x30, 0xc6, 0x8a, 0xf2, 0x5d, 0xad, 0x83, 0x56, 0x79, 0x2b, 0xfc, 0x85, 0x01, 0x96, 0x9d,
+	0x7e, 0x12, 0xd9, 0x61, 0xc4, 0x02, 0xc7, 0xa7, 0xcf, 0x09, 0x5a, 0x50, 0x4e, 0x9e, 0x8e, 0x04,
+	0x5e, 0x92, 0xcc, 0xc7, 0x39, 0x51, 0x64, 0xa0, 0x82, 0x7e, 0xd9, 0x9b, 0x83, 0x93, 0xaa, 0xfc,
+	0xb5, 0x59, 0x55, 0xbb, 0xf0, 0x29, 0x58, 0x0a, 0x68, 0x68, 0x7b, 0x94, 0x1f, 0xda, 0x1d, 0x46,
+	0x08, 0x5a, 0xdc, 0x32, 0xb6, 0x17, 0x76, 0x17, 0xf3, 0xb6, 0x3a, 0xa0, 0xcf, 0x49, 0x73, 0x3b,
+	0xeb, 0xa0, 0x85, 0x80, 0x86, 0x7b, 0x94, 0x1f, 0xee, 0x33, 0x22, 0x23, 0x5a, 0x53, 0x11, 0x95,
+	0x30, 0xd3, 0x2a, 0x2b, 0x60, 0x17, 0x80, 0xf1, 0x39, 0x8a, 0x96, 0x94, 0x61, 0x9c, 0x1b, 0xfe,
+	0x51, 0xc1, 0x54, 0xbb, 0xf5, 0xcd, 0xcc, 0x57, 0x69, 0x6b, 0x2a, 0xf0, 0xaa, 0x72, 0x35, 0x86,
+	0x4c, 0xab, 0xc4, 0xc3, 0xf7, 0xc1, 0x25, 0x37, 0x8a, 0x29, 0x61, 0x1c, 0x2d, 0xab, 0xc2, 0xfa,
+	0x9a, 0x6c, 0xf7, 0x0c, 0x2a, 0x26, 0x75, 0xb6, 0xce, 0x4b, 0xc4, 0xca, 0x05, 0xf0, 0x1f, 0x06,
+	0xb8, 0x2a, 0x4f, 0x70, 0xc2, 0xec, 0xc0, 0x39, 0xb6, 0x63, 0x12, 0x7a, 0x34, 0xec, 0xda, 0x87,
+	0xb4, 0x8d, 0x56, 0x94, 0xb9, 0xdf, 0xcb, 0x3a, 0xbd, 0xdc, 0x52, 0x92, 0x87, 0xce, 0x71, 0x4b,
+	0x0b, 0x1e, 0xd0, 0xe6, 0x48, 0xe0, 0xcb, 0xf1, 0x24, 0x9c, 0x0a, 0x7c, 0x5d, 0x8f, 0xc7, 0x49,
+	0xae, 0x54, 0xa1, 0x53, 0xb7, 0x4e, 0x87, 0x4f, 0x86, 0x8d, 0x69, 0xfe, 0xad, 0x29, 0xda, 0xb6,
+	0x4c, 0x47, 0xcf, 0xe1, 0x3d, 0x99, 0x8e, 0xd5, 0x71, 0x3a, 0x32, 0xa8, 0x48, 0x47, 0xb6, 0x1e,
+	0xa7, 0x23, 0x03, 0xe0, 0x87, 0xe0, 0x82, 0xba, 0xcb, 0xa0, 0x35, 0x35, 0xb6, 0xd7, 0xf2, 0x37,
+	0x26, 0xfd, 0x3f, 0x92, 0x44, 0x13, 0xc9, 0x63, 0x4c, 0x69, 0x52, 0x81, 0x17, 0x94, 0x35, 0xb5,
+	0x32, 0x2d, 0x8d, 0xc2, 0x07, 0x60, 0x29, 0xeb, 0x1d, 0x8f, 0xf8, 0x24, 0x21, 0x08, 0xaa, 0xba,
+	0x7e, 0x53, 0x9d, 0xdc, 0x8a, 0xd8, 0x53, 0x78, 0x2a, 0x30, 0x2c, 0x75, 0x8f, 0x06, 0x4d, 0xab,
+	0xa2, 0x81, 0xc7, 0x00, 0xa9, 0x91, 0x1c, 0xb3, 0xa8, 0xcb, 0x08, 0xe7, 0xe5, 0xd9, 0x7c, 0x59,
+	0x3d, 0x9f, 0x3c, 0x56, 0xd7, 0xa5, 0xa6, 0x95, 0x49, 0xca, 0x13, 0xfa, 0x86, 0x72, 0x30, 0x95,
+	0x2d, 0x9e, 0x7d, 0xfa, 0x66, 0x78, 0x00, 0x96, 0xb3, 0xba, 0x88, 0x9d, 0x3e, 0x27, 0x36, 0x47,
+	0x57, 0x94, 0xbf, 0x9b, 0xf2, 0x39, 0x34, 0xd3, 0x92, 0xc4, 0x41, 0xf1, 0x1c, 0x65, 0xb0, 0xb0,
+	0x5e, 0x91, 0x42, 0x02, 0x96, 0x64, 0x95, 0xc9, 0xa4, 0xfa, 0xd4, 0x4d, 0x38, 0x5a, 0x57, 0x36,
+	0xbf, 0x23, 0x6d, 0x06, 0xce, 0xf1, 0xbd, 0x1c, 0x4f, 0x05, 0xc6, 0xba, 0xc1, 0x4a, 0x60, 0xa9,
+	0xd9, 0x6f, 0xde, 0xc9, 0x1d, 0xc8, 0xa1, 0x76, 0xf3, 0x8e, 0x55, 0xd9, 0x0d, 0x3d, 0x70, 0xc5,
+	0xa3, 0x5c, 0x0e, 0x61, 0x9b, 0xc7, 0x0e, 0xe3, 0xc4, 0x56, 0x47, 0x3b, 0xba, 0xaa, 0xde, 0xc4,
+	0xee, 0x48, 0x60, 0x98, 0xf1, 0x07, 0x8a, 0x56, 0x97, 0x86, 0x54, 0x60, 0xa4, 0x8f, 0xc6, 0x09,
+	0xca, 0xb4, 0xa6, 0xe8, 0xcb, 0x5e, 0x12, 0x12, 0xc4, 0x36, 0x0d, 0x3d, 0x72, 0x4c, 0x38, 0xba,
+	0x36, 0xe1, 0xe5, 0x31, 0x09, 0xe2, 0xfb, 0x9a, 0xad, 0x7b, 0x29, 0x51, 0x63, 0x2f, 0x25, 0x10,
+	0xee, 0x82, 0x8b, 0xea, 0x05, 0x78, 0x08, 0x29, 0xbb, 0x1b, 0x23, 0x81, 0x33, 0xa4, 0x38, 0xcc,
+	0xf5, 0xd2, 0xb4, 0x32, 0x1c, 0x26, 0xe0, 0xda, 0x11, 0x71, 0x0e, 0x6d, 0x59, 0xd5, 0x76, 0xd2,
+	0x63, 0x84, 0xf7, 0x22, 0xdf, 0xb3, 0x63, 0x37, 0x41, 0xd7, 0x55, 0xc2, 0xe5, 0x24, 0xbf, 0x22,
+	0x25, 0xdf, 0x73, 0x78, 0xef, 0x71, 0x2e, 0x68, 0xb9, 0x49, 0x2a, 0xf0, 0x86, 0x32, 0x39, 0x8d,
+	0x2c, 0x5e, 0xea, 0xd4, 0xad, 0xf0, 0x1e, 0x58, 0x08, 0x1c, 0x76, 0x48, 0x98, 0x1d, 0x3a, 0x01,
+	0x41, 0x1b, 0xea, 0xda, 0x64, 0xca, 0x71, 0xa6, 0xe1, 0x8f, 0x9d, 0x80, 0x14, 0xe3, 0x6c, 0x0c,
+	0x99, 0x56, 0x89, 0x87, 0x03, 0xb0, 0x21, 0x3f, 0x12, 0xec, 0xe8, 0x28, 0x24, 0x8c, 0xf7, 0x68,
+	0x6c, 0x77, 0x58, 0x14, 0xd8, 0xb1, 0xc3, 0x48, 0x98, 0xa0, 0x1b, 0x2a, 0x05, 0xef, 0x8d, 0x04,
+	0xbe, 0x26, 0x55, 0x8f, 0x72, 0xd1, 0x3e, 0x8b, 0x82, 0x96, 0x92, 0xa4, 0x02, 0xbf, 0x9e, 0x4f,
+	0xbc, 0x69, 0xbc, 0x69, 0x7d, 0xd9, 0x4e, 0xf8, 0x4b, 0x03, 0xac, 0x05, 0x91, 0x67, 0x27, 0x34,
+	0x20, 0xf6, 0x11, 0x0d, 0xbd, 0xe8, 0xc8, 0xe6, 0xe8, 0x35, 0x95, 0xb0, 0x9f, 0x9c, 0x09, 0xbc,
+	0x66, 0x39, 0x47, 0x0f, 0x23, 0xef, 0x31, 0x0d, 0xc8, 0x13, 0xc5, 0xca, 0xe3, 0x7a, 0x39, 0xa8,
+	0x20, 0xc5, 0xe5, 0xb2, 0x0a, 0xe7, 0x99, 0x3b, 0x19, 0x36, 0x26, 0xad, 0x58, 0x35, 0x1b, 0xf0,
+	0x85, 0x01, 0xd6, 0xb3, 0x36, 0x71, 0xfb, 0x4c, 0xc6, 0x66, 0x1f, 0x31, 0x9a, 0x10, 0x8e, 0x5e,
+	0x57, 0xc1, 0xfc, 0x40, 0x8e, 0x5e, 0x5d, 0xf0, 0x19, 0xff, 0x44, 0xd1, 0xa9, 0xc0, 0x5f, 0x2f,
+	0x75, 0x4d, 0x85, 0x2b, 0x35, 0xcf, 0x6e, 0xa9, 0x77, 0x8c, 0x5d, 0x6b, 0x9a, 0x25, 0x39, 0xc4,
+	0xf2, 0xda, 0xee, 0xc8, 0x2f, 0x12, 0xb4, 0x39, 0x1e, 0x62, 0x19, 0xb1, 0x2f, 0xf1, 0xa2, 0xf9,
+	0xcb, 0xa0, 0x69, 0x55, 0x34, 0xd0, 0x07, 0xab, 0xea, 0x4b, 0xd1, 0x96, 0xb3, 0xc0, 0xd6, 0xf3,
+	0x15, 0xab, 0xf9, 0x7a, 0x35, 0x9f, 0xaf, 0x4d, 0xc9, 0x8f, 0x87, 0xac, 0xba, 0xb6, 0xb7, 0x2b,
+	0x58, 0x91, 0xd9, 0x2a, 0x6c, 0x5a, 0x35, 0x1d, 0xfc, 0xd4, 0x00, 0x6b, 0xaa, 0x84, 0xd4, 0x87,
+	0xa6, 0xad, 0xbf, 0x34, 0xd1, 0x96, 0xf2, 0x77, 0x59, 0x7e, 0x22, 0xdc, 0x8b, 0xe2, 0x81, 0x25,
+	0xb9, 0x87, 0x8a, 0x6a, 0x3e, 0x90, 0xb7, 0x2e, 0xb7, 0x0a, 0xa6, 0x02, 0x6f, 0x17, 0x65, 0x54,
+	0xc2, 0x4b, 0x69, 0xe4, 0x89, 0x13, 0x7a, 0x0e, 0xf3, 0xcc, 0x57, 0xa7, 0x8d, 0xb9, 0x7c, 0x61,
+	0xd5, 0x0d, 0xc1, 0x3f, 0xc9, 0x70, 0x1c, 0x39, 0x40, 0x49, 0xc8, 0x69, 0x42, 0x9f, 0xc9, 0x8c,
+	0xa2, 0x37, 0x54, 0x3a, 0x8f, 0xe5, 0x15, 0xf0, 0x9e, 0xc3, 0xc9, 0x41, 0xce, 0xed, 0xab, 0x2b,
+	0xa0, 0x5b, 0x85, 0x52, 0x81, 0xd7, 0x75, 0x30, 0x55, 0x5c, 0x5e, 0x77, 0x26, 0xb4, 0x93, 0x90,
+	0xbc, 0xf1, 0xd5, 0x9c, 0x58, 0x35, 0x0d, 0x87, 0x7f, 0x34, 0xc0, 0x6a, 0x27, 0xf2, 0xfd, 0xe8,
+	0xc8, 0xfe, 0xa4, 0x1f, 0xba, 0xf2, 0x3a, 0xc2, 0x91, 0x39, 0x8e, 0xf2, 0xfb, 0x39, 0xf8, 0x21,
+	0xdf, 0xa3, 0x8c, 0xcb, 0x28, 0x3f, 0xa9, 0x42, 0x45, 0x94, 0x35, 0x5c, 0x45, 0x59, 0xd7, 0x4e,
+	0x42, 0x32, 0xca, 0x9a, 0x13, 0x6b, 0x45, 0x47, 0x54, 0xc0, 0xf0, 0x10, 0xcc, 0x33, 0xe2, 0x78,
+	0x76, 0x14, 0xfa, 0x03, 0xf4, 0x97, 0x7d, 0x15, 0xde, 0xc3, 0x33, 0x81, 0xe1, 0x1e, 0x89, 0x19,
+	0x71, 0x9d, 0x84, 0x78, 0x16, 0x71, 0xbc, 0x47, 0xa1, 0x3f, 0x18, 0x09, 0x6c, 0xdc, 0x2c, 0xbe,
+	0x8e, 0x59, 0xa4, 0x6e, 0x82, 0xef, 0x44, 0x01, 0x95, 0xb3, 0x3a, 0x19, 0xa8, 0xaf, 0xe3, 0x09,
+	0x14, 0x19, 0xd6, 0x1c, 0xcb, 0x0c, 0xc0, 0x9f, 0x83, 0xb5, 0xca, 0xf5, 0x50, 0xcd, 0xcf, 0xbf,
+	0x4a, 0xa7, 0x46, 0xf3, 0xa3, 0x33, 0x81, 0xd1, 0xd8, 0xe9, 0xc3, 0xf1, 0xcd, 0xaf, 0xe5, 0x26,
+	0xb9, 0xeb, 0xcd, 0xfa, 0x1d, 0xb1, 0xe5, 0x26, 0xa5, 0x08, 0x90, 0x61, 0x2d, 0x57, 0x49, 0xf8,
+	0x63, 0x70, 0x49, 0x9f, 0x97, 0x1c, 0x7d, 0xb6, 0xaf, 0x7a, 0xfd, 0x03, 0x39, 0x78, 0xc6, 0x8e,
+	0xf4, 0x3d, 0x88, 0x57, 0x1f, 0x2e, 0xdb, 0x52, 0x32, 0x9d, 0x35, 0x38, 0x32, 0xac, 0xdc, 0x5e,
+	0xf3, 0xbb, 0x9f, 0x7f, 0xb1, 0x39, 0x33, 0xfc, 0x62, 0x73, 0xe6, 0xdf, 0x67, 0x9b, 0x33, 0xbf,
+	0x7d, 0xb9, 0x39, 0xf3, 0x87, 0x97, 0x9b, 0xc6, 0xf0, 0xe5, 0xe6, 0xcc, 0x3f, 0x5f, 0x6e, 0xce,
+	0x3c, 0x7d, 0xeb, 0xff, 0xf8, 0x2f, 0x42, 0xb7, 0x6a, 0xfb, 0xa2, 0xfa, 0x4f, 0xe2, 0xdd, 0xff,
+	0x06, 0x00, 0x00, 0xff, 0xff, 0xe9, 0xb3, 0xf1, 0x6d, 0xb1, 0x12, 0x00, 0x00,
+}
+
+func (m *FolderDeviceConfiguration) ProtoSize() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = m.DeviceID.ProtoSize()
+	n += 1 + l + sovFolderconfiguration(uint64(l))
+	l = m.IntroducedBy.ProtoSize()
+	n += 1 + l + sovFolderconfiguration(uint64(l))
+	return n
+}
+
+func (m *FolderConfiguration) ProtoSize() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.ID)
+	if l > 0 {
+		n += 1 + l + sovFolderconfiguration(uint64(l))
+	}
+	l = len(m.Label)
+	if l > 0 {
+		n += 1 + l + sovFolderconfiguration(uint64(l))
+	}
+	if m.FilesystemType != 0 {
+		n += 1 + sovFolderconfiguration(uint64(m.FilesystemType))
+	}
+	l = len(m.Path)
+	if l > 0 {
+		n += 1 + l + sovFolderconfiguration(uint64(l))
+	}
+	if m.Type != 0 {
+		n += 1 + sovFolderconfiguration(uint64(m.Type))
+	}
+	if len(m.Devices) > 0 {
+		for _, e := range m.Devices {
+			l = e.ProtoSize()
+			n += 1 + l + sovFolderconfiguration(uint64(l))
+		}
+	}
+	if m.RescanIntervalS != 0 {
+		n += 1 + sovFolderconfiguration(uint64(m.RescanIntervalS))
+	}
+	if m.FSWatcherEnabled {
+		n += 2
+	}
+	if m.FSWatcherDelayS != 0 {
+		n += 1 + sovFolderconfiguration(uint64(m.FSWatcherDelayS))
+	}
+	if m.IgnorePerms {
+		n += 2
+	}
+	if m.AutoNormalize {
+		n += 2
+	}
+	l = m.MinDiskFree.ProtoSize()
+	n += 1 + l + sovFolderconfiguration(uint64(l))
+	l = m.Versioning.ProtoSize()
+	n += 1 + l + sovFolderconfiguration(uint64(l))
+	if m.Copiers != 0 {
+		n += 1 + sovFolderconfiguration(uint64(m.Copiers))
+	}
+	if m.PullerMaxPendingKiB != 0 {
+		n += 1 + sovFolderconfiguration(uint64(m.PullerMaxPendingKiB))
+	}
+	if m.Hashers != 0 {
+		n += 2 + sovFolderconfiguration(uint64(m.Hashers))
+	}
+	if m.Order != 0 {
+		n += 2 + sovFolderconfiguration(uint64(m.Order))
+	}
+	if m.IgnoreDelete {
+		n += 3
+	}
+	if m.ScanProgressIntervalS != 0 {
+		n += 2 + sovFolderconfiguration(uint64(m.ScanProgressIntervalS))
+	}
+	if m.PullerPauseS != 0 {
+		n += 2 + sovFolderconfiguration(uint64(m.PullerPauseS))
+	}
+	if m.MaxConflicts != 0 {
+		n += 2 + sovFolderconfiguration(uint64(m.MaxConflicts))
+	}
+	if m.DisableSparseFiles {
+		n += 3
+	}
+	if m.DisableTempIndexes {
+		n += 3
+	}
+	if m.Paused {
+		n += 3
+	}
+	if m.WeakHashThresholdPct != 0 {
+		n += 2 + sovFolderconfiguration(uint64(m.WeakHashThresholdPct))
+	}
+	l = len(m.MarkerName)
+	if l > 0 {
+		n += 2 + l + sovFolderconfiguration(uint64(l))
+	}
+	if m.CopyOwnershipFromParent {
+		n += 3
+	}
+	if m.RawModTimeWindowS != 0 {
+		n += 2 + sovFolderconfiguration(uint64(m.RawModTimeWindowS))
+	}
+	if m.MaxConcurrentWrites != 0 {
+		n += 2 + sovFolderconfiguration(uint64(m.MaxConcurrentWrites))
+	}
+	if m.DisableFsync {
+		n += 3
+	}
+	if m.BlockPullOrder != 0 {
+		n += 2 + sovFolderconfiguration(uint64(m.BlockPullOrder))
+	}
+	if m.CopyRangeMethod != 0 {
+		n += 2 + sovFolderconfiguration(uint64(m.CopyRangeMethod))
+	}
+	if m.CaseSensitiveFS {
+		n += 3
+	}
+	if m.JunctionsAsDirs {
+		n += 3
+	}
+	if m.DeprecatedReadOnly {
+		n += 4
+	}
+	if m.DeprecatedMinDiskFreePct != 0 {
+		n += 11
+	}
+	if m.DeprecatedPullers != 0 {
+		n += 3 + sovFolderconfiguration(uint64(m.DeprecatedPullers))
+	}
+	return n
+}
+
+func sovFolderconfiguration(x uint64) (n int) {
+	return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozFolderconfiguration(x uint64) (n int) {
+	return sovFolderconfiguration(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}

+ 0 - 8
lib/config/foldertype.go

@@ -6,14 +6,6 @@
 
 
 package config
 package config
 
 
-type FolderType int
-
-const (
-	FolderTypeSendReceive FolderType = iota // default is sendreceive
-	FolderTypeSendOnly
-	FolderTypeReceiveOnly
-)
-
 func (t FolderType) String() string {
 func (t FolderType) String() string {
 	switch t {
 	switch t {
 	case FolderTypeSendReceive:
 	case FolderTypeSendReceive:

+ 69 - 0
lib/config/foldertype.pb.go

@@ -0,0 +1,69 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: lib/config/foldertype.proto
+
+package config
+
+import (
+	fmt "fmt"
+	proto "github.com/gogo/protobuf/proto"
+	math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+type FolderType int32
+
+const (
+	FolderTypeSendReceive FolderType = 0
+	FolderTypeSendOnly    FolderType = 1
+	FolderTypeReceiveOnly FolderType = 2
+)
+
+var FolderType_name = map[int32]string{
+	0: "FOLDER_TYPE_SEND_RECEIVE",
+	1: "FOLDER_TYPE_SEND_ONLY",
+	2: "FOLDER_TYPE_RECEIVE_ONLY",
+}
+
+var FolderType_value = map[string]int32{
+	"FOLDER_TYPE_SEND_RECEIVE": 0,
+	"FOLDER_TYPE_SEND_ONLY":    1,
+	"FOLDER_TYPE_RECEIVE_ONLY": 2,
+}
+
+func (FolderType) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_ea6ddb20c0633575, []int{0}
+}
+
+func init() {
+	proto.RegisterEnum("config.FolderType", FolderType_name, FolderType_value)
+}
+
+func init() { proto.RegisterFile("lib/config/foldertype.proto", fileDescriptor_ea6ddb20c0633575) }
+
+var fileDescriptor_ea6ddb20c0633575 = []byte{
+	// 220 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xce, 0xc9, 0x4c, 0xd2,
+	0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0x4f, 0xcb, 0xcf, 0x49, 0x49, 0x2d, 0x2a, 0xa9, 0x2c,
+	0x48, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0x48, 0x68, 0x6d, 0x64, 0xe4, 0xe2,
+	0x72, 0x03, 0x4b, 0x86, 0x54, 0x16, 0xa4, 0x0a, 0x99, 0x73, 0x49, 0xb8, 0xf9, 0xfb, 0xb8, 0xb8,
+	0x06, 0xc5, 0x87, 0x44, 0x06, 0xb8, 0xc6, 0x07, 0xbb, 0xfa, 0xb9, 0xc4, 0x07, 0xb9, 0x3a, 0xbb,
+	0x7a, 0x86, 0xb9, 0x0a, 0x30, 0x48, 0x49, 0x76, 0xcd, 0x55, 0x10, 0x45, 0xa8, 0x0e, 0x4e, 0xcd,
+	0x4b, 0x09, 0x4a, 0x4d, 0x4e, 0xcd, 0x2c, 0x4b, 0x15, 0x32, 0xe4, 0x12, 0xc5, 0xd0, 0xe8, 0xef,
+	0xe7, 0x13, 0x29, 0xc0, 0x28, 0x25, 0xd6, 0x35, 0x57, 0x41, 0x08, 0x55, 0x97, 0x7f, 0x5e, 0x4e,
+	0x25, 0xba, 0x5d, 0x50, 0x6b, 0x20, 0xba, 0x98, 0xd0, 0xed, 0x82, 0xda, 0x03, 0xd2, 0xe8, 0xe4,
+	0x7e, 0xe2, 0xa1, 0x1c, 0xc3, 0x85, 0x87, 0x72, 0x0c, 0x2f, 0x1e, 0xc9, 0x31, 0x4c, 0x78, 0x2c,
+	0xc7, 0xb0, 0xe0, 0xb1, 0x1c, 0xe3, 0x85, 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, 0x69,
+	0xa6, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0x17, 0x57, 0xe6, 0x25, 0x97,
+	0x64, 0x64, 0xe6, 0xa5, 0x23, 0xb1, 0x10, 0xa1, 0x92, 0xc4, 0x06, 0x0e, 0x0b, 0x63, 0x40, 0x00,
+	0x00, 0x00, 0xff, 0xff, 0x7b, 0x44, 0x34, 0x9f, 0x2a, 0x01, 0x00, 0x00,
+}

+ 0 - 16
lib/config/guiconfiguration.go

@@ -13,22 +13,6 @@ import (
 	"strings"
 	"strings"
 )
 )
 
 
-type GUIConfiguration struct {
-	Enabled                   bool     `xml:"enabled,attr" json:"enabled" default:"true"`
-	RawAddress                string   `xml:"address" json:"address" default:"127.0.0.1:8384"`
-	RawUnixSocketPermissions  string   `xml:"unixSocketPermissions,omitempty" json:"unixSocketPermissions"`
-	User                      string   `xml:"user,omitempty" json:"user"`
-	Password                  string   `xml:"password,omitempty" json:"password"`
-	AuthMode                  AuthMode `xml:"authMode,omitempty" json:"authMode"`
-	RawUseTLS                 bool     `xml:"tls,attr" json:"useTLS"`
-	APIKey                    string   `xml:"apikey,omitempty" json:"apiKey"`
-	InsecureAdminAccess       bool     `xml:"insecureAdminAccess,omitempty" json:"insecureAdminAccess"`
-	Theme                     string   `xml:"theme" json:"theme" default:"default"`
-	Debugging                 bool     `xml:"debugging,attr" json:"debugging"`
-	InsecureSkipHostCheck     bool     `xml:"insecureSkipHostcheck,omitempty" json:"insecureSkipHostcheck"`
-	InsecureAllowFrameLoading bool     `xml:"insecureAllowFrameLoading,omitempty" json:"insecureAllowFrameLoading"`
-}
-
 func (c GUIConfiguration) IsAuthEnabled() bool {
 func (c GUIConfiguration) IsAuthEnabled() bool {
 	return c.AuthMode == AuthModeLDAP || (len(c.User) > 0 && len(c.Password) > 0)
 	return c.AuthMode == AuthModeLDAP || (len(c.User) > 0 && len(c.Password) > 0)
 }
 }

+ 187 - 0
lib/config/guiconfiguration.pb.go

@@ -0,0 +1,187 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: lib/config/guiconfiguration.proto
+
+package config
+
+import (
+	fmt "fmt"
+	proto "github.com/gogo/protobuf/proto"
+	_ "github.com/syncthing/syncthing/proto/ext"
+	math "math"
+	math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+type GUIConfiguration struct {
+	Enabled                   bool     `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled" xml:"enabled,attr" default:"true"`
+	RawAddress                string   `protobuf:"bytes,2,opt,name=address,proto3" json:"address" xml:"address" default:"127.0.0.1:8384"`
+	RawUnixSocketPermissions  string   `protobuf:"bytes,3,opt,name=unix_socket_permissions,json=unixSocketPermissions,proto3" json:"unixSocketPermissions" xml:"unixSocketPermissions,omitempty"`
+	User                      string   `protobuf:"bytes,4,opt,name=user,proto3" json:"user" xml:"user,omitempty"`
+	Password                  string   `protobuf:"bytes,5,opt,name=password,proto3" json:"password" xml:"password,omitempty"`
+	AuthMode                  AuthMode `protobuf:"varint,6,opt,name=auth_mode,json=authMode,proto3,enum=config.AuthMode" json:"authMode" xml:"authMode,omitempty"`
+	RawUseTLS                 bool     `protobuf:"varint,7,opt,name=use_tls,json=useTls,proto3" json:"useTLS" xml:"tls,attr"`
+	APIKey                    string   `protobuf:"bytes,8,opt,name=api_key,json=apiKey,proto3" json:"apiKey" xml:"apikey,omitempty"`
+	InsecureAdminAccess       bool     `protobuf:"varint,9,opt,name=insecure_admin_access,json=insecureAdminAccess,proto3" json:"insecureAdminAccess" xml:"insecureAdminAccess,omitempty"`
+	Theme                     string   `protobuf:"bytes,10,opt,name=theme,proto3" json:"theme" xml:"theme" default:"default"`
+	Debugging                 bool     `protobuf:"varint,11,opt,name=debugging,proto3" json:"debugging" xml:"debugging,attr"`
+	InsecureSkipHostCheck     bool     `protobuf:"varint,12,opt,name=insecure_skip_host_check,json=insecureSkipHostCheck,proto3" json:"insecureSkipHostcheck" xml:"insecureSkipHostcheck,omitempty"`
+	InsecureAllowFrameLoading bool     `protobuf:"varint,13,opt,name=insecure_allow_frame_loading,json=insecureAllowFrameLoading,proto3" json:"insecureAllowFrameLoading" xml:"insecureAllowFrameLoading,omitempty"`
+}
+
+func (m *GUIConfiguration) Reset()         { *m = GUIConfiguration{} }
+func (m *GUIConfiguration) String() string { return proto.CompactTextString(m) }
+func (*GUIConfiguration) ProtoMessage()    {}
+func (*GUIConfiguration) Descriptor() ([]byte, []int) {
+	return fileDescriptor_2a9586d611855d64, []int{0}
+}
+func (m *GUIConfiguration) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_GUIConfiguration.Unmarshal(m, b)
+}
+func (m *GUIConfiguration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_GUIConfiguration.Marshal(b, m, deterministic)
+}
+func (m *GUIConfiguration) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_GUIConfiguration.Merge(m, src)
+}
+func (m *GUIConfiguration) XXX_Size() int {
+	return xxx_messageInfo_GUIConfiguration.Size(m)
+}
+func (m *GUIConfiguration) XXX_DiscardUnknown() {
+	xxx_messageInfo_GUIConfiguration.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GUIConfiguration proto.InternalMessageInfo
+
+func init() {
+	proto.RegisterType((*GUIConfiguration)(nil), "config.GUIConfiguration")
+}
+
+func init() { proto.RegisterFile("lib/config/guiconfiguration.proto", fileDescriptor_2a9586d611855d64) }
+
+var fileDescriptor_2a9586d611855d64 = []byte{
+	// 834 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x55, 0xcd, 0x6e, 0xdb, 0x46,
+	0x10, 0x16, 0x5b, 0x47, 0xb2, 0xb6, 0xae, 0x60, 0xb0, 0x4d, 0xcb, 0x04, 0x8d, 0x56, 0x51, 0xd8,
+	0xc2, 0x01, 0x02, 0x39, 0x71, 0x5a, 0x24, 0xf0, 0xa1, 0x80, 0x1c, 0x20, 0x3f, 0xb0, 0x0b, 0x04,
+	0x74, 0x7d, 0xc9, 0x85, 0x58, 0x91, 0x6b, 0x69, 0x21, 0xfe, 0x95, 0xbb, 0x84, 0xa4, 0x43, 0xfb,
+	0x0c, 0x85, 0x7a, 0x2e, 0xd0, 0x67, 0xe8, 0xa5, 0xaf, 0xd0, 0x9b, 0x74, 0x2a, 0x72, 0x5a, 0x20,
+	0xd2, 0xa5, 0xe0, 0x91, 0xc7, 0x9c, 0x8a, 0x5d, 0xfe, 0x48, 0x94, 0x95, 0x26, 0xb7, 0x9d, 0x6f,
+	0xbe, 0x99, 0x6f, 0x66, 0x38, 0x03, 0x82, 0xdb, 0x0e, 0xe9, 0x1d, 0x5a, 0xbe, 0x77, 0x49, 0xfa,
+	0x87, 0xfd, 0x88, 0xa4, 0xaf, 0x28, 0x44, 0x8c, 0xf8, 0x5e, 0x27, 0x08, 0x7d, 0xe6, 0xab, 0xd5,
+	0x14, 0xbc, 0x79, 0x63, 0x8d, 0x8a, 0x22, 0x36, 0x70, 0x7d, 0x1b, 0xa7, 0x94, 0x9b, 0x75, 0x3c,
+	0x66, 0xe9, 0xb3, 0xfd, 0x7a, 0x0f, 0xec, 0x3f, 0xbb, 0x78, 0xf1, 0x64, 0x3d, 0x91, 0xda, 0x03,
+	0x35, 0xec, 0xa1, 0x9e, 0x83, 0x6d, 0x4d, 0x69, 0x29, 0x07, 0xbb, 0x27, 0xcf, 0x63, 0x0e, 0x73,
+	0x28, 0xe1, 0xf0, 0xf6, 0xd8, 0x75, 0x8e, 0xdb, 0x99, 0x7d, 0x0f, 0x31, 0x16, 0xb6, 0x5b, 0x36,
+	0xbe, 0x44, 0x91, 0xc3, 0x8e, 0xdb, 0x2c, 0x8c, 0x70, 0x3b, 0x9e, 0xe9, 0x7b, 0xeb, 0xfe, 0xb7,
+	0x33, 0x7d, 0x47, 0x38, 0x8c, 0x3c, 0x8b, 0xfa, 0x33, 0xa8, 0x21, 0xdb, 0x0e, 0x31, 0xa5, 0xda,
+	0x47, 0x2d, 0xe5, 0xa0, 0x7e, 0x62, 0x2d, 0x38, 0x04, 0x06, 0x1a, 0x75, 0x53, 0x54, 0x28, 0x66,
+	0x84, 0x84, 0xc3, 0x6f, 0xa4, 0x62, 0x66, 0xaf, 0x89, 0x3d, 0x38, 0x7a, 0xd4, 0xb9, 0xdf, 0xb9,
+	0xdf, 0x79, 0x70, 0xfc, 0xf8, 0xe1, 0xe3, 0x6f, 0xdb, 0x6f, 0x67, 0x7a, 0xa3, 0x0c, 0x4d, 0xe7,
+	0xfa, 0x5a, 0x52, 0x23, 0x4f, 0xa9, 0xfe, 0xa3, 0x80, 0x2f, 0x23, 0x8f, 0x8c, 0x4d, 0xea, 0x5b,
+	0x43, 0xcc, 0xcc, 0x00, 0x87, 0x2e, 0xa1, 0x94, 0xf8, 0x1e, 0xd5, 0x3e, 0x96, 0xf5, 0xfc, 0xae,
+	0x2c, 0x38, 0xd4, 0x0c, 0x34, 0xba, 0xf0, 0xc8, 0xf8, 0x5c, 0xb2, 0x5e, 0xae, 0x48, 0x31, 0x87,
+	0xd7, 0xa3, 0x6d, 0x8e, 0x84, 0xc3, 0xaf, 0x65, 0xb1, 0x5b, 0xbd, 0xf7, 0x7c, 0x97, 0x30, 0xec,
+	0x06, 0x6c, 0x22, 0x46, 0x04, 0xdf, 0xc3, 0x99, 0xce, 0xf5, 0x77, 0x16, 0x60, 0x6c, 0x97, 0x57,
+	0x9f, 0x82, 0x9d, 0x88, 0xe2, 0x50, 0xdb, 0x91, 0x4d, 0x1c, 0xc5, 0x1c, 0x4a, 0x3b, 0xe1, 0xf0,
+	0xf3, 0xb4, 0x2c, 0x8a, 0xc3, 0x72, 0x15, 0x8d, 0x32, 0x64, 0x48, 0xbe, 0xfa, 0x0a, 0xec, 0x06,
+	0x88, 0xd2, 0x91, 0x1f, 0xda, 0xda, 0x35, 0x99, 0xeb, 0xfb, 0x98, 0xc3, 0x02, 0x4b, 0x38, 0xd4,
+	0x64, 0xbe, 0x1c, 0x28, 0xe7, 0x54, 0xaf, 0xc2, 0x46, 0x11, 0xab, 0xba, 0xa0, 0x2e, 0x36, 0xd2,
+	0x14, 0x2b, 0xa9, 0x55, 0x5b, 0xca, 0x41, 0xe3, 0x68, 0xbf, 0x93, 0xae, 0x6a, 0xa7, 0x1b, 0xb1,
+	0xc1, 0x0f, 0xbe, 0x8d, 0x53, 0x39, 0x94, 0x59, 0x85, 0x5c, 0x0e, 0x6c, 0xc8, 0x5d, 0x85, 0x8d,
+	0x22, 0x56, 0xc5, 0xa0, 0x16, 0x51, 0x6c, 0x32, 0x87, 0x6a, 0x35, 0xb9, 0xce, 0x67, 0x0b, 0x0e,
+	0xeb, 0x62, 0xb0, 0x14, 0xff, 0x78, 0x76, 0x1e, 0x73, 0x58, 0x8d, 0xe4, 0x2b, 0xe1, 0xb0, 0x21,
+	0x55, 0x98, 0x43, 0xd3, 0xb5, 0x8e, 0x67, 0xfa, 0x6e, 0x6e, 0x24, 0x33, 0x3d, 0xe3, 0x4d, 0xe7,
+	0xfa, 0x2a, 0xdc, 0x90, 0xa0, 0x43, 0x85, 0x0c, 0x0a, 0x88, 0x39, 0xc4, 0x13, 0x6d, 0x57, 0x0e,
+	0x4c, 0xc8, 0x54, 0xbb, 0x2f, 0x5f, 0x9c, 0xe2, 0x89, 0xd0, 0x40, 0x01, 0x39, 0xc5, 0x93, 0x84,
+	0xc3, 0x2f, 0xd2, 0x4e, 0x02, 0x32, 0xc4, 0x93, 0x72, 0x1f, 0xfb, 0x9b, 0xe0, 0x74, 0xae, 0x67,
+	0x19, 0x8c, 0x2c, 0x5e, 0xfd, 0x4d, 0x01, 0xd7, 0x89, 0x47, 0xb1, 0x15, 0x85, 0xd8, 0x44, 0xb6,
+	0x4b, 0x3c, 0x13, 0x59, 0x96, 0xb8, 0xa3, 0xba, 0x6c, 0xce, 0x8c, 0x39, 0xfc, 0x2c, 0x27, 0x74,
+	0x85, 0xbf, 0x2b, 0xdd, 0x09, 0x87, 0x77, 0xa4, 0xf0, 0x16, 0x5f, 0xb9, 0x8a, 0x5b, 0xff, 0xcb,
+	0x30, 0xb6, 0x25, 0x57, 0x4f, 0xc1, 0x35, 0x36, 0xc0, 0x2e, 0xd6, 0x80, 0x6c, 0xfd, 0xbb, 0x98,
+	0xc3, 0x14, 0x48, 0x38, 0xbc, 0x95, 0xce, 0x54, 0x58, 0x6b, 0xa7, 0x9b, 0x3d, 0xc4, 0xcd, 0xd6,
+	0xb2, 0xb7, 0x91, 0x86, 0xa8, 0x17, 0xa0, 0x6e, 0xe3, 0x5e, 0xd4, 0xef, 0x13, 0xaf, 0xaf, 0x7d,
+	0x22, 0xbb, 0x7a, 0x14, 0x73, 0xb8, 0x02, 0x8b, 0x6d, 0x2e, 0x90, 0xe2, 0x73, 0x35, 0xca, 0x90,
+	0xb1, 0x0a, 0x52, 0xff, 0x52, 0x80, 0x56, 0x4c, 0x8e, 0x0e, 0x49, 0x60, 0x0e, 0x7c, 0xca, 0x4c,
+	0x6b, 0x80, 0xad, 0xa1, 0xb6, 0x27, 0x65, 0x7e, 0x11, 0x77, 0x9d, 0x73, 0xce, 0x87, 0x24, 0x78,
+	0xee, 0x53, 0x26, 0x09, 0xc5, 0x5d, 0x6f, 0xf5, 0x6e, 0xdc, 0xf5, 0x7b, 0x38, 0xc9, 0x4c, 0xdf,
+	0x2e, 0x62, 0x5c, 0x81, 0x9f, 0x08, 0x58, 0xfd, 0x53, 0x01, 0x5f, 0xad, 0xbe, 0xb9, 0xe3, 0xf8,
+	0x23, 0xf3, 0x32, 0x44, 0x2e, 0x36, 0x1d, 0x1f, 0xd9, 0x62, 0x48, 0x9f, 0xca, 0xea, 0x7f, 0x8a,
+	0x39, 0xbc, 0x51, 0x7c, 0x1d, 0x41, 0x7b, 0x2a, 0x58, 0x67, 0x29, 0x29, 0xe1, 0xf0, 0x6e, 0x79,
+	0x01, 0x36, 0x19, 0xe5, 0x2e, 0xee, 0x7c, 0x00, 0xcf, 0x78, 0xb7, 0xdc, 0xc9, 0xb3, 0xbf, 0xdf,
+	0x34, 0x2b, 0xf3, 0x37, 0xcd, 0xca, 0xbf, 0x8b, 0x66, 0xe5, 0xd7, 0x65, 0xb3, 0xf2, 0xc7, 0xb2,
+	0xa9, 0xcc, 0x97, 0xcd, 0xca, 0xeb, 0x65, 0xb3, 0xf2, 0xea, 0x6e, 0x9f, 0xb0, 0x41, 0xd4, 0xeb,
+	0x58, 0xbe, 0x7b, 0x48, 0x27, 0x9e, 0xc5, 0x06, 0xc4, 0xeb, 0xaf, 0xbd, 0x56, 0x7f, 0xaf, 0x5e,
+	0x55, 0xfe, 0xaa, 0x1e, 0xfe, 0x17, 0x00, 0x00, 0xff, 0xff, 0xfa, 0x2b, 0x9a, 0x81, 0xfd, 0x06,
+	0x00, 0x00,
+}
+
+func (m *GUIConfiguration) ProtoSize() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Enabled {
+		n += 2
+	}
+	l = len(m.RawAddress)
+	if l > 0 {
+		n += 1 + l + sovGuiconfiguration(uint64(l))
+	}
+	l = len(m.RawUnixSocketPermissions)
+	if l > 0 {
+		n += 1 + l + sovGuiconfiguration(uint64(l))
+	}
+	l = len(m.User)
+	if l > 0 {
+		n += 1 + l + sovGuiconfiguration(uint64(l))
+	}
+	l = len(m.Password)
+	if l > 0 {
+		n += 1 + l + sovGuiconfiguration(uint64(l))
+	}
+	if m.AuthMode != 0 {
+		n += 1 + sovGuiconfiguration(uint64(m.AuthMode))
+	}
+	if m.RawUseTLS {
+		n += 2
+	}
+	l = len(m.APIKey)
+	if l > 0 {
+		n += 1 + l + sovGuiconfiguration(uint64(l))
+	}
+	if m.InsecureAdminAccess {
+		n += 2
+	}
+	l = len(m.Theme)
+	if l > 0 {
+		n += 1 + l + sovGuiconfiguration(uint64(l))
+	}
+	if m.Debugging {
+		n += 2
+	}
+	if m.InsecureSkipHostCheck {
+		n += 2
+	}
+	if m.InsecureAllowFrameLoading {
+		n += 2
+	}
+	return n
+}
+
+func sovGuiconfiguration(x uint64) (n int) {
+	return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozGuiconfiguration(x uint64) (n int) {
+	return sovGuiconfiguration(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}

+ 0 - 9
lib/config/ldapconfiguration.go

@@ -6,15 +6,6 @@
 
 
 package config
 package config
 
 
-type LDAPConfiguration struct {
-	Address            string        `xml:"address,omitempty" json:"address"`
-	BindDN             string        `xml:"bindDN,omitempty" json:"bindDN"`
-	Transport          LDAPTransport `xml:"transport,omitempty" json:"transport"`
-	InsecureSkipVerify bool          `xml:"insecureSkipVerify,omitempty" json:"insecureSkipVerify" default:"false"`
-	SearchBaseDN       string        `xml:"searchBaseDN,omitempty" json:"searchBaseDN"`
-	SearchFilter       string        `xml:"searchFilter,omitempty" json:"searchFilter"`
-}
-
 func (c LDAPConfiguration) Copy() LDAPConfiguration {
 func (c LDAPConfiguration) Copy() LDAPConfiguration {
 	return c
 	return c
 }
 }

+ 138 - 0
lib/config/ldapconfiguration.pb.go

@@ -0,0 +1,138 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: lib/config/ldapconfiguration.proto
+
+package config
+
+import (
+	fmt "fmt"
+	proto "github.com/gogo/protobuf/proto"
+	_ "github.com/syncthing/syncthing/proto/ext"
+	math "math"
+	math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+type LDAPConfiguration struct {
+	Address            string        `protobuf:"bytes,1,opt,name=address,proto3" json:"address" xml:"address,omitempty"`
+	BindDN             string        `protobuf:"bytes,2,opt,name=bind_dn,json=bindDn,proto3" json:"bindDN" xml:"bindDN,omitempty"`
+	Transport          LDAPTransport `protobuf:"varint,3,opt,name=transport,proto3,enum=config.LDAPTransport" json:"transport" xml:"transport,omitempty"`
+	InsecureSkipVerify bool          `protobuf:"varint,4,opt,name=insecure_skip_verify,json=insecureSkipVerify,proto3" json:"insecureSkipVerify" xml:"insecureSkipVerify,omitempty" default:"false"`
+	SearchBaseDN       string        `protobuf:"bytes,5,opt,name=search_base_dn,json=searchBaseDn,proto3" json:"searchBaseDN" xml:"searchBaseDN,omitempty"`
+	SearchFilter       string        `protobuf:"bytes,6,opt,name=search_filter,json=searchFilter,proto3" json:"searchFilter" xml:"searchFilter,omitempty"`
+}
+
+func (m *LDAPConfiguration) Reset()         { *m = LDAPConfiguration{} }
+func (m *LDAPConfiguration) String() string { return proto.CompactTextString(m) }
+func (*LDAPConfiguration) ProtoMessage()    {}
+func (*LDAPConfiguration) Descriptor() ([]byte, []int) {
+	return fileDescriptor_9681ad7e41c73956, []int{0}
+}
+func (m *LDAPConfiguration) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_LDAPConfiguration.Unmarshal(m, b)
+}
+func (m *LDAPConfiguration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_LDAPConfiguration.Marshal(b, m, deterministic)
+}
+func (m *LDAPConfiguration) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_LDAPConfiguration.Merge(m, src)
+}
+func (m *LDAPConfiguration) XXX_Size() int {
+	return xxx_messageInfo_LDAPConfiguration.Size(m)
+}
+func (m *LDAPConfiguration) XXX_DiscardUnknown() {
+	xxx_messageInfo_LDAPConfiguration.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_LDAPConfiguration proto.InternalMessageInfo
+
+func init() {
+	proto.RegisterType((*LDAPConfiguration)(nil), "config.LDAPConfiguration")
+}
+
+func init() {
+	proto.RegisterFile("lib/config/ldapconfiguration.proto", fileDescriptor_9681ad7e41c73956)
+}
+
+var fileDescriptor_9681ad7e41c73956 = []byte{
+	// 498 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x53, 0x4d, 0x6f, 0xd3, 0x40,
+	0x10, 0xb5, 0x81, 0xba, 0xc4, 0x2a, 0x15, 0x35, 0x50, 0x42, 0x55, 0x79, 0x23, 0xcb, 0x87, 0x20,
+	0xa1, 0x44, 0x2a, 0xb7, 0x72, 0xaa, 0xa9, 0x40, 0x42, 0x08, 0x21, 0x17, 0x7a, 0xe0, 0x12, 0xf9,
+	0x63, 0x9d, 0xac, 0xea, 0xec, 0x5a, 0xbb, 0xeb, 0xaa, 0xe1, 0x57, 0x40, 0x7f, 0x41, 0x6f, 0xfc,
+	0x15, 0x6e, 0xc9, 0x91, 0xd3, 0x4a, 0x4d, 0x2e, 0xc8, 0x47, 0x1f, 0x39, 0xa1, 0xac, 0x9d, 0xc6,
+	0x4e, 0xa3, 0xde, 0x66, 0xde, 0x9b, 0x79, 0xf3, 0x76, 0x47, 0xa3, 0x5b, 0x31, 0xf2, 0xbb, 0x01,
+	0xc1, 0x11, 0xea, 0x77, 0xe3, 0xd0, 0x4b, 0x8a, 0x30, 0xa5, 0x1e, 0x47, 0x04, 0x77, 0x12, 0x4a,
+	0x38, 0x31, 0xb4, 0x02, 0xdc, 0x33, 0x57, 0x6a, 0x39, 0xf5, 0x30, 0x4b, 0x08, 0xe5, 0x45, 0xdd,
+	0x5e, 0x03, 0x5e, 0x94, 0xa1, 0xf5, 0x53, 0xd3, 0x77, 0x3e, 0x1e, 0x1f, 0x7d, 0x7e, 0x5b, 0x95,
+	0x33, 0xbe, 0xea, 0x9b, 0x5e, 0x18, 0x52, 0xc8, 0x58, 0x53, 0x6d, 0xa9, 0xed, 0x86, 0xf3, 0x26,
+	0x13, 0x60, 0x01, 0xe5, 0x02, 0x3c, 0xbf, 0x18, 0xc6, 0x87, 0x56, 0x99, 0xbf, 0x22, 0x43, 0xc4,
+	0xe1, 0x30, 0xe1, 0x23, 0x2b, 0x1b, 0xdb, 0x3b, 0xb7, 0x50, 0x77, 0xd1, 0x68, 0x10, 0x7d, 0xd3,
+	0x47, 0x38, 0xec, 0x85, 0xb8, 0x79, 0x4f, 0xca, 0x9e, 0x4e, 0x05, 0xd0, 0x1c, 0x84, 0xc3, 0xe3,
+	0x4f, 0x99, 0x00, 0x9a, 0x2f, 0xa3, 0x5c, 0x80, 0x5d, 0xa9, 0x5f, 0xa4, 0x75, 0xf9, 0xc7, 0xab,
+	0x60, 0x3e, 0xb6, 0xcb, 0xbe, 0xcb, 0x89, 0x5d, 0x6a, 0xb9, 0x05, 0x82, 0x8d, 0x73, 0xbd, 0x71,
+	0xf3, 0xf6, 0xe6, 0xfd, 0x96, 0xda, 0xde, 0x3e, 0x78, 0xd6, 0x29, 0x3e, 0xa6, 0x33, 0x7f, 0xf5,
+	0x97, 0x05, 0xe9, 0x1c, 0x65, 0x02, 0x2c, 0x6b, 0x73, 0x01, 0x5e, 0x48, 0x0b, 0x37, 0x48, 0xdd,
+	0xc5, 0x93, 0x35, 0xb8, 0xbb, 0x6c, 0x37, 0x7e, 0xa9, 0xfa, 0x53, 0x84, 0x19, 0x0c, 0x52, 0x0a,
+	0x7b, 0xec, 0x0c, 0x25, 0xbd, 0x73, 0x48, 0x51, 0x34, 0x6a, 0x3e, 0x68, 0xa9, 0xed, 0x87, 0x4e,
+	0x9a, 0x09, 0x60, 0x2c, 0xf8, 0x93, 0x33, 0x94, 0x9c, 0x4a, 0x36, 0x17, 0xe0, 0x40, 0x4e, 0xbd,
+	0x4d, 0x55, 0xc6, 0xb7, 0x42, 0x18, 0x79, 0x69, 0xcc, 0x0f, 0xad, 0xc8, 0x8b, 0x19, 0x9c, 0xdb,
+	0xd9, 0xbf, 0xab, 0xe1, 0xdf, 0xd8, 0xde, 0x90, 0x95, 0xee, 0x9a, 0x91, 0xc6, 0x95, 0xaa, 0x6f,
+	0x33, 0xe8, 0xd1, 0x60, 0xd0, 0xf3, 0x3d, 0x06, 0xe7, 0xab, 0xd9, 0x90, 0xab, 0xf9, 0x3e, 0x15,
+	0x60, 0xeb, 0x44, 0x32, 0x8e, 0xc7, 0xa0, 0x5c, 0xd0, 0x16, 0xab, 0xe4, 0xb9, 0x00, 0xfb, 0xd2,
+	0x6d, 0x15, 0xac, 0x7f, 0xd3, 0xee, 0x7a, 0x2a, 0x1f, 0xdb, 0x35, 0xa5, 0xcb, 0x89, 0x5d, 0x9b,
+	0xe4, 0x56, 0x59, 0x6c, 0x10, 0xfd, 0x51, 0xe9, 0x30, 0x42, 0x31, 0x87, 0xb4, 0xa9, 0x49, 0x83,
+	0x1f, 0x96, 0x86, 0xde, 0x49, 0x7c, 0xc5, 0x50, 0x01, 0xae, 0x35, 0xb4, 0x4a, 0xb9, 0x35, 0x1d,
+	0xe7, 0xfd, 0xef, 0x6b, 0x53, 0x99, 0x5c, 0x9b, 0xca, 0xdf, 0xa9, 0xa9, 0xfc, 0x98, 0x99, 0xca,
+	0xd5, 0xcc, 0x54, 0x27, 0x33, 0x53, 0xf9, 0x33, 0x33, 0x95, 0x6f, 0x2f, 0xfb, 0x88, 0x0f, 0x52,
+	0xbf, 0x13, 0x90, 0x61, 0x97, 0x8d, 0x70, 0xc0, 0x07, 0x08, 0xf7, 0x2b, 0xd1, 0xf2, 0xf6, 0x7c,
+	0x4d, 0xde, 0xd8, 0xeb, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0xca, 0xa1, 0xc5, 0x0d, 0xbc, 0x03,
+	0x00, 0x00,
+}
+
+func (m *LDAPConfiguration) ProtoSize() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.Address)
+	if l > 0 {
+		n += 1 + l + sovLdapconfiguration(uint64(l))
+	}
+	l = len(m.BindDN)
+	if l > 0 {
+		n += 1 + l + sovLdapconfiguration(uint64(l))
+	}
+	if m.Transport != 0 {
+		n += 1 + sovLdapconfiguration(uint64(m.Transport))
+	}
+	if m.InsecureSkipVerify {
+		n += 2
+	}
+	l = len(m.SearchBaseDN)
+	if l > 0 {
+		n += 1 + l + sovLdapconfiguration(uint64(l))
+	}
+	l = len(m.SearchFilter)
+	if l > 0 {
+		n += 1 + l + sovLdapconfiguration(uint64(l))
+	}
+	return n
+}
+
+func sovLdapconfiguration(x uint64) (n int) {
+	return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozLdapconfiguration(x uint64) (n int) {
+	return sovLdapconfiguration(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}

+ 0 - 8
lib/config/ldaptransport.go

@@ -6,14 +6,6 @@
 
 
 package config
 package config
 
 
-type LDAPTransport int
-
-const (
-	LDAPTransportPlain LDAPTransport = iota // default is plain
-	LDAPTransportTLS
-	LDAPTransportStartTLS
-)
-
 func (t LDAPTransport) String() string {
 func (t LDAPTransport) String() string {
 	switch t {
 	switch t {
 	case LDAPTransportPlain:
 	case LDAPTransportPlain:

+ 74 - 0
lib/config/ldaptransport.pb.go

@@ -0,0 +1,74 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: lib/config/ldaptransport.proto
+
+package config
+
+import (
+	fmt "fmt"
+	_ "github.com/gogo/protobuf/gogoproto"
+	proto "github.com/gogo/protobuf/proto"
+	_ "github.com/syncthing/syncthing/proto/ext"
+	math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+type LDAPTransport int32
+
+const (
+	LDAPTransportPlain    LDAPTransport = 0
+	LDAPTransportTLS      LDAPTransport = 2
+	LDAPTransportStartTLS LDAPTransport = 3
+)
+
+var LDAPTransport_name = map[int32]string{
+	0: "LDAP_TRANSPORT_PLAIN",
+	2: "LDAP_TRANSPORT_TLS",
+	3: "LDAP_TRANSPORT_START_TLS",
+}
+
+var LDAPTransport_value = map[string]int32{
+	"LDAP_TRANSPORT_PLAIN":     0,
+	"LDAP_TRANSPORT_TLS":       2,
+	"LDAP_TRANSPORT_START_TLS": 3,
+}
+
+func (LDAPTransport) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_79795fc8505b82bf, []int{0}
+}
+
+func init() {
+	proto.RegisterEnum("config.LDAPTransport", LDAPTransport_name, LDAPTransport_value)
+}
+
+func init() { proto.RegisterFile("lib/config/ldaptransport.proto", fileDescriptor_79795fc8505b82bf) }
+
+var fileDescriptor_79795fc8505b82bf = []byte{
+	// 269 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xcb, 0xc9, 0x4c, 0xd2,
+	0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0xcf, 0x49, 0x49, 0x2c, 0x28, 0x29, 0x4a, 0xcc, 0x2b,
+	0x2e, 0xc8, 0x2f, 0x2a, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0xc8, 0x49, 0x29,
+	0x17, 0xa5, 0x16, 0xe4, 0x17, 0xeb, 0x83, 0x05, 0x93, 0x4a, 0xd3, 0xf4, 0xd3, 0xf3, 0xd3, 0xf3,
+	0xc1, 0x1c, 0x30, 0x0b, 0xa2, 0x58, 0x8a, 0x33, 0xb5, 0x02, 0xaa, 0x4f, 0xeb, 0x23, 0x23, 0x17,
+	0xaf, 0x8f, 0x8b, 0x63, 0x40, 0x08, 0xcc, 0x3c, 0x21, 0x37, 0x2e, 0x11, 0x90, 0x40, 0x7c, 0x48,
+	0x90, 0xa3, 0x5f, 0x70, 0x80, 0x7f, 0x50, 0x48, 0x7c, 0x80, 0x8f, 0xa3, 0xa7, 0x9f, 0x00, 0x83,
+	0x94, 0x4e, 0xd7, 0x5c, 0x05, 0x21, 0x14, 0xc5, 0x01, 0x39, 0x89, 0x99, 0x79, 0x97, 0xfa, 0x54,
+	0xb1, 0x88, 0x0a, 0x39, 0x70, 0x09, 0xa1, 0x99, 0x13, 0xe2, 0x13, 0x2c, 0xc0, 0x24, 0xa5, 0xd1,
+	0x35, 0x57, 0x41, 0x00, 0x45, 0x7d, 0x88, 0x4f, 0xf0, 0xa5, 0x3e, 0x55, 0x0c, 0x31, 0xa1, 0x00,
+	0x2e, 0x09, 0x34, 0x13, 0x82, 0x43, 0x1c, 0xa1, 0xe6, 0x30, 0x4b, 0x19, 0x75, 0xcd, 0x55, 0x10,
+	0x45, 0xd1, 0x13, 0x5c, 0x92, 0x08, 0x33, 0x0c, 0xbb, 0x84, 0x14, 0xcb, 0x8a, 0x25, 0x72, 0x0c,
+	0x4e, 0xee, 0x27, 0x1e, 0xca, 0x31, 0x5c, 0x78, 0x28, 0xc7, 0xf0, 0xe2, 0x91, 0x1c, 0xc3, 0x84,
+	0xc7, 0x72, 0x0c, 0x0b, 0x1e, 0xcb, 0x31, 0x5e, 0x78, 0x2c, 0xc7, 0x70, 0xe3, 0xb1, 0x1c, 0x43,
+	0x94, 0x66, 0x7a, 0x66, 0x49, 0x46, 0x69, 0x92, 0x5e, 0x72, 0x7e, 0xae, 0x7e, 0x71, 0x65, 0x5e,
+	0x72, 0x49, 0x46, 0x66, 0x5e, 0x3a, 0x12, 0x0b, 0x11, 0x11, 0x49, 0x6c, 0xe0, 0x30, 0x34, 0x06,
+	0x04, 0x00, 0x00, 0xff, 0xff, 0xc8, 0x64, 0xce, 0xb9, 0x9d, 0x01, 0x00, 0x00,
+}

+ 0 - 26
lib/config/observed.go

@@ -1,26 +0,0 @@
-// Copyright (C) 2018 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 config
-
-import (
-	"time"
-
-	"github.com/syncthing/syncthing/lib/protocol"
-)
-
-type ObservedFolder struct {
-	Time  time.Time `xml:"time,attr" json:"time"`
-	ID    string    `xml:"id,attr" json:"id"`
-	Label string    `xml:"label,attr" json:"label"`
-}
-
-type ObservedDevice struct {
-	Time    time.Time         `xml:"time,attr" json:"time"`
-	ID      protocol.DeviceID `xml:"id,attr" json:"deviceID"`
-	Name    string            `xml:"name,attr" json:"name"`
-	Address string            `xml:"address,attr" json:"address"`
-}

+ 175 - 0
lib/config/observed.pb.go

@@ -0,0 +1,175 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: lib/config/observed.proto
+
+package config
+
+import (
+	fmt "fmt"
+	proto "github.com/gogo/protobuf/proto"
+	github_com_gogo_protobuf_types "github.com/gogo/protobuf/types"
+	_ "github.com/golang/protobuf/ptypes/timestamp"
+	github_com_syncthing_syncthing_lib_protocol "github.com/syncthing/syncthing/lib/protocol"
+	_ "github.com/syncthing/syncthing/proto/ext"
+	math "math"
+	math_bits "math/bits"
+	time "time"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+var _ = time.Kitchen
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+type ObservedFolder struct {
+	Time  time.Time `protobuf:"bytes,1,opt,name=time,proto3,stdtime" json:"time" xml:"time,attr"`
+	ID    string    `protobuf:"bytes,2,opt,name=id,proto3" json:"id" xml:"id,attr"`
+	Label string    `protobuf:"bytes,3,opt,name=label,proto3" json:"label" xml:"label,attr"`
+}
+
+func (m *ObservedFolder) Reset()         { *m = ObservedFolder{} }
+func (m *ObservedFolder) String() string { return proto.CompactTextString(m) }
+func (*ObservedFolder) ProtoMessage()    {}
+func (*ObservedFolder) Descriptor() ([]byte, []int) {
+	return fileDescriptor_49f68ff7b178722f, []int{0}
+}
+func (m *ObservedFolder) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_ObservedFolder.Unmarshal(m, b)
+}
+func (m *ObservedFolder) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_ObservedFolder.Marshal(b, m, deterministic)
+}
+func (m *ObservedFolder) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ObservedFolder.Merge(m, src)
+}
+func (m *ObservedFolder) XXX_Size() int {
+	return xxx_messageInfo_ObservedFolder.Size(m)
+}
+func (m *ObservedFolder) XXX_DiscardUnknown() {
+	xxx_messageInfo_ObservedFolder.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ObservedFolder proto.InternalMessageInfo
+
+type ObservedDevice struct {
+	Time    time.Time                                            `protobuf:"bytes,1,opt,name=time,proto3,stdtime" json:"time" xml:"time,attr"`
+	ID      github_com_syncthing_syncthing_lib_protocol.DeviceID `protobuf:"bytes,2,opt,name=id,proto3,customtype=github.com/syncthing/syncthing/lib/protocol.DeviceID" json:"deviceID" xml:"id,attr"`
+	Name    string                                               `protobuf:"bytes,3,opt,name=name,proto3" json:"name" xml:"name,attr"`
+	Address string                                               `protobuf:"bytes,4,opt,name=address,proto3" json:"address" xml:"address,attr"`
+}
+
+func (m *ObservedDevice) Reset()         { *m = ObservedDevice{} }
+func (m *ObservedDevice) String() string { return proto.CompactTextString(m) }
+func (*ObservedDevice) ProtoMessage()    {}
+func (*ObservedDevice) Descriptor() ([]byte, []int) {
+	return fileDescriptor_49f68ff7b178722f, []int{1}
+}
+func (m *ObservedDevice) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_ObservedDevice.Unmarshal(m, b)
+}
+func (m *ObservedDevice) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_ObservedDevice.Marshal(b, m, deterministic)
+}
+func (m *ObservedDevice) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ObservedDevice.Merge(m, src)
+}
+func (m *ObservedDevice) XXX_Size() int {
+	return xxx_messageInfo_ObservedDevice.Size(m)
+}
+func (m *ObservedDevice) XXX_DiscardUnknown() {
+	xxx_messageInfo_ObservedDevice.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ObservedDevice proto.InternalMessageInfo
+
+func init() {
+	proto.RegisterType((*ObservedFolder)(nil), "config.ObservedFolder")
+	proto.RegisterType((*ObservedDevice)(nil), "config.ObservedDevice")
+}
+
+func init() { proto.RegisterFile("lib/config/observed.proto", fileDescriptor_49f68ff7b178722f) }
+
+var fileDescriptor_49f68ff7b178722f = []byte{
+	// 438 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x93, 0x3f, 0x6f, 0xd4, 0x30,
+	0x00, 0xc5, 0xe3, 0xf4, 0x68, 0x39, 0x53, 0xfe, 0x28, 0xd3, 0x71, 0x43, 0x5c, 0x9d, 0x32, 0x1c,
+	0x02, 0x25, 0xfc, 0x9b, 0x10, 0x42, 0x22, 0x8a, 0x40, 0x27, 0x06, 0xa4, 0x88, 0x89, 0x89, 0x24,
+	0x76, 0x53, 0x4b, 0x49, 0x5c, 0x25, 0x6e, 0x55, 0x36, 0x46, 0xc6, 0x96, 0x4f, 0xc0, 0xc7, 0xe9,
+	0x76, 0x19, 0x11, 0x83, 0x51, 0x9b, 0x05, 0x65, 0x8c, 0xc4, 0x8e, 0x62, 0x27, 0xee, 0x4d, 0x88,
+	0xa9, 0x9b, 0xdf, 0xd3, 0xf3, 0x4f, 0x7e, 0x2f, 0x0a, 0xbc, 0x9f, 0xd1, 0xd8, 0x4b, 0x58, 0xb1,
+	0x4f, 0x53, 0x8f, 0xc5, 0x15, 0x29, 0x8f, 0x09, 0x76, 0x0f, 0x4b, 0xc6, 0x99, 0xb5, 0xad, 0xec,
+	0x39, 0x4a, 0x19, 0x4b, 0x33, 0xe2, 0x49, 0x37, 0x3e, 0xda, 0xf7, 0x38, 0xcd, 0x49, 0xc5, 0xa3,
+	0xfc, 0x50, 0x05, 0xe7, 0x53, 0x72, 0xc2, 0xd5, 0x71, 0xf1, 0x07, 0xc0, 0x3b, 0xef, 0x07, 0xcc,
+	0x1b, 0x96, 0x61, 0x52, 0x5a, 0x9f, 0xe0, 0xa4, 0xbf, 0x30, 0x03, 0x7b, 0x60, 0x79, 0xeb, 0xe9,
+	0xdc, 0x55, 0x34, 0x77, 0xa4, 0xb9, 0x1f, 0x46, 0x9a, 0xff, 0xf8, 0x5c, 0x20, 0xa3, 0x15, 0x48,
+	0xe6, 0x3b, 0x81, 0xee, 0x9e, 0xe4, 0xd9, 0x8b, 0x45, 0x2f, 0x1e, 0x45, 0x9c, 0x97, 0x8b, 0xd3,
+	0x5f, 0x08, 0xb4, 0x6b, 0x67, 0xaa, 0x9d, 0x50, 0x26, 0xad, 0x57, 0xd0, 0xa4, 0x78, 0x66, 0xee,
+	0x81, 0xe5, 0xd4, 0x77, 0x2f, 0x05, 0x32, 0x57, 0x41, 0x2b, 0x90, 0x49, 0x71, 0x27, 0xd0, 0x6d,
+	0xc9, 0xa0, 0x58, 0x11, 0xda, 0xb5, 0xb3, 0x33, 0x9c, 0xbf, 0xd5, 0x8e, 0xb9, 0x0a, 0x42, 0x93,
+	0x62, 0xeb, 0x35, 0xbc, 0x91, 0x45, 0x31, 0xc9, 0x66, 0x5b, 0x12, 0xf1, 0xb0, 0x15, 0x48, 0x19,
+	0x9d, 0x40, 0xf7, 0xe4, 0x7d, 0xa9, 0x34, 0x02, 0x5e, 0xc9, 0x50, 0x05, 0x17, 0x67, 0x5b, 0x57,
+	0xbd, 0x03, 0x72, 0x4c, 0x13, 0x72, 0x0d, 0xbd, 0xcf, 0x80, 0x2e, 0xbe, 0xeb, 0x7f, 0x01, 0x3d,
+	0xe5, 0xa7, 0x40, 0xcf, 0x53, 0xca, 0x0f, 0x8e, 0x62, 0x37, 0x61, 0xb9, 0x57, 0x7d, 0x2e, 0x12,
+	0x7e, 0x40, 0x8b, 0x74, 0xe3, 0xd4, 0x7f, 0x70, 0xf9, 0x88, 0x84, 0x65, 0xae, 0x7a, 0xeb, 0x2a,
+	0xd0, 0xab, 0xdd, 0xc4, 0x83, 0xf3, 0xaf, 0xed, 0xba, 0xb5, 0xa3, 0x73, 0x5f, 0x6b, 0x07, 0x6c,
+	0x6c, 0xf9, 0x12, 0x4e, 0x8a, 0x28, 0x27, 0xc3, 0x94, 0xcb, 0xbe, 0x55, 0xaf, 0x75, 0xab, 0x5e,
+	0x68, 0xde, 0x54, 0xab, 0x50, 0xa6, 0xac, 0x77, 0x70, 0x27, 0xc2, 0xb8, 0x24, 0x55, 0x35, 0x9b,
+	0x48, 0xc0, 0x93, 0x56, 0xa0, 0xd1, 0xea, 0x04, 0xb2, 0x24, 0x63, 0xd0, 0x1a, 0xb3, 0xbb, 0x69,
+	0x84, 0x63, 0xdc, 0x7f, 0x7b, 0x7e, 0x61, 0x1b, 0xf5, 0x85, 0x6d, 0xfc, 0xbe, 0xb4, 0x8d, 0xd3,
+	0xc6, 0x36, 0xbe, 0x37, 0x36, 0xa8, 0x1b, 0xdb, 0xf8, 0xd1, 0xd8, 0xc6, 0xc7, 0x07, 0xff, 0x31,
+	0x93, 0xfa, 0x01, 0xe2, 0x6d, 0x39, 0xd7, 0xb3, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xfb, 0xcb,
+	0x46, 0x92, 0x2c, 0x03, 0x00, 0x00,
+}
+
+func (m *ObservedFolder) ProtoSize() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Time)
+	n += 1 + l + sovObserved(uint64(l))
+	l = len(m.ID)
+	if l > 0 {
+		n += 1 + l + sovObserved(uint64(l))
+	}
+	l = len(m.Label)
+	if l > 0 {
+		n += 1 + l + sovObserved(uint64(l))
+	}
+	return n
+}
+
+func (m *ObservedDevice) ProtoSize() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Time)
+	n += 1 + l + sovObserved(uint64(l))
+	l = m.ID.ProtoSize()
+	n += 1 + l + sovObserved(uint64(l))
+	l = len(m.Name)
+	if l > 0 {
+		n += 1 + l + sovObserved(uint64(l))
+	}
+	l = len(m.Address)
+	if l > 0 {
+		n += 1 + l + sovObserved(uint64(l))
+	}
+	return n
+}
+
+func sovObserved(x uint64) (n int) {
+	return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozObserved(x uint64) (n int) {
+	return sovObserved(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}

+ 0 - 57
lib/config/optionsconfiguration.go

@@ -15,63 +15,6 @@ import (
 	"github.com/syncthing/syncthing/lib/util"
 	"github.com/syncthing/syncthing/lib/util"
 )
 )
 
 
-type OptionsConfiguration struct {
-	RawListenAddresses      []string `xml:"listenAddress" json:"listenAddresses" default:"default"`
-	RawGlobalAnnServers     []string `xml:"globalAnnounceServer" json:"globalAnnounceServers" default:"default"`
-	GlobalAnnEnabled        bool     `xml:"globalAnnounceEnabled" json:"globalAnnounceEnabled" default:"true"`
-	LocalAnnEnabled         bool     `xml:"localAnnounceEnabled" json:"localAnnounceEnabled" default:"true"`
-	LocalAnnPort            int      `xml:"localAnnouncePort" json:"localAnnouncePort" default:"21027"`
-	LocalAnnMCAddr          string   `xml:"localAnnounceMCAddr" json:"localAnnounceMCAddr" default:"[ff12::8384]:21027"`
-	MaxSendKbps             int      `xml:"maxSendKbps" json:"maxSendKbps"`
-	MaxRecvKbps             int      `xml:"maxRecvKbps" json:"maxRecvKbps"`
-	ReconnectIntervalS      int      `xml:"reconnectionIntervalS" json:"reconnectionIntervalS" default:"60"`
-	RelaysEnabled           bool     `xml:"relaysEnabled" json:"relaysEnabled" default:"true"`
-	RelayReconnectIntervalM int      `xml:"relayReconnectIntervalM" json:"relayReconnectIntervalM" default:"10"`
-	StartBrowser            bool     `xml:"startBrowser" json:"startBrowser" default:"true"`
-	NATEnabled              bool     `xml:"natEnabled" json:"natEnabled" default:"true"`
-	NATLeaseM               int      `xml:"natLeaseMinutes" json:"natLeaseMinutes" default:"60"`
-	NATRenewalM             int      `xml:"natRenewalMinutes" json:"natRenewalMinutes" default:"30"`
-	NATTimeoutS             int      `xml:"natTimeoutSeconds" json:"natTimeoutSeconds" default:"10"`
-	URAccepted              int      `xml:"urAccepted" json:"urAccepted"`                                    // Accepted usage reporting version; 0 for off (undecided), -1 for off (permanently)
-	URSeen                  int      `xml:"urSeen" json:"urSeen"`                                            // Report which the user has been prompted for.
-	URUniqueID              string   `xml:"urUniqueID" json:"urUniqueId"`                                    // Unique ID for reporting purposes, regenerated when UR is turned on.
-	URURL                   string   `xml:"urURL" json:"urURL" default:"https://data.syncthing.net/newdata"` // usage reporting URL
-	URPostInsecurely        bool     `xml:"urPostInsecurely" json:"urPostInsecurely" default:"false"`        // For testing
-	URInitialDelayS         int      `xml:"urInitialDelayS" json:"urInitialDelayS" default:"1800"`
-	RestartOnWakeup         bool     `xml:"restartOnWakeup" json:"restartOnWakeup" default:"true"`
-	AutoUpgradeIntervalH    int      `xml:"autoUpgradeIntervalH" json:"autoUpgradeIntervalH" default:"12"` // 0 for off
-	UpgradeToPreReleases    bool     `xml:"upgradeToPreReleases" json:"upgradeToPreReleases"`              // when auto upgrades are enabled
-	KeepTemporariesH        int      `xml:"keepTemporariesH" json:"keepTemporariesH" default:"24"`         // 0 for off
-	CacheIgnoredFiles       bool     `xml:"cacheIgnoredFiles" json:"cacheIgnoredFiles" default:"false"`
-	ProgressUpdateIntervalS int      `xml:"progressUpdateIntervalS" json:"progressUpdateIntervalS" default:"5"`
-	LimitBandwidthInLan     bool     `xml:"limitBandwidthInLan" json:"limitBandwidthInLan" default:"false"`
-	MinHomeDiskFree         Size     `xml:"minHomeDiskFree" json:"minHomeDiskFree" default:"1 %"`
-	ReleasesURL             string   `xml:"releasesURL" json:"releasesURL" default:"https://upgrades.syncthing.net/meta.json"`
-	AlwaysLocalNets         []string `xml:"alwaysLocalNet" json:"alwaysLocalNets"`
-	OverwriteRemoteDevNames bool     `xml:"overwriteRemoteDeviceNamesOnConnect" json:"overwriteRemoteDeviceNamesOnConnect" default:"false"`
-	TempIndexMinBlocks      int      `xml:"tempIndexMinBlocks" json:"tempIndexMinBlocks" default:"10"`
-	UnackedNotificationIDs  []string `xml:"unackedNotificationID" json:"unackedNotificationIDs"`
-	TrafficClass            int      `xml:"trafficClass" json:"trafficClass"`
-	DefaultFolderPath       string   `xml:"defaultFolderPath" json:"defaultFolderPath" default:"~"`
-	SetLowPriority          bool     `xml:"setLowPriority" json:"setLowPriority" default:"true"`
-	RawMaxFolderConcurrency int      `xml:"maxFolderConcurrency" json:"maxFolderConcurrency"`
-	CRURL                   string   `xml:"crashReportingURL" json:"crURL" default:"https://crash.syncthing.net/newcrash"` // crash reporting URL
-	CREnabled               bool     `xml:"crashReportingEnabled" json:"crashReportingEnabled" default:"true"`             // Read in the monitor, but it's read before every attempt to report stuff, so does not require a restart.
-	StunKeepaliveStartS     int      `xml:"stunKeepaliveStartS" json:"stunKeepaliveStartS" default:"180"`                  // 0 for off
-	StunKeepaliveMinS       int      `xml:"stunKeepaliveMinS" json:"stunKeepaliveMinS" default:"20"`                       // 0 for off
-	RawStunServers          []string `xml:"stunServer" json:"stunServers" default:"default"`
-	DatabaseTuning          Tuning   `xml:"databaseTuning" json:"databaseTuning" restart:"true"` // Can't be adjusted once the database has been opened
-	RawMaxCIRequestKiB      int      `xml:"maxConcurrentIncomingRequestKiB" json:"maxConcurrentIncomingRequestKiB"`
-
-	DeprecatedUPnPEnabled        bool     `xml:"upnpEnabled,omitempty" json:"-"`
-	DeprecatedUPnPLeaseM         int      `xml:"upnpLeaseMinutes,omitempty" json:"-"`
-	DeprecatedUPnPRenewalM       int      `xml:"upnpRenewalMinutes,omitempty" json:"-"`
-	DeprecatedUPnPTimeoutS       int      `xml:"upnpTimeoutSeconds,omitempty" json:"-"`
-	DeprecatedRelayServers       []string `xml:"relayServer,omitempty" json:"-"`
-	DeprecatedMinHomeDiskFreePct float64  `xml:"minHomeDiskFreePct,omitempty" json:"-"`
-	DeprecatedMaxConcurrentScans int      `xml:"maxConcurrentScans,omitempty" json:"-"`
-}
-
 func (opts OptionsConfiguration) Copy() OptionsConfiguration {
 func (opts OptionsConfiguration) Copy() OptionsConfiguration {
 	optsCopy := opts
 	optsCopy := opts
 	optsCopy.RawListenAddresses = make([]string, len(opts.RawListenAddresses))
 	optsCopy.RawListenAddresses = make([]string, len(opts.RawListenAddresses))

+ 502 - 0
lib/config/optionsconfiguration.pb.go

@@ -0,0 +1,502 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: lib/config/optionsconfiguration.proto
+
+package config
+
+import (
+	fmt "fmt"
+	proto "github.com/gogo/protobuf/proto"
+	_ "github.com/syncthing/syncthing/proto/ext"
+	math "math"
+	math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+type OptionsConfiguration struct {
+	RawListenAddresses      []string `protobuf:"bytes,1,rep,name=listen_addresses,json=listenAddresses,proto3" json:"listenAddresses" xml:"listenAddress" default:"default"`
+	RawGlobalAnnServers     []string `protobuf:"bytes,2,rep,name=global_discovery_servers,json=globalDiscoveryServers,proto3" json:"globalAnnounceServers" xml:"globalAnnounceServer" default:"default"`
+	GlobalAnnEnabled        bool     `protobuf:"varint,3,opt,name=global_discovery_enabled,json=globalDiscoveryEnabled,proto3" json:"globalAnnounceEnabled" xml:"globalAnnounceEnabled" default:"true"`
+	LocalAnnEnabled         bool     `protobuf:"varint,4,opt,name=local_discovery_enabled,json=localDiscoveryEnabled,proto3" json:"localAnnounceEnabled" xml:"localAnnounceEnabled" default:"true"`
+	LocalAnnPort            int      `protobuf:"varint,5,opt,name=local_announce_port,json=localAnnouncePort,proto3,casttype=int" json:"localAnnouncePort" xml:"localAnnouncePort" default:"21027"`
+	LocalAnnMCAddr          string   `protobuf:"bytes,6,opt,name=local_announce_multicast_address,json=localAnnounceMulticastAddress,proto3" json:"localAnnounceMCAddr" xml:"localAnnounceMCAddr" default:"[ff12::8384]:21027"`
+	MaxSendKbps             int      `protobuf:"varint,7,opt,name=max_send_kbps,json=maxSendKbps,proto3,casttype=int" json:"maxSendKbps" xml:"maxSendKbps"`
+	MaxRecvKbps             int      `protobuf:"varint,8,opt,name=max_recv_kbps,json=maxRecvKbps,proto3,casttype=int" json:"maxRecvKbps" xml:"maxRecvKbps"`
+	ReconnectIntervalS      int      `protobuf:"varint,9,opt,name=reconnection_interval_s,json=reconnectionIntervalS,proto3,casttype=int" json:"reconnectionIntervalS" xml:"reconnectionIntervalS" default:"60"`
+	RelaysEnabled           bool     `protobuf:"varint,10,opt,name=relays_enabled,json=relaysEnabled,proto3" json:"relaysEnabled" xml:"relaysEnabled" default:"true"`
+	RelayReconnectIntervalM int      `protobuf:"varint,11,opt,name=relays_reconnect_interval_m,json=relaysReconnectIntervalM,proto3,casttype=int" json:"relayReconnectIntervalM" xml:"relayReconnectIntervalM" default:"10"`
+	StartBrowser            bool     `protobuf:"varint,12,opt,name=start_browser,json=startBrowser,proto3" json:"startBrowser" xml:"startBrowser" default:"true"`
+	NATEnabled              bool     `protobuf:"varint,14,opt,name=nat_traversal_enabled,json=natTraversalEnabled,proto3" json:"natEnabled" xml:"natEnabled" default:"true"`
+	NATLeaseM               int      `protobuf:"varint,15,opt,name=nat_traversal_lease_m,json=natTraversalLeaseM,proto3,casttype=int" json:"natLeaseMinutes" xml:"natLeaseMinutes" default:"60"`
+	NATRenewalM             int      `protobuf:"varint,16,opt,name=nat_traversal_renewal_m,json=natTraversalRenewalM,proto3,casttype=int" json:"natRenewalMinutes" xml:"natRenewalMinutes" default:"30"`
+	NATTimeoutS             int      `protobuf:"varint,17,opt,name=nat_traversal_timeout_s,json=natTraversalTimeoutS,proto3,casttype=int" json:"natTimeoutSeconds" xml:"natTimeoutSeconds" default:"10"`
+	URAccepted              int      `protobuf:"varint,18,opt,name=usage_reporting_accepted,json=usageReportingAccepted,proto3,casttype=int" json:"urAccepted" xml:"urAccepted"`
+	URSeen                  int      `protobuf:"varint,19,opt,name=usage_reporting_seen,json=usageReportingSeen,proto3,casttype=int" json:"urSeen" xml:"urSeen"`
+	URUniqueID              string   `protobuf:"bytes,20,opt,name=usage_reporting_unique_id,json=usageReportingUniqueId,proto3" json:"urUniqueId" xml:"urUniqueID"`
+	URURL                   string   `protobuf:"bytes,21,opt,name=usage_reporting_url,json=usageReportingUrl,proto3" json:"urURL" xml:"urURL" default:"https://data.syncthing.net/newdata"`
+	URPostInsecurely        bool     `protobuf:"varint,22,opt,name=usage_reporting_post_insecurely,json=usageReportingPostInsecurely,proto3" json:"urPostInsecurely" xml:"urPostInsecurely" default:"false"`
+	URInitialDelayS         int      `protobuf:"varint,23,opt,name=usage_reporting_initial_delay_s,json=usageReportingInitialDelayS,proto3,casttype=int" json:"urInitialDelayS" xml:"urInitialDelayS" default:"1800"`
+	RestartOnWakeup         bool     `protobuf:"varint,24,opt,name=restart_on_wakeup,json=restartOnWakeup,proto3" json:"restartOnWakeup" xml:"restartOnWakeup" default:"true"`
+	AutoUpgradeIntervalH    int      `protobuf:"varint,25,opt,name=auto_upgrade_interval_h,json=autoUpgradeIntervalH,proto3,casttype=int" json:"autoUpgradeIntervalH" xml:"autoUpgradeIntervalH" default:"12"`
+	UpgradeToPreReleases    bool     `protobuf:"varint,26,opt,name=upgrade_to_pre_releases,json=upgradeToPreReleases,proto3" json:"upgradeToPreReleases" xml:"upgradeToPreReleases"`
+	KeepTemporariesH        int      `protobuf:"varint,27,opt,name=keep_temporaries_h,json=keepTemporariesH,proto3,casttype=int" json:"keepTemporariesH" xml:"keepTemporariesH" default:"24"`
+	CacheIgnoredFiles       bool     `protobuf:"varint,28,opt,name=cache_ignored_files,json=cacheIgnoredFiles,proto3" json:"cacheIgnoredFiles" xml:"cacheIgnoredFiles" default:"false"`
+	ProgressUpdateIntervalS int      `protobuf:"varint,29,opt,name=progress_update_interval_s,json=progressUpdateIntervalS,proto3,casttype=int" json:"progressUpdateIntervalS" xml:"progressUpdateIntervalS" default:"5"`
+	LimitBandwidthInLan     bool     `protobuf:"varint,30,opt,name=limit_bandwidth_in_lan,json=limitBandwidthInLan,proto3" json:"limitBandwidthInLan" xml:"limitBandwidthInLan" default:"false"`
+	MinHomeDiskFree         Size     `protobuf:"bytes,31,opt,name=min_home_disk_free,json=minHomeDiskFree,proto3" json:"minHomeDiskFree" xml:"minHomeDiskFree" default:"1 %"`
+	ReleasesURL             string   `protobuf:"bytes,32,opt,name=releases_url,json=releasesUrl,proto3" json:"releasesURL" xml:"releasesURL" default:"https://upgrades.syncthing.net/meta.json"`
+	AlwaysLocalNets         []string `protobuf:"bytes,33,rep,name=always_local_nets,json=alwaysLocalNets,proto3" json:"alwaysLocalNets" xml:"alwaysLocalNet"`
+	OverwriteRemoteDevNames bool     `protobuf:"varint,34,opt,name=overwrite_remote_device_names_on_connect,json=overwriteRemoteDeviceNamesOnConnect,proto3" json:"overwriteRemoteDeviceNamesOnConnect" xml:"overwriteRemoteDeviceNamesOnConnect" default:"false"`
+	TempIndexMinBlocks      int      `protobuf:"varint,35,opt,name=temp_index_min_blocks,json=tempIndexMinBlocks,proto3,casttype=int" json:"tempIndexMinBlocks" xml:"tempIndexMinBlocks" default:"10"`
+	UnackedNotificationIDs  []string `protobuf:"bytes,36,rep,name=unacked_notification_ids,json=unackedNotificationIds,proto3" json:"unackedNotificationIDs" xml:"unackedNotificationID"`
+	TrafficClass            int      `protobuf:"varint,37,opt,name=traffic_class,json=trafficClass,proto3,casttype=int" json:"trafficClass" xml:"trafficClass"`
+	DefaultFolderPath       string   `protobuf:"bytes,38,opt,name=default_folder_path,json=defaultFolderPath,proto3" json:"defaultFolderPath" xml:"defaultFolderPath" default:"~"`
+	SetLowPriority          bool     `protobuf:"varint,39,opt,name=set_low_priority,json=setLowPriority,proto3" json:"setLowPriority" xml:"setLowPriority" default:"true"`
+	RawMaxFolderConcurrency int      `protobuf:"varint,40,opt,name=max_folder_concurrency,json=maxFolderConcurrency,proto3,casttype=int" json:"maxFolderConcurrency" xml:"maxFolderConcurrency"`
+	CRURL                   string   `protobuf:"bytes,41,opt,name=crash_reporting_url,json=crashReportingUrl,proto3" json:"crURL" xml:"crashReportingURL" default:"https://crash.syncthing.net/newcrash"`
+	CREnabled               bool     `protobuf:"varint,42,opt,name=crash_reporting_enabled,json=crashReportingEnabled,proto3" json:"crashReportingEnabled" xml:"crashReportingEnabled" default:"true"`
+	StunKeepaliveStartS     int      `protobuf:"varint,43,opt,name=stun_keepalive_start_s,json=stunKeepaliveStartS,proto3,casttype=int" json:"stunKeepaliveStartS" xml:"stunKeepaliveStartS" default:"180"`
+	StunKeepaliveMinS       int      `protobuf:"varint,44,opt,name=stun_keepalive_min_s,json=stunKeepaliveMinS,proto3,casttype=int" json:"stunKeepaliveMinS" xml:"stunKeepaliveMinS" default:"20"`
+	RawStunServers          []string `protobuf:"bytes,45,rep,name=stun_servers,json=stunServers,proto3" json:"stunServers" xml:"stunServer" default:"default"`
+	DatabaseTuning          Tuning   `protobuf:"varint,46,opt,name=database_tuning,json=databaseTuning,proto3,enum=config.Tuning" json:"databaseTuning" xml:"databaseTuning" restart:"true"`
+	RawMaxCIRequestKiB      int      `protobuf:"varint,47,opt,name=max_concurrent_incoming_request_kib,json=maxConcurrentIncomingRequestKib,proto3,casttype=int" json:"maxConcurrentIncomingRequestKiB" xml:"maxConcurrentIncomingRequestKiB"`
+	// Legacy deprecated
+	DeprecatedUPnPEnabled        bool     `protobuf:"varint,9000,opt,name=upnp_enabled,json=upnpEnabled,proto3" json:"-" xml:"upnpEnabled,omitempty"`                                    // Deprecated: Do not use.
+	DeprecatedUPnPLeaseM         int      `protobuf:"varint,9001,opt,name=upnp_lease_m,json=upnpLeaseM,proto3,casttype=int" json:"-" xml:"upnpLeaseMinutes,omitempty"`                   // Deprecated: Do not use.
+	DeprecatedUPnPRenewalM       int      `protobuf:"varint,9002,opt,name=upnp_renewal_m,json=upnpRenewalM,proto3,casttype=int" json:"-" xml:"upnpRenewalMinutes,omitempty"`             // Deprecated: Do not use.
+	DeprecatedUPnPTimeoutS       int      `protobuf:"varint,9003,opt,name=upnp_timeout_s,json=upnpTimeoutS,proto3,casttype=int" json:"-" xml:"upnpTimeoutSeconds,omitempty"`             // Deprecated: Do not use.
+	DeprecatedRelayServers       []string `protobuf:"bytes,9004,rep,name=relay_servers,json=relayServers,proto3" json:"-" xml:"relayServer,omitempty"`                                   // Deprecated: Do not use.
+	DeprecatedMinHomeDiskFreePct float64  `protobuf:"fixed64,9005,opt,name=min_home_disk_free_pct,json=minHomeDiskFreePct,proto3" json:"-" xml:"minHomeDiskFreePct,omitempty"`           // Deprecated: Do not use.
+	DeprecatedMaxConcurrentScans int      `protobuf:"varint,9006,opt,name=max_concurrent_scans,json=maxConcurrentScans,proto3,casttype=int" json:"-" xml:"maxConcurrentScans,omitempty"` // Deprecated: Do not use.
+}
+
+func (m *OptionsConfiguration) Reset()         { *m = OptionsConfiguration{} }
+func (m *OptionsConfiguration) String() string { return proto.CompactTextString(m) }
+func (*OptionsConfiguration) ProtoMessage()    {}
+func (*OptionsConfiguration) Descriptor() ([]byte, []int) {
+	return fileDescriptor_d09882599506ca03, []int{0}
+}
+func (m *OptionsConfiguration) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_OptionsConfiguration.Unmarshal(m, b)
+}
+func (m *OptionsConfiguration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_OptionsConfiguration.Marshal(b, m, deterministic)
+}
+func (m *OptionsConfiguration) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_OptionsConfiguration.Merge(m, src)
+}
+func (m *OptionsConfiguration) XXX_Size() int {
+	return xxx_messageInfo_OptionsConfiguration.Size(m)
+}
+func (m *OptionsConfiguration) XXX_DiscardUnknown() {
+	xxx_messageInfo_OptionsConfiguration.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_OptionsConfiguration proto.InternalMessageInfo
+
+func init() {
+	proto.RegisterType((*OptionsConfiguration)(nil), "config.OptionsConfiguration")
+}
+
+func init() {
+	proto.RegisterFile("lib/config/optionsconfiguration.proto", fileDescriptor_d09882599506ca03)
+}
+
+var fileDescriptor_d09882599506ca03 = []byte{
+	// 3006 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x5a, 0x5b, 0x6c, 0x24, 0x47,
+	0xd5, 0x76, 0xef, 0x66, 0x37, 0xd9, 0xb6, 0xd7, 0x5e, 0xb7, 0x6f, 0x9d, 0xdd, 0x8d, 0xdb, 0x99,
+	0x9d, 0x4d, 0x9c, 0x9b, 0x6f, 0x9b, 0xec, 0xbf, 0xff, 0x4a, 0xbf, 0x7e, 0x7c, 0x89, 0x13, 0x13,
+	0x7b, 0xd7, 0x2a, 0xdb, 0x0a, 0x0a, 0x42, 0xad, 0x9a, 0x9e, 0xb2, 0xdd, 0xb8, 0xa7, 0x7a, 0xb6,
+	0xab, 0xda, 0x97, 0x80, 0x42, 0x14, 0xc4, 0xe5, 0x0d, 0xb0, 0xb8, 0x48, 0x20, 0xa1, 0x20, 0x40,
+	0x22, 0x04, 0x10, 0x12, 0x12, 0x12, 0x48, 0x08, 0x84, 0x84, 0x14, 0xc1, 0x83, 0xfd, 0x88, 0x44,
+	0x68, 0x14, 0x2f, 0x0f, 0x68, 0x1e, 0x78, 0x98, 0x47, 0xf3, 0x82, 0x4e, 0xf5, 0xad, 0xfa, 0x32,
+	0xd9, 0x7d, 0x9b, 0x3a, 0xdf, 0xa9, 0x53, 0xdf, 0x39, 0x55, 0x75, 0xaa, 0x4e, 0xf5, 0xa8, 0xd7,
+	0x1d, 0xbb, 0x36, 0x69, 0xb9, 0x74, 0xd3, 0xde, 0x9a, 0x74, 0x9b, 0xdc, 0x76, 0x29, 0x0b, 0x5b,
+	0xbe, 0x87, 0xa1, 0x35, 0xd1, 0xf4, 0x5c, 0xee, 0x6a, 0xe7, 0x43, 0xe1, 0xe5, 0x11, 0x49, 0x9d,
+	0xfb, 0xd4, 0xa6, 0x5b, 0xa1, 0xc2, 0xe5, 0x21, 0x09, 0x60, 0xf6, 0x9b, 0x24, 0x12, 0x5f, 0x20,
+	0xfb, 0x3c, 0xfc, 0x59, 0xf9, 0xdd, 0xbc, 0x3a, 0x78, 0x37, 0x1c, 0x61, 0x5e, 0x1e, 0x41, 0xfb,
+	0xbe, 0xa2, 0x5e, 0x72, 0x6c, 0xc6, 0x09, 0x35, 0x71, 0xbd, 0xee, 0x11, 0xc6, 0x08, 0xd3, 0x95,
+	0xb1, 0xb3, 0xe3, 0x17, 0xe6, 0xd8, 0x49, 0x60, 0x68, 0x08, 0xef, 0x2d, 0x0b, 0x78, 0x36, 0x46,
+	0x5b, 0x81, 0xd1, 0xe7, 0x64, 0x45, 0xed, 0xc0, 0xb8, 0xbe, 0xdf, 0x70, 0x6e, 0x57, 0x32, 0xf2,
+	0xca, 0x58, 0x9d, 0x6c, 0x62, 0xdf, 0xe1, 0xb7, 0x2b, 0xd1, 0x8f, 0xca, 0xe9, 0x51, 0xf5, 0xd1,
+	0xe8, 0xf7, 0xe1, 0x71, 0xb5, 0xc4, 0x38, 0xca, 0x9b, 0xd6, 0xfe, 0xad, 0xa8, 0xfa, 0x96, 0xe3,
+	0xd6, 0xb0, 0x63, 0xd6, 0x6d, 0x66, 0xb9, 0xbb, 0xc4, 0x3b, 0x30, 0x19, 0xf1, 0x76, 0x89, 0xc7,
+	0xf4, 0x33, 0x82, 0xe8, 0xaf, 0x94, 0x93, 0xc0, 0x18, 0x40, 0x78, 0xef, 0x15, 0xa1, 0x37, 0x4b,
+	0xe9, 0x5a, 0x88, 0xb7, 0x02, 0x63, 0x68, 0x2b, 0x96, 0xb9, 0x3e, 0xb5, 0x48, 0x04, 0xb4, 0x03,
+	0xe3, 0x79, 0x41, 0xb8, 0x0c, 0x2d, 0xe1, 0xdd, 0x3a, 0xaa, 0x0e, 0x96, 0xa9, 0xb6, 0x8f, 0xaa,
+	0xe5, 0x03, 0x64, 0x1d, 0x2d, 0xe3, 0x86, 0x86, 0xc3, 0x8e, 0x0b, 0xb1, 0x53, 0x91, 0x5c, 0xfb,
+	0x67, 0x99, 0xc3, 0x84, 0xe2, 0x9a, 0x43, 0xea, 0xfa, 0xd9, 0x31, 0x65, 0xfc, 0xb1, 0xb9, 0xf7,
+	0xc0, 0xe1, 0x4b, 0x89, 0xc5, 0x97, 0x43, 0xb0, 0xe8, 0x6d, 0x04, 0xb4, 0x03, 0xe3, 0xd9, 0x12,
+	0x6f, 0x23, 0x54, 0x72, 0x97, 0x7b, 0x3e, 0x01, 0x5f, 0x3b, 0x98, 0xe9, 0x04, 0x9c, 0x1e, 0x55,
+	0x1f, 0x81, 0xae, 0x87, 0xc7, 0xd5, 0x02, 0xa9, 0x82, 0x9b, 0x91, 0x5c, 0xfb, 0x50, 0x51, 0x47,
+	0x1c, 0xd7, 0x2a, 0xf5, 0xf2, 0x11, 0xe1, 0xe5, 0x0f, 0xc1, 0xcb, 0xbe, 0x65, 0xd0, 0xc9, 0x38,
+	0x39, 0xe8, 0x44, 0xa2, 0x9c, 0x8f, 0xcf, 0x84, 0x4b, 0xb0, 0x04, 0x2c, 0x71, 0xb1, 0xdc, 0x48,
+	0x07, 0xb9, 0xe4, 0x60, 0x9e, 0x0f, 0x1a, 0x12, 0x1d, 0x0a, 0xee, 0xfd, 0x45, 0x51, 0x07, 0x42,
+	0xf7, 0x70, 0x64, 0xcb, 0x6c, 0xba, 0x1e, 0xd7, 0xcf, 0x8d, 0x29, 0xe3, 0xe7, 0xe6, 0xbe, 0x0b,
+	0xae, 0xf5, 0xc4, 0xa6, 0x56, 0x5d, 0x8f, 0xb7, 0x02, 0xa3, 0x3f, 0x33, 0x34, 0x08, 0xdb, 0x81,
+	0xf1, 0x74, 0xd1, 0x29, 0x40, 0x24, 0x8f, 0x66, 0xa6, 0xa7, 0x66, 0xfe, 0xa7, 0x72, 0x1a, 0x18,
+	0x67, 0x6d, 0xca, 0x5b, 0x47, 0xd5, 0x12, 0x33, 0x65, 0xc2, 0xd3, 0xa3, 0xea, 0x39, 0xd1, 0xf5,
+	0xf0, 0xb8, 0x9a, 0x61, 0x82, 0x8a, 0xba, 0xda, 0x17, 0xcf, 0xa8, 0x63, 0x39, 0x6f, 0x1a, 0xbe,
+	0xc3, 0x6d, 0x0b, 0x33, 0x1e, 0xe7, 0x0d, 0xfd, 0xfc, 0x98, 0x32, 0x7e, 0x61, 0xee, 0x37, 0xe0,
+	0x5a, 0x6f, 0x6c, 0x70, 0x65, 0x1e, 0x76, 0x72, 0x2b, 0x30, 0x06, 0x32, 0x46, 0x43, 0x71, 0x3b,
+	0x30, 0x6e, 0x16, 0xdd, 0x0b, 0x31, 0xc9, 0xc1, 0x4f, 0x6f, 0x6e, 0x4e, 0xcf, 0xdc, 0xbe, 0x7d,
+	0xeb, 0xc6, 0xad, 0x17, 0x3f, 0x73, 0x3b, 0xf4, 0xb6, 0x75, 0x54, 0x2d, 0x35, 0x58, 0x2e, 0x3e,
+	0x3d, 0xaa, 0x6a, 0x45, 0x23, 0x87, 0xc7, 0xd5, 0x1c, 0x4d, 0xf4, 0x44, 0xb6, 0x73, 0xec, 0x61,
+	0x94, 0x8c, 0xb4, 0xbb, 0xea, 0xc5, 0x06, 0xde, 0x37, 0x19, 0xa1, 0x75, 0x73, 0xa7, 0xd6, 0x64,
+	0xfa, 0xa3, 0x62, 0x32, 0x9f, 0x6b, 0x05, 0x46, 0x77, 0x03, 0xef, 0xaf, 0x11, 0x5a, 0x7f, 0xad,
+	0xd6, 0x84, 0xe4, 0xd2, 0x2f, 0xdc, 0x92, 0x64, 0xf1, 0xfc, 0x20, 0x59, 0x31, 0x36, 0xe8, 0x11,
+	0x6b, 0x37, 0x34, 0xf8, 0x58, 0xc6, 0x20, 0x22, 0xd6, 0x6e, 0xde, 0x60, 0x2c, 0xcb, 0x18, 0x8c,
+	0x85, 0xda, 0xaf, 0x15, 0x75, 0xc4, 0x23, 0x96, 0x4b, 0x29, 0xb1, 0x20, 0xbd, 0x9b, 0x36, 0xe5,
+	0xc4, 0xdb, 0xc5, 0x8e, 0xc9, 0xf4, 0x0b, 0xc2, 0xf6, 0x5b, 0x22, 0xa9, 0xc7, 0x2a, 0x4b, 0x11,
+	0xbc, 0x06, 0xb9, 0x43, 0xee, 0x98, 0x00, 0xed, 0xc0, 0x18, 0x17, 0x63, 0x97, 0xa2, 0xd2, 0x2c,
+	0xdd, 0x9c, 0x8a, 0x29, 0x9d, 0x1e, 0x55, 0xcf, 0xdc, 0x9c, 0x12, 0xf9, 0xbd, 0x30, 0x0e, 0x2a,
+	0x1f, 0x45, 0xdb, 0x54, 0x7b, 0x3d, 0xe2, 0xe0, 0x03, 0x96, 0xe4, 0x00, 0x55, 0xe4, 0x80, 0xff,
+	0x6f, 0x05, 0xc6, 0xc5, 0x10, 0x49, 0x37, 0x7a, 0x25, 0x22, 0x24, 0x49, 0xf3, 0x3b, 0x3c, 0xde,
+	0xb1, 0x28, 0xdb, 0x59, 0x7b, 0xe7, 0x8c, 0x7a, 0x25, 0x1a, 0x28, 0x21, 0x92, 0x06, 0xa9, 0xa1,
+	0x77, 0x8b, 0x20, 0xfd, 0x11, 0xd6, 0xf0, 0x08, 0x02, 0xbd, 0x82, 0x0b, 0x2b, 0xad, 0xc0, 0x18,
+	0xf1, 0xca, 0xa1, 0x24, 0xd1, 0x76, 0xc0, 0x25, 0x96, 0xd3, 0x53, 0xd2, 0x96, 0xed, 0x68, 0xaf,
+	0x33, 0x04, 0x41, 0x9e, 0x86, 0x20, 0x77, 0xa2, 0x89, 0xf4, 0xd0, 0xcf, 0x22, 0xa2, 0xd5, 0xd4,
+	0x8b, 0x8c, 0x63, 0x8f, 0x9b, 0x35, 0xcf, 0xdd, 0x63, 0xc4, 0xd3, 0x7b, 0x44, 0xac, 0xff, 0xaf,
+	0x15, 0x18, 0x3d, 0x02, 0x98, 0x0b, 0xe5, 0xed, 0xc0, 0x78, 0x52, 0xb8, 0x23, 0x0b, 0x3b, 0x46,
+	0x3a, 0xd3, 0x55, 0xfb, 0xb1, 0xa2, 0x0e, 0x51, 0xcc, 0x4d, 0xee, 0x61, 0x38, 0xd5, 0xb0, 0x93,
+	0x4c, 0x6c, 0xaf, 0x18, 0xec, 0xde, 0x49, 0x60, 0xa8, 0x77, 0x66, 0xd7, 0xd3, 0xb4, 0xae, 0x52,
+	0xcc, 0xd3, 0x39, 0x36, 0xc4, 0xc0, 0xa9, 0xa8, 0x24, 0x85, 0xcb, 0x1d, 0x32, 0x2d, 0x29, 0x5d,
+	0x4b, 0x43, 0xa0, 0x01, 0x8a, 0xf9, 0x7a, 0x4c, 0x27, 0x5e, 0x10, 0xbf, 0x2d, 0xf0, 0x74, 0x08,
+	0x66, 0xc4, 0x6c, 0xe8, 0x7d, 0x62, 0x29, 0x7c, 0x19, 0x96, 0xc2, 0x85, 0x3b, 0xb3, 0xeb, 0xcb,
+	0x20, 0x86, 0xc9, 0xef, 0xa3, 0x98, 0x87, 0x0d, 0x9b, 0xfa, 0x5c, 0x5c, 0x7e, 0x2a, 0x31, 0x59,
+	0x59, 0x5e, 0xba, 0x37, 0x5a, 0x47, 0xd5, 0x42, 0xff, 0xa2, 0x28, 0xd9, 0x41, 0xe9, 0xc0, 0x48,
+	0x93, 0xd9, 0x87, 0x32, 0xed, 0xcf, 0x8a, 0x3a, 0x92, 0x25, 0xef, 0x11, 0x4a, 0xf6, 0xc4, 0x4a,
+	0xbe, 0x24, 0xe8, 0x1f, 0x02, 0xfd, 0xee, 0x3b, 0xb3, 0xeb, 0x28, 0x04, 0xc0, 0x81, 0x7e, 0x8a,
+	0x79, 0xdc, 0x4c, 0x5c, 0xa8, 0xc6, 0x2e, 0x64, 0x11, 0xc9, 0x89, 0x1b, 0xb2, 0x13, 0x25, 0x36,
+	0xca, 0x84, 0xe0, 0xc8, 0x0d, 0x70, 0x44, 0xa6, 0x80, 0x06, 0x65, 0x57, 0x62, 0x69, 0x89, 0x33,
+	0xdc, 0x6e, 0x10, 0xd7, 0xe7, 0x26, 0xd3, 0xfb, 0xb3, 0xce, 0xac, 0x87, 0xc0, 0x5a, 0xe4, 0x4c,
+	0xdc, 0x84, 0x95, 0x5e, 0xcf, 0x38, 0x93, 0x45, 0x3a, 0x6d, 0xbf, 0x12, 0x1b, 0x65, 0xc2, 0x64,
+	0xcb, 0xc9, 0x14, 0xb2, 0xce, 0xc4, 0x52, 0xed, 0x7b, 0x8a, 0xaa, 0xfb, 0x0c, 0x6f, 0x11, 0xd3,
+	0x23, 0x70, 0xee, 0xdb, 0x74, 0xcb, 0xc4, 0x96, 0x45, 0x9a, 0x9c, 0xd4, 0x75, 0x4d, 0x78, 0x83,
+	0x61, 0x07, 0x6c, 0xa0, 0xd9, 0x48, 0x0a, 0x3b, 0xc0, 0xf7, 0xe2, 0x56, 0x3b, 0x30, 0x2e, 0x09,
+	0x27, 0x52, 0x91, 0x44, 0x58, 0x56, 0xcc, 0xb4, 0x60, 0xc5, 0xa7, 0x26, 0xd1, 0xb0, 0xa0, 0x80,
+	0x62, 0x06, 0xb1, 0x5c, 0xfb, 0x9c, 0x3a, 0x98, 0x27, 0xc7, 0x08, 0xa1, 0xfa, 0x80, 0x20, 0xb6,
+	0x74, 0x12, 0x18, 0xe7, 0x37, 0xd0, 0x1a, 0x21, 0xb4, 0x15, 0x18, 0xe7, 0x7d, 0x0f, 0x7e, 0xb5,
+	0x03, 0xa3, 0x27, 0x22, 0x04, 0x4d, 0x89, 0x4c, 0xac, 0x90, 0xfc, 0x3a, 0x3c, 0xae, 0x46, 0xdd,
+	0x91, 0x96, 0x25, 0x00, 0x32, 0xed, 0x5b, 0x8a, 0xfa, 0x78, 0x7e, 0x74, 0x9f, 0xda, 0xf7, 0x7c,
+	0x62, 0xda, 0x75, 0x7d, 0x50, 0x5c, 0x22, 0xde, 0x08, 0x63, 0xb3, 0x21, 0xc4, 0x4b, 0x0b, 0x61,
+	0x6c, 0xa2, 0x96, 0x1c, 0x9b, 0x58, 0xa1, 0x12, 0x06, 0x25, 0x6e, 0xb6, 0xe5, 0x56, 0x14, 0x94,
+	0x18, 0xcb, 0x07, 0x25, 0xd6, 0xd2, 0xfe, 0xa0, 0xa8, 0x03, 0x05, 0x5e, 0x9e, 0xa3, 0x0f, 0x09,
+	0x46, 0x5f, 0x83, 0xb5, 0x77, 0x6e, 0x03, 0x6d, 0xa0, 0xe5, 0x56, 0x60, 0x9c, 0xf3, 0xbd, 0x0d,
+	0xb4, 0xdc, 0x0e, 0x8c, 0x5b, 0x31, 0x11, 0xb4, 0x2c, 0xad, 0xae, 0x6d, 0xce, 0x9b, 0xec, 0xf6,
+	0xe4, 0x64, 0x1d, 0x73, 0x3c, 0xc1, 0x0e, 0xa8, 0xc5, 0xb7, 0xa1, 0x58, 0xa3, 0x84, 0x4f, 0x52,
+	0xb2, 0x07, 0x52, 0x20, 0x1c, 0x19, 0x89, 0x7f, 0x9c, 0x1e, 0x55, 0x1f, 0xa2, 0xe3, 0xe1, 0x71,
+	0x35, 0x64, 0x81, 0xfa, 0x73, 0x7e, 0x78, 0x8e, 0xf6, 0x0f, 0x45, 0x35, 0xf2, 0x2e, 0x34, 0x5d,
+	0x06, 0x27, 0x1c, 0x23, 0x96, 0xef, 0x11, 0xe7, 0x40, 0x1f, 0x16, 0xe9, 0xf7, 0x3b, 0xa2, 0x82,
+	0xd8, 0x40, 0xab, 0x2e, 0xe3, 0x4b, 0x09, 0xd8, 0x0a, 0x8c, 0x4b, 0xbe, 0x97, 0x95, 0xb5, 0x03,
+	0xe3, 0xa9, 0xc8, 0xc9, 0x2c, 0x20, 0xf9, 0xbb, 0x89, 0x1d, 0x26, 0x52, 0x72, 0xb1, 0x77, 0x89,
+	0x0c, 0x6e, 0x9e, 0xa2, 0x07, 0xd4, 0x0b, 0x79, 0x0a, 0xe8, 0x6a, 0xd6, 0xad, 0x2c, 0xaa, 0xfd,
+	0xbd, 0xc4, 0x43, 0x9b, 0xda, 0xdc, 0x86, 0x3a, 0x02, 0xce, 0x3b, 0x93, 0xe9, 0x23, 0x62, 0x15,
+	0x7f, 0x5b, 0x54, 0x0f, 0x1b, 0x68, 0x29, 0x44, 0x17, 0x00, 0x84, 0x84, 0xd1, 0xe7, 0x7b, 0x19,
+	0x51, 0x92, 0x2e, 0x72, 0x72, 0x39, 0x59, 0xdc, 0x9a, 0xca, 0x24, 0xf0, 0xbc, 0x85, 0xa2, 0x08,
+	0x4e, 0x20, 0xe8, 0x05, 0x05, 0x43, 0x8e, 0x02, 0xba, 0x92, 0x75, 0x30, 0x03, 0x6a, 0xae, 0xda,
+	0xef, 0x91, 0xf0, 0x70, 0x76, 0xa9, 0xb9, 0x87, 0x77, 0x88, 0xdf, 0xd4, 0x75, 0x31, 0x65, 0xf3,
+	0x40, 0x3e, 0x02, 0xef, 0xd2, 0xd7, 0x05, 0x94, 0x90, 0xcf, 0xc9, 0x3b, 0x1e, 0xd2, 0x79, 0x03,
+	0xda, 0x57, 0x14, 0x75, 0x04, 0xfb, 0xdc, 0x35, 0xfd, 0xe6, 0x96, 0x87, 0xeb, 0x24, 0xbd, 0x0c,
+	0x6d, 0xeb, 0x8f, 0x8b, 0x40, 0xae, 0x42, 0xc9, 0x05, 0x2a, 0x1b, 0xa1, 0x46, 0x7c, 0x8f, 0x78,
+	0x35, 0xa9, 0x4e, 0xca, 0x40, 0x39, 0x7c, 0x33, 0xf2, 0xcd, 0x70, 0x7a, 0x06, 0x95, 0x5a, 0xd3,
+	0x1a, 0xea, 0x48, 0xcc, 0x81, 0xbb, 0x66, 0xd3, 0x83, 0x29, 0x16, 0x67, 0x31, 0xd3, 0x2f, 0x8b,
+	0x00, 0xdc, 0x04, 0x22, 0x91, 0xca, 0xba, 0xbb, 0xea, 0x11, 0x14, 0xe1, 0xed, 0xc0, 0xb8, 0x1c,
+	0x4e, 0x61, 0x09, 0x58, 0x41, 0xa5, 0x7d, 0xb4, 0x5d, 0x55, 0xdb, 0x21, 0xa4, 0x69, 0x72, 0xd2,
+	0x68, 0xba, 0x1e, 0xf6, 0x6c, 0xc2, 0xcc, 0x6d, 0xfd, 0x8a, 0x70, 0xf9, 0x55, 0xd8, 0x08, 0x80,
+	0xae, 0xa7, 0x20, 0xb8, 0x7b, 0x4d, 0x8c, 0x92, 0x07, 0xe4, 0x5a, 0xec, 0x45, 0xd9, 0xd5, 0x99,
+	0x17, 0x51, 0xc1, 0x8a, 0x76, 0xa0, 0x0e, 0x58, 0xd8, 0xda, 0x26, 0xa6, 0xbd, 0x45, 0x5d, 0x8f,
+	0xd4, 0xcd, 0x4d, 0xdb, 0x21, 0x4c, 0xbf, 0x2a, 0x5c, 0x5c, 0x82, 0x13, 0x4d, 0xc0, 0x4b, 0x21,
+	0xba, 0x08, 0x60, 0x12, 0xe8, 0x02, 0x52, 0xd8, 0x83, 0xc9, 0xde, 0x42, 0x45, 0x33, 0xda, 0x37,
+	0x14, 0xf5, 0x72, 0xd3, 0x73, 0xb7, 0xa0, 0x98, 0x31, 0xfd, 0x66, 0x1d, 0x73, 0x22, 0x17, 0x08,
+	0x4f, 0x08, 0xdf, 0xd7, 0xe1, 0x7e, 0x1b, 0x6b, 0x6d, 0x08, 0x25, 0xb9, 0x18, 0x08, 0x8b, 0xec,
+	0x0e, 0xb8, 0x44, 0xe7, 0x25, 0x29, 0x10, 0xca, 0x4b, 0xa8, 0x93, 0x45, 0xed, 0x1d, 0x45, 0x1d,
+	0x76, 0xec, 0x86, 0xcd, 0xcd, 0x1a, 0xa6, 0xf5, 0x3d, 0xbb, 0xce, 0xb7, 0x4d, 0x9b, 0x9a, 0x0e,
+	0xa6, 0xfa, 0xa8, 0x08, 0xc9, 0x8a, 0x28, 0x1e, 0x41, 0x63, 0x2e, 0x56, 0x58, 0xa2, 0xcb, 0x98,
+	0xa6, 0x05, 0x7f, 0x11, 0xfb, 0x98, 0xb0, 0x94, 0x99, 0xd2, 0xde, 0x56, 0x54, 0xad, 0x61, 0x53,
+	0x73, 0xdb, 0x6d, 0x10, 0xb3, 0x6e, 0xb3, 0x1d, 0x73, 0xd3, 0x23, 0x44, 0x37, 0xc6, 0x94, 0xf1,
+	0xee, 0x99, 0x9e, 0x89, 0xf0, 0x65, 0x6d, 0x62, 0xcd, 0x7e, 0x93, 0xcc, 0xbd, 0xfc, 0x41, 0x60,
+	0x74, 0xc1, 0x4e, 0x6c, 0xd8, 0xf4, 0x55, 0xb7, 0x41, 0x16, 0x6c, 0xb6, 0xb3, 0xe8, 0x11, 0x92,
+	0xac, 0x8e, 0x9c, 0x5c, 0xde, 0x07, 0x63, 0xd7, 0x81, 0xc8, 0xd9, 0xe9, 0xb1, 0xeb, 0x28, 0xdf,
+	0x5d, 0xbb, 0xaf, 0xa8, 0x3d, 0xf1, 0x7a, 0x17, 0xc7, 0xce, 0x98, 0x38, 0x76, 0x7e, 0x2f, 0xae,
+	0x3c, 0xf1, 0xa2, 0x0d, 0x0f, 0x9f, 0x6e, 0x2f, 0x6d, 0xb6, 0x03, 0x63, 0x21, 0xae, 0x38, 0x62,
+	0x59, 0xc9, 0x41, 0x14, 0xed, 0x00, 0x96, 0x3b, 0x53, 0x1a, 0x84, 0xe3, 0x89, 0xcf, 0x32, 0x97,
+	0x42, 0xee, 0xce, 0x98, 0xcd, 0x36, 0x4f, 0x8f, 0xaa, 0xe3, 0x0f, 0x6b, 0x0a, 0xee, 0x47, 0x12,
+	0x5f, 0x94, 0xda, 0xf1, 0x1c, 0xed, 0x75, 0xb5, 0x1f, 0x3b, 0x7b, 0x50, 0x7d, 0x85, 0xaf, 0x09,
+	0x94, 0x70, 0xa6, 0x3f, 0x29, 0x1e, 0xf1, 0xa0, 0xe8, 0xed, 0x0b, 0x41, 0x51, 0x95, 0xdf, 0x21,
+	0x1c, 0x16, 0xfe, 0x60, 0x98, 0x61, 0x32, 0xf2, 0x0a, 0xca, 0x2b, 0x6a, 0xff, 0x51, 0xd4, 0x71,
+	0x77, 0x97, 0x78, 0x7b, 0x9e, 0xcd, 0x21, 0x71, 0x34, 0x5c, 0x4e, 0xcc, 0x3a, 0xd9, 0xb5, 0x2d,
+	0x62, 0x52, 0xdc, 0x20, 0x0c, 0xd2, 0x69, 0x54, 0x08, 0xe9, 0x95, 0xf4, 0x79, 0x69, 0xe4, 0x6e,
+	0xdc, 0x09, 0x89, 0x3e, 0x0b, 0x64, 0xf7, 0x0e, 0xa8, 0xb7, 0x02, 0xe3, 0x9a, 0x5b, 0x80, 0x6c,
+	0x8b, 0x08, 0xf4, 0x2e, 0x9d, 0x0f, 0x4d, 0xb5, 0x03, 0xe3, 0x7f, 0x05, 0xc1, 0x87, 0xd0, 0xed,
+	0xbc, 0x28, 0xa1, 0x8a, 0xeb, 0xc0, 0x03, 0x3d, 0x0c, 0x0b, 0xed, 0x0b, 0xea, 0x10, 0xa4, 0x31,
+	0xd3, 0xa6, 0x75, 0xb2, 0x6f, 0xc2, 0x4a, 0xae, 0x39, 0xae, 0xb5, 0xc3, 0xf4, 0x6b, 0x62, 0x4b,
+	0xc3, 0xa2, 0xd1, 0x40, 0x61, 0x09, 0xf0, 0x15, 0x9b, 0xce, 0x09, 0x34, 0x79, 0xb5, 0x2d, 0x42,
+	0xa5, 0x37, 0xe5, 0xf0, 0xfe, 0x8b, 0x4a, 0x2c, 0x69, 0x7f, 0x83, 0xeb, 0x2e, 0xc5, 0xd6, 0x0e,
+	0xa9, 0x9b, 0xd4, 0xe5, 0xf6, 0xa6, 0x6d, 0xe1, 0xf0, 0xfd, 0xa1, 0xce, 0xf4, 0xaa, 0x98, 0xdf,
+	0x77, 0x21, 0xdc, 0xc3, 0x1b, 0xa1, 0xd2, 0x1d, 0x49, 0x67, 0x69, 0x01, 0xa2, 0x3d, 0xec, 0x97,
+	0x22, 0xed, 0xc0, 0xb8, 0x12, 0xa6, 0xf6, 0x32, 0x58, 0xbc, 0x55, 0x96, 0x22, 0xed, 0xa3, 0x6a,
+	0x07, 0x8b, 0x87, 0xc7, 0xd5, 0x0e, 0x2c, 0x50, 0x69, 0x8f, 0x3a, 0xd3, 0x90, 0x7a, 0x91, 0x7b,
+	0x78, 0x73, 0xd3, 0xb6, 0x4c, 0xcb, 0xc1, 0x8c, 0xe9, 0xd7, 0x45, 0x58, 0x5f, 0x80, 0x7a, 0x39,
+	0x02, 0xe6, 0x41, 0xde, 0x0e, 0x0c, 0x2d, 0x0c, 0xa8, 0x24, 0x4c, 0x1e, 0x6a, 0x32, 0xaa, 0xda,
+	0x3d, 0x75, 0x20, 0x0a, 0xb1, 0xb9, 0xe9, 0x3a, 0x75, 0xe2, 0x99, 0x4d, 0xcc, 0xb7, 0xf5, 0xa7,
+	0xc4, 0xae, 0x9f, 0x85, 0x63, 0x20, 0x82, 0x17, 0x05, 0xba, 0x8a, 0xf9, 0x76, 0x92, 0x62, 0x0a,
+	0x88, 0x34, 0x5d, 0x6f, 0xc1, 0xb2, 0x52, 0xde, 0x42, 0xc5, 0xee, 0xda, 0x8e, 0x7a, 0x89, 0x11,
+	0x6e, 0x3a, 0xee, 0x9e, 0xd9, 0xf4, 0x6c, 0xd7, 0xb3, 0xf9, 0x81, 0xfe, 0xb4, 0xd8, 0x0a, 0x30,
+	0x5e, 0x2f, 0x23, 0x7c, 0xd9, 0xdd, 0x5b, 0x8d, 0x90, 0x64, 0xb0, 0xac, 0xb8, 0xe3, 0xc5, 0x22,
+	0xd7, 0x5d, 0x7b, 0x4f, 0x51, 0x87, 0x1b, 0x78, 0x3f, 0x76, 0xce, 0x72, 0xa9, 0xe5, 0x7b, 0x1e,
+	0xa1, 0xd6, 0x81, 0x3e, 0x2e, 0xa2, 0xc7, 0xc4, 0x13, 0x0b, 0xde, 0x5b, 0xc1, 0xfb, 0x21, 0xc7,
+	0xf9, 0x54, 0x05, 0x0e, 0xfa, 0x46, 0x89, 0x3c, 0x39, 0xe8, 0xcb, 0xc0, 0x38, 0xd0, 0xe2, 0x4d,
+	0xa4, 0xdc, 0x2e, 0x2a, 0xb5, 0xaa, 0x7d, 0xa8, 0xa8, 0x03, 0x96, 0x87, 0xd9, 0x76, 0xee, 0xe6,
+	0xff, 0x8c, 0x98, 0x8c, 0xf7, 0xc5, 0xcd, 0x7f, 0x3e, 0xbe, 0xf9, 0x5b, 0xd1, 0xcd, 0x7f, 0x31,
+	0x3c, 0x91, 0xa1, 0x5b, 0x7a, 0x07, 0x2f, 0x4d, 0xbe, 0x42, 0xa7, 0x78, 0x9b, 0x17, 0x62, 0x58,
+	0xc1, 0xfd, 0x05, 0x23, 0x50, 0x13, 0x58, 0x51, 0x4d, 0x50, 0x7d, 0x18, 0x33, 0x50, 0x15, 0xcc,
+	0x87, 0x55, 0x41, 0xce, 0x98, 0xe7, 0x68, 0x3f, 0x50, 0xd4, 0x91, 0xbc, 0x7b, 0xf1, 0x63, 0xcc,
+	0xb3, 0x62, 0xfe, 0xed, 0x93, 0xc0, 0xb8, 0x30, 0x8f, 0xa4, 0xef, 0x08, 0x59, 0x2b, 0xf9, 0xef,
+	0x08, 0xa5, 0x68, 0xa7, 0xa5, 0x71, 0x78, 0x5c, 0x4d, 0x6d, 0xa3, 0x72, 0xcb, 0xda, 0x97, 0x14,
+	0x75, 0x98, 0x71, 0x9f, 0x9a, 0x70, 0x5f, 0xc2, 0x8e, 0xbd, 0x4b, 0xcc, 0xf0, 0x16, 0xcc, 0xf4,
+	0xe7, 0x92, 0x5b, 0xe8, 0x00, 0x68, 0xbc, 0x16, 0x2b, 0xac, 0x01, 0xbe, 0x96, 0xdc, 0x8d, 0x4a,
+	0xb0, 0xec, 0x15, 0x5e, 0x4a, 0x63, 0x67, 0xa7, 0x6f, 0x4d, 0xa1, 0x32, 0x6b, 0x50, 0x19, 0xe7,
+	0x68, 0x40, 0x36, 0x65, 0xfa, 0xf3, 0x82, 0xc4, 0x27, 0x61, 0x5f, 0x66, 0xba, 0xad, 0xd8, 0x34,
+	0xad, 0x20, 0x0a, 0x88, 0x7c, 0x33, 0xcc, 0xa4, 0xd1, 0x99, 0x29, 0x54, 0xb4, 0x03, 0x77, 0xf1,
+	0x1e, 0x31, 0x7a, 0xfc, 0x79, 0xeb, 0x05, 0x91, 0x39, 0xeb, 0x27, 0x81, 0xd1, 0x8b, 0xf0, 0xde,
+	0x1a, 0xf7, 0xa5, 0x0f, 0x5b, 0xdd, 0x2c, 0x6d, 0x26, 0x4f, 0x50, 0xa9, 0xec, 0x81, 0x1f, 0xdf,
+	0x72, 0x16, 0x91, 0x6c, 0x4f, 0xdb, 0x55, 0xfb, 0xa0, 0xd8, 0xac, 0x61, 0x46, 0xcc, 0xf0, 0x4b,
+	0xa3, 0x3e, 0x31, 0xa6, 0x8c, 0xf7, 0xce, 0xf4, 0xc6, 0x97, 0xa1, 0x75, 0x21, 0x15, 0x6f, 0x86,
+	0xbd, 0xb1, 0x6a, 0x28, 0x4b, 0xd3, 0x54, 0x46, 0x5c, 0x19, 0x8b, 0x4a, 0x8f, 0x68, 0x79, 0xbc,
+	0x7d, 0x5c, 0x55, 0x50, 0xae, 0xab, 0xf6, 0xcd, 0x33, 0xea, 0x35, 0xc8, 0x1a, 0x49, 0xba, 0x80,
+	0xd2, 0xd5, 0x72, 0x1b, 0xb0, 0x64, 0x3d, 0x72, 0xcf, 0x27, 0x8c, 0x9b, 0x3b, 0x76, 0x4d, 0x9f,
+	0x14, 0xd3, 0xf1, 0x27, 0x25, 0xfa, 0x42, 0xb9, 0x82, 0xf7, 0xe7, 0x97, 0x50, 0x88, 0xbf, 0x66,
+	0xcf, 0xb5, 0x02, 0xc3, 0x68, 0xe0, 0xfd, 0x64, 0x8b, 0xf3, 0xa5, 0xc8, 0x46, 0xaa, 0x92, 0x9c,
+	0x7d, 0x0f, 0xd0, 0x93, 0xca, 0xbe, 0x07, 0x9a, 0x7c, 0xb0, 0x4a, 0xf4, 0xcd, 0x33, 0x47, 0x17,
+	0x3d, 0xa0, 0x5b, 0x4d, 0xfb, 0xbc, 0xda, 0xe3, 0x37, 0x69, 0x33, 0xd9, 0xb5, 0x3f, 0x59, 0x14,
+	0xdb, 0xf6, 0x53, 0x27, 0x81, 0x31, 0xb4, 0x40, 0x9a, 0x1e, 0xb1, 0x30, 0x27, 0xf5, 0x8d, 0x55,
+	0xba, 0x9a, 0x6e, 0x61, 0xe5, 0x85, 0xf4, 0xec, 0x6c, 0xd2, 0x66, 0x04, 0x3c, 0xef, 0x36, 0x6c,
+	0x38, 0xbf, 0xf9, 0x41, 0xe5, 0xf0, 0xb8, 0x5a, 0xde, 0x59, 0x57, 0x50, 0xb7, 0xd4, 0x45, 0xfb,
+	0x91, 0x12, 0x0d, 0x1f, 0xbf, 0x8c, 0xbe, 0xb7, 0x28, 0xc2, 0xff, 0x36, 0x84, 0x7f, 0x30, 0x6b,
+	0x22, 0x79, 0x25, 0x15, 0xc3, 0x8f, 0x25, 0xc3, 0xcb, 0xaf, 0x9b, 0x12, 0x87, 0x34, 0xba, 0x97,
+	0x3b, 0x6b, 0x1d, 0x1e, 0x57, 0x4b, 0x47, 0xd1, 0x15, 0xa4, 0xa6, 0xbd, 0xb4, 0x5f, 0x2a, 0x6a,
+	0xaf, 0xa0, 0x99, 0xbe, 0x81, 0xfe, 0x34, 0x24, 0xfa, 0x55, 0x71, 0xf5, 0xc8, 0x9a, 0x90, 0xde,
+	0x43, 0x05, 0xd5, 0x4a, 0x42, 0x35, 0xfb, 0x82, 0x59, 0x4a, 0xf6, 0xea, 0xc7, 0xe9, 0xc1, 0x05,
+	0xa3, 0x7c, 0x2c, 0x5d, 0x41, 0x3d, 0x72, 0xcf, 0x94, 0x72, 0xfa, 0xd2, 0xf9, 0x7e, 0x67, 0xca,
+	0xd2, 0xab, 0x67, 0x8e, 0x72, 0xf6, 0x9d, 0xb2, 0x33, 0xe5, 0x4e, 0x7a, 0x45, 0xca, 0xb1, 0x66,
+	0x4c, 0x39, 0x79, 0xd8, 0xdc, 0x54, 0xc3, 0x2f, 0x2a, 0x49, 0x8e, 0xfa, 0xd9, 0xa2, 0x48, 0x52,
+	0x9f, 0xc8, 0xf2, 0x15, 0x1f, 0x25, 0xd2, 0x64, 0x25, 0x2d, 0x46, 0x2f, 0x45, 0x24, 0xa2, 0x30,
+	0x8e, 0x84, 0x30, 0x51, 0x17, 0x16, 0x4b, 0x32, 0xb3, 0x69, 0x71, 0xfd, 0xe7, 0x10, 0x22, 0x65,
+	0x6e, 0xe5, 0x24, 0x30, 0xae, 0xa6, 0x23, 0xae, 0x64, 0x0b, 0xaa, 0x55, 0x8b, 0x67, 0xe3, 0xd4,
+	0x28, 0xe0, 0xd9, 0xe1, 0xb5, 0xa2, 0x02, 0x24, 0xe4, 0xc1, 0x5c, 0x3a, 0x62, 0x16, 0xa6, 0x4c,
+	0xff, 0x45, 0x38, 0x4b, 0xeb, 0x39, 0x0a, 0xf2, 0x36, 0x5e, 0x03, 0xc5, 0x1c, 0x85, 0x02, 0x5e,
+	0x9c, 0x2a, 0xc1, 0xa4, 0xa0, 0x37, 0xf7, 0xca, 0x07, 0x1f, 0x8d, 0x76, 0x1d, 0x7f, 0x34, 0xda,
+	0xf5, 0xaf, 0x93, 0xd1, 0xae, 0xaf, 0xdf, 0x1f, 0xed, 0x7a, 0xf7, 0xfe, 0xa8, 0x72, 0x7c, 0x7f,
+	0xb4, 0xeb, 0xaf, 0xf7, 0x47, 0xbb, 0xde, 0x78, 0x66, 0xcb, 0xe6, 0xdb, 0x7e, 0x6d, 0xc2, 0x72,
+	0x1b, 0x93, 0xc9, 0x05, 0x41, 0xfa, 0x95, 0xfe, 0x3d, 0xa4, 0x76, 0x5e, 0xfc, 0x1f, 0xe4, 0xc6,
+	0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xa4, 0xc7, 0xba, 0x90, 0x7b, 0x22, 0x00, 0x00,
+}
+
+func (m *OptionsConfiguration) ProtoSize() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if len(m.RawListenAddresses) > 0 {
+		for _, s := range m.RawListenAddresses {
+			l = len(s)
+			n += 1 + l + sovOptionsconfiguration(uint64(l))
+		}
+	}
+	if len(m.RawGlobalAnnServers) > 0 {
+		for _, s := range m.RawGlobalAnnServers {
+			l = len(s)
+			n += 1 + l + sovOptionsconfiguration(uint64(l))
+		}
+	}
+	if m.GlobalAnnEnabled {
+		n += 2
+	}
+	if m.LocalAnnEnabled {
+		n += 2
+	}
+	if m.LocalAnnPort != 0 {
+		n += 1 + sovOptionsconfiguration(uint64(m.LocalAnnPort))
+	}
+	l = len(m.LocalAnnMCAddr)
+	if l > 0 {
+		n += 1 + l + sovOptionsconfiguration(uint64(l))
+	}
+	if m.MaxSendKbps != 0 {
+		n += 1 + sovOptionsconfiguration(uint64(m.MaxSendKbps))
+	}
+	if m.MaxRecvKbps != 0 {
+		n += 1 + sovOptionsconfiguration(uint64(m.MaxRecvKbps))
+	}
+	if m.ReconnectIntervalS != 0 {
+		n += 1 + sovOptionsconfiguration(uint64(m.ReconnectIntervalS))
+	}
+	if m.RelaysEnabled {
+		n += 2
+	}
+	if m.RelayReconnectIntervalM != 0 {
+		n += 1 + sovOptionsconfiguration(uint64(m.RelayReconnectIntervalM))
+	}
+	if m.StartBrowser {
+		n += 2
+	}
+	if m.NATEnabled {
+		n += 2
+	}
+	if m.NATLeaseM != 0 {
+		n += 1 + sovOptionsconfiguration(uint64(m.NATLeaseM))
+	}
+	if m.NATRenewalM != 0 {
+		n += 2 + sovOptionsconfiguration(uint64(m.NATRenewalM))
+	}
+	if m.NATTimeoutS != 0 {
+		n += 2 + sovOptionsconfiguration(uint64(m.NATTimeoutS))
+	}
+	if m.URAccepted != 0 {
+		n += 2 + sovOptionsconfiguration(uint64(m.URAccepted))
+	}
+	if m.URSeen != 0 {
+		n += 2 + sovOptionsconfiguration(uint64(m.URSeen))
+	}
+	l = len(m.URUniqueID)
+	if l > 0 {
+		n += 2 + l + sovOptionsconfiguration(uint64(l))
+	}
+	l = len(m.URURL)
+	if l > 0 {
+		n += 2 + l + sovOptionsconfiguration(uint64(l))
+	}
+	if m.URPostInsecurely {
+		n += 3
+	}
+	if m.URInitialDelayS != 0 {
+		n += 2 + sovOptionsconfiguration(uint64(m.URInitialDelayS))
+	}
+	if m.RestartOnWakeup {
+		n += 3
+	}
+	if m.AutoUpgradeIntervalH != 0 {
+		n += 2 + sovOptionsconfiguration(uint64(m.AutoUpgradeIntervalH))
+	}
+	if m.UpgradeToPreReleases {
+		n += 3
+	}
+	if m.KeepTemporariesH != 0 {
+		n += 2 + sovOptionsconfiguration(uint64(m.KeepTemporariesH))
+	}
+	if m.CacheIgnoredFiles {
+		n += 3
+	}
+	if m.ProgressUpdateIntervalS != 0 {
+		n += 2 + sovOptionsconfiguration(uint64(m.ProgressUpdateIntervalS))
+	}
+	if m.LimitBandwidthInLan {
+		n += 3
+	}
+	l = m.MinHomeDiskFree.ProtoSize()
+	n += 2 + l + sovOptionsconfiguration(uint64(l))
+	l = len(m.ReleasesURL)
+	if l > 0 {
+		n += 2 + l + sovOptionsconfiguration(uint64(l))
+	}
+	if len(m.AlwaysLocalNets) > 0 {
+		for _, s := range m.AlwaysLocalNets {
+			l = len(s)
+			n += 2 + l + sovOptionsconfiguration(uint64(l))
+		}
+	}
+	if m.OverwriteRemoteDevNames {
+		n += 3
+	}
+	if m.TempIndexMinBlocks != 0 {
+		n += 2 + sovOptionsconfiguration(uint64(m.TempIndexMinBlocks))
+	}
+	if len(m.UnackedNotificationIDs) > 0 {
+		for _, s := range m.UnackedNotificationIDs {
+			l = len(s)
+			n += 2 + l + sovOptionsconfiguration(uint64(l))
+		}
+	}
+	if m.TrafficClass != 0 {
+		n += 2 + sovOptionsconfiguration(uint64(m.TrafficClass))
+	}
+	l = len(m.DefaultFolderPath)
+	if l > 0 {
+		n += 2 + l + sovOptionsconfiguration(uint64(l))
+	}
+	if m.SetLowPriority {
+		n += 3
+	}
+	if m.RawMaxFolderConcurrency != 0 {
+		n += 2 + sovOptionsconfiguration(uint64(m.RawMaxFolderConcurrency))
+	}
+	l = len(m.CRURL)
+	if l > 0 {
+		n += 2 + l + sovOptionsconfiguration(uint64(l))
+	}
+	if m.CREnabled {
+		n += 3
+	}
+	if m.StunKeepaliveStartS != 0 {
+		n += 2 + sovOptionsconfiguration(uint64(m.StunKeepaliveStartS))
+	}
+	if m.StunKeepaliveMinS != 0 {
+		n += 2 + sovOptionsconfiguration(uint64(m.StunKeepaliveMinS))
+	}
+	if len(m.RawStunServers) > 0 {
+		for _, s := range m.RawStunServers {
+			l = len(s)
+			n += 2 + l + sovOptionsconfiguration(uint64(l))
+		}
+	}
+	if m.DatabaseTuning != 0 {
+		n += 2 + sovOptionsconfiguration(uint64(m.DatabaseTuning))
+	}
+	if m.RawMaxCIRequestKiB != 0 {
+		n += 2 + sovOptionsconfiguration(uint64(m.RawMaxCIRequestKiB))
+	}
+	if m.DeprecatedUPnPEnabled {
+		n += 4
+	}
+	if m.DeprecatedUPnPLeaseM != 0 {
+		n += 3 + sovOptionsconfiguration(uint64(m.DeprecatedUPnPLeaseM))
+	}
+	if m.DeprecatedUPnPRenewalM != 0 {
+		n += 3 + sovOptionsconfiguration(uint64(m.DeprecatedUPnPRenewalM))
+	}
+	if m.DeprecatedUPnPTimeoutS != 0 {
+		n += 3 + sovOptionsconfiguration(uint64(m.DeprecatedUPnPTimeoutS))
+	}
+	if len(m.DeprecatedRelayServers) > 0 {
+		for _, s := range m.DeprecatedRelayServers {
+			l = len(s)
+			n += 3 + l + sovOptionsconfiguration(uint64(l))
+		}
+	}
+	if m.DeprecatedMinHomeDiskFreePct != 0 {
+		n += 11
+	}
+	if m.DeprecatedMaxConcurrentScans != 0 {
+		n += 3 + sovOptionsconfiguration(uint64(m.DeprecatedMaxConcurrentScans))
+	}
+	return n
+}
+
+func sovOptionsconfiguration(x uint64) (n int) {
+	return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozOptionsconfiguration(x uint64) (n int) {
+	return sovOptionsconfiguration(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}

+ 13 - 24
lib/config/pullorder.go

@@ -6,30 +6,19 @@
 
 
 package config
 package config
 
 
-type PullOrder int
-
-const (
-	OrderRandom PullOrder = iota // default is random
-	OrderAlphabetic
-	OrderSmallestFirst
-	OrderLargestFirst
-	OrderOldestFirst
-	OrderNewestFirst
-)
-
 func (o PullOrder) String() string {
 func (o PullOrder) String() string {
 	switch o {
 	switch o {
-	case OrderRandom:
+	case PullOrderRandom:
 		return "random"
 		return "random"
-	case OrderAlphabetic:
+	case PullOrderAlphabetic:
 		return "alphabetic"
 		return "alphabetic"
-	case OrderSmallestFirst:
+	case PullOrderSmallestFirst:
 		return "smallestFirst"
 		return "smallestFirst"
-	case OrderLargestFirst:
+	case PullOrderLargestFirst:
 		return "largestFirst"
 		return "largestFirst"
-	case OrderOldestFirst:
+	case PullOrderOldestFirst:
 		return "oldestFirst"
 		return "oldestFirst"
-	case OrderNewestFirst:
+	case PullOrderNewestFirst:
 		return "newestFirst"
 		return "newestFirst"
 	default:
 	default:
 		return "unknown"
 		return "unknown"
@@ -43,19 +32,19 @@ func (o PullOrder) MarshalText() ([]byte, error) {
 func (o *PullOrder) UnmarshalText(bs []byte) error {
 func (o *PullOrder) UnmarshalText(bs []byte) error {
 	switch string(bs) {
 	switch string(bs) {
 	case "random":
 	case "random":
-		*o = OrderRandom
+		*o = PullOrderRandom
 	case "alphabetic":
 	case "alphabetic":
-		*o = OrderAlphabetic
+		*o = PullOrderAlphabetic
 	case "smallestFirst":
 	case "smallestFirst":
-		*o = OrderSmallestFirst
+		*o = PullOrderSmallestFirst
 	case "largestFirst":
 	case "largestFirst":
-		*o = OrderLargestFirst
+		*o = PullOrderLargestFirst
 	case "oldestFirst":
 	case "oldestFirst":
-		*o = OrderOldestFirst
+		*o = PullOrderOldestFirst
 	case "newestFirst":
 	case "newestFirst":
-		*o = OrderNewestFirst
+		*o = PullOrderNewestFirst
 	default:
 	default:
-		*o = OrderRandom
+		*o = PullOrderRandom
 	}
 	}
 	return nil
 	return nil
 }
 }

+ 87 - 0
lib/config/pullorder.pb.go

@@ -0,0 +1,87 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: lib/config/pullorder.proto
+
+package config
+
+import (
+	fmt "fmt"
+	_ "github.com/gogo/protobuf/gogoproto"
+	proto "github.com/gogo/protobuf/proto"
+	math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+type PullOrder int32
+
+const (
+	PullOrderRandom        PullOrder = 0
+	PullOrderAlphabetic    PullOrder = 1
+	PullOrderSmallestFirst PullOrder = 2
+	PullOrderLargestFirst  PullOrder = 3
+	PullOrderOldestFirst   PullOrder = 4
+	PullOrderNewestFirst   PullOrder = 5
+)
+
+var PullOrder_name = map[int32]string{
+	0: "PULL_ORDER_RANDOM",
+	1: "PULL_ORDER_ALPHABETIC",
+	2: "PULL_ORDER_SMALLEST_FIRST",
+	3: "PULL_ORDER_LARGEST_FIRST",
+	4: "PULL_ORDER_OLDEST_FIRST",
+	5: "PULL_ORDER_NEWEST_FIRST",
+}
+
+var PullOrder_value = map[string]int32{
+	"PULL_ORDER_RANDOM":         0,
+	"PULL_ORDER_ALPHABETIC":     1,
+	"PULL_ORDER_SMALLEST_FIRST": 2,
+	"PULL_ORDER_LARGEST_FIRST":  3,
+	"PULL_ORDER_OLDEST_FIRST":   4,
+	"PULL_ORDER_NEWEST_FIRST":   5,
+}
+
+func (PullOrder) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_2fa3f5222a7755bf, []int{0}
+}
+
+func init() {
+	proto.RegisterEnum("config.PullOrder", PullOrder_name, PullOrder_value)
+}
+
+func init() { proto.RegisterFile("lib/config/pullorder.proto", fileDescriptor_2fa3f5222a7755bf) }
+
+var fileDescriptor_2fa3f5222a7755bf = []byte{
+	// 343 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xca, 0xc9, 0x4c, 0xd2,
+	0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0x2f, 0x28, 0xcd, 0xc9, 0xc9, 0x2f, 0x4a, 0x49, 0x2d,
+	0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0x88, 0x4b, 0x29, 0x17, 0xa5, 0x16, 0xe4,
+	0x17, 0xeb, 0x83, 0x05, 0x93, 0x4a, 0xd3, 0xf4, 0xd3, 0xf3, 0xd3, 0xf3, 0xc1, 0x1c, 0x30, 0x0b,
+	0xa2, 0x58, 0xeb, 0x32, 0x13, 0x17, 0x67, 0x40, 0x69, 0x4e, 0x8e, 0x3f, 0xc8, 0x00, 0x21, 0x2d,
+	0x2e, 0xc1, 0x80, 0x50, 0x1f, 0x9f, 0x78, 0xff, 0x20, 0x17, 0xd7, 0xa0, 0xf8, 0x20, 0x47, 0x3f,
+	0x17, 0x7f, 0x5f, 0x01, 0x06, 0x29, 0xe1, 0xae, 0xb9, 0x0a, 0xfc, 0x70, 0x55, 0x41, 0x89, 0x79,
+	0x29, 0xf9, 0xb9, 0x42, 0x46, 0x5c, 0xa2, 0x48, 0x6a, 0x1d, 0x7d, 0x02, 0x3c, 0x1c, 0x9d, 0x5c,
+	0x43, 0x3c, 0x9d, 0x05, 0x18, 0xa5, 0xc4, 0xbb, 0xe6, 0x2a, 0x08, 0xc3, 0xd5, 0x3b, 0xe6, 0x14,
+	0x64, 0x24, 0x26, 0xa5, 0x96, 0x64, 0x26, 0x0b, 0x59, 0x72, 0x49, 0x22, 0xe9, 0x09, 0xf6, 0x75,
+	0xf4, 0xf1, 0x71, 0x0d, 0x0e, 0x89, 0x77, 0xf3, 0x0c, 0x0a, 0x0e, 0x11, 0x60, 0x92, 0x92, 0xea,
+	0x9a, 0xab, 0x20, 0x06, 0xd7, 0x17, 0x9c, 0x9b, 0x98, 0x93, 0x93, 0x5a, 0x5c, 0xe2, 0x96, 0x59,
+	0x54, 0x5c, 0x22, 0x64, 0xce, 0x25, 0x81, 0xa4, 0xd5, 0xc7, 0x31, 0xc8, 0x1d, 0xa1, 0x93, 0x59,
+	0x4a, 0xb2, 0x6b, 0xae, 0x82, 0x28, 0x5c, 0xa7, 0x4f, 0x62, 0x51, 0x3a, 0x5c, 0xa3, 0x29, 0x97,
+	0x38, 0x92, 0x46, 0x7f, 0x1f, 0x17, 0x84, 0x3e, 0x16, 0x29, 0x89, 0xae, 0xb9, 0x0a, 0x22, 0x70,
+	0x7d, 0xfe, 0x39, 0x29, 0x38, 0xb4, 0xf9, 0xb9, 0x86, 0x23, 0xb4, 0xb1, 0xa2, 0x69, 0xf3, 0x4b,
+	0x2d, 0x87, 0x69, 0x93, 0x62, 0x59, 0xb1, 0x44, 0x8e, 0xc1, 0xc9, 0xfd, 0xc4, 0x43, 0x39, 0x86,
+	0x0b, 0x0f, 0xe5, 0x18, 0x5e, 0x3c, 0x92, 0x63, 0x98, 0xf0, 0x58, 0x8e, 0x61, 0xc1, 0x63, 0x39,
+	0xc6, 0x0b, 0x8f, 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, 0xd2, 0x4c, 0xcf, 0x2c, 0xc9, 0x28,
+	0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x2f, 0xae, 0xcc, 0x4b, 0x2e, 0xc9, 0xc8, 0xcc, 0x4b, 0x47,
+	0x62, 0x21, 0xe2, 0x36, 0x89, 0x0d, 0x1c, 0x4b, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x34,
+	0x1f, 0xbc, 0x31, 0xf0, 0x01, 0x00, 0x00,
+}

+ 0 - 5
lib/config/size.go

@@ -14,11 +14,6 @@ import (
 	"github.com/syncthing/syncthing/lib/fs"
 	"github.com/syncthing/syncthing/lib/fs"
 )
 )
 
 
-type Size struct {
-	Value float64 `json:"value" xml:",chardata"`
-	Unit  string  `json:"unit" xml:"unit,attr"`
-}
-
 func ParseSize(s string) (Size, error) {
 func ParseSize(s string) (Size, error) {
 	s = strings.TrimSpace(s)
 	s = strings.TrimSpace(s)
 	if len(s) == 0 {
 	if len(s) == 0 {

+ 101 - 0
lib/config/size.pb.go

@@ -0,0 +1,101 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: lib/config/size.proto
+
+package config
+
+import (
+	fmt "fmt"
+	_ "github.com/gogo/protobuf/gogoproto"
+	proto "github.com/gogo/protobuf/proto"
+	_ "github.com/syncthing/syncthing/proto/ext"
+	math "math"
+	math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+type Size struct {
+	Value float64 `protobuf:"fixed64,1,opt,name=value,proto3" json:"value" xml:",chardata"`
+	Unit  string  `protobuf:"bytes,2,opt,name=unit,proto3" json:"unit" xml:"unit,attr"`
+}
+
+func (m *Size) Reset()      { *m = Size{} }
+func (*Size) ProtoMessage() {}
+func (*Size) Descriptor() ([]byte, []int) {
+	return fileDescriptor_4d75cb8f619bd299, []int{0}
+}
+func (m *Size) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Size.Unmarshal(m, b)
+}
+func (m *Size) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Size.Marshal(b, m, deterministic)
+}
+func (m *Size) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Size.Merge(m, src)
+}
+func (m *Size) XXX_Size() int {
+	return xxx_messageInfo_Size.Size(m)
+}
+func (m *Size) XXX_DiscardUnknown() {
+	xxx_messageInfo_Size.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Size proto.InternalMessageInfo
+
+func init() {
+	proto.RegisterType((*Size)(nil), "config.Size")
+}
+
+func init() { proto.RegisterFile("lib/config/size.proto", fileDescriptor_4d75cb8f619bd299) }
+
+var fileDescriptor_4d75cb8f619bd299 = []byte{
+	// 246 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xcd, 0xc9, 0x4c, 0xd2,
+	0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0x2f, 0xce, 0xac, 0x4a, 0xd5, 0x2b, 0x28, 0xca, 0x2f,
+	0xc9, 0x17, 0x62, 0x83, 0x08, 0x49, 0x29, 0x17, 0xa5, 0x16, 0xe4, 0x17, 0xeb, 0x83, 0x05, 0x93,
+	0x4a, 0xd3, 0xf4, 0xd3, 0xf3, 0xd3, 0xf3, 0xc1, 0x1c, 0x30, 0x0b, 0xa2, 0x58, 0x8a, 0x33, 0xb5,
+	0xa2, 0x04, 0xc2, 0x54, 0xea, 0x66, 0xe4, 0x62, 0x09, 0xce, 0xac, 0x4a, 0x15, 0xb2, 0xe7, 0x62,
+	0x2d, 0x4b, 0xcc, 0x29, 0x4d, 0x95, 0x60, 0x54, 0x60, 0xd4, 0x60, 0x74, 0xd2, 0x7c, 0x75, 0x4f,
+	0x1e, 0x22, 0xf0, 0xe9, 0x9e, 0x3c, 0x7f, 0x45, 0x6e, 0x8e, 0x95, 0x92, 0x4e, 0x72, 0x46, 0x62,
+	0x51, 0x4a, 0x62, 0x49, 0xa2, 0xd2, 0xab, 0xf3, 0x2a, 0x9c, 0x70, 0x5e, 0x10, 0x44, 0x99, 0x90,
+	0x0d, 0x17, 0x4b, 0x69, 0x5e, 0x66, 0x89, 0x04, 0x93, 0x02, 0xa3, 0x06, 0xa7, 0x93, 0xc6, 0xab,
+	0x7b, 0xf2, 0x60, 0x3e, 0x5c, 0x3b, 0x88, 0xa3, 0x93, 0x58, 0x52, 0x52, 0x04, 0xd6, 0x0e, 0xe7,
+	0x05, 0x81, 0x55, 0x59, 0xb1, 0xcc, 0x58, 0x20, 0xcf, 0xe0, 0xe4, 0x7e, 0xe2, 0xa1, 0x1c, 0xc3,
+	0x85, 0x87, 0x72, 0x0c, 0x2f, 0x1e, 0xc9, 0x31, 0x4c, 0x78, 0x2c, 0xc7, 0xb0, 0xe0, 0xb1, 0x1c,
+	0xe3, 0x85, 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, 0x69, 0xa6, 0x67, 0x96, 0x64, 0x94,
+	0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0x17, 0x57, 0xe6, 0x25, 0x97, 0x64, 0x64, 0xe6, 0xa5, 0x23,
+	0xb1, 0x10, 0x21, 0x93, 0xc4, 0x06, 0xf6, 0x9d, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0x67, 0x60,
+	0xd6, 0x9a, 0x2e, 0x01, 0x00, 0x00,
+}
+
+func (m *Size) ProtoSize() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Value != 0 {
+		n += 9
+	}
+	l = len(m.Unit)
+	if l > 0 {
+		n += 1 + l + sovSize(uint64(l))
+	}
+	return n
+}
+
+func sovSize(x uint64) (n int) {
+	return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozSize(x uint64) (n int) {
+	return sovSize(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}

+ 0 - 9
lib/config/tuning.go

@@ -6,15 +6,6 @@
 
 
 package config
 package config
 
 
-type Tuning int
-
-const (
-	// N.b. these constants must match those in lib/db.Tuning!
-	TuningAuto Tuning = iota // default is auto
-	TuningSmall
-	TuningLarge
-)
-
 func (t Tuning) String() string {
 func (t Tuning) String() string {
 	switch t {
 	switch t {
 	case TuningAuto:
 	case TuningAuto:

+ 70 - 0
lib/config/tuning.pb.go

@@ -0,0 +1,70 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: lib/config/tuning.proto
+
+package config
+
+import (
+	fmt "fmt"
+	_ "github.com/gogo/protobuf/gogoproto"
+	proto "github.com/gogo/protobuf/proto"
+	math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+type Tuning int32
+
+const (
+	TuningAuto  Tuning = 0
+	TuningSmall Tuning = 1
+	TuningLarge Tuning = 2
+)
+
+var Tuning_name = map[int32]string{
+	0: "TUNING_AUTO",
+	1: "TUNING_SMALL",
+	2: "TUNING_LARGE",
+}
+
+var Tuning_value = map[string]int32{
+	"TUNING_AUTO":  0,
+	"TUNING_SMALL": 1,
+	"TUNING_LARGE": 2,
+}
+
+func (Tuning) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_204cfa1615fdfefd, []int{0}
+}
+
+func init() {
+	proto.RegisterEnum("config.Tuning", Tuning_name, Tuning_value)
+}
+
+func init() { proto.RegisterFile("lib/config/tuning.proto", fileDescriptor_204cfa1615fdfefd) }
+
+var fileDescriptor_204cfa1615fdfefd = []byte{
+	// 224 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xcf, 0xc9, 0x4c, 0xd2,
+	0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0x2f, 0x29, 0xcd, 0xcb, 0xcc, 0x4b, 0xd7, 0x2b, 0x28,
+	0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0x08, 0x4a, 0x29, 0x17, 0xa5, 0x16, 0xe4, 0x17, 0xeb, 0x83,
+	0x05, 0x93, 0x4a, 0xd3, 0xf4, 0xd3, 0xf3, 0xd3, 0xf3, 0xc1, 0x1c, 0x30, 0x0b, 0xa2, 0x58, 0xab,
+	0x94, 0x8b, 0x2d, 0x04, 0xac, 0x59, 0x48, 0x9e, 0x8b, 0x3b, 0x24, 0xd4, 0xcf, 0xd3, 0xcf, 0x3d,
+	0xde, 0x31, 0x34, 0xc4, 0x5f, 0x80, 0x41, 0x8a, 0xaf, 0x6b, 0xae, 0x02, 0x17, 0x44, 0xd2, 0xb1,
+	0xb4, 0x24, 0x5f, 0x48, 0x91, 0x8b, 0x07, 0xaa, 0x20, 0xd8, 0xd7, 0xd1, 0xc7, 0x47, 0x80, 0x51,
+	0x8a, 0xbf, 0x6b, 0xae, 0x02, 0x37, 0x44, 0x45, 0x70, 0x6e, 0x62, 0x4e, 0x0e, 0x92, 0x12, 0x1f,
+	0xc7, 0x20, 0x77, 0x57, 0x01, 0x26, 0x64, 0x25, 0x3e, 0x89, 0x45, 0xe9, 0xa9, 0x52, 0x2c, 0x2b,
+	0x96, 0xc8, 0x31, 0x38, 0xb9, 0x9f, 0x78, 0x28, 0xc7, 0x70, 0xe1, 0xa1, 0x1c, 0xc3, 0x8b, 0x47,
+	0x72, 0x0c, 0x13, 0x1e, 0xcb, 0x31, 0x2c, 0x78, 0x2c, 0xc7, 0x78, 0xe1, 0xb1, 0x1c, 0xc3, 0x8d,
+	0xc7, 0x72, 0x0c, 0x51, 0x9a, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xfa,
+	0xc5, 0x95, 0x79, 0xc9, 0x25, 0x19, 0x99, 0x79, 0xe9, 0x48, 0x2c, 0x84, 0xcf, 0x93, 0xd8, 0xc0,
+	0xde, 0x30, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0xfe, 0xdf, 0xc4, 0xd9, 0x0e, 0x01, 0x00, 0x00,
+}

+ 0 - 7
lib/config/versioningconfiguration.go

@@ -14,13 +14,6 @@ import (
 	"github.com/syncthing/syncthing/lib/util"
 	"github.com/syncthing/syncthing/lib/util"
 )
 )
 
 
-// VersioningConfiguration is used in the code and for JSON serialization
-type VersioningConfiguration struct {
-	Type             string            `json:"type"`
-	Params           map[string]string `json:"params"`
-	CleanupIntervalS int               `json:"cleanupIntervalS" default:"3600"`
-}
-
 // internalVersioningConfiguration is used in XML serialization
 // internalVersioningConfiguration is used in XML serialization
 type internalVersioningConfiguration struct {
 type internalVersioningConfiguration struct {
 	Type             string          `xml:"type,attr,omitempty"`
 	Type             string          `xml:"type,attr,omitempty"`

+ 122 - 0
lib/config/versioningconfiguration.pb.go

@@ -0,0 +1,122 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: lib/config/versioningconfiguration.proto
+
+package config
+
+import (
+	fmt "fmt"
+	proto "github.com/gogo/protobuf/proto"
+	_ "github.com/syncthing/syncthing/proto/ext"
+	math "math"
+	math_bits "math/bits"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+// VersioningConfiguration is used in the code and for JSON serialization
+type VersioningConfiguration struct {
+	Type             string            `protobuf:"bytes,1,opt,name=type,proto3" json:"type" `
+	Params           map[string]string `protobuf:"bytes,2,rep,name=parameters,proto3" json:"params"  protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+	CleanupIntervalS int               `protobuf:"varint,3,opt,name=cleanup_interval_s,json=cleanupIntervalS,proto3,casttype=int" json:"cleanupIntervalS" default:"3600"`
+}
+
+func (m *VersioningConfiguration) Reset()         { *m = VersioningConfiguration{} }
+func (m *VersioningConfiguration) String() string { return proto.CompactTextString(m) }
+func (*VersioningConfiguration) ProtoMessage()    {}
+func (*VersioningConfiguration) Descriptor() ([]byte, []int) {
+	return fileDescriptor_95ba6bdb22ffea81, []int{0}
+}
+func (m *VersioningConfiguration) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_VersioningConfiguration.Unmarshal(m, b)
+}
+func (m *VersioningConfiguration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_VersioningConfiguration.Marshal(b, m, deterministic)
+}
+func (m *VersioningConfiguration) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_VersioningConfiguration.Merge(m, src)
+}
+func (m *VersioningConfiguration) XXX_Size() int {
+	return xxx_messageInfo_VersioningConfiguration.Size(m)
+}
+func (m *VersioningConfiguration) XXX_DiscardUnknown() {
+	xxx_messageInfo_VersioningConfiguration.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_VersioningConfiguration proto.InternalMessageInfo
+
+func init() {
+	proto.RegisterType((*VersioningConfiguration)(nil), "config.VersioningConfiguration")
+	proto.RegisterMapType((map[string]string)(nil), "config.VersioningConfiguration.ParametersEntry")
+}
+
+func init() {
+	proto.RegisterFile("lib/config/versioningconfiguration.proto", fileDescriptor_95ba6bdb22ffea81)
+}
+
+var fileDescriptor_95ba6bdb22ffea81 = []byte{
+	// 383 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x52, 0xcf, 0x8b, 0x9b, 0x40,
+	0x18, 0x1d, 0x63, 0x22, 0x64, 0xd2, 0x5f, 0x78, 0xa9, 0x04, 0xea, 0x48, 0xea, 0xc1, 0x5e, 0x34,
+	0x34, 0xb4, 0x94, 0x1c, 0x2d, 0xa5, 0xf4, 0x56, 0x52, 0x28, 0xb4, 0x97, 0x60, 0xec, 0xc4, 0x0c,
+	0x35, 0xa3, 0xe8, 0x18, 0xea, 0xb1, 0x87, 0x42, 0x8f, 0xed, 0xfe, 0x05, 0xfb, 0xe7, 0xe4, 0x96,
+	0x1c, 0xf7, 0x34, 0x90, 0x78, 0x59, 0x3c, 0xe6, 0x98, 0xd3, 0xe2, 0x28, 0xd9, 0xb0, 0xcb, 0xde,
+	0xde, 0x7b, 0xdf, 0x7b, 0xdf, 0x93, 0xcf, 0x81, 0x56, 0x48, 0x66, 0x8e, 0x1f, 0xd1, 0x39, 0x09,
+	0x9c, 0x15, 0x4e, 0x52, 0x12, 0x51, 0x42, 0x83, 0x5a, 0xc8, 0x12, 0x8f, 0x91, 0x88, 0xda, 0x71,
+	0x12, 0xb1, 0x48, 0x55, 0x6a, 0xb1, 0xdf, 0xc5, 0xbf, 0x58, 0x2d, 0x0d, 0xfe, 0xc8, 0xf0, 0xf9,
+	0xd7, 0x53, 0xe8, 0xfd, 0x79, 0x48, 0x35, 0x60, 0x9b, 0xe5, 0x31, 0xd6, 0x24, 0x43, 0xb2, 0xba,
+	0xee, 0xa3, 0x92, 0x23, 0xc1, 0x0f, 0x1c, 0x81, 0x89, 0x40, 0xea, 0x6f, 0x09, 0xc2, 0xd8, 0x4b,
+	0xbc, 0x25, 0x66, 0x38, 0x49, 0xb5, 0x96, 0x21, 0x5b, 0xbd, 0xd7, 0x8e, 0x5d, 0xd7, 0xd8, 0x0f,
+	0xec, 0xb5, 0x3f, 0x9f, 0x12, 0x1f, 0x28, 0x4b, 0x72, 0x77, 0xb8, 0xe6, 0x08, 0xec, 0x39, 0x52,
+	0xc4, 0x20, 0x2d, 0x39, 0x52, 0xc4, 0xd2, 0xb4, 0x6a, 0x3a, 0x6c, 0xcc, 0x86, 0x5d, 0x6c, 0xcd,
+	0xc6, 0x31, 0x39, 0x2b, 0x55, 0x7d, 0xa8, 0xfa, 0x21, 0xf6, 0x68, 0x16, 0x4f, 0x09, 0x65, 0x38,
+	0x59, 0x79, 0xe1, 0x34, 0xd5, 0x64, 0x43, 0xb2, 0x3a, 0xee, 0x9b, 0x92, 0xa3, 0x67, 0xcd, 0xf4,
+	0x53, 0x33, 0xfc, 0x72, 0xe0, 0xe8, 0xc9, 0x0f, 0x3c, 0xf7, 0xb2, 0x90, 0x8d, 0x07, 0xa3, 0xb7,
+	0xc3, 0xe1, 0xe0, 0xc8, 0x91, 0x4c, 0x28, 0x3b, 0x6e, 0xcc, 0x76, 0xc5, 0x27, 0xf7, 0x22, 0xfd,
+	0x6f, 0xf0, 0xe9, 0x9d, 0xaf, 0x56, 0x5f, 0x40, 0xf9, 0x27, 0xce, 0x9b, 0xe3, 0xf4, 0x4a, 0x8e,
+	0x2a, 0x2a, 0x6e, 0x53, 0x01, 0xf5, 0x25, 0xec, 0xac, 0xbc, 0x30, 0xc3, 0x5a, 0x4b, 0x18, 0x1e,
+	0x97, 0x1c, 0xd5, 0x82, 0xb0, 0xd4, 0x70, 0xdc, 0x7a, 0x27, 0x8d, 0xdb, 0x7f, 0xff, 0x9b, 0xc0,
+	0xfd, 0xb8, 0xde, 0xe9, 0x60, 0xbb, 0xd3, 0xc1, 0xf5, 0x5e, 0x07, 0xff, 0x0a, 0x1d, 0x5c, 0x16,
+	0xba, 0xb4, 0x2d, 0x74, 0x70, 0x55, 0xe8, 0xe0, 0xfb, 0xab, 0x80, 0xb0, 0x45, 0x36, 0xb3, 0xfd,
+	0x68, 0xe9, 0xa4, 0x39, 0xf5, 0xd9, 0x82, 0xd0, 0xe0, 0x0c, 0xdd, 0xbe, 0x80, 0x99, 0x22, 0xfe,
+	0xeb, 0xe8, 0x26, 0x00, 0x00, 0xff, 0xff, 0x08, 0x18, 0x19, 0x5e, 0x16, 0x02, 0x00, 0x00,
+}
+
+func (m *VersioningConfiguration) ProtoSize() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.Type)
+	if l > 0 {
+		n += 1 + l + sovVersioningconfiguration(uint64(l))
+	}
+	if len(m.Params) > 0 {
+		for k, v := range m.Params {
+			_ = k
+			_ = v
+			mapEntrySize := 1 + len(k) + sovVersioningconfiguration(uint64(len(k))) + 1 + len(v) + sovVersioningconfiguration(uint64(len(v)))
+			n += mapEntrySize + 1 + sovVersioningconfiguration(uint64(mapEntrySize))
+		}
+	}
+	if m.CleanupIntervalS != 0 {
+		n += 1 + sovVersioningconfiguration(uint64(m.CleanupIntervalS))
+	}
+	return n
+}
+
+func sovVersioningconfiguration(x uint64) (n int) {
+	return (math_bits.Len64(x|1) + 6) / 7
+}
+func sozVersioningconfiguration(x uint64) (n int) {
+	return sovVersioningconfiguration(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}

+ 5 - 14
lib/config/wrapper.go

@@ -54,7 +54,6 @@ func (noopWaiter) Wait() {}
 // A Wrapper around a Configuration that manages loads, saves and published
 // A Wrapper around a Configuration that manages loads, saves and published
 // notifications of changes to registered Handlers
 // notifications of changes to registered Handlers
 type Wrapper interface {
 type Wrapper interface {
-	MyName() string
 	ConfigPath() string
 	ConfigPath() string
 
 
 	RawCopy() Configuration
 	RawCopy() Configuration
@@ -117,19 +116,19 @@ func Wrap(path string, cfg Configuration, evLogger events.Logger) Wrapper {
 
 
 // Load loads an existing file on disk and returns a new configuration
 // Load loads an existing file on disk and returns a new configuration
 // wrapper.
 // wrapper.
-func Load(path string, myID protocol.DeviceID, evLogger events.Logger) (Wrapper, error) {
+func Load(path string, myID protocol.DeviceID, evLogger events.Logger) (Wrapper, int, error) {
 	fd, err := os.Open(path)
 	fd, err := os.Open(path)
 	if err != nil {
 	if err != nil {
-		return nil, err
+		return nil, 0, err
 	}
 	}
 	defer fd.Close()
 	defer fd.Close()
 
 
-	cfg, err := ReadXML(fd, myID)
+	cfg, originalVersion, err := ReadXML(fd, myID)
 	if err != nil {
 	if err != nil {
-		return nil, err
+		return nil, 0, err
 	}
 	}
 
 
-	return Wrap(path, cfg, evLogger), nil
+	return Wrap(path, cfg, evLogger), originalVersion, nil
 }
 }
 
 
 func (w *wrapper) ConfigPath() string {
 func (w *wrapper) ConfigPath() string {
@@ -447,14 +446,6 @@ func (w *wrapper) setRequiresRestart() {
 	atomic.StoreUint32(&w.requiresRestart, 1)
 	atomic.StoreUint32(&w.requiresRestart, 1)
 }
 }
 
 
-func (w *wrapper) MyName() string {
-	w.mut.Lock()
-	myID := w.cfg.MyID
-	w.mut.Unlock()
-	cfg, _ := w.Device(myID)
-	return cfg.Name
-}
-
 func (w *wrapper) AddOrUpdatePendingDevice(device protocol.DeviceID, name, address string) {
 func (w *wrapper) AddOrUpdatePendingDevice(device protocol.DeviceID, name, address string) {
 	w.mut.Lock()
 	w.mut.Lock()
 	defer w.mut.Unlock()
 	defer w.mut.Unlock()

+ 4 - 2
lib/connections/limiter.go

@@ -21,6 +21,7 @@ import (
 // limiter manages a read and write rate limit, reacting to config changes
 // limiter manages a read and write rate limit, reacting to config changes
 // as appropriate.
 // as appropriate.
 type limiter struct {
 type limiter struct {
+	myID                protocol.DeviceID
 	mu                  sync.Mutex
 	mu                  sync.Mutex
 	write               *rate.Limiter
 	write               *rate.Limiter
 	read                *rate.Limiter
 	read                *rate.Limiter
@@ -40,8 +41,9 @@ const (
 	maxSingleWriteSize = 8 << 10
 	maxSingleWriteSize = 8 << 10
 )
 )
 
 
-func newLimiter(cfg config.Wrapper) *limiter {
+func newLimiter(myId protocol.DeviceID, cfg config.Wrapper) *limiter {
 	l := &limiter{
 	l := &limiter{
+		myID:                myId,
 		write:               rate.NewLimiter(rate.Inf, limiterBurstSize),
 		write:               rate.NewLimiter(rate.Inf, limiterBurstSize),
 		read:                rate.NewLimiter(rate.Inf, limiterBurstSize),
 		read:                rate.NewLimiter(rate.Inf, limiterBurstSize),
 		mu:                  sync.NewMutex(),
 		mu:                  sync.NewMutex(),
@@ -89,7 +91,7 @@ func (lim *limiter) processDevicesConfigurationLocked(from, to config.Configurat
 
 
 	// Mark devices which should not be removed, create new limiters if needed and assign new limiter rate
 	// Mark devices which should not be removed, create new limiters if needed and assign new limiter rate
 	for _, dev := range to.Devices {
 	for _, dev := range to.Devices {
-		if dev.DeviceID == to.MyID {
+		if dev.DeviceID == lim.myID {
 			// This limiter was created for local device. Should skip this device
 			// This limiter was created for local device. Should skip this device
 			continue
 			continue
 		}
 		}

+ 5 - 5
lib/connections/limiter_test.go

@@ -46,7 +46,7 @@ func initConfig() config.Wrapper {
 
 
 func TestLimiterInit(t *testing.T) {
 func TestLimiterInit(t *testing.T) {
 	cfg := initConfig()
 	cfg := initConfig()
-	lim := newLimiter(cfg)
+	lim := newLimiter(device1, cfg)
 
 
 	device2ReadLimit := dev2Conf.MaxRecvKbps
 	device2ReadLimit := dev2Conf.MaxRecvKbps
 	device2WriteLimit := dev2Conf.MaxSendKbps
 	device2WriteLimit := dev2Conf.MaxSendKbps
@@ -71,7 +71,7 @@ func TestLimiterInit(t *testing.T) {
 
 
 func TestSetDeviceLimits(t *testing.T) {
 func TestSetDeviceLimits(t *testing.T) {
 	cfg := initConfig()
 	cfg := initConfig()
-	lim := newLimiter(cfg)
+	lim := newLimiter(device1, cfg)
 
 
 	// should still be inf/inf because this is local device
 	// should still be inf/inf because this is local device
 	dev1ReadLimit := rand.Int() % 100000
 	dev1ReadLimit := rand.Int() % 100000
@@ -109,7 +109,7 @@ func TestSetDeviceLimits(t *testing.T) {
 
 
 func TestRemoveDevice(t *testing.T) {
 func TestRemoveDevice(t *testing.T) {
 	cfg := initConfig()
 	cfg := initConfig()
-	lim := newLimiter(cfg)
+	lim := newLimiter(device1, cfg)
 
 
 	waiter, _ := cfg.RemoveDevice(device3)
 	waiter, _ := cfg.RemoveDevice(device3)
 	waiter.Wait()
 	waiter.Wait()
@@ -129,7 +129,7 @@ func TestRemoveDevice(t *testing.T) {
 
 
 func TestAddDevice(t *testing.T) {
 func TestAddDevice(t *testing.T) {
 	cfg := initConfig()
 	cfg := initConfig()
-	lim := newLimiter(cfg)
+	lim := newLimiter(device1, cfg)
 
 
 	addedDevice, _ := protocol.DeviceIDFromString("XZJ4UNS-ENI7QGJ-J45DT6G-QSGML2K-6I4XVOG-NAZ7BF5-2VAOWNT-TFDOMQU")
 	addedDevice, _ := protocol.DeviceIDFromString("XZJ4UNS-ENI7QGJ-J45DT6G-QSGML2K-6I4XVOG-NAZ7BF5-2VAOWNT-TFDOMQU")
 	addDevConf := config.NewDeviceConfiguration(addedDevice, "addedDevice")
 	addDevConf := config.NewDeviceConfiguration(addedDevice, "addedDevice")
@@ -160,7 +160,7 @@ func TestAddDevice(t *testing.T) {
 
 
 func TestAddAndRemove(t *testing.T) {
 func TestAddAndRemove(t *testing.T) {
 	cfg := initConfig()
 	cfg := initConfig()
-	lim := newLimiter(cfg)
+	lim := newLimiter(device1, cfg)
 
 
 	addedDevice, _ := protocol.DeviceIDFromString("XZJ4UNS-ENI7QGJ-J45DT6G-QSGML2K-6I4XVOG-NAZ7BF5-2VAOWNT-TFDOMQU")
 	addedDevice, _ := protocol.DeviceIDFromString("XZJ4UNS-ENI7QGJ-J45DT6G-QSGML2K-6I4XVOG-NAZ7BF5-2VAOWNT-TFDOMQU")
 	addDevConf := config.NewDeviceConfiguration(addedDevice, "addedDevice")
 	addDevConf := config.NewDeviceConfiguration(addedDevice, "addedDevice")

+ 1 - 1
lib/connections/service.go

@@ -149,7 +149,7 @@ func NewService(cfg config.Wrapper, myID protocol.DeviceID, mdl Model, tlsCfg *t
 		conns:                make(chan internalConn),
 		conns:                make(chan internalConn),
 		bepProtocolName:      bepProtocolName,
 		bepProtocolName:      bepProtocolName,
 		tlsDefaultCommonName: tlsDefaultCommonName,
 		tlsDefaultCommonName: tlsDefaultCommonName,
-		limiter:              newLimiter(cfg),
+		limiter:              newLimiter(myID, cfg),
 		natService:           nat.NewService(myID, cfg),
 		natService:           nat.NewService(myID, cfg),
 		evLogger:             evLogger,
 		evLogger:             evLogger,
 
 

+ 2 - 2
lib/db/structs.go

@@ -4,8 +4,8 @@
 // License, v. 2.0. If a copy of the MPL was not distributed with this file,
 // 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/.
 // You can obtain one at https://mozilla.org/MPL/2.0/.
 
 
-//go:generate go run ../../script/protofmt.go structs.proto
-//go:generate protoc -I ../../ -I . --gogofast_out=Mlib/protocol/bep.proto=github.com/syncthing/syncthing/lib/protocol:. structs.proto
+//go:generate go run ../../proto/scripts/protofmt.go structs.proto
+//go:generate protoc -I ../../ -I ../../proto -I . --gogofast_out=Mlib/protocol/bep.proto=github.com/syncthing/syncthing/lib/protocol:. structs.proto
 
 
 package db
 package db
 
 

+ 1 - 1
lib/discover/local.go

@@ -4,7 +4,7 @@
 // License, v. 2.0. If a copy of the MPL was not distributed with this file,
 // 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/.
 // You can obtain one at https://mozilla.org/MPL/2.0/.
 
 
-//go:generate go run ../../script/protofmt.go local.proto
+//go:generate go run ../../proto/scripts/protofmt.go local.proto
 //go:generate protoc -I ../../ -I . --gogofast_out=. local.proto
 //go:generate protoc -I ../../ -I . --gogofast_out=. local.proto
 
 
 package discover
 package discover

+ 0 - 11
lib/fs/filesystem_copy_range_method.go → lib/fs/copyrangemethod.go

@@ -6,17 +6,6 @@
 
 
 package fs
 package fs
 
 
-type CopyRangeMethod int
-
-const (
-	CopyRangeMethodStandard CopyRangeMethod = iota
-	CopyRangeMethodIoctl
-	CopyRangeMethodCopyFileRange
-	CopyRangeMethodSendFile
-	CopyRangeMethodDuplicateExtents
-	CopyRangeMethodAllWithFallback
-)
-
 func (o CopyRangeMethod) String() string {
 func (o CopyRangeMethod) String() string {
 	switch o {
 	switch o {
 	case CopyRangeMethodStandard:
 	case CopyRangeMethodStandard:

+ 87 - 0
lib/fs/copyrangemethod.pb.go

@@ -0,0 +1,87 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: lib/fs/copyrangemethod.proto
+
+package fs
+
+import (
+	fmt "fmt"
+	proto "github.com/gogo/protobuf/proto"
+	math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+type CopyRangeMethod int32
+
+const (
+	CopyRangeMethodStandard         CopyRangeMethod = 0
+	CopyRangeMethodIoctl            CopyRangeMethod = 1
+	CopyRangeMethodCopyFileRange    CopyRangeMethod = 2
+	CopyRangeMethodSendFile         CopyRangeMethod = 3
+	CopyRangeMethodDuplicateExtents CopyRangeMethod = 4
+	CopyRangeMethodAllWithFallback  CopyRangeMethod = 5
+)
+
+var CopyRangeMethod_name = map[int32]string{
+	0: "COPY_RANGE_METHOD_STANDARD",
+	1: "COPY_RANGE_METHOD_IOCTL",
+	2: "COPY_RANGE_METHOD_COPY_FILE_RANGE",
+	3: "COPY_RANGE_METHOD_SEND_FILE",
+	4: "COPY_RANGE_METHOD_DUPLICATE_EXTENTS",
+	5: "COPY_RANGE_METHOD_ALL_WITH_FALLBACK",
+}
+
+var CopyRangeMethod_value = map[string]int32{
+	"COPY_RANGE_METHOD_STANDARD":          0,
+	"COPY_RANGE_METHOD_IOCTL":             1,
+	"COPY_RANGE_METHOD_COPY_FILE_RANGE":   2,
+	"COPY_RANGE_METHOD_SEND_FILE":         3,
+	"COPY_RANGE_METHOD_DUPLICATE_EXTENTS": 4,
+	"COPY_RANGE_METHOD_ALL_WITH_FALLBACK": 5,
+}
+
+func (CopyRangeMethod) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_78e1061c3022e87e, []int{0}
+}
+
+func init() {
+	proto.RegisterEnum("fs.CopyRangeMethod", CopyRangeMethod_name, CopyRangeMethod_value)
+}
+
+func init() { proto.RegisterFile("lib/fs/copyrangemethod.proto", fileDescriptor_78e1061c3022e87e) }
+
+var fileDescriptor_78e1061c3022e87e = []byte{
+	// 357 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x92, 0xbf, 0x4e, 0xc2, 0x40,
+	0x00, 0xc6, 0x0b, 0xa8, 0x43, 0x17, 0x9b, 0xc6, 0x04, 0x53, 0xc8, 0x59, 0x25, 0x2e, 0x0e, 0x30,
+	0x18, 0x27, 0x5d, 0x8e, 0xf6, 0x0a, 0x0d, 0x47, 0x21, 0x50, 0x83, 0xba, 0x34, 0xfd, 0x07, 0x6d,
+	0x3c, 0xda, 0x86, 0x1e, 0x89, 0xbc, 0x42, 0x27, 0x5f, 0xa0, 0x89, 0x9b, 0xaf, 0xe2, 0xc8, 0xe8,
+	0x8a, 0x5d, 0x7c, 0x0c, 0x43, 0x59, 0x4c, 0x61, 0xbb, 0xfb, 0xbe, 0xfc, 0x7e, 0xf9, 0x92, 0x3b,
+	0xb6, 0x4e, 0x7c, 0xab, 0x35, 0x8d, 0x5b, 0x76, 0x18, 0xad, 0x16, 0x66, 0x30, 0x73, 0xe7, 0x2e,
+	0xf5, 0x42, 0xa7, 0x19, 0x2d, 0x42, 0x1a, 0xf2, 0xe5, 0x69, 0x7c, 0xf3, 0x59, 0x61, 0x4f, 0xa5,
+	0x30, 0x5a, 0x8d, 0xb6, 0x6d, 0x3f, 0x6f, 0xf9, 0x7b, 0x56, 0x90, 0x06, 0xc3, 0x67, 0x63, 0x04,
+	0xb5, 0x0e, 0x32, 0xfa, 0x48, 0xef, 0x0e, 0x64, 0x63, 0xac, 0x43, 0x4d, 0x86, 0x23, 0x99, 0x63,
+	0x84, 0x5a, 0x92, 0x8a, 0xd5, 0x02, 0x34, 0xa6, 0x66, 0xe0, 0x98, 0x0b, 0x87, 0xbf, 0x63, 0xab,
+	0xfb, 0xb0, 0x3a, 0x90, 0x74, 0xcc, 0x95, 0x84, 0xf3, 0x24, 0x15, 0xcf, 0x0a, 0xa4, 0x1a, 0xda,
+	0x94, 0xf0, 0x1d, 0xf6, 0x72, 0x1f, 0xcb, 0x13, 0x45, 0xc5, 0x68, 0x17, 0x73, 0x65, 0x41, 0x4c,
+	0x52, 0xb1, 0x5e, 0x10, 0x6c, 0xaf, 0x8a, 0x4f, 0xdc, 0x3c, 0xe2, 0x1f, 0xd8, 0xda, 0x81, 0xf1,
+	0x48, 0x93, 0x73, 0x11, 0x57, 0x39, 0xbc, 0xde, 0x0d, 0x9c, 0xad, 0x82, 0xc7, 0x6c, 0x63, 0x9f,
+	0x96, 0x1f, 0x87, 0x58, 0x95, 0xa0, 0x8e, 0x0c, 0xf4, 0xa4, 0x23, 0x4d, 0x1f, 0x73, 0x47, 0x42,
+	0x23, 0x49, 0xc5, 0x8b, 0x82, 0x45, 0x5e, 0x46, 0xc4, 0xb7, 0x4d, 0xea, 0xa2, 0x37, 0xea, 0x06,
+	0x34, 0xe6, 0x7b, 0x87, 0x6c, 0x10, 0x63, 0x63, 0xa2, 0xea, 0x5d, 0x43, 0x81, 0x18, 0xb7, 0xa1,
+	0xd4, 0xe3, 0x8e, 0x85, 0xab, 0x24, 0x15, 0x41, 0xc1, 0x06, 0x09, 0x99, 0xf8, 0xd4, 0x53, 0x4c,
+	0x42, 0x2c, 0xd3, 0x7e, 0x6d, 0x4b, 0x5f, 0x1b, 0xc0, 0xac, 0x37, 0x80, 0xf9, 0xfd, 0x01, 0xcc,
+	0x7b, 0x06, 0x98, 0x8f, 0x0c, 0x94, 0xd6, 0x19, 0x60, 0xbe, 0x33, 0xc0, 0xbc, 0x5c, 0xcf, 0x7c,
+	0xea, 0x2d, 0xad, 0xa6, 0x1d, 0xce, 0x5b, 0xf1, 0x2a, 0xb0, 0xa9, 0xe7, 0x07, 0xb3, 0x7f, 0xa7,
+	0xdd, 0x47, 0xb0, 0x4e, 0xf2, 0x97, 0xbf, 0xfd, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x06, 0xa6, 0xad,
+	0xd0, 0x19, 0x02, 0x00, 0x00,
+}

+ 0 - 7
lib/fs/types.go

@@ -6,13 +6,6 @@
 
 
 package fs
 package fs
 
 
-type FilesystemType int
-
-const (
-	FilesystemTypeBasic FilesystemType = iota // default is basic
-	FilesystemTypeFake
-)
-
 func (t FilesystemType) String() string {
 func (t FilesystemType) String() string {
 	switch t {
 	switch t {
 	case FilesystemTypeBasic:
 	case FilesystemTypeBasic:

+ 65 - 0
lib/fs/types.pb.go

@@ -0,0 +1,65 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: lib/fs/types.proto
+
+package fs
+
+import (
+	fmt "fmt"
+	proto "github.com/gogo/protobuf/proto"
+	math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+type FilesystemType int32
+
+const (
+	FilesystemTypeBasic FilesystemType = 0
+	FilesystemTypeFake  FilesystemType = 1
+)
+
+var FilesystemType_name = map[int32]string{
+	0: "FILESYSTEM_TYPE_BASIC",
+	1: "FILESYSTEM_TYPE_FAKE",
+}
+
+var FilesystemType_value = map[string]int32{
+	"FILESYSTEM_TYPE_BASIC": 0,
+	"FILESYSTEM_TYPE_FAKE":  1,
+}
+
+func (FilesystemType) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_b556f45c4309ad5d, []int{0}
+}
+
+func init() {
+	proto.RegisterEnum("fs.FilesystemType", FilesystemType_name, FilesystemType_value)
+}
+
+func init() { proto.RegisterFile("lib/fs/types.proto", fileDescriptor_b556f45c4309ad5d) }
+
+var fileDescriptor_b556f45c4309ad5d = []byte{
+	// 194 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xca, 0xc9, 0x4c, 0xd2,
+	0x4f, 0x2b, 0xd6, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62,
+	0x4a, 0x2b, 0xd6, 0x2a, 0xe3, 0xe2, 0x73, 0xcb, 0xcc, 0x49, 0x2d, 0xae, 0x2c, 0x2e, 0x49, 0xcd,
+	0x0d, 0xa9, 0x2c, 0x48, 0x15, 0x32, 0xe2, 0x12, 0x75, 0xf3, 0xf4, 0x71, 0x0d, 0x8e, 0x0c, 0x0e,
+	0x71, 0xf5, 0x8d, 0x0f, 0x89, 0x0c, 0x70, 0x8d, 0x77, 0x72, 0x0c, 0xf6, 0x74, 0x16, 0x60, 0x90,
+	0x12, 0xef, 0x9a, 0xab, 0x20, 0x8c, 0xaa, 0xdc, 0x29, 0xb1, 0x38, 0x33, 0x59, 0xc8, 0x80, 0x4b,
+	0x04, 0x5d, 0x8f, 0x9b, 0xa3, 0xb7, 0xab, 0x00, 0xa3, 0x94, 0x58, 0xd7, 0x5c, 0x05, 0x21, 0x54,
+	0x2d, 0x6e, 0x89, 0xd9, 0xa9, 0x4e, 0xce, 0x27, 0x1e, 0xca, 0x31, 0x5c, 0x78, 0x28, 0xc7, 0xf0,
+	0xe2, 0x91, 0x1c, 0xc3, 0x84, 0xc7, 0x72, 0x0c, 0x0b, 0x1e, 0xcb, 0x31, 0x5e, 0x78, 0x2c, 0xc7,
+	0x70, 0xe3, 0xb1, 0x1c, 0x43, 0x94, 0x6a, 0x7a, 0x66, 0x49, 0x46, 0x69, 0x92, 0x5e, 0x72, 0x7e,
+	0xae, 0x7e, 0x71, 0x65, 0x5e, 0x72, 0x49, 0x46, 0x66, 0x5e, 0x3a, 0x12, 0x0b, 0xe2, 0x99, 0x24,
+	0x36, 0xb0, 0x3f, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x86, 0xe8, 0x6b, 0xac, 0xdd, 0x00,
+	0x00, 0x00,
+}

+ 13 - 11
lib/model/folder.go

@@ -44,11 +44,12 @@ type folder struct {
 
 
 	localFlags uint32
 	localFlags uint32
 
 
-	model   *model
-	shortID protocol.ShortID
-	fset    *db.FileSet
-	ignores *ignore.Matcher
-	ctx     context.Context
+	model         *model
+	shortID       protocol.ShortID
+	fset          *db.FileSet
+	ignores       *ignore.Matcher
+	modTimeWindow time.Duration
+	ctx           context.Context
 
 
 	scanInterval           time.Duration
 	scanInterval           time.Duration
 	scanTimer              *time.Timer
 	scanTimer              *time.Timer
@@ -95,10 +96,11 @@ func newFolder(model *model, fset *db.FileSet, ignores *ignore.Matcher, cfg conf
 		FolderStatisticsReference: stats.NewFolderStatisticsReference(model.db, cfg.ID),
 		FolderStatisticsReference: stats.NewFolderStatisticsReference(model.db, cfg.ID),
 		ioLimiter:                 ioLimiter,
 		ioLimiter:                 ioLimiter,
 
 
-		model:   model,
-		shortID: model.shortID,
-		fset:    fset,
-		ignores: ignores,
+		model:         model,
+		shortID:       model.shortID,
+		fset:          fset,
+		ignores:       ignores,
+		modTimeWindow: cfg.ModTimeWindow(),
 
 
 		scanInterval:           time.Duration(cfg.RescanIntervalS) * time.Second,
 		scanInterval:           time.Duration(cfg.RescanIntervalS) * time.Second,
 		scanTimer:              time.NewTimer(0), // The first scan should be done immediately.
 		scanTimer:              time.NewTimer(0), // The first scan should be done immediately.
@@ -457,7 +459,7 @@ func (f *folder) scanSubdirs(subDirs []string) error {
 		ShortID:               f.shortID,
 		ShortID:               f.shortID,
 		ProgressTickIntervalS: f.ScanProgressIntervalS,
 		ProgressTickIntervalS: f.ScanProgressIntervalS,
 		LocalFlags:            f.localFlags,
 		LocalFlags:            f.localFlags,
-		ModTimeWindow:         f.ModTimeWindow(),
+		ModTimeWindow:         f.modTimeWindow,
 		EventLogger:           f.evLogger,
 		EventLogger:           f.evLogger,
 	})
 	})
 
 
@@ -480,7 +482,7 @@ func (f *folder) scanSubdirs(subDirs []string) error {
 		batchAppend = func(fi protocol.FileInfo, snap *db.Snapshot) {
 		batchAppend = func(fi protocol.FileInfo, snap *db.Snapshot) {
 			switch gf, ok := snap.GetGlobal(fi.Name); {
 			switch gf, ok := snap.GetGlobal(fi.Name); {
 			case !ok:
 			case !ok:
-			case gf.IsEquivalentOptional(fi, f.ModTimeWindow(), false, false, protocol.FlagLocalReceiveOnly):
+			case gf.IsEquivalentOptional(fi, f.modTimeWindow, false, false, protocol.FlagLocalReceiveOnly):
 				// What we have locally is equivalent to the global file.
 				// What we have locally is equivalent to the global file.
 				fi.Version = fi.Version.Merge(gf.Version)
 				fi.Version = fi.Version.Merge(gf.Version)
 				fallthrough
 				fallthrough

+ 1 - 1
lib/model/folder_sendonly.go

@@ -77,7 +77,7 @@ func (f *sendOnlyFolder) pull() bool {
 		}
 		}
 
 
 		file := intf.(protocol.FileInfo)
 		file := intf.(protocol.FileInfo)
-		if !file.IsEquivalentOptional(curFile, f.ModTimeWindow(), f.IgnorePerms, false, 0) {
+		if !file.IsEquivalentOptional(curFile, f.modTimeWindow, f.IgnorePerms, false, 0) {
 			return true
 			return true
 		}
 		}
 
 

+ 10 - 10
lib/model/folder_sendrecv.go

@@ -420,17 +420,17 @@ func (f *sendReceiveFolder) processNeeded(snap *db.Snapshot, dbUpdateChan chan<-
 	// Now do the file queue. Reorder it according to configuration.
 	// Now do the file queue. Reorder it according to configuration.
 
 
 	switch f.Order {
 	switch f.Order {
-	case config.OrderRandom:
+	case config.PullOrderRandom:
 		f.queue.Shuffle()
 		f.queue.Shuffle()
-	case config.OrderAlphabetic:
+	case config.PullOrderAlphabetic:
 	// The queue is already in alphabetic order.
 	// The queue is already in alphabetic order.
-	case config.OrderSmallestFirst:
+	case config.PullOrderSmallestFirst:
 		f.queue.SortSmallestFirst()
 		f.queue.SortSmallestFirst()
-	case config.OrderLargestFirst:
+	case config.PullOrderLargestFirst:
 		f.queue.SortLargestFirst()
 		f.queue.SortLargestFirst()
-	case config.OrderOldestFirst:
+	case config.PullOrderOldestFirst:
 		f.queue.SortOldestFirst()
 		f.queue.SortOldestFirst()
-	case config.OrderNewestFirst:
+	case config.PullOrderNewestFirst:
 		f.queue.SortNewestFirst()
 		f.queue.SortNewestFirst()
 	}
 	}
 
 
@@ -651,7 +651,7 @@ func (f *sendReceiveFolder) handleDir(file protocol.FileInfo, snap *db.Snapshot,
 	// don't handle modification times on directories, because that sucks...)
 	// don't handle modification times on directories, because that sucks...)
 	// It's OK to change mode bits on stuff within non-writable directories.
 	// It's OK to change mode bits on stuff within non-writable directories.
 	if !f.IgnorePerms && !file.NoPermissions {
 	if !f.IgnorePerms && !file.NoPermissions {
-		if err := f.fs.Chmod(file.Name, mode|(fs.FileMode(info.Mode())&retainBits)); err != nil {
+		if err := f.fs.Chmod(file.Name, mode|(info.Mode()&retainBits)); err != nil {
 			f.newPullError(file.Name, err)
 			f.newPullError(file.Name, err)
 			return
 			return
 		}
 		}
@@ -962,7 +962,7 @@ func (f *sendReceiveFolder) renameFile(cur, source, target protocol.FileInfo, sn
 	default:
 	default:
 		var fi protocol.FileInfo
 		var fi protocol.FileInfo
 		if fi, err = scanner.CreateFileInfo(stat, target.Name, f.fs); err == nil {
 		if fi, err = scanner.CreateFileInfo(stat, target.Name, f.fs); err == nil {
-			if !fi.IsEquivalentOptional(curTarget, f.ModTimeWindow(), f.IgnorePerms, true, protocol.LocalAllFlags) {
+			if !fi.IsEquivalentOptional(curTarget, f.modTimeWindow, f.IgnorePerms, true, protocol.LocalAllFlags) {
 				// Target changed
 				// Target changed
 				scanChan <- target.Name
 				scanChan <- target.Name
 				err = errModified
 				err = errModified
@@ -1874,7 +1874,7 @@ func (f *sendReceiveFolder) deleteDirOnDisk(dir string, snap *db.Snapshot, scanC
 			hasToBeScanned = true
 			hasToBeScanned = true
 			continue
 			continue
 		}
 		}
-		if !cf.IsEquivalentOptional(diskFile, f.ModTimeWindow(), f.IgnorePerms, true, protocol.LocalAllFlags) {
+		if !cf.IsEquivalentOptional(diskFile, f.modTimeWindow, f.IgnorePerms, true, protocol.LocalAllFlags) {
 			// File on disk changed compared to what we have in db
 			// File on disk changed compared to what we have in db
 			// -> schedule scan.
 			// -> schedule scan.
 			scanChan <- fullDirFile
 			scanChan <- fullDirFile
@@ -1946,7 +1946,7 @@ func (f *sendReceiveFolder) scanIfItemChanged(name string, stat fs.FileInfo, ite
 		return errors.Wrap(err, "comparing item on disk to db")
 		return errors.Wrap(err, "comparing item on disk to db")
 	}
 	}
 
 
-	if !statItem.IsEquivalentOptional(item, f.ModTimeWindow(), f.IgnorePerms, true, protocol.LocalAllFlags) {
+	if !statItem.IsEquivalentOptional(item, f.modTimeWindow, f.IgnorePerms, true, protocol.LocalAllFlags) {
 		return errModified
 		return errModified
 	}
 	}
 
 

+ 4 - 1
lib/model/model.go

@@ -1781,7 +1781,10 @@ func (m *model) OnHello(remoteID protocol.DeviceID, addr net.Addr, hello protoco
 func (m *model) GetHello(id protocol.DeviceID) protocol.HelloIntf {
 func (m *model) GetHello(id protocol.DeviceID) protocol.HelloIntf {
 	name := ""
 	name := ""
 	if _, ok := m.cfg.Device(id); ok {
 	if _, ok := m.cfg.Device(id); ok {
-		name = m.cfg.MyName()
+		// Set our name (from the config of our device ID) only if we already know about the other side device ID.
+		if myCfg, ok := m.cfg.Device(m.id); ok {
+			name = myCfg.Name
+		}
 	}
 	}
 	return &protocol.Hello{
 	return &protocol.Hello{
 		DeviceName:    name,
 		DeviceName:    name,

+ 1 - 1
lib/model/model_test.go

@@ -340,7 +340,7 @@ func TestDeviceRename(t *testing.T) {
 		t.Errorf("Device name got overwritten")
 		t.Errorf("Device name got overwritten")
 	}
 	}
 
 
-	cfgw, err := config.Load("testdata/tmpconfig.xml", myID, events.NoopLogger)
+	cfgw, _, err := config.Load("testdata/tmpconfig.xml", myID, events.NoopLogger)
 	if err != nil {
 	if err != nil {
 		t.Error(err)
 		t.Error(err)
 		return
 		return

+ 138 - 138
lib/protocol/bep.pb.go

@@ -1,5 +1,5 @@
 // Code generated by protoc-gen-gogo. DO NOT EDIT.
 // Code generated by protoc-gen-gogo. DO NOT EDIT.
-// source: bep.proto
+// source: lib/protocol/bep.proto
 
 
 package protocol
 package protocol
 
 
@@ -63,7 +63,7 @@ func (x MessageType) String() string {
 }
 }
 
 
 func (MessageType) EnumDescriptor() ([]byte, []int) {
 func (MessageType) EnumDescriptor() ([]byte, []int) {
-	return fileDescriptor_e3f59eb60afbbc6e, []int{0}
+	return fileDescriptor_311ef540e10d9705, []int{0}
 }
 }
 
 
 type MessageCompression int32
 type MessageCompression int32
@@ -88,7 +88,7 @@ func (x MessageCompression) String() string {
 }
 }
 
 
 func (MessageCompression) EnumDescriptor() ([]byte, []int) {
 func (MessageCompression) EnumDescriptor() ([]byte, []int) {
-	return fileDescriptor_e3f59eb60afbbc6e, []int{1}
+	return fileDescriptor_311ef540e10d9705, []int{1}
 }
 }
 
 
 type Compression int32
 type Compression int32
@@ -116,7 +116,7 @@ func (x Compression) String() string {
 }
 }
 
 
 func (Compression) EnumDescriptor() ([]byte, []int) {
 func (Compression) EnumDescriptor() ([]byte, []int) {
-	return fileDescriptor_e3f59eb60afbbc6e, []int{2}
+	return fileDescriptor_311ef540e10d9705, []int{2}
 }
 }
 
 
 type FileInfoType int32
 type FileInfoType int32
@@ -150,7 +150,7 @@ func (x FileInfoType) String() string {
 }
 }
 
 
 func (FileInfoType) EnumDescriptor() ([]byte, []int) {
 func (FileInfoType) EnumDescriptor() ([]byte, []int) {
-	return fileDescriptor_e3f59eb60afbbc6e, []int{3}
+	return fileDescriptor_311ef540e10d9705, []int{3}
 }
 }
 
 
 type ErrorCode int32
 type ErrorCode int32
@@ -181,7 +181,7 @@ func (x ErrorCode) String() string {
 }
 }
 
 
 func (ErrorCode) EnumDescriptor() ([]byte, []int) {
 func (ErrorCode) EnumDescriptor() ([]byte, []int) {
-	return fileDescriptor_e3f59eb60afbbc6e, []int{4}
+	return fileDescriptor_311ef540e10d9705, []int{4}
 }
 }
 
 
 type FileDownloadProgressUpdateType int32
 type FileDownloadProgressUpdateType int32
@@ -206,7 +206,7 @@ func (x FileDownloadProgressUpdateType) String() string {
 }
 }
 
 
 func (FileDownloadProgressUpdateType) EnumDescriptor() ([]byte, []int) {
 func (FileDownloadProgressUpdateType) EnumDescriptor() ([]byte, []int) {
-	return fileDescriptor_e3f59eb60afbbc6e, []int{5}
+	return fileDescriptor_311ef540e10d9705, []int{5}
 }
 }
 
 
 type Hello struct {
 type Hello struct {
@@ -219,7 +219,7 @@ func (m *Hello) Reset()         { *m = Hello{} }
 func (m *Hello) String() string { return proto.CompactTextString(m) }
 func (m *Hello) String() string { return proto.CompactTextString(m) }
 func (*Hello) ProtoMessage()    {}
 func (*Hello) ProtoMessage()    {}
 func (*Hello) Descriptor() ([]byte, []int) {
 func (*Hello) Descriptor() ([]byte, []int) {
-	return fileDescriptor_e3f59eb60afbbc6e, []int{0}
+	return fileDescriptor_311ef540e10d9705, []int{0}
 }
 }
 func (m *Hello) XXX_Unmarshal(b []byte) error {
 func (m *Hello) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
 	return m.Unmarshal(b)
@@ -257,7 +257,7 @@ func (m *Header) Reset()         { *m = Header{} }
 func (m *Header) String() string { return proto.CompactTextString(m) }
 func (m *Header) String() string { return proto.CompactTextString(m) }
 func (*Header) ProtoMessage()    {}
 func (*Header) ProtoMessage()    {}
 func (*Header) Descriptor() ([]byte, []int) {
 func (*Header) Descriptor() ([]byte, []int) {
-	return fileDescriptor_e3f59eb60afbbc6e, []int{1}
+	return fileDescriptor_311ef540e10d9705, []int{1}
 }
 }
 func (m *Header) XXX_Unmarshal(b []byte) error {
 func (m *Header) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
 	return m.Unmarshal(b)
@@ -294,7 +294,7 @@ func (m *ClusterConfig) Reset()         { *m = ClusterConfig{} }
 func (m *ClusterConfig) String() string { return proto.CompactTextString(m) }
 func (m *ClusterConfig) String() string { return proto.CompactTextString(m) }
 func (*ClusterConfig) ProtoMessage()    {}
 func (*ClusterConfig) ProtoMessage()    {}
 func (*ClusterConfig) Descriptor() ([]byte, []int) {
 func (*ClusterConfig) Descriptor() ([]byte, []int) {
-	return fileDescriptor_e3f59eb60afbbc6e, []int{2}
+	return fileDescriptor_311ef540e10d9705, []int{2}
 }
 }
 func (m *ClusterConfig) XXX_Unmarshal(b []byte) error {
 func (m *ClusterConfig) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
 	return m.Unmarshal(b)
@@ -338,7 +338,7 @@ func (m *Folder) Reset()         { *m = Folder{} }
 func (m *Folder) String() string { return proto.CompactTextString(m) }
 func (m *Folder) String() string { return proto.CompactTextString(m) }
 func (*Folder) ProtoMessage()    {}
 func (*Folder) ProtoMessage()    {}
 func (*Folder) Descriptor() ([]byte, []int) {
 func (*Folder) Descriptor() ([]byte, []int) {
-	return fileDescriptor_e3f59eb60afbbc6e, []int{3}
+	return fileDescriptor_311ef540e10d9705, []int{3}
 }
 }
 func (m *Folder) XXX_Unmarshal(b []byte) error {
 func (m *Folder) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
 	return m.Unmarshal(b)
@@ -383,7 +383,7 @@ func (m *Device) Reset()         { *m = Device{} }
 func (m *Device) String() string { return proto.CompactTextString(m) }
 func (m *Device) String() string { return proto.CompactTextString(m) }
 func (*Device) ProtoMessage()    {}
 func (*Device) ProtoMessage()    {}
 func (*Device) Descriptor() ([]byte, []int) {
 func (*Device) Descriptor() ([]byte, []int) {
-	return fileDescriptor_e3f59eb60afbbc6e, []int{4}
+	return fileDescriptor_311ef540e10d9705, []int{4}
 }
 }
 func (m *Device) XXX_Unmarshal(b []byte) error {
 func (m *Device) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
 	return m.Unmarshal(b)
@@ -421,7 +421,7 @@ func (m *Index) Reset()         { *m = Index{} }
 func (m *Index) String() string { return proto.CompactTextString(m) }
 func (m *Index) String() string { return proto.CompactTextString(m) }
 func (*Index) ProtoMessage()    {}
 func (*Index) ProtoMessage()    {}
 func (*Index) Descriptor() ([]byte, []int) {
 func (*Index) Descriptor() ([]byte, []int) {
-	return fileDescriptor_e3f59eb60afbbc6e, []int{5}
+	return fileDescriptor_311ef540e10d9705, []int{5}
 }
 }
 func (m *Index) XXX_Unmarshal(b []byte) error {
 func (m *Index) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
 	return m.Unmarshal(b)
@@ -459,7 +459,7 @@ func (m *IndexUpdate) Reset()         { *m = IndexUpdate{} }
 func (m *IndexUpdate) String() string { return proto.CompactTextString(m) }
 func (m *IndexUpdate) String() string { return proto.CompactTextString(m) }
 func (*IndexUpdate) ProtoMessage()    {}
 func (*IndexUpdate) ProtoMessage()    {}
 func (*IndexUpdate) Descriptor() ([]byte, []int) {
 func (*IndexUpdate) Descriptor() ([]byte, []int) {
-	return fileDescriptor_e3f59eb60afbbc6e, []int{6}
+	return fileDescriptor_311ef540e10d9705, []int{6}
 }
 }
 func (m *IndexUpdate) XXX_Unmarshal(b []byte) error {
 func (m *IndexUpdate) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
 	return m.Unmarshal(b)
@@ -518,7 +518,7 @@ type FileInfo struct {
 func (m *FileInfo) Reset()      { *m = FileInfo{} }
 func (m *FileInfo) Reset()      { *m = FileInfo{} }
 func (*FileInfo) ProtoMessage() {}
 func (*FileInfo) ProtoMessage() {}
 func (*FileInfo) Descriptor() ([]byte, []int) {
 func (*FileInfo) Descriptor() ([]byte, []int) {
-	return fileDescriptor_e3f59eb60afbbc6e, []int{7}
+	return fileDescriptor_311ef540e10d9705, []int{7}
 }
 }
 func (m *FileInfo) XXX_Unmarshal(b []byte) error {
 func (m *FileInfo) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
 	return m.Unmarshal(b)
@@ -557,7 +557,7 @@ type BlockInfo struct {
 func (m *BlockInfo) Reset()      { *m = BlockInfo{} }
 func (m *BlockInfo) Reset()      { *m = BlockInfo{} }
 func (*BlockInfo) ProtoMessage() {}
 func (*BlockInfo) ProtoMessage() {}
 func (*BlockInfo) Descriptor() ([]byte, []int) {
 func (*BlockInfo) Descriptor() ([]byte, []int) {
-	return fileDescriptor_e3f59eb60afbbc6e, []int{8}
+	return fileDescriptor_311ef540e10d9705, []int{8}
 }
 }
 func (m *BlockInfo) XXX_Unmarshal(b []byte) error {
 func (m *BlockInfo) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
 	return m.Unmarshal(b)
@@ -594,7 +594,7 @@ func (m *Vector) Reset()         { *m = Vector{} }
 func (m *Vector) String() string { return proto.CompactTextString(m) }
 func (m *Vector) String() string { return proto.CompactTextString(m) }
 func (*Vector) ProtoMessage()    {}
 func (*Vector) ProtoMessage()    {}
 func (*Vector) Descriptor() ([]byte, []int) {
 func (*Vector) Descriptor() ([]byte, []int) {
-	return fileDescriptor_e3f59eb60afbbc6e, []int{9}
+	return fileDescriptor_311ef540e10d9705, []int{9}
 }
 }
 func (m *Vector) XXX_Unmarshal(b []byte) error {
 func (m *Vector) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
 	return m.Unmarshal(b)
@@ -632,7 +632,7 @@ func (m *Counter) Reset()         { *m = Counter{} }
 func (m *Counter) String() string { return proto.CompactTextString(m) }
 func (m *Counter) String() string { return proto.CompactTextString(m) }
 func (*Counter) ProtoMessage()    {}
 func (*Counter) ProtoMessage()    {}
 func (*Counter) Descriptor() ([]byte, []int) {
 func (*Counter) Descriptor() ([]byte, []int) {
-	return fileDescriptor_e3f59eb60afbbc6e, []int{10}
+	return fileDescriptor_311ef540e10d9705, []int{10}
 }
 }
 func (m *Counter) XXX_Unmarshal(b []byte) error {
 func (m *Counter) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
 	return m.Unmarshal(b)
@@ -676,7 +676,7 @@ func (m *Request) Reset()         { *m = Request{} }
 func (m *Request) String() string { return proto.CompactTextString(m) }
 func (m *Request) String() string { return proto.CompactTextString(m) }
 func (*Request) ProtoMessage()    {}
 func (*Request) ProtoMessage()    {}
 func (*Request) Descriptor() ([]byte, []int) {
 func (*Request) Descriptor() ([]byte, []int) {
-	return fileDescriptor_e3f59eb60afbbc6e, []int{11}
+	return fileDescriptor_311ef540e10d9705, []int{11}
 }
 }
 func (m *Request) XXX_Unmarshal(b []byte) error {
 func (m *Request) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
 	return m.Unmarshal(b)
@@ -715,7 +715,7 @@ func (m *Response) Reset()         { *m = Response{} }
 func (m *Response) String() string { return proto.CompactTextString(m) }
 func (m *Response) String() string { return proto.CompactTextString(m) }
 func (*Response) ProtoMessage()    {}
 func (*Response) ProtoMessage()    {}
 func (*Response) Descriptor() ([]byte, []int) {
 func (*Response) Descriptor() ([]byte, []int) {
-	return fileDescriptor_e3f59eb60afbbc6e, []int{12}
+	return fileDescriptor_311ef540e10d9705, []int{12}
 }
 }
 func (m *Response) XXX_Unmarshal(b []byte) error {
 func (m *Response) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
 	return m.Unmarshal(b)
@@ -753,7 +753,7 @@ func (m *DownloadProgress) Reset()         { *m = DownloadProgress{} }
 func (m *DownloadProgress) String() string { return proto.CompactTextString(m) }
 func (m *DownloadProgress) String() string { return proto.CompactTextString(m) }
 func (*DownloadProgress) ProtoMessage()    {}
 func (*DownloadProgress) ProtoMessage()    {}
 func (*DownloadProgress) Descriptor() ([]byte, []int) {
 func (*DownloadProgress) Descriptor() ([]byte, []int) {
-	return fileDescriptor_e3f59eb60afbbc6e, []int{13}
+	return fileDescriptor_311ef540e10d9705, []int{13}
 }
 }
 func (m *DownloadProgress) XXX_Unmarshal(b []byte) error {
 func (m *DownloadProgress) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
 	return m.Unmarshal(b)
@@ -794,7 +794,7 @@ func (m *FileDownloadProgressUpdate) Reset()         { *m = FileDownloadProgress
 func (m *FileDownloadProgressUpdate) String() string { return proto.CompactTextString(m) }
 func (m *FileDownloadProgressUpdate) String() string { return proto.CompactTextString(m) }
 func (*FileDownloadProgressUpdate) ProtoMessage()    {}
 func (*FileDownloadProgressUpdate) ProtoMessage()    {}
 func (*FileDownloadProgressUpdate) Descriptor() ([]byte, []int) {
 func (*FileDownloadProgressUpdate) Descriptor() ([]byte, []int) {
-	return fileDescriptor_e3f59eb60afbbc6e, []int{14}
+	return fileDescriptor_311ef540e10d9705, []int{14}
 }
 }
 func (m *FileDownloadProgressUpdate) XXX_Unmarshal(b []byte) error {
 func (m *FileDownloadProgressUpdate) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
 	return m.Unmarshal(b)
@@ -830,7 +830,7 @@ func (m *Ping) Reset()         { *m = Ping{} }
 func (m *Ping) String() string { return proto.CompactTextString(m) }
 func (m *Ping) String() string { return proto.CompactTextString(m) }
 func (*Ping) ProtoMessage()    {}
 func (*Ping) ProtoMessage()    {}
 func (*Ping) Descriptor() ([]byte, []int) {
 func (*Ping) Descriptor() ([]byte, []int) {
-	return fileDescriptor_e3f59eb60afbbc6e, []int{15}
+	return fileDescriptor_311ef540e10d9705, []int{15}
 }
 }
 func (m *Ping) XXX_Unmarshal(b []byte) error {
 func (m *Ping) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
 	return m.Unmarshal(b)
@@ -867,7 +867,7 @@ func (m *Close) Reset()         { *m = Close{} }
 func (m *Close) String() string { return proto.CompactTextString(m) }
 func (m *Close) String() string { return proto.CompactTextString(m) }
 func (*Close) ProtoMessage()    {}
 func (*Close) ProtoMessage()    {}
 func (*Close) Descriptor() ([]byte, []int) {
 func (*Close) Descriptor() ([]byte, []int) {
-	return fileDescriptor_e3f59eb60afbbc6e, []int{16}
+	return fileDescriptor_311ef540e10d9705, []int{16}
 }
 }
 func (m *Close) XXX_Unmarshal(b []byte) error {
 func (m *Close) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
 	return m.Unmarshal(b)
@@ -922,126 +922,126 @@ func init() {
 	proto.RegisterType((*Close)(nil), "protocol.Close")
 	proto.RegisterType((*Close)(nil), "protocol.Close")
 }
 }
 
 
-func init() { proto.RegisterFile("bep.proto", fileDescriptor_e3f59eb60afbbc6e) }
+func init() { proto.RegisterFile("lib/protocol/bep.proto", fileDescriptor_311ef540e10d9705) }
 
 
-var fileDescriptor_e3f59eb60afbbc6e = []byte{
-	// 1842 bytes of a gzipped FileDescriptorProto
+var fileDescriptor_311ef540e10d9705 = []byte{
+	// 1846 bytes of a gzipped FileDescriptorProto
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0xcf, 0x73, 0xdb, 0xc6,
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0xcf, 0x73, 0xdb, 0xc6,
 	0xf5, 0x27, 0x48, 0xf0, 0xd7, 0x23, 0xa5, 0x40, 0x6b, 0x5b, 0x5f, 0x7c, 0x61, 0x9b, 0x84, 0x69,
 	0xf5, 0x27, 0x48, 0xf0, 0xd7, 0x23, 0xa5, 0x40, 0x6b, 0x5b, 0x5f, 0x7c, 0x61, 0x9b, 0x84, 0x69,
 	0x3b, 0x66, 0x34, 0xa9, 0xed, 0x26, 0x69, 0x3b, 0xed, 0xb4, 0x9d, 0xe1, 0x0f, 0x48, 0xe6, 0x54,
 	0x3b, 0x66, 0x34, 0xa9, 0xed, 0x26, 0x69, 0x3b, 0xed, 0xb4, 0x9d, 0xe1, 0x0f, 0x48, 0xe6, 0x54,
-	0x26, 0xd5, 0x25, 0xe5, 0xd4, 0x39, 0x14, 0x03, 0x11, 0x4b, 0x0a, 0x63, 0x10, 0xcb, 0x02, 0xa0,
+	0x26, 0xd5, 0x25, 0xe5, 0xd4, 0x39, 0x14, 0x03, 0x12, 0x4b, 0x09, 0x63, 0x10, 0xcb, 0x02, 0xa0,
 	0x64, 0xe6, 0x4f, 0xe0, 0xa9, 0xc7, 0x5e, 0x38, 0x93, 0x99, 0x9c, 0xfa, 0x9f, 0xf8, 0xe8, 0xf6,
 	0x64, 0xe6, 0x4f, 0xe0, 0xa9, 0xc7, 0x5e, 0x38, 0x93, 0x99, 0x9c, 0xfa, 0x9f, 0xf8, 0xe8, 0xf6,
 	0xd4, 0xe9, 0x41, 0xd3, 0xc8, 0x97, 0xf4, 0xd6, 0x4b, 0xaf, 0x9d, 0xce, 0xee, 0x02, 0x24, 0x28,
 	0xd4, 0xe9, 0x41, 0xd3, 0xc8, 0x97, 0xf4, 0xd6, 0x4b, 0xaf, 0x9d, 0xce, 0xee, 0x02, 0x24, 0x28,
-	0xc5, 0x99, 0x1c, 0x7a, 0xc2, 0xee, 0x7b, 0x9f, 0x7d, 0xbb, 0xef, 0xb3, 0xef, 0x7d, 0x16, 0x50,
-	0x3c, 0x21, 0xd3, 0xc7, 0x53, 0x9f, 0x86, 0x14, 0x15, 0xf8, 0x67, 0x48, 0x5d, 0xed, 0xbe, 0x4f,
-	0xa6, 0x34, 0x78, 0xc2, 0xe7, 0x27, 0xb3, 0xd1, 0x93, 0x31, 0x1d, 0x53, 0x3e, 0xe1, 0x23, 0x01,
-	0xaf, 0x4d, 0x21, 0xfb, 0x8c, 0xb8, 0x2e, 0x45, 0x55, 0x28, 0xd9, 0xe4, 0xcc, 0x19, 0x12, 0xd3,
-	0xb3, 0x26, 0x44, 0x95, 0x74, 0xa9, 0x5e, 0xc4, 0x20, 0x4c, 0x5d, 0x6b, 0x42, 0x18, 0x60, 0xe8,
-	0x3a, 0xc4, 0x0b, 0x05, 0x20, 0x2d, 0x00, 0xc2, 0xc4, 0x01, 0x0f, 0x61, 0x3b, 0x02, 0x9c, 0x11,
-	0x3f, 0x70, 0xa8, 0xa7, 0x66, 0x38, 0x66, 0x4b, 0x58, 0x5f, 0x08, 0x63, 0x2d, 0x80, 0xdc, 0x33,
-	0x62, 0xd9, 0xc4, 0x47, 0x1f, 0x81, 0x1c, 0xce, 0xa7, 0x62, 0xaf, 0xed, 0x4f, 0x6e, 0x3d, 0x8e,
-	0x4f, 0xfe, 0xf8, 0x39, 0x09, 0x02, 0x6b, 0x4c, 0x06, 0xf3, 0x29, 0xc1, 0x1c, 0x82, 0x7e, 0x0d,
-	0xa5, 0x21, 0x9d, 0x4c, 0x7d, 0x12, 0xf0, 0xc0, 0x69, 0xbe, 0xe2, 0xce, 0xb5, 0x15, 0xad, 0x35,
-	0x06, 0x27, 0x17, 0xd4, 0x1a, 0xb0, 0xd5, 0x72, 0x67, 0x41, 0x48, 0xfc, 0x16, 0xf5, 0x46, 0xce,
-	0x18, 0x3d, 0x85, 0xfc, 0x88, 0xba, 0x36, 0xf1, 0x03, 0x55, 0xd2, 0x33, 0xf5, 0xd2, 0x27, 0xca,
-	0x3a, 0xd8, 0x3e, 0x77, 0x34, 0xe5, 0x37, 0x17, 0xd5, 0x14, 0x8e, 0x61, 0xb5, 0xaf, 0xd3, 0x90,
-	0x13, 0x1e, 0xb4, 0x0b, 0x69, 0xc7, 0x16, 0x14, 0x35, 0x73, 0x97, 0x17, 0xd5, 0x74, 0xa7, 0x8d,
-	0xd3, 0x8e, 0x8d, 0x6e, 0x42, 0xd6, 0xb5, 0x4e, 0x88, 0x1b, 0x91, 0x23, 0x26, 0xe8, 0x36, 0x14,
-	0x7d, 0x62, 0xd9, 0x26, 0xf5, 0xdc, 0x39, 0xa7, 0xa4, 0x80, 0x0b, 0xcc, 0xd0, 0xf3, 0xdc, 0x39,
-	0xfa, 0x11, 0x20, 0x67, 0xec, 0x51, 0x9f, 0x98, 0x53, 0xe2, 0x4f, 0x1c, 0x7e, 0xda, 0x40, 0x95,
-	0x39, 0x6a, 0x47, 0x78, 0x8e, 0xd6, 0x0e, 0x74, 0x1f, 0xb6, 0x22, 0xb8, 0x4d, 0x5c, 0x12, 0x12,
-	0x35, 0xcb, 0x91, 0x65, 0x61, 0x6c, 0x73, 0x1b, 0x7a, 0x0a, 0x37, 0x6d, 0x27, 0xb0, 0x4e, 0x5c,
-	0x62, 0x86, 0x64, 0x32, 0x35, 0x1d, 0xcf, 0x26, 0xaf, 0x49, 0xa0, 0xe6, 0x38, 0x16, 0x45, 0xbe,
-	0x01, 0x99, 0x4c, 0x3b, 0xc2, 0x83, 0x76, 0x21, 0x37, 0xb5, 0x66, 0x01, 0xb1, 0xd5, 0x3c, 0xc7,
-	0x44, 0x33, 0xc6, 0x92, 0xa8, 0x80, 0x40, 0x55, 0xae, 0xb2, 0xd4, 0xe6, 0x8e, 0x98, 0xa5, 0x08,
-	0x56, 0xfb, 0x57, 0x1a, 0x72, 0xc2, 0x83, 0x3e, 0x5c, 0xb1, 0x54, 0x6e, 0xee, 0x32, 0xd4, 0xdf,
-	0x2f, 0xaa, 0x05, 0xe1, 0xeb, 0xb4, 0x13, 0xac, 0x21, 0x90, 0x13, 0x15, 0xc5, 0xc7, 0xe8, 0x0e,
-	0x14, 0x2d, 0xdb, 0x66, 0xb7, 0x47, 0x02, 0x35, 0xa3, 0x67, 0xea, 0x45, 0xbc, 0x36, 0xa0, 0x9f,
-	0x6d, 0x56, 0x83, 0x7c, 0xb5, 0x7e, 0xde, 0x57, 0x06, 0xec, 0x2a, 0x86, 0xc4, 0x8f, 0x2a, 0x38,
-	0xcb, 0xf7, 0x2b, 0x30, 0x03, 0xaf, 0xdf, 0x7b, 0x50, 0x9e, 0x58, 0xaf, 0xcd, 0x80, 0xfc, 0x61,
-	0x46, 0xbc, 0x21, 0xe1, 0x74, 0x65, 0x70, 0x69, 0x62, 0xbd, 0xee, 0x47, 0x26, 0x54, 0x01, 0x70,
-	0xbc, 0xd0, 0xa7, 0xf6, 0x6c, 0x48, 0xfc, 0x88, 0xab, 0x84, 0x05, 0xfd, 0x04, 0x0a, 0x9c, 0x6c,
-	0xd3, 0xb1, 0xd5, 0x82, 0x2e, 0xd5, 0xe5, 0xa6, 0x16, 0x25, 0x9e, 0xe7, 0x54, 0xf3, 0xbc, 0xe3,
-	0x21, 0xce, 0x73, 0x6c, 0xc7, 0x46, 0xbf, 0x04, 0x2d, 0x78, 0xe5, 0xb0, 0x8b, 0x12, 0x91, 0x42,
-	0x87, 0x7a, 0xa6, 0x4f, 0x26, 0xf4, 0xcc, 0x72, 0x03, 0xb5, 0xc8, 0xb7, 0x51, 0x19, 0xa2, 0x93,
-	0x00, 0xe0, 0xc8, 0x5f, 0xeb, 0x41, 0x96, 0x47, 0x64, 0xb7, 0x28, 0x8a, 0x35, 0xea, 0xde, 0x68,
-	0x86, 0x1e, 0x43, 0x76, 0xe4, 0xb8, 0x24, 0x50, 0xd3, 0xfc, 0x0e, 0x51, 0xa2, 0xd2, 0x1d, 0x97,
-	0x74, 0xbc, 0x11, 0x8d, 0x6e, 0x51, 0xc0, 0x6a, 0xc7, 0x50, 0xe2, 0x01, 0x8f, 0xa7, 0xb6, 0x15,
-	0x92, 0xff, 0x59, 0xd8, 0xaf, 0xb3, 0x50, 0x88, 0x3d, 0xab, 0x4b, 0x97, 0x12, 0x97, 0x8e, 0x40,
-	0x0e, 0x9c, 0x2f, 0x09, 0xef, 0x91, 0x0c, 0xe6, 0x63, 0x74, 0x17, 0x60, 0x42, 0x6d, 0x67, 0xe4,
-	0x10, 0xdb, 0x0c, 0xf8, 0x95, 0x65, 0x70, 0x31, 0xb6, 0xf4, 0xd1, 0x53, 0x28, 0xad, 0xdc, 0x27,
-	0x73, 0xb5, 0xcc, 0x39, 0xff, 0x20, 0xe6, 0xbc, 0x7f, 0x4a, 0xfd, 0xb0, 0xd3, 0xc6, 0xab, 0x10,
-	0xcd, 0x39, 0x2b, 0xe9, 0x58, 0x9e, 0x18, 0xb1, 0x1b, 0x25, 0xfd, 0x82, 0x0c, 0x43, 0xba, 0x6a,
-	0xfc, 0x08, 0x86, 0x34, 0x28, 0xac, 0x6a, 0x02, 0xf8, 0x01, 0x56, 0x73, 0xf4, 0x63, 0xc8, 0x9d,
-	0xb8, 0x74, 0xf8, 0x2a, 0xee, 0x8f, 0x1b, 0xeb, 0x60, 0x4d, 0x66, 0x4f, 0xb0, 0x10, 0x01, 0x99,
-	0x4c, 0x06, 0xf3, 0x89, 0xeb, 0x78, 0xaf, 0xcc, 0xd0, 0xf2, 0xc7, 0x24, 0x54, 0x77, 0x84, 0x4c,
-	0x46, 0xd6, 0x01, 0x37, 0x32, 0xb9, 0x15, 0x0b, 0xcc, 0x53, 0x2b, 0x38, 0x55, 0x11, 0x6b, 0x23,
-	0x0c, 0xc2, 0xf4, 0xcc, 0x0a, 0x4e, 0xd1, 0x5e, 0xa4, 0x9e, 0x42, 0x0b, 0x77, 0xaf, 0xb3, 0x9f,
-	0x90, 0x4f, 0x1d, 0x4a, 0x57, 0xe5, 0x65, 0x0b, 0x27, 0x4d, 0x6c, 0xbb, 0x15, 0x91, 0x5e, 0xa0,
-	0x96, 0x74, 0xa9, 0x9e, 0x5d, 0xf3, 0xd6, 0x0d, 0xd0, 0x13, 0x10, 0x9b, 0x9b, 0xfc, 0x8a, 0xb6,
-	0x98, 0xbf, 0xa9, 0x5c, 0x5e, 0x54, 0xcb, 0xd8, 0x3a, 0xe7, 0xa9, 0xf6, 0x9d, 0x2f, 0x09, 0x2e,
-	0x9e, 0xc4, 0x43, 0xb6, 0xa7, 0x4b, 0x87, 0x96, 0x6b, 0x8e, 0x5c, 0x6b, 0x1c, 0xa8, 0xdf, 0xe6,
-	0xf9, 0xa6, 0xc0, 0x6d, 0xfb, 0xcc, 0x84, 0x6a, 0x50, 0x8e, 0x38, 0x16, 0x39, 0xfe, 0x33, 0xcf,
-	0x93, 0x2c, 0x45, 0x46, 0x9e, 0xa5, 0xca, 0x14, 0x88, 0xa9, 0x9a, 0x1d, 0xc9, 0x57, 0x3c, 0x45,
-	0x75, 0xc8, 0x3b, 0xde, 0x99, 0xe5, 0x3a, 0x91, 0x68, 0x35, 0xb7, 0x2f, 0x2f, 0xaa, 0x80, 0xad,
-	0xf3, 0x8e, 0xb0, 0xe2, 0xd8, 0xcd, 0x18, 0xf7, 0xe8, 0x86, 0xbe, 0x16, 0x78, 0xa8, 0x2d, 0x8f,
-	0x26, 0xb4, 0xf5, 0x17, 0xf2, 0x9f, 0xbe, 0xaa, 0xa6, 0x6a, 0x1e, 0x14, 0x57, 0x37, 0xc7, 0x2a,
-	0x92, 0x9f, 0x2c, 0xc3, 0x0f, 0xc6, 0xc7, 0xac, 0x1d, 0xe8, 0x68, 0x14, 0x90, 0x90, 0xd7, 0x6e,
-	0x06, 0x47, 0xb3, 0x55, 0xf5, 0xa6, 0x39, 0x75, 0xa2, 0x7a, 0x6f, 0x43, 0xf1, 0x9c, 0x58, 0xaf,
-	0x44, 0x7a, 0x82, 0xf5, 0x02, 0x33, 0xb0, 0xd4, 0xa2, 0xfd, 0x7e, 0x05, 0x39, 0x51, 0x76, 0xe8,
-	0x53, 0x28, 0x0c, 0xe9, 0xcc, 0x0b, 0xd7, 0x6f, 0xd2, 0x4e, 0x52, 0xd2, 0xb8, 0x27, 0xaa, 0xa5,
-	0x15, 0xb0, 0xb6, 0x0f, 0xf9, 0xc8, 0x85, 0x1e, 0xae, 0xf4, 0x56, 0x6e, 0xde, 0xba, 0xd2, 0x02,
-	0x9b, 0x8f, 0xd4, 0x99, 0xe5, 0xce, 0xc4, 0x41, 0x65, 0x2c, 0x26, 0xb5, 0xbf, 0x48, 0x90, 0xc7,
-	0xac, 0xaa, 0x83, 0x30, 0xf1, 0xbc, 0x65, 0x37, 0x9e, 0xb7, 0xb5, 0x10, 0xa4, 0x37, 0x84, 0x20,
-	0xee, 0xe5, 0x4c, 0xa2, 0x97, 0xd7, 0x2c, 0xc9, 0xdf, 0xc9, 0x52, 0x36, 0xc1, 0x52, 0xcc, 0x72,
-	0x2e, 0xc1, 0xf2, 0x43, 0xd8, 0x1e, 0xf9, 0x74, 0xc2, 0x1f, 0x30, 0xea, 0x5b, 0xfe, 0x3c, 0x52,
-	0xdb, 0x2d, 0x66, 0x1d, 0xc4, 0xc6, 0x4d, 0x82, 0x0b, 0x9b, 0x04, 0xd7, 0x4c, 0x28, 0x60, 0x12,
-	0x4c, 0xa9, 0x17, 0x90, 0xf7, 0xe6, 0x84, 0x40, 0xb6, 0xad, 0xd0, 0xe2, 0x19, 0x95, 0x31, 0x1f,
-	0xa3, 0x47, 0x20, 0x0f, 0xa9, 0x2d, 0xf2, 0xd9, 0x4e, 0xb6, 0xb4, 0xe1, 0xfb, 0xd4, 0x6f, 0x51,
-	0x9b, 0x60, 0x0e, 0xa8, 0x4d, 0x41, 0x69, 0xd3, 0x73, 0xcf, 0xa5, 0x96, 0x7d, 0xe4, 0xd3, 0x31,
-	0x7b, 0x65, 0xde, 0xab, 0x96, 0x6d, 0xc8, 0xcf, 0xb8, 0x9e, 0xc6, 0x7a, 0xf9, 0x60, 0xb3, 0x63,
-	0xaf, 0x06, 0x12, 0xe2, 0x1b, 0x6b, 0x51, 0xb4, 0xb4, 0xf6, 0x6f, 0x09, 0xb4, 0xf7, 0xa3, 0x51,
-	0x07, 0x4a, 0x02, 0x69, 0x26, 0x7e, 0xac, 0xea, 0x3f, 0x64, 0x23, 0x2e, 0x16, 0x30, 0x5b, 0x8d,
-	0xbf, 0xf3, 0x55, 0x4e, 0x68, 0x67, 0xe6, 0x87, 0x69, 0xe7, 0x23, 0xd8, 0x12, 0xaa, 0x11, 0xff,
-	0x83, 0xc8, 0x7a, 0xa6, 0x9e, 0x6d, 0xa6, 0x95, 0x14, 0x2e, 0x9f, 0x88, 0x36, 0x13, 0x7f, 0x20,
-	0x77, 0x37, 0xe4, 0x45, 0x54, 0xc7, 0x5a, 0x4c, 0x6a, 0x39, 0x90, 0x8f, 0x1c, 0x6f, 0x5c, 0xab,
-	0x42, 0xb6, 0xe5, 0x52, 0x7e, 0x9f, 0x39, 0x9f, 0x58, 0x01, 0xf5, 0x62, 0x9a, 0xc5, 0x6c, 0xef,
-	0xaf, 0x69, 0x28, 0x25, 0x7e, 0x1f, 0xd1, 0x53, 0xd8, 0x6e, 0x1d, 0x1e, 0xf7, 0x07, 0x06, 0x36,
-	0x5b, 0xbd, 0xee, 0x7e, 0xe7, 0x40, 0x49, 0x69, 0x77, 0x16, 0x4b, 0x5d, 0x9d, 0xac, 0x41, 0x9b,
-	0x7f, 0x86, 0x55, 0xc8, 0x76, 0xba, 0x6d, 0xe3, 0x77, 0x8a, 0xa4, 0xdd, 0x5c, 0x2c, 0x75, 0x25,
-	0x01, 0x14, 0xcf, 0xec, 0xc7, 0x50, 0xe6, 0x00, 0xf3, 0xf8, 0xa8, 0xdd, 0x18, 0x18, 0x4a, 0x5a,
-	0xd3, 0x16, 0x4b, 0x7d, 0xf7, 0x2a, 0x2e, 0xba, 0x92, 0xfb, 0x90, 0xc7, 0xc6, 0x6f, 0x8f, 0x8d,
-	0xfe, 0x40, 0xc9, 0x68, 0xbb, 0x8b, 0xa5, 0x8e, 0x12, 0xc0, 0xb8, 0xe3, 0x1e, 0x42, 0x01, 0x1b,
-	0xfd, 0xa3, 0x5e, 0xb7, 0x6f, 0x28, 0xb2, 0xf6, 0x7f, 0x8b, 0xa5, 0x7e, 0x63, 0x03, 0x15, 0x15,
-	0xf1, 0x4f, 0x61, 0xa7, 0xdd, 0xfb, 0xbc, 0x7b, 0xd8, 0x6b, 0xb4, 0xcd, 0x23, 0xdc, 0x3b, 0xc0,
-	0x46, 0xbf, 0xaf, 0x64, 0xb5, 0xea, 0x62, 0xa9, 0xdf, 0x4e, 0xe0, 0xaf, 0xd5, 0xe4, 0x5d, 0x90,
-	0x8f, 0x3a, 0xdd, 0x03, 0x25, 0xa7, 0xdd, 0x58, 0x2c, 0xf5, 0x0f, 0x12, 0x50, 0x46, 0x2a, 0xcb,
-	0xb8, 0x75, 0xd8, 0xeb, 0x1b, 0x4a, 0xfe, 0x5a, 0xc6, 0x9c, 0xec, 0xbd, 0xdf, 0x03, 0xba, 0xfe,
-	0x83, 0x8d, 0x1e, 0x80, 0xdc, 0xed, 0x75, 0x0d, 0x25, 0x25, 0xf2, 0xbf, 0x8e, 0xe8, 0x52, 0x8f,
-	0xa0, 0x1a, 0x64, 0x0e, 0xbf, 0xf8, 0x4c, 0x91, 0xb4, 0xff, 0x5f, 0x2c, 0xf5, 0x5b, 0xd7, 0x41,
-	0x87, 0x5f, 0x7c, 0xb6, 0x47, 0xa1, 0x94, 0x0c, 0x5c, 0x83, 0xc2, 0x73, 0x63, 0xd0, 0x68, 0x37,
-	0x06, 0x0d, 0x25, 0x25, 0x8e, 0x14, 0xbb, 0x9f, 0x93, 0xd0, 0xe2, 0x3d, 0x7a, 0x07, 0xb2, 0x5d,
-	0xe3, 0x85, 0x81, 0x15, 0x49, 0xdb, 0x59, 0x2c, 0xf5, 0xad, 0x18, 0xd0, 0x25, 0x67, 0xc4, 0x47,
-	0x15, 0xc8, 0x35, 0x0e, 0x3f, 0x6f, 0xbc, 0xec, 0x2b, 0x69, 0x0d, 0x2d, 0x96, 0xfa, 0x76, 0xec,
-	0x6e, 0xb8, 0xe7, 0xd6, 0x3c, 0xd8, 0xfb, 0x8f, 0x04, 0xe5, 0xe4, 0x33, 0x89, 0x2a, 0x20, 0xef,
-	0x77, 0x0e, 0x8d, 0x78, 0xbb, 0xa4, 0x8f, 0x8d, 0x51, 0x1d, 0x8a, 0xed, 0x0e, 0x36, 0x5a, 0x83,
-	0x1e, 0x7e, 0x19, 0xe7, 0x92, 0x04, 0xb5, 0x1d, 0x9f, 0xd7, 0xff, 0x1c, 0xfd, 0x1c, 0xca, 0xfd,
-	0x97, 0xcf, 0x0f, 0x3b, 0xdd, 0xdf, 0x98, 0x3c, 0x62, 0x5a, 0x7b, 0xb4, 0x58, 0xea, 0xf7, 0x36,
-	0xc0, 0x64, 0xea, 0x93, 0xa1, 0x15, 0x12, 0xbb, 0x2f, 0x9e, 0x7c, 0xe6, 0x2c, 0x48, 0xa8, 0x05,
-	0x3b, 0xf1, 0xd2, 0xf5, 0x66, 0x19, 0xed, 0xe3, 0xc5, 0x52, 0xff, 0xf0, 0x7b, 0xd7, 0xaf, 0x76,
-	0x2f, 0x48, 0xe8, 0x01, 0xe4, 0xa3, 0x20, 0x71, 0x25, 0x25, 0x97, 0x46, 0x0b, 0xf6, 0xfe, 0x2c,
-	0x41, 0x71, 0xa5, 0x66, 0x8c, 0xf0, 0x6e, 0xcf, 0x34, 0x30, 0xee, 0xe1, 0x98, 0x81, 0x95, 0xb3,
-	0x4b, 0xf9, 0x10, 0xdd, 0x83, 0xfc, 0x81, 0xd1, 0x35, 0x70, 0xa7, 0x15, 0x37, 0xc6, 0x0a, 0x72,
-	0x40, 0x3c, 0xe2, 0x3b, 0x43, 0xf4, 0x11, 0x94, 0xbb, 0x3d, 0xb3, 0x7f, 0xdc, 0x7a, 0x16, 0xa7,
-	0xce, 0xf7, 0x4f, 0x84, 0xea, 0xcf, 0x86, 0xa7, 0x9c, 0xcf, 0x3d, 0xd6, 0x43, 0x2f, 0x1a, 0x87,
-	0x9d, 0xb6, 0x80, 0x66, 0x34, 0x75, 0xb1, 0xd4, 0x6f, 0xae, 0xa0, 0xd1, 0x1b, 0xce, 0xb0, 0x7b,
-	0x36, 0x54, 0xbe, 0x5f, 0xb7, 0x90, 0x0e, 0xb9, 0xc6, 0xd1, 0x91, 0xd1, 0x6d, 0xc7, 0xa7, 0x5f,
-	0xfb, 0x1a, 0xd3, 0x29, 0xf1, 0x6c, 0x86, 0xd8, 0xef, 0xe1, 0x03, 0x63, 0x10, 0x1f, 0x7e, 0x8d,
-	0xd8, 0xa7, 0xec, 0x7f, 0xab, 0x59, 0x7f, 0xf3, 0x4d, 0x25, 0xf5, 0xf6, 0x9b, 0x4a, 0xea, 0xcd,
-	0x65, 0x45, 0x7a, 0x7b, 0x59, 0x91, 0xfe, 0x71, 0x59, 0x49, 0x7d, 0x7b, 0x59, 0x91, 0xfe, 0xf8,
-	0xae, 0x92, 0xfa, 0xea, 0x5d, 0x45, 0x7a, 0xfb, 0xae, 0x92, 0xfa, 0xdb, 0xbb, 0x4a, 0xea, 0x24,
-	0xc7, 0x35, 0xef, 0xd3, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0xfb, 0x99, 0x31, 0x0e, 0x75, 0x0f,
-	0x00, 0x00,
+	0xc5, 0x99, 0x1c, 0x7a, 0xdb, 0x7d, 0xef, 0xb3, 0x6f, 0xf7, 0x7d, 0xf6, 0xbd, 0xcf, 0x2e, 0xec,
+	0xba, 0xce, 0xf0, 0xc9, 0xd4, 0xa7, 0x21, 0x1d, 0x51, 0xf7, 0xc9, 0x90, 0x4c, 0x1f, 0xf3, 0x09,
+	0x2a, 0xc4, 0x36, 0xed, 0xbe, 0x4f, 0xa6, 0x34, 0x10, 0x98, 0xe1, 0x6c, 0xfc, 0xe4, 0x84, 0x9e,
+	0x50, 0x3e, 0xe1, 0x23, 0x01, 0xaf, 0x4d, 0x21, 0xfb, 0x8c, 0xb8, 0x2e, 0x45, 0x55, 0x28, 0xd9,
+	0xe4, 0xcc, 0x19, 0x11, 0xd3, 0xb3, 0x26, 0x44, 0x95, 0x74, 0xa9, 0x5e, 0xc4, 0x20, 0x4c, 0x5d,
+	0x6b, 0x42, 0x18, 0x60, 0xe4, 0x3a, 0xc4, 0x0b, 0x05, 0x20, 0x2d, 0x00, 0xc2, 0xc4, 0x01, 0x0f,
+	0x61, 0x3b, 0x02, 0x9c, 0x11, 0x3f, 0x70, 0xa8, 0xa7, 0x66, 0x38, 0x66, 0x4b, 0x58, 0x5f, 0x08,
+	0x63, 0x2d, 0x80, 0xdc, 0x33, 0x62, 0xd9, 0xc4, 0x47, 0x1f, 0x81, 0x1c, 0xce, 0xa7, 0x62, 0xaf,
+	0xed, 0x4f, 0x6e, 0x3d, 0x8e, 0x4f, 0xfe, 0xf8, 0x39, 0x09, 0x02, 0xeb, 0x84, 0x0c, 0xe6, 0x53,
+	0x82, 0x39, 0x04, 0xfd, 0x1a, 0x4a, 0x23, 0x3a, 0x99, 0xfa, 0x24, 0xe0, 0x81, 0xd3, 0x7c, 0xc5,
+	0x9d, 0x6b, 0x2b, 0x5a, 0x6b, 0x0c, 0x4e, 0x2e, 0xa8, 0x35, 0x60, 0xab, 0xe5, 0xce, 0x82, 0x90,
+	0xf8, 0x2d, 0xea, 0x8d, 0x9d, 0x13, 0xf4, 0x14, 0xf2, 0x63, 0xea, 0xda, 0xc4, 0x0f, 0x54, 0x49,
+	0xcf, 0xd4, 0x4b, 0x9f, 0x28, 0xeb, 0x60, 0xfb, 0xdc, 0xd1, 0x94, 0xdf, 0x5c, 0x54, 0x53, 0x38,
+	0x86, 0xd5, 0xbe, 0x4e, 0x43, 0x4e, 0x78, 0xd0, 0x2e, 0xa4, 0x1d, 0x5b, 0x50, 0xd4, 0xcc, 0x5d,
+	0x5e, 0x54, 0xd3, 0x9d, 0x36, 0x4e, 0x3b, 0x36, 0xba, 0x09, 0x59, 0xd7, 0x1a, 0x12, 0x37, 0x22,
+	0x47, 0x4c, 0xd0, 0x6d, 0x28, 0xfa, 0xc4, 0xb2, 0x4d, 0xea, 0xb9, 0x73, 0x4e, 0x49, 0x01, 0x17,
+	0x98, 0xa1, 0xe7, 0xb9, 0x73, 0xf4, 0x23, 0x40, 0xce, 0x89, 0x47, 0x7d, 0x62, 0x4e, 0x89, 0x3f,
+	0x71, 0xf8, 0x69, 0x03, 0x55, 0xe6, 0xa8, 0x1d, 0xe1, 0x39, 0x5a, 0x3b, 0xd0, 0x7d, 0xd8, 0x8a,
+	0xe0, 0x36, 0x71, 0x49, 0x48, 0xd4, 0x2c, 0x47, 0x96, 0x85, 0xb1, 0xcd, 0x6d, 0xe8, 0x29, 0xdc,
+	0xb4, 0x9d, 0xc0, 0x1a, 0xba, 0xc4, 0x0c, 0xc9, 0x64, 0x6a, 0x3a, 0x9e, 0x4d, 0x5e, 0x93, 0x40,
+	0xcd, 0x71, 0x2c, 0x8a, 0x7c, 0x03, 0x32, 0x99, 0x76, 0x84, 0x07, 0xed, 0x42, 0x6e, 0x6a, 0xcd,
+	0x02, 0x62, 0xab, 0x79, 0x8e, 0x89, 0x66, 0x8c, 0x25, 0x51, 0x01, 0x81, 0xaa, 0x5c, 0x65, 0xa9,
+	0xcd, 0x1d, 0x31, 0x4b, 0x11, 0xac, 0xf6, 0xaf, 0x34, 0xe4, 0x84, 0x07, 0x7d, 0xb8, 0x62, 0xa9,
+	0xdc, 0xdc, 0x65, 0xa8, 0xbf, 0x5f, 0x54, 0x0b, 0xc2, 0xd7, 0x69, 0x27, 0x58, 0x43, 0x20, 0x27,
+	0x2a, 0x8a, 0x8f, 0xd1, 0x1d, 0x28, 0x5a, 0xb6, 0xcd, 0x6e, 0x8f, 0x04, 0x6a, 0x46, 0xcf, 0xd4,
+	0x8b, 0x78, 0x6d, 0x40, 0x3f, 0xdb, 0xac, 0x06, 0xf9, 0x6a, 0xfd, 0xbc, 0xaf, 0x0c, 0xd8, 0x55,
+	0x8c, 0x88, 0x1f, 0x55, 0x70, 0x96, 0xef, 0x57, 0x60, 0x06, 0x5e, 0xbf, 0xf7, 0xa0, 0x3c, 0xb1,
+	0x5e, 0x9b, 0x01, 0xf9, 0xc3, 0x8c, 0x78, 0x23, 0xc2, 0xe9, 0xca, 0xe0, 0xd2, 0xc4, 0x7a, 0xdd,
+	0x8f, 0x4c, 0xa8, 0x02, 0xe0, 0x78, 0xa1, 0x4f, 0xed, 0xd9, 0x88, 0xf8, 0x11, 0x57, 0x09, 0x0b,
+	0xfa, 0x09, 0x14, 0x38, 0xd9, 0xa6, 0x63, 0xab, 0x05, 0x5d, 0xaa, 0xcb, 0x4d, 0x2d, 0x4a, 0x3c,
+	0xcf, 0xa9, 0xe6, 0x79, 0xc7, 0x43, 0x9c, 0xe7, 0xd8, 0x8e, 0x8d, 0x7e, 0x09, 0x5a, 0xf0, 0xca,
+	0x61, 0x17, 0x25, 0x22, 0x85, 0x0e, 0xf5, 0x4c, 0x9f, 0x4c, 0xe8, 0x99, 0xe5, 0x06, 0x6a, 0x91,
+	0x6f, 0xa3, 0x32, 0x44, 0x27, 0x01, 0xc0, 0x91, 0xbf, 0xd6, 0x83, 0x2c, 0x8f, 0xc8, 0x6e, 0x51,
+	0x14, 0x6b, 0xd4, 0xbd, 0xd1, 0x0c, 0x3d, 0x86, 0xec, 0xd8, 0x71, 0x49, 0xa0, 0xa6, 0xf9, 0x1d,
+	0xa2, 0x44, 0xa5, 0x3b, 0x2e, 0xe9, 0x78, 0x63, 0x1a, 0xdd, 0xa2, 0x80, 0xd5, 0x8e, 0xa1, 0xc4,
+	0x03, 0x1e, 0x4f, 0x6d, 0x2b, 0x24, 0xff, 0xb3, 0xb0, 0x5f, 0x67, 0xa1, 0x10, 0x7b, 0x56, 0x97,
+	0x2e, 0x25, 0x2e, 0x1d, 0x81, 0x1c, 0x38, 0x5f, 0x12, 0xde, 0x23, 0x19, 0xcc, 0xc7, 0xe8, 0x2e,
+	0xc0, 0x84, 0xda, 0xce, 0xd8, 0x21, 0xb6, 0x19, 0xf0, 0x2b, 0xcb, 0xe0, 0x62, 0x6c, 0xe9, 0xa3,
+	0xa7, 0x50, 0x5a, 0xb9, 0x87, 0x73, 0xb5, 0xcc, 0x39, 0xff, 0x20, 0xe6, 0xbc, 0x7f, 0x4a, 0xfd,
+	0xb0, 0xd3, 0xc6, 0xab, 0x10, 0xcd, 0x39, 0x2b, 0xe9, 0x58, 0x9e, 0x18, 0xb1, 0x1b, 0x25, 0xfd,
+	0x82, 0x8c, 0x42, 0xba, 0x6a, 0xfc, 0x08, 0x86, 0x34, 0x28, 0xac, 0x6a, 0x02, 0xf8, 0x01, 0x56,
+	0x73, 0xf4, 0x63, 0xc8, 0x0d, 0x5d, 0x3a, 0x7a, 0x15, 0xf7, 0xc7, 0x8d, 0x75, 0xb0, 0x26, 0xb3,
+	0x27, 0x58, 0x88, 0x80, 0x4c, 0x26, 0x83, 0xf9, 0xc4, 0x75, 0xbc, 0x57, 0x66, 0x68, 0xf9, 0x27,
+	0x24, 0x54, 0x77, 0x84, 0x4c, 0x46, 0xd6, 0x01, 0x37, 0x32, 0xb9, 0x15, 0x0b, 0xcc, 0x53, 0x2b,
+	0x38, 0x55, 0x11, 0x6b, 0x23, 0x0c, 0xc2, 0xf4, 0xcc, 0x0a, 0x4e, 0xd1, 0x5e, 0xa4, 0x9e, 0x42,
+	0x0b, 0x77, 0xaf, 0xb3, 0x9f, 0x90, 0x4f, 0x1d, 0x4a, 0x57, 0xe5, 0x65, 0x0b, 0x27, 0x4d, 0x6c,
+	0xbb, 0x15, 0x91, 0x5e, 0xa0, 0x96, 0x74, 0xa9, 0x9e, 0x5d, 0xf3, 0xd6, 0x0d, 0xd0, 0x13, 0x10,
+	0x9b, 0x9b, 0xfc, 0x8a, 0xb6, 0x98, 0xbf, 0xa9, 0x5c, 0x5e, 0x54, 0xcb, 0xd8, 0x3a, 0xe7, 0xa9,
+	0xf6, 0x9d, 0x2f, 0x09, 0x2e, 0x0e, 0xe3, 0x21, 0xdb, 0xd3, 0xa5, 0x23, 0xcb, 0x35, 0xc7, 0xae,
+	0x75, 0x12, 0xa8, 0xdf, 0xe6, 0xf9, 0xa6, 0xc0, 0x6d, 0xfb, 0xcc, 0x84, 0x6a, 0x50, 0x8e, 0x38,
+	0x16, 0x39, 0xfe, 0x33, 0xcf, 0x93, 0x2c, 0x45, 0x46, 0x9e, 0xa5, 0xca, 0x14, 0x88, 0xa9, 0x9a,
+	0x1d, 0xc9, 0x57, 0x3c, 0x45, 0x75, 0xc8, 0x3b, 0xde, 0x99, 0xe5, 0x3a, 0x91, 0x68, 0x35, 0xb7,
+	0x2f, 0x2f, 0xaa, 0x80, 0xad, 0xf3, 0x8e, 0xb0, 0xe2, 0xd8, 0xcd, 0x18, 0xf7, 0xe8, 0x86, 0xbe,
+	0x16, 0x78, 0xa8, 0x2d, 0x8f, 0x26, 0xb4, 0xf5, 0x17, 0xf2, 0x9f, 0xbe, 0xaa, 0xa6, 0x6a, 0x1e,
+	0x14, 0x57, 0x37, 0xc7, 0x2a, 0x92, 0x9f, 0x2c, 0xc3, 0x0f, 0xc6, 0xc7, 0xac, 0x1d, 0xe8, 0x78,
+	0x1c, 0x90, 0x90, 0xd7, 0x6e, 0x06, 0x47, 0xb3, 0x55, 0xf5, 0xa6, 0x39, 0x75, 0xa2, 0x7a, 0x6f,
+	0x43, 0xf1, 0x9c, 0x58, 0xaf, 0x44, 0x7a, 0x82, 0xf5, 0x02, 0x33, 0xb0, 0xd4, 0xa2, 0xfd, 0x7e,
+	0x05, 0x39, 0x51, 0x76, 0xe8, 0x53, 0x28, 0x8c, 0xe8, 0xcc, 0x0b, 0xd7, 0x6f, 0xd2, 0x4e, 0x52,
+	0xd2, 0xb8, 0x27, 0xaa, 0xa5, 0x15, 0xb0, 0xb6, 0x0f, 0xf9, 0xc8, 0x85, 0x1e, 0xae, 0xf4, 0x56,
+	0x6e, 0xde, 0xba, 0xd2, 0x02, 0x9b, 0x8f, 0xd4, 0x99, 0xe5, 0xce, 0xc4, 0x41, 0x65, 0x2c, 0x26,
+	0xb5, 0xbf, 0x48, 0x90, 0xc7, 0xac, 0xaa, 0x83, 0x30, 0xf1, 0xbc, 0x65, 0x37, 0x9e, 0xb7, 0xb5,
+	0x10, 0xa4, 0x37, 0x84, 0x20, 0xee, 0xe5, 0x4c, 0xa2, 0x97, 0xd7, 0x2c, 0xc9, 0xdf, 0xc9, 0x52,
+	0x36, 0xc1, 0x52, 0xcc, 0x72, 0x2e, 0xc1, 0xf2, 0x43, 0xd8, 0x1e, 0xfb, 0x74, 0xc2, 0x1f, 0x30,
+	0xea, 0x5b, 0xfe, 0x3c, 0x52, 0xdb, 0x2d, 0x66, 0x1d, 0xc4, 0xc6, 0x4d, 0x82, 0x0b, 0x9b, 0x04,
+	0xd7, 0x4c, 0x28, 0x60, 0x12, 0x4c, 0xa9, 0x17, 0x90, 0xf7, 0xe6, 0x84, 0x40, 0xb6, 0xad, 0xd0,
+	0xe2, 0x19, 0x95, 0x31, 0x1f, 0xa3, 0x47, 0x20, 0x8f, 0xa8, 0x2d, 0xf2, 0xd9, 0x4e, 0xb6, 0xb4,
+	0xe1, 0xfb, 0xd4, 0x6f, 0x51, 0x9b, 0x60, 0x0e, 0xa8, 0x4d, 0x41, 0x69, 0xd3, 0x73, 0xcf, 0xa5,
+	0x96, 0x7d, 0xe4, 0xd3, 0x13, 0xf6, 0xca, 0xbc, 0x57, 0x2d, 0xdb, 0x90, 0x9f, 0x71, 0x3d, 0x8d,
+	0xf5, 0xf2, 0xc1, 0x66, 0xc7, 0x5e, 0x0d, 0x24, 0xc4, 0x37, 0xd6, 0xa2, 0x68, 0x69, 0xed, 0xdf,
+	0x12, 0x68, 0xef, 0x47, 0xa3, 0x0e, 0x94, 0x04, 0xd2, 0x4c, 0x7c, 0xac, 0xea, 0x3f, 0x64, 0x23,
+	0x2e, 0x16, 0x30, 0x5b, 0x8d, 0xbf, 0xf3, 0x55, 0x4e, 0x68, 0x67, 0xe6, 0x87, 0x69, 0xe7, 0x23,
+	0xd8, 0x12, 0xaa, 0x11, 0xff, 0x41, 0x64, 0x3d, 0x53, 0xcf, 0x36, 0xd3, 0x4a, 0x0a, 0x97, 0x87,
+	0xa2, 0xcd, 0xc4, 0x0f, 0xe4, 0xee, 0x86, 0xbc, 0x88, 0xea, 0x58, 0x8b, 0x49, 0x2d, 0x07, 0xf2,
+	0x91, 0xe3, 0x9d, 0xd4, 0xaa, 0x90, 0x6d, 0xb9, 0x94, 0xdf, 0x67, 0xce, 0x27, 0x56, 0x40, 0xbd,
+	0x98, 0x66, 0x31, 0xdb, 0xfb, 0x6b, 0x1a, 0x4a, 0x89, 0xef, 0x23, 0x7a, 0x0a, 0xdb, 0xad, 0xc3,
+	0xe3, 0xfe, 0xc0, 0xc0, 0x66, 0xab, 0xd7, 0xdd, 0xef, 0x1c, 0x28, 0x29, 0xed, 0xce, 0x62, 0xa9,
+	0xab, 0x93, 0x35, 0x68, 0xf3, 0x67, 0x58, 0x85, 0x6c, 0xa7, 0xdb, 0x36, 0x7e, 0xa7, 0x48, 0xda,
+	0xcd, 0xc5, 0x52, 0x57, 0x12, 0x40, 0xf1, 0xcc, 0x7e, 0x0c, 0x65, 0x0e, 0x30, 0x8f, 0x8f, 0xda,
+	0x8d, 0x81, 0xa1, 0xa4, 0x35, 0x6d, 0xb1, 0xd4, 0x77, 0xaf, 0xe2, 0xa2, 0x2b, 0xb9, 0x0f, 0x79,
+	0x6c, 0xfc, 0xf6, 0xd8, 0xe8, 0x0f, 0x94, 0x8c, 0xb6, 0xbb, 0x58, 0xea, 0x28, 0x01, 0x8c, 0x3b,
+	0xee, 0x21, 0x14, 0xb0, 0xd1, 0x3f, 0xea, 0x75, 0xfb, 0x86, 0x22, 0x6b, 0xff, 0xb7, 0x58, 0xea,
+	0x37, 0x36, 0x50, 0x51, 0x11, 0xff, 0x14, 0x76, 0xda, 0xbd, 0xcf, 0xbb, 0x87, 0xbd, 0x46, 0xdb,
+	0x3c, 0xc2, 0xbd, 0x03, 0x6c, 0xf4, 0xfb, 0x4a, 0x56, 0xab, 0x2e, 0x96, 0xfa, 0xed, 0x04, 0xfe,
+	0x5a, 0x4d, 0xde, 0x05, 0xf9, 0xa8, 0xd3, 0x3d, 0x50, 0x72, 0xda, 0x8d, 0xc5, 0x52, 0xff, 0x20,
+	0x01, 0x65, 0xa4, 0xb2, 0x8c, 0x5b, 0x87, 0xbd, 0xbe, 0xa1, 0xe4, 0xaf, 0x65, 0xcc, 0xc9, 0xde,
+	0xfb, 0x3d, 0xa0, 0xeb, 0x1f, 0x6c, 0xf4, 0x00, 0xe4, 0x6e, 0xaf, 0x6b, 0x28, 0x29, 0x91, 0xff,
+	0x75, 0x44, 0x97, 0x7a, 0x04, 0xd5, 0x20, 0x73, 0xf8, 0xc5, 0x67, 0x8a, 0xa4, 0xfd, 0xff, 0x62,
+	0xa9, 0xdf, 0xba, 0x0e, 0x3a, 0xfc, 0xe2, 0xb3, 0x3d, 0x0a, 0xa5, 0x64, 0xe0, 0x1a, 0x14, 0x9e,
+	0x1b, 0x83, 0x46, 0xbb, 0x31, 0x68, 0x28, 0x29, 0x71, 0xa4, 0xd8, 0xfd, 0x9c, 0x84, 0x16, 0xef,
+	0xd1, 0x3b, 0x90, 0xed, 0x1a, 0x2f, 0x0c, 0xac, 0x48, 0xda, 0xce, 0x62, 0xa9, 0x6f, 0xc5, 0x80,
+	0x2e, 0x39, 0x23, 0x3e, 0xaa, 0x40, 0xae, 0x71, 0xf8, 0x79, 0xe3, 0x65, 0x5f, 0x49, 0x6b, 0x68,
+	0xb1, 0xd4, 0xb7, 0x63, 0x77, 0xc3, 0x3d, 0xb7, 0xe6, 0xc1, 0xde, 0x7f, 0x24, 0x28, 0x27, 0x9f,
+	0x49, 0x54, 0x01, 0x79, 0xbf, 0x73, 0x68, 0xc4, 0xdb, 0x25, 0x7d, 0x6c, 0x8c, 0xea, 0x50, 0x6c,
+	0x77, 0xb0, 0xd1, 0x1a, 0xf4, 0xf0, 0xcb, 0x38, 0x97, 0x24, 0xa8, 0xed, 0xf8, 0xbc, 0xfe, 0xe7,
+	0xe8, 0xe7, 0x50, 0xee, 0xbf, 0x7c, 0x7e, 0xd8, 0xe9, 0xfe, 0xc6, 0xe4, 0x11, 0xd3, 0xda, 0xa3,
+	0xc5, 0x52, 0xbf, 0xb7, 0x01, 0x26, 0x53, 0x9f, 0x8c, 0xac, 0x90, 0xd8, 0x7d, 0xf1, 0xe4, 0x33,
+	0x67, 0x41, 0x42, 0x2d, 0xd8, 0x89, 0x97, 0xae, 0x37, 0xcb, 0x68, 0x1f, 0x2f, 0x96, 0xfa, 0x87,
+	0xdf, 0xbb, 0x7e, 0xb5, 0x7b, 0x41, 0x42, 0x0f, 0x20, 0x1f, 0x05, 0x89, 0x2b, 0x29, 0xb9, 0x34,
+	0x5a, 0xb0, 0xf7, 0x67, 0x09, 0x8a, 0x2b, 0x35, 0x63, 0x84, 0x77, 0x7b, 0xa6, 0x81, 0x71, 0x0f,
+	0xc7, 0x0c, 0xac, 0x9c, 0x5d, 0xca, 0x87, 0xe8, 0x1e, 0xe4, 0x0f, 0x8c, 0xae, 0x81, 0x3b, 0xad,
+	0xb8, 0x31, 0x56, 0x90, 0x03, 0xe2, 0x11, 0xdf, 0x19, 0xa1, 0x8f, 0xa0, 0xdc, 0xed, 0x99, 0xfd,
+	0xe3, 0xd6, 0xb3, 0x38, 0x75, 0xbe, 0x7f, 0x22, 0x54, 0x7f, 0x36, 0x3a, 0xe5, 0x7c, 0xee, 0xb1,
+	0x1e, 0x7a, 0xd1, 0x38, 0xec, 0xb4, 0x05, 0x34, 0xa3, 0xa9, 0x8b, 0xa5, 0x7e, 0x73, 0x05, 0x8d,
+	0xde, 0x70, 0x86, 0xdd, 0xb3, 0xa1, 0xf2, 0xfd, 0xba, 0x85, 0x74, 0xc8, 0x35, 0x8e, 0x8e, 0x8c,
+	0x6e, 0x3b, 0x3e, 0xfd, 0xda, 0xd7, 0x98, 0x4e, 0x89, 0x67, 0x33, 0xc4, 0x7e, 0x0f, 0x1f, 0x18,
+	0x83, 0xf8, 0xf0, 0x6b, 0xc4, 0x3e, 0x65, 0xff, 0xad, 0x66, 0xfd, 0xcd, 0x37, 0x95, 0xd4, 0xdb,
+	0x6f, 0x2a, 0xa9, 0x37, 0x97, 0x15, 0xe9, 0xed, 0x65, 0x45, 0xfa, 0xc7, 0x65, 0x25, 0xf5, 0xed,
+	0x65, 0x45, 0xfa, 0xe3, 0xbb, 0x4a, 0xea, 0xab, 0x77, 0x15, 0xe9, 0xed, 0xbb, 0x4a, 0xea, 0x6f,
+	0xef, 0x2a, 0xa9, 0x61, 0x8e, 0x6b, 0xde, 0xa7, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xc7, 0x7a,
+	0xfc, 0x00, 0x82, 0x0f, 0x00, 0x00,
 }
 }
 
 
 func (m *Hello) Marshal() (dAtA []byte, err error) {
 func (m *Hello) Marshal() (dAtA []byte, err error) {

+ 0 - 3
lib/protocol/bep_extensions.go

@@ -1,8 +1,5 @@
 // Copyright (C) 2014 The Protocol Authors.
 // Copyright (C) 2014 The Protocol Authors.
 
 
-//go:generate go run ../../script/protofmt.go bep.proto
-//go:generate protoc -I ../../ -I . --gogofast_out=. bep.proto
-
 package protocol
 package protocol
 
 
 import (
 import (

+ 1 - 1
lib/protocol/deviceid_test.go

@@ -1,6 +1,6 @@
 // Copyright (C) 2014 The Protocol Authors.
 // Copyright (C) 2014 The Protocol Authors.
 
 
-//go:generate go run ../../script/protofmt.go deviceid_test.proto
+//go:generate go run ../../proto/scripts/protofmt.go deviceid_test.proto
 //go:generate protoc -I ../../ -I . --gogofast_out=. deviceid_test.proto
 //go:generate protoc -I ../../ -I . --gogofast_out=. deviceid_test.proto
 
 
 package protocol
 package protocol

+ 1 - 1
lib/rc/rc.go

@@ -499,7 +499,7 @@ func (p *Process) eventLoop() {
 				p.id = id
 				p.id = id
 
 
 				home := data["home"].(string)
 				home := data["home"].(string)
-				w, err := config.Load(filepath.Join(home, "config.xml"), protocol.LocalDeviceID, events.NoopLogger)
+				w, _, err := config.Load(filepath.Join(home, "config.xml"), protocol.LocalDeviceID, events.NoopLogger)
 				if err != nil {
 				if err != nil {
 					log.Println("eventLoop: Starting:", err)
 					log.Println("eventLoop: Starting:", err)
 					continue
 					continue

+ 8 - 8
lib/syncthing/utils.go

@@ -63,7 +63,7 @@ func DefaultConfig(path string, myID protocol.DeviceID, evLogger events.Logger,
 // necessary or returns an error, if the version isn't compatible.
 // necessary or returns an error, if the version isn't compatible.
 func LoadConfigAtStartup(path string, cert tls.Certificate, evLogger events.Logger, allowNewerConfig, noDefaultFolder bool) (config.Wrapper, error) {
 func LoadConfigAtStartup(path string, cert tls.Certificate, evLogger events.Logger, allowNewerConfig, noDefaultFolder bool) (config.Wrapper, error) {
 	myID := protocol.NewDeviceID(cert.Certificate[0])
 	myID := protocol.NewDeviceID(cert.Certificate[0])
-	cfg, err := config.Load(path, myID, evLogger)
+	cfg, originalVersion, err := config.Load(path, myID, evLogger)
 	if fs.IsNotExist(err) {
 	if fs.IsNotExist(err) {
 		cfg, err = DefaultConfig(path, myID, evLogger, noDefaultFolder)
 		cfg, err = DefaultConfig(path, myID, evLogger, noDefaultFolder)
 		if err != nil {
 		if err != nil {
@@ -80,14 +80,14 @@ func LoadConfigAtStartup(path string, cert tls.Certificate, evLogger events.Logg
 		return nil, errors.Wrap(err, "failed to load config")
 		return nil, errors.Wrap(err, "failed to load config")
 	}
 	}
 
 
-	if cfg.RawCopy().OriginalVersion != config.CurrentVersion {
-		if cfg.RawCopy().OriginalVersion == config.CurrentVersion+1101 {
+	if originalVersion != config.CurrentVersion {
+		if originalVersion == config.CurrentVersion+1101 {
 			l.Infof("Now, THAT's what we call a config from the future! Don't worry. As long as you hit that wire with the connecting hook at precisely eighty-eight miles per hour the instant the lightning strikes the tower... everything will be fine.")
 			l.Infof("Now, THAT's what we call a config from the future! Don't worry. As long as you hit that wire with the connecting hook at precisely eighty-eight miles per hour the instant the lightning strikes the tower... everything will be fine.")
 		}
 		}
-		if cfg.RawCopy().OriginalVersion > config.CurrentVersion && !allowNewerConfig {
-			return nil, fmt.Errorf("config file version (%d) is newer than supported version (%d). If this is expected, use -allow-newer-config to override.", cfg.RawCopy().OriginalVersion, config.CurrentVersion)
+		if originalVersion > config.CurrentVersion && !allowNewerConfig {
+			return nil, fmt.Errorf("config file version (%d) is newer than supported version (%d). If this is expected, use -allow-newer-config to override.", originalVersion, config.CurrentVersion)
 		}
 		}
-		err = archiveAndSaveConfig(cfg)
+		err = archiveAndSaveConfig(cfg, originalVersion)
 		if err != nil {
 		if err != nil {
 			return nil, errors.Wrap(err, "config archive")
 			return nil, errors.Wrap(err, "config archive")
 		}
 		}
@@ -96,9 +96,9 @@ func LoadConfigAtStartup(path string, cert tls.Certificate, evLogger events.Logg
 	return cfg, nil
 	return cfg, nil
 }
 }
 
 
-func archiveAndSaveConfig(cfg config.Wrapper) error {
+func archiveAndSaveConfig(cfg config.Wrapper, originalVersion int) error {
 	// Copy the existing config to an archive copy
 	// Copy the existing config to an archive copy
-	archivePath := cfg.ConfigPath() + fmt.Sprintf(".v%d", cfg.RawCopy().OriginalVersion)
+	archivePath := cfg.ConfigPath() + fmt.Sprintf(".v%d", originalVersion)
 	l.Infoln("Archiving a copy of old config file format at:", archivePath)
 	l.Infoln("Archiving a copy of old config file format at:", archivePath)
 	if err := copyFile(cfg.ConfigPath(), archivePath); err != nil {
 	if err := copyFile(cfg.ConfigPath(), archivePath); err != nil {
 		return err
 		return err

+ 2 - 2
lib/util/utils.go

@@ -58,14 +58,14 @@ func SetDefaults(data interface{}) {
 			case string:
 			case string:
 				f.SetString(v)
 				f.SetString(v)
 
 
-			case int:
+			case int, uint32, int32, int64, uint64:
 				i, err := strconv.ParseInt(v, 10, 64)
 				i, err := strconv.ParseInt(v, 10, 64)
 				if err != nil {
 				if err != nil {
 					panic(err)
 					panic(err)
 				}
 				}
 				f.SetInt(i)
 				f.SetInt(i)
 
 
-			case float64:
+			case float64, float32:
 				i, err := strconv.ParseFloat(v, 64)
 				i, err := strconv.ParseFloat(v, 64)
 				if err != nil {
 				if err != nil {
 					panic(err)
 					panic(err)

+ 2 - 1
meta/gofmt_test.go

@@ -11,6 +11,7 @@ import (
 	"os"
 	"os"
 	"os/exec"
 	"os/exec"
 	"path/filepath"
 	"path/filepath"
+	"strings"
 	"testing"
 	"testing"
 )
 )
 
 
@@ -25,7 +26,7 @@ func TestCheckGoFmt(t *testing.T) {
 			if path == ".git" {
 			if path == ".git" {
 				return filepath.SkipDir
 				return filepath.SkipDir
 			}
 			}
-			if filepath.Ext(path) != ".go" {
+			if filepath.Ext(path) != ".go" || strings.HasSuffix(path, ".pb.go") {
 				return nil
 				return nil
 			}
 			}
 			cmd := exec.Command("gofmt", "-s", "-d", path)
 			cmd := exec.Command("gofmt", "-s", "-d", path)

+ 24 - 0
proto/ext.proto

@@ -0,0 +1,24 @@
+syntax = "proto2";
+
+package ext;
+
+import "google/protobuf/descriptor.proto";
+
+option go_package = "github.com/syncthing/syncthing/proto/ext";
+
+extend google.protobuf.MessageOptions {
+    optional bool xml_tags = 74001;
+}
+
+extend google.protobuf.FieldOptions {
+    optional string xml       = 75005;
+    optional string json      = 75006;
+    optional string default   = 75007;
+    optional bool   restart   = 75008;
+    optional bool   device_id = 75009;
+    optional string goname    = 75010;
+}
+
+extend google.protobuf.EnumValueOptions {
+    optional string enumgoname = 76010;
+}

+ 131 - 0
proto/ext/ext.pb.go

@@ -0,0 +1,131 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: ext.proto
+
+package ext
+
+import (
+	fmt "fmt"
+	proto "github.com/gogo/protobuf/proto"
+	descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
+	math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
+
+var E_XmlTags = &proto.ExtensionDesc{
+	ExtendedType:  (*descriptor.MessageOptions)(nil),
+	ExtensionType: (*bool)(nil),
+	Field:         74001,
+	Name:          "ext.xml_tags",
+	Tag:           "varint,74001,opt,name=xml_tags",
+	Filename:      "ext.proto",
+}
+
+var E_Xml = &proto.ExtensionDesc{
+	ExtendedType:  (*descriptor.FieldOptions)(nil),
+	ExtensionType: (*string)(nil),
+	Field:         75005,
+	Name:          "ext.xml",
+	Tag:           "bytes,75005,opt,name=xml",
+	Filename:      "ext.proto",
+}
+
+var E_Json = &proto.ExtensionDesc{
+	ExtendedType:  (*descriptor.FieldOptions)(nil),
+	ExtensionType: (*string)(nil),
+	Field:         75006,
+	Name:          "ext.json",
+	Tag:           "bytes,75006,opt,name=json",
+	Filename:      "ext.proto",
+}
+
+var E_Default = &proto.ExtensionDesc{
+	ExtendedType:  (*descriptor.FieldOptions)(nil),
+	ExtensionType: (*string)(nil),
+	Field:         75007,
+	Name:          "ext.default",
+	Tag:           "bytes,75007,opt,name=default",
+	Filename:      "ext.proto",
+}
+
+var E_Restart = &proto.ExtensionDesc{
+	ExtendedType:  (*descriptor.FieldOptions)(nil),
+	ExtensionType: (*bool)(nil),
+	Field:         75008,
+	Name:          "ext.restart",
+	Tag:           "varint,75008,opt,name=restart",
+	Filename:      "ext.proto",
+}
+
+var E_DeviceId = &proto.ExtensionDesc{
+	ExtendedType:  (*descriptor.FieldOptions)(nil),
+	ExtensionType: (*bool)(nil),
+	Field:         75009,
+	Name:          "ext.device_id",
+	Tag:           "varint,75009,opt,name=device_id",
+	Filename:      "ext.proto",
+}
+
+var E_Goname = &proto.ExtensionDesc{
+	ExtendedType:  (*descriptor.FieldOptions)(nil),
+	ExtensionType: (*string)(nil),
+	Field:         75010,
+	Name:          "ext.goname",
+	Tag:           "bytes,75010,opt,name=goname",
+	Filename:      "ext.proto",
+}
+
+var E_Enumgoname = &proto.ExtensionDesc{
+	ExtendedType:  (*descriptor.EnumValueOptions)(nil),
+	ExtensionType: (*string)(nil),
+	Field:         76010,
+	Name:          "ext.enumgoname",
+	Tag:           "bytes,76010,opt,name=enumgoname",
+	Filename:      "ext.proto",
+}
+
+func init() {
+	proto.RegisterExtension(E_XmlTags)
+	proto.RegisterExtension(E_Xml)
+	proto.RegisterExtension(E_Json)
+	proto.RegisterExtension(E_Default)
+	proto.RegisterExtension(E_Restart)
+	proto.RegisterExtension(E_DeviceId)
+	proto.RegisterExtension(E_Goname)
+	proto.RegisterExtension(E_Enumgoname)
+}
+
+func init() { proto.RegisterFile("ext.proto", fileDescriptor_95fe6908ffcf64d3) }
+
+var fileDescriptor_95fe6908ffcf64d3 = []byte{
+	// 305 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0xd1, 0x3d, 0x4b, 0x03, 0x31,
+	0x18, 0xc0, 0x71, 0x8e, 0x16, 0xdb, 0x66, 0xec, 0x24, 0x82, 0xb5, 0x6e, 0x9d, 0xee, 0x10, 0x41,
+	0x31, 0x74, 0x52, 0x14, 0x1c, 0x44, 0x28, 0xe2, 0xe0, 0x52, 0xd2, 0xcb, 0xd3, 0x34, 0x92, 0x97,
+	0x72, 0x49, 0x24, 0x6e, 0xea, 0x37, 0xf0, 0x2b, 0x39, 0x69, 0x27, 0xfd, 0x06, 0xd2, 0xd1, 0xef,
+	0xe0, 0x0b, 0x77, 0x97, 0x93, 0x42, 0x87, 0xdb, 0x42, 0xf8, 0xff, 0x1e, 0x12, 0x1e, 0xd4, 0x01,
+	0x6f, 0xe3, 0x79, 0xa6, 0xad, 0xee, 0x36, 0xc0, 0xdb, 0xad, 0x3e, 0xd3, 0x9a, 0x09, 0x48, 0x8a,
+	0xab, 0x89, 0x9b, 0x26, 0x14, 0x4c, 0x9a, 0xf1, 0xb9, 0xd5, 0x59, 0x99, 0xe1, 0x21, 0x6a, 0x7b,
+	0x29, 0xc6, 0x96, 0x30, 0xd3, 0xdd, 0x89, 0xcb, 0x3c, 0xae, 0xf2, 0xf8, 0x02, 0x8c, 0x21, 0x0c,
+	0x2e, 0xe7, 0x96, 0x6b, 0x65, 0x36, 0x9f, 0x5f, 0x9a, 0xfd, 0x68, 0xd0, 0x1e, 0xb5, 0xbc, 0x14,
+	0x57, 0x84, 0x19, 0xbc, 0x87, 0x1a, 0x5e, 0x8a, 0xee, 0xf6, 0x1a, 0x3c, 0xe3, 0x20, 0x68, 0xc5,
+	0xbe, 0xdf, 0x72, 0xd6, 0x19, 0xe5, 0x2d, 0xde, 0x47, 0xcd, 0x5b, 0xa3, 0x55, 0x9d, 0xf9, 0x09,
+	0xa6, 0x88, 0xf1, 0x11, 0x6a, 0x51, 0x98, 0x12, 0x27, 0x6c, 0x9d, 0xfb, 0x0d, 0xae, 0xea, 0x73,
+	0x9a, 0x81, 0xb1, 0x24, 0xab, 0xa5, 0x0f, 0x8b, 0xf0, 0xbb, 0xd0, 0xe3, 0x21, 0xea, 0x50, 0xb8,
+	0xe3, 0x29, 0x8c, 0x39, 0xad, 0xc3, 0x8f, 0x01, 0xb7, 0x4b, 0x71, 0x4e, 0xf1, 0x21, 0xda, 0x60,
+	0x5a, 0x11, 0x09, 0x75, 0xf4, 0x69, 0x51, 0x3e, 0x39, 0xe4, 0xf8, 0x04, 0x21, 0x50, 0x4e, 0x06,
+	0xbc, 0xbb, 0x86, 0x4f, 0x95, 0x93, 0xd7, 0x44, 0xb8, 0xff, 0xb5, 0x7c, 0x7d, 0x94, 0x03, 0x56,
+	0xd8, 0xf1, 0xc1, 0xeb, 0xb2, 0x17, 0xbd, 0x2f, 0x7b, 0xd1, 0xe7, 0xb2, 0x17, 0xdd, 0x0c, 0x18,
+	0xb7, 0x33, 0x37, 0x89, 0x53, 0x2d, 0x13, 0x73, 0xaf, 0x52, 0x3b, 0xe3, 0x8a, 0xad, 0x9c, 0x8a,
+	0xd9, 0x09, 0x78, 0xfb, 0x17, 0x00, 0x00, 0xff, 0xff, 0xcd, 0x40, 0x4c, 0x73, 0x42, 0x02, 0x00,
+	0x00,
+}

+ 55 - 0
proto/generate.go

@@ -0,0 +1,55 @@
+// Copyright (C) 2020 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/.
+
+//+build ignore
+
+package main
+
+import (
+	"log"
+	"os"
+	"os/exec"
+	"path/filepath"
+)
+
+//go:generate go run scripts/protofmt.go .
+
+// First generate extensions using standard proto compiler.
+//go:generate protoc -I ../ -I . --gogofast_out=Mgoogle/protobuf/descriptor.proto=github.com/gogo/protobuf/protoc-gen-gogo/descriptor,paths=source_relative:ext ext.proto
+
+// Then build our vanity compiler that uses the new extensions
+//go:generate go build -o scripts/protoc-gen-gosyncthing scripts/protoc_plugin.go
+
+// Inception, go generate calls the script itself that then deals with generation.
+// This is only done because go:generate does not support wildcards in paths.
+//go:generate go run generate.go lib/config lib/fs
+
+// Use the standard compiler here. We can revisit this later, but we don't plan on exposing this via any APIs.
+//go:generate protoc -I ../ -I . --gogofast_out=paths=source_relative:.. lib/protocol/bep.proto
+
+func main() {
+	for _, path := range os.Args[1:] {
+		matches, err := filepath.Glob(filepath.Join(path, "*proto"))
+		if err != nil {
+			log.Fatal(err)
+		}
+		log.Println(path, "returned:", matches)
+		args := []string{
+			"-I", "..",
+			"-I", ".",
+			"--plugin=protoc-gen-gosyncthing=scripts/protoc-gen-gosyncthing",
+			"--gosyncthing_out=paths=source_relative:..",
+		}
+		args = append(args, matches...)
+		cmd := exec.Command("protoc", args...)
+		cmd.Stdout = os.Stdout
+		cmd.Stderr = os.Stderr
+
+		if err := cmd.Run(); err != nil {
+			log.Fatal("Failed generating", path)
+		}
+	}
+}

+ 14 - 0
proto/lib/config/authmode.proto

@@ -0,0 +1,14 @@
+syntax = "proto3";
+
+package config;
+
+import "repos/protobuf/gogoproto/gogo.proto";
+
+import "ext.proto";
+
+enum AuthMode {
+    option (gogoproto.goproto_enum_stringer) = false;
+
+    AUTH_MODE_STATIC = 0;
+    AUTH_MODE_LDAP   = 1 [(ext.enumgoname) = "AuthModeLDAP"];
+}

+ 9 - 0
proto/lib/config/blockpullorder.proto

@@ -0,0 +1,9 @@
+syntax = "proto3";
+
+package config;
+
+enum BlockPullOrder {
+    BLOCK_PULL_ORDER_STANDARD = 0;
+    BLOCK_PULL_ORDER_RANDOM   = 1;
+    BLOCK_PULL_ORDER_IN_ORDER = 2;
+}

+ 23 - 0
proto/lib/config/config.proto

@@ -0,0 +1,23 @@
+syntax = "proto3";
+
+package config;
+
+import "lib/config/folderconfiguration.proto";
+import "lib/config/deviceconfiguration.proto";
+import "lib/config/guiconfiguration.proto";
+import "lib/config/ldapconfiguration.proto";
+import "lib/config/optionsconfiguration.proto";
+import "lib/config/observed.proto";
+
+import "ext.proto";
+
+message Configuration {
+    int32                        version         = 1 [(ext.xml) = "version,attr"];
+    repeated FolderConfiguration folders         = 2;
+    repeated DeviceConfiguration devices         = 3;
+    GUIConfiguration             gui             = 4 [(ext.goname) = "GUI"];
+    LDAPConfiguration            ldap            = 5 [(ext.goname) = "LDAP"];
+    OptionsConfiguration         options         = 6;
+    repeated ObservedDevice      ignored_devices = 7 [(ext.json) = "remoteIgnoredDevices", (ext.xml) = "remoteIgnoredDevice"];
+    repeated ObservedDevice      pending_devices = 8;
+}

+ 27 - 0
proto/lib/config/deviceconfiguration.proto

@@ -0,0 +1,27 @@
+syntax = "proto3";
+
+package config;
+
+import "lib/protocol/bep.proto";
+import "lib/config/observed.proto";
+
+import "ext.proto";
+
+message DeviceConfiguration {
+    bytes                   device_id                  = 1 [(ext.goname) = "DeviceID", (ext.xml) = "id,attr", (ext.json) = "deviceID", (ext.device_id) = true];
+    string                  name                       = 2 [(ext.xml) = "name,attr,omitempty"];
+    repeated string         addresses                  = 3 [(ext.xml) = "address,omitempty", (ext.default) = "dynamic"];
+    protocol.Compression    compression                = 4 [(ext.xml) = "compression,attr"];
+    string                  cert_name                  = 5 [(ext.xml) = "certName,attr,omitempty"];
+    bool                    introducer                 = 6 [(ext.xml) = "introducer,attr"];
+    bool                    skip_introduction_removals = 7 [(ext.xml) = "skipIntroductionRemovals,attr"];
+    bytes                   introduced_by              = 8 [(ext.xml) = "introducedBy,attr", (ext.device_id) = true];
+    bool                    paused                     = 9;
+    repeated string         allowed_networks           = 10 [(ext.xml) = "allowedNetwork,omitempty"];
+    bool                    auto_accept_folders        = 11;
+    int32                   max_send_kbps              = 12;
+    int32                   max_recv_kbps              = 13;
+    repeated ObservedFolder ignored_folders            = 14;
+    repeated ObservedFolder pending_folders            = 15;
+    int32                   max_request_kib            = 16 [(ext.goname) = "MaxRequestKiB", (ext.xml) = "maxRequestKiB", (ext.json) = "maxRequestKiB"];
+}

+ 61 - 0
proto/lib/config/folderconfiguration.proto

@@ -0,0 +1,61 @@
+syntax = "proto3";
+
+package config;
+
+import "lib/config/foldertype.proto";
+import "lib/config/size.proto";
+import "lib/config/pullorder.proto";
+import "lib/config/versioningconfiguration.proto";
+import "lib/config/blockpullorder.proto";
+
+import "lib/fs/types.proto";
+import "lib/fs/copyrangemethod.proto";
+
+import "ext.proto";
+
+message FolderDeviceConfiguration {
+    bytes device_id     = 1 [(ext.goname) = "DeviceID", (ext.xml) = "id,attr", (ext.json) = "deviceID", (ext.device_id) = true];
+    bytes introduced_by = 2 [(ext.xml) = "introducedBy,attr", (ext.device_id) = true];
+}
+
+message FolderConfiguration {
+    string                             id                         = 1 [(ext.goname) = "ID", (ext.xml) = "id,attr"];
+    string                             label                      = 2 [(ext.xml) = "label,attr", (ext.restart) = false];
+    fs.FilesystemType                  filesystem_type            = 3;
+    string                             path                       = 4 [(ext.xml) = "path,attr"];
+    FolderType                         type                       = 5 [(ext.xml) = "type,attr"];
+    repeated FolderDeviceConfiguration devices                    = 6;
+    int32                              rescan_interval_s          = 7 [(ext.xml) = "rescanIntervalS,attr", (ext.default) = "3600"];
+    bool                               fs_watcher_enabled         = 8 [(ext.goname) = "FSWatcherEnabled", (ext.xml) = "fsWatcherEnabled,attr", (ext.default) = "true"];
+    int32                              fs_watcher_delay_s         = 9 [(ext.goname) = "FSWatcherDelayS", (ext.xml) = "fsWatcherDelayS,attr", (ext.default) = "10"];
+    bool                               ignore_perms               = 10 [(ext.xml) = "ignorePerms,attr"];
+    bool                               auto_normalize             = 11 [(ext.xml) = "autoNormalize,attr", (ext.default) = "true"];
+    Size                               min_disk_free              = 12;
+    VersioningConfiguration            versioning                 = 13;
+    int32                              copiers                    = 14;
+    int32                              puller_max_pending_kib     = 15 [(ext.goname) = "PullerMaxPendingKiB", (ext.xml) = "pullerMaxPendingKiB", (ext.json) = "pullerMaxPendingKiB"];
+    int32                              hashers                    = 16;
+    PullOrder                          order                      = 17;
+    bool                               ignore_delete              = 18;
+    int32                              scan_progress_interval_s   = 19;
+    int32                              puller_pause_s             = 20;
+    int32                              max_conflicts              = 21 [(ext.default) = "-1"];
+    bool                               disable_sparse_files       = 22;
+    bool                               disable_temp_indexes       = 23;
+    bool                               paused                     = 24;
+    int32                              weak_hash_threshold_pct    = 25;
+    string                             marker_name                = 26;
+    bool                               copy_ownership_from_parent = 27;
+    int32                              mod_time_window_s          = 28 [(ext.goname) = "RawModTimeWindowS"];
+    int32                              max_concurrent_writes      = 29 [(ext.default) = "2"];
+    bool                               disable_fsync              = 30;
+    BlockPullOrder                     block_pull_order           = 31;
+    fs.CopyRangeMethod                 copy_range_method          = 32 [(ext.default) = "standard"];
+    bool                               case_sensitive_fs          = 33 [(ext.goname) = "CaseSensitiveFS", (ext.xml) = "caseSensitiveFS", (ext.json) = "caseSensitiveFS"];
+    bool                               follow_junctions           = 34 [(ext.goname) = "JunctionsAsDirs", (ext.xml) = "junctionsAsDirs", (ext.json) = "junctionsAsDirs"];
+
+    // Legacy deprecated
+    bool   read_only         = 9000 [deprecated=true, (ext.xml) = "ro,attr,omitempty"];
+    double min_disk_free_pct = 9001 [deprecated=true];
+    int32  pullers           = 9002 [deprecated=true];
+}

+ 9 - 0
proto/lib/config/foldertype.proto

@@ -0,0 +1,9 @@
+syntax = "proto3";
+
+package config;
+
+enum FolderType {
+    FOLDER_TYPE_SEND_RECEIVE = 0;
+    FOLDER_TYPE_SEND_ONLY    = 1;
+    FOLDER_TYPE_RECEIVE_ONLY = 2;
+}

+ 23 - 0
proto/lib/config/guiconfiguration.proto

@@ -0,0 +1,23 @@
+syntax = "proto3";
+
+package config;
+
+import "lib/config/authmode.proto";
+
+import "ext.proto";
+
+message GUIConfiguration {
+    bool     enabled                      = 1 [(ext.xml) = "enabled,attr", (ext.default) = "true"];
+    string   address                      = 2 [(ext.goname) = "RawAddress", (ext.default) = "127.0.0.1:8384"];
+    string   unix_socket_permissions      = 3 [(ext.goname) = "RawUnixSocketPermissions", (ext.xml) = "unixSocketPermissions,omitempty"];
+    string   user                         = 4 [(ext.xml) = "user,omitempty"];
+    string   password                     = 5 [(ext.xml) = "password,omitempty"];
+    AuthMode auth_mode                    = 6 [(ext.xml) = "authMode,omitempty"];
+    bool     use_tls                      = 7 [(ext.goname) = "RawUseTLS", (ext.xml) = "tls,attr", (ext.json) = "useTLS"];
+    string   api_key                      = 8 [(ext.goname) = "APIKey", (ext.xml) = "apikey,omitempty"];
+    bool     insecure_admin_access        = 9 [(ext.xml) = "insecureAdminAccess,omitempty"];
+    string   theme                        = 10 [(ext.default) = "default"];
+    bool     debugging                    = 11 [(ext.xml) = "debugging,attr"];
+    bool     insecure_skip_host_check     = 12 [(ext.xml) = "insecureSkipHostcheck,omitempty", (ext.json) = "insecureSkipHostcheck"];
+    bool     insecure_allow_frame_loading = 13 [(ext.xml) = "insecureAllowFrameLoading,omitempty"];
+}

+ 17 - 0
proto/lib/config/ldapconfiguration.proto

@@ -0,0 +1,17 @@
+syntax = "proto3";
+
+package config;
+
+import "lib/config/ldaptransport.proto";
+
+import "ext.proto";
+
+
+message LDAPConfiguration {
+    string        address              = 1 [(ext.xml) = "address,omitempty"];
+    string        bind_dn              = 2 [(ext.goname) = "BindDN", (ext.xml) = "bindDN,omitempty", (ext.json) = "bindDN"];
+    LDAPTransport transport            = 3 [(ext.xml) = "transport,omitempty"];
+    bool          insecure_skip_verify = 4 [(ext.xml) = "insecureSkipVerify,omitempty", (ext.default) = "false"];
+    string        search_base_dn       = 5 [(ext.goname) = "SearchBaseDN", (ext.xml) = "searchBaseDN,omitempty", (ext.json) = "searchBaseDN"];
+    string        search_filter        = 6 [(ext.xml) = "searchFilter,omitempty"];
+}

+ 15 - 0
proto/lib/config/ldaptransport.proto

@@ -0,0 +1,15 @@
+syntax = "proto3";
+
+package config;
+
+import "repos/protobuf/gogoproto/gogo.proto";
+
+import "ext.proto";
+
+enum LDAPTransport {
+    option (gogoproto.goproto_enum_stringer) = false;
+
+    LDAP_TRANSPORT_PLAIN     = 0 [(ext.enumgoname) = "LDAPTransportPlain"];
+    LDAP_TRANSPORT_TLS       = 2 [(ext.enumgoname) = "LDAPTransportTLS"];
+    LDAP_TRANSPORT_START_TLS = 3 [(ext.enumgoname) = "LDAPTransportStartTLS"];
+}

+ 20 - 0
proto/lib/config/observed.proto

@@ -0,0 +1,20 @@
+syntax = "proto3";
+
+package config;
+
+import "google/protobuf/timestamp.proto";
+
+import "ext.proto";
+
+message ObservedFolder {
+    google.protobuf.Timestamp time  = 1 [(ext.xml) = "time,attr"];
+    string                    id    = 2 [(ext.goname) = "ID", (ext.xml) = "id,attr"];
+    string                    label = 3 [(ext.xml) = "label,attr"];
+}
+
+message ObservedDevice {
+    google.protobuf.Timestamp time    = 1 [(ext.xml) = "time,attr"];
+    bytes                     id      = 2 [(ext.goname) = "ID", (ext.json) = "deviceID", (ext.xml) = "id,attr", (ext.device_id) = true];
+    string                    name    = 3 [(ext.xml) = "name,attr"];
+    string                    address = 4 [(ext.xml) = "address,attr"];
+}

+ 66 - 0
proto/lib/config/optionsconfiguration.proto

@@ -0,0 +1,66 @@
+syntax = "proto3";
+
+package config;
+
+import "lib/config/tuning.proto";
+import "lib/config/size.proto";
+
+import "ext.proto";
+
+message OptionsConfiguration {
+    repeated string listen_addresses                         = 1 [(ext.goname) = "RawListenAddresses", (ext.default) = "default"];
+    repeated string global_discovery_servers                 = 2 [(ext.goname) = "RawGlobalAnnServers", (ext.xml) = "globalAnnounceServer", (ext.json) = "globalAnnounceServers", (ext.default) = "default"];
+    bool            global_discovery_enabled                 = 3 [(ext.goname) = "GlobalAnnEnabled", (ext.xml) = "globalAnnounceEnabled", (ext.json) = "globalAnnounceEnabled", (ext.default) = "true"];
+    bool            local_discovery_enabled                  = 4 [(ext.goname) = "LocalAnnEnabled", (ext.xml) = "localAnnounceEnabled", (ext.json) = "localAnnounceEnabled", (ext.default) = "true"];
+    int32           local_announce_port                      = 5 [(ext.goname) = "LocalAnnPort", (ext.xml) = "localAnnouncePort", (ext.json) = "localAnnouncePort", (ext.default) = "21027"];
+    string          local_announce_multicast_address         = 6 [(ext.goname) = "LocalAnnMCAddr", (ext.xml) = "localAnnounceMCAddr", (ext.json) = "localAnnounceMCAddr", (ext.default) = "[ff12::8384]:21027"];
+    int32           max_send_kbps                            = 7;
+    int32           max_recv_kbps                            = 8;
+    int32           reconnection_interval_s                  = 9 [(ext.goname) = "ReconnectIntervalS", (ext.default) = "60"];
+    bool            relays_enabled                           = 10 [(ext.default) = "true"];
+    int32           relays_reconnect_interval_m              = 11 [(ext.goname) = "RelayReconnectIntervalM", (ext.xml) = "relayReconnectIntervalM", (ext.json) = "relayReconnectIntervalM", (ext.default) = "10"];
+    bool            start_browser                            = 12 [(ext.default) = "true"];
+    bool            nat_traversal_enabled                    = 14 [(ext.goname) = "NATEnabled", (ext.xml) = "natEnabled", (ext.json) = "natEnabled", (ext.default) = "true"];
+    int32           nat_traversal_lease_m                    = 15 [(ext.goname) = "NATLeaseM", (ext.xml) = "natLeaseMinutes", (ext.json) = "natLeaseMinutes", (ext.default) = "60"];
+    int32           nat_traversal_renewal_m                  = 16 [(ext.goname) = "NATRenewalM", (ext.xml) = "natRenewalMinutes", (ext.json) = "natRenewalMinutes", (ext.default) = "30"];
+    int32           nat_traversal_timeout_s                  = 17 [(ext.goname) = "NATTimeoutS", (ext.xml) = "natTimeoutSeconds", (ext.json) = "natTimeoutSeconds", (ext.default) = "10"];
+    int32           usage_reporting_accepted                 = 18 [(ext.goname) = "URAccepted", (ext.xml) = "urAccepted", (ext.json) = "urAccepted"];
+    int32           usage_reporting_seen                     = 19 [(ext.goname) = "URSeen", (ext.xml) = "urSeen", (ext.json) = "urSeen"];
+    string          usage_reporting_unique_id                = 20 [(ext.goname) = "URUniqueID", (ext.xml) = "urUniqueID", (ext.json) = "urUniqueId"];
+    string          usage_reporting_url                      = 21 [(ext.goname) = "URURL", (ext.xml) = "urURL", (ext.json) = "urURL", (ext.default) = "https://data.syncthing.net/newdata"];
+    bool            usage_reporting_post_insecurely          = 22 [(ext.goname) = "URPostInsecurely", (ext.xml) = "urPostInsecurely", (ext.json) = "urPostInsecurely", (ext.default) = "false"];
+    int32           usage_reporting_initial_delay_s          = 23 [(ext.goname) = "URInitialDelayS", (ext.xml) = "urInitialDelayS", (ext.json) = "urInitialDelayS", (ext.default) = "1800"];
+    bool            restart_on_wakeup                        = 24 [(ext.default) = "true"];
+    int32           auto_upgrade_interval_h                  = 25 [(ext.default) = "12"];
+    bool            upgrade_to_pre_releases                  = 26;
+    int32           keep_temporaries_h                       = 27 [(ext.default) = "24"];
+    bool            cache_ignored_files                      = 28 [(ext.default) = "false"];
+    int32           progress_update_interval_s               = 29 [(ext.default) = "5"];
+    bool            limit_bandwidth_in_lan                   = 30 [(ext.default) = "false"];
+    Size            min_home_disk_free                       = 31 [(ext.default) = "1 %"];
+    string          releases_url                             = 32 [(ext.goname) = "ReleasesURL", (ext.xml) = "releasesURL", (ext.json) = "releasesURL", (ext.default) = "https://upgrades.syncthing.net/meta.json"];
+    repeated string always_local_nets                        = 33;
+    bool            overwrite_remote_device_names_on_connect = 34 [(ext.goname) = "OverwriteRemoteDevNames", (ext.default) = "false"];
+    int32           temp_index_min_blocks                    = 35 [(ext.default) = "10"];
+    repeated string unacked_notification_ids                 = 36 [(ext.goname) = "UnackedNotificationIDs", (ext.xml) = "unackedNotificationID", (ext.json) = "unackedNotificationIDs"];
+    int32           traffic_class                            = 37;
+    string          default_folder_path                      = 38 [(ext.default) = "~"];
+    bool            set_low_priority                         = 39 [(ext.default) = "true"];
+    int32           max_folder_concurrency                   = 40 [(ext.goname) = "RawMaxFolderConcurrency"];
+    string          crash_reporting_url                      = 41 [(ext.goname) = "CRURL", (ext.xml) = "crashReportingURL", (ext.json) = "crURL", (ext.default) = "https://crash.syncthing.net/newcrash"];
+    bool            crash_reporting_enabled                  = 42 [(ext.goname) = "CREnabled", (ext.default) = "true"];
+    int32           stun_keepalive_start_s                   = 43 [(ext.default) = "180"];
+    int32           stun_keepalive_min_s                     = 44 [(ext.default) = "20"];
+    repeated string stun_servers                             = 45 [(ext.goname) = "RawStunServers", (ext.default) = "default"];
+    Tuning          database_tuning                          = 46 [(ext.restart) = true];
+    int32           max_concurrent_incoming_request_kib      = 47 [(ext.goname) = "RawMaxCIRequestKiB", (ext.xml) = "maxConcurrentIncomingRequestKiB", (ext.json) = "maxConcurrentIncomingRequestKiB"];
+
+    // Legacy deprecated
+    bool            upnp_enabled           = 9000 [deprecated = true, (ext.goname) = "DeprecatedUPnPEnabled"];
+    int32           upnp_lease_m           = 9001 [deprecated = true, (ext.goname) = "DeprecatedUPnPLeaseM", (ext.xml) = "upnpLeaseMinutes,omitempty"];
+    int32           upnp_renewal_m         = 9002 [deprecated = true, (ext.goname) = "DeprecatedUPnPRenewalM", (ext.xml) = "upnpRenewalMinutes,omitempty"];
+    int32           upnp_timeout_s         = 9003 [deprecated = true, (ext.goname) = "DeprecatedUPnPTimeoutS", (ext.xml) = "upnpTimeoutSeconds,omitempty"];
+    repeated string relay_servers          = 9004 [deprecated = true];
+    double          min_home_disk_free_pct = 9005 [deprecated = true];
+    int32           max_concurrent_scans   = 9006 [deprecated = true];
+}

+ 16 - 0
proto/lib/config/pullorder.proto

@@ -0,0 +1,16 @@
+syntax = "proto3";
+
+package config;
+
+import "repos/protobuf/gogoproto/gogo.proto";
+
+enum PullOrder {
+    option (gogoproto.goproto_enum_stringer) = false;
+
+    PULL_ORDER_RANDOM         = 0;
+    PULL_ORDER_ALPHABETIC     = 1;
+    PULL_ORDER_SMALLEST_FIRST = 2;
+    PULL_ORDER_LARGEST_FIRST  = 3;
+    PULL_ORDER_OLDEST_FIRST   = 4;
+    PULL_ORDER_NEWEST_FIRST   = 5;
+}

+ 14 - 0
proto/lib/config/size.proto

@@ -0,0 +1,14 @@
+syntax = "proto3";
+
+package config;
+
+import "repos/protobuf/gogoproto/gogo.proto";
+
+import "ext.proto";
+
+message Size {
+    option (gogoproto.goproto_stringer) = false;
+
+    double value = 1 [(ext.xml) = ",chardata"];
+    string unit  = 2 [(ext.xml) = "unit,attr"];
+}

+ 13 - 0
proto/lib/config/tuning.proto

@@ -0,0 +1,13 @@
+syntax = "proto3";
+
+package config;
+
+import "repos/protobuf/gogoproto/gogo.proto";
+
+enum Tuning {
+    option (gogoproto.goproto_enum_stringer) = false;
+
+    TUNING_AUTO  = 0;
+    TUNING_SMALL = 1;
+    TUNING_LARGE = 2;
+}

+ 14 - 0
proto/lib/config/versioningconfiguration.proto

@@ -0,0 +1,14 @@
+syntax = "proto3";
+
+package config;
+
+import "ext.proto";
+
+// VersioningConfiguration is used in the code and for JSON serialization
+message VersioningConfiguration {
+    option (ext.xml_tags) = false;
+
+    string              type               = 1;
+    map<string, string> parameters         = 2 [(ext.goname) = "Params", (ext.json) = "params"];
+    int32               cleanup_interval_s = 3 [(ext.default) = "3600"];
+}

+ 12 - 0
proto/lib/fs/copyrangemethod.proto

@@ -0,0 +1,12 @@
+syntax = "proto3";
+
+package fs;
+
+enum CopyRangeMethod {
+    COPY_RANGE_METHOD_STANDARD          = 0;
+    COPY_RANGE_METHOD_IOCTL             = 1;
+    COPY_RANGE_METHOD_COPY_FILE_RANGE   = 2;
+    COPY_RANGE_METHOD_SEND_FILE         = 3;
+    COPY_RANGE_METHOD_DUPLICATE_EXTENTS = 4;
+    COPY_RANGE_METHOD_ALL_WITH_FALLBACK = 5;
+}

+ 8 - 0
proto/lib/fs/types.proto

@@ -0,0 +1,8 @@
+syntax = "proto3";
+
+package fs;
+
+enum FilesystemType {
+    FILESYSTEM_TYPE_BASIC = 0;
+    FILESYSTEM_TYPE_FAKE  = 1;
+}

+ 0 - 0
lib/protocol/bep.proto → proto/lib/protocol/bep.proto


+ 68 - 0
proto/scripts/dump_tags.go

@@ -0,0 +1,68 @@
+// Copyright (C) 2020 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/.
+
+//+build ignore
+
+package main
+
+import (
+	"encoding/csv"
+	"fmt"
+	"os"
+	"path/filepath"
+	"reflect"
+	"strings"
+
+	"github.com/syncthing/syncthing/lib/config"
+)
+
+func main() {
+	new, err := os.Create("tags.csv")
+	if err != nil {
+		panic(err)
+	}
+	fmt.Println(filepath.Abs(new.Name()))
+	w := csv.NewWriter(new)
+	w.Write([]string{
+		"path", "json", "xml", "default", "restart",
+	})
+	walk(w, "", &config.Configuration{})
+	w.Flush()
+	new.Close()
+}
+
+func walk(w *csv.Writer, prefix string, data interface{}) {
+	s := reflect.ValueOf(data).Elem()
+	t := s.Type()
+	for i := 0; i < s.NumField(); i++ {
+		f := s.Field(i)
+		ft := t.Field(i)
+
+		for f.Kind() == reflect.Ptr {
+			f = f.Elem()
+		}
+
+		pfx := prefix + "." + s.Type().Field(i).Name
+		if f.Kind() == reflect.Slice {
+			slc := reflect.MakeSlice(f.Type(), 1, 1)
+			f = slc.Index(0)
+			pfx = prefix + "." + s.Type().Field(i).Name + "[]"
+		}
+
+		if f.Kind() == reflect.Struct && strings.HasPrefix(f.Type().PkgPath(), "github.com/syncthing/syncthing") {
+			walk(w, pfx, f.Addr().Interface())
+		} else {
+			jsonTag := ft.Tag.Get("json")
+			xmlTag := ft.Tag.Get("xml")
+			defaultTag := ft.Tag.Get("default")
+			restartTag := ft.Tag.Get("restart")
+			w.Write([]string{
+				strings.ToLower(pfx), jsonTag, xmlTag, defaultTag, restartTag,
+			})
+		}
+	}
+
+}

+ 291 - 0
proto/scripts/protoc_plugin.go

@@ -0,0 +1,291 @@
+// Copyright (C) 2020 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/.
+
+//+build ignore
+
+package main
+
+import (
+	"fmt"
+	"path/filepath"
+	"strings"
+	"unicode"
+
+	"github.com/syncthing/syncthing/proto/ext"
+
+	"github.com/gogo/protobuf/gogoproto"
+	"github.com/gogo/protobuf/proto"
+	"github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
+	"github.com/gogo/protobuf/vanity"
+	"github.com/gogo/protobuf/vanity/command"
+)
+
+func main() {
+	req := command.Read()
+	files := req.GetProtoFile()
+	files = vanity.FilterFiles(files, vanity.NotGoogleProtobufDescriptorProto)
+
+	vanity.ForEachFile(files, vanity.TurnOffGoGettersAll)
+	vanity.ForEachFile(files, TurnOnProtoSizerAll)
+	vanity.ForEachFile(files, vanity.TurnOffGoEnumPrefixAll)
+	vanity.ForEachFile(files, vanity.TurnOffGoUnrecognizedAll)
+	vanity.ForEachFile(files, vanity.TurnOffGoUnkeyedAll)
+	vanity.ForEachFile(files, vanity.TurnOffGoSizecacheAll)
+	vanity.ForEachFile(files, vanity.TurnOffGoEnumStringerAll)
+	vanity.ForEachEnumInFiles(files, HandleCustomEnumExtensions)
+	vanity.ForEachFile(files, SetPackagePrefix("github.com/syncthing/syncthing"))
+
+	vanity.ForEachMessageInFiles(files, HandleCustomExtensions)
+	vanity.ForEachFieldInFilesExcludingExtensions(files, TurnOffNullableForMessages)
+
+	resp := command.Generate(req)
+	command.Write(resp)
+}
+
+func TurnOnProtoSizerAll(file *descriptor.FileDescriptorProto) {
+	vanity.SetBoolFileOption(gogoproto.E_ProtosizerAll, true)(file)
+}
+
+func TurnOffNullableForMessages(field *descriptor.FieldDescriptorProto) {
+	if !vanity.FieldHasBoolExtension(field, gogoproto.E_Nullable) {
+		_, hasCustomType := GetFieldStringExtension(field, gogoproto.E_Customtype)
+		if field.IsMessage() || hasCustomType {
+			vanity.SetBoolFieldOption(gogoproto.E_Nullable, false)(field)
+		}
+	}
+}
+
+func HandleCustomEnumExtensions(enum *descriptor.EnumDescriptorProto) {
+	for _, field := range enum.Value {
+		if field == nil {
+			continue
+		}
+		if field.Options == nil {
+			field.Options = &descriptor.EnumValueOptions{}
+		}
+		customName := gogoproto.GetEnumValueCustomName(field)
+		if customName != "" {
+			continue
+		}
+		if v, ok := GetEnumValueStringExtension(field, ext.E_Enumgoname); ok {
+			SetEnumValueStringFieldOption(field, gogoproto.E_EnumvalueCustomname, v)
+		} else {
+			SetEnumValueStringFieldOption(field, gogoproto.E_EnumvalueCustomname, toCamelCase(*field.Name, true))
+		}
+
+	}
+}
+
+func SetPackagePrefix(prefix string) func(file *descriptor.FileDescriptorProto) {
+	return func(file *descriptor.FileDescriptorProto) {
+		if file.Options.GoPackage == nil {
+			pkg, _ := filepath.Split(file.GetName())
+			fullPkg := prefix + "/" + strings.TrimSuffix(pkg, "/")
+			file.Options.GoPackage = &fullPkg
+		}
+	}
+}
+
+func toCamelCase(input string, firstUpper bool) string {
+	runes := []rune(strings.ToLower(input))
+	outputRunes := make([]rune, 0, len(runes))
+
+	nextUpper := false
+	for i, rune := range runes {
+		if rune == '_' {
+			nextUpper = true
+			continue
+		}
+		if (firstUpper && i == 0) || nextUpper {
+			rune = unicode.ToUpper(rune)
+			nextUpper = false
+		}
+		outputRunes = append(outputRunes, rune)
+	}
+	return string(outputRunes)
+}
+
+func SetStringFieldOption(field *descriptor.FieldDescriptorProto, extension *proto.ExtensionDesc, value string) {
+	if _, ok := GetFieldStringExtension(field, extension); ok {
+		return
+	}
+	if field.Options == nil {
+		field.Options = &descriptor.FieldOptions{}
+	}
+	if err := proto.SetExtension(field.Options, extension, &value); err != nil {
+		panic(err)
+	}
+}
+
+func SetEnumValueStringFieldOption(field *descriptor.EnumValueDescriptorProto, extension *proto.ExtensionDesc, value string) {
+	if _, ok := GetEnumValueStringExtension(field, extension); ok {
+		return
+	}
+	if field.Options == nil {
+		field.Options = &descriptor.EnumValueOptions{}
+	}
+	if err := proto.SetExtension(field.Options, extension, &value); err != nil {
+		panic(err)
+	}
+}
+
+func GetEnumValueStringExtension(enumValue *descriptor.EnumValueDescriptorProto, extension *proto.ExtensionDesc) (string, bool) {
+	if enumValue.Options == nil {
+		return "", false
+	}
+	value, err := proto.GetExtension(enumValue.Options, extension)
+	if err != nil {
+		return "", false
+	}
+	if value == nil {
+		return "", false
+	}
+	if v, ok := value.(*string); !ok || v == nil {
+		return "", false
+	} else {
+		return *v, true
+	}
+}
+
+func GetFieldStringExtension(field *descriptor.FieldDescriptorProto, extension *proto.ExtensionDesc) (string, bool) {
+	if field.Options == nil {
+		return "", false
+	}
+	value, err := proto.GetExtension(field.Options, extension)
+	if err != nil {
+		return "", false
+	}
+	if value == nil {
+		return "", false
+	}
+	if v, ok := value.(*string); !ok || v == nil {
+		return "", false
+	} else {
+		return *v, true
+	}
+}
+
+func GetFieldBooleanExtension(field *descriptor.FieldDescriptorProto, extension *proto.ExtensionDesc) (bool, bool) {
+	if field.Options == nil {
+		return false, false
+	}
+	value, err := proto.GetExtension(field.Options, extension)
+	if err != nil {
+		return false, false
+	}
+	if value == nil {
+		return false, false
+	}
+	if v, ok := value.(*bool); !ok || v == nil {
+		return false, false
+	} else {
+		return *v, true
+	}
+}
+
+func GetMessageBoolExtension(msg *descriptor.DescriptorProto, extension *proto.ExtensionDesc) (bool, bool) {
+	if msg.Options == nil {
+		return false, false
+	}
+	value, err := proto.GetExtension(msg.Options, extension)
+	if err != nil {
+		return false, false
+	}
+	if value == nil {
+		return false, false
+	}
+	val, ok := value.(*bool)
+	if !ok || val == nil {
+		return false, false
+	}
+	return *val, true
+}
+
+func HandleCustomExtensions(msg *descriptor.DescriptorProto) {
+	generateXmlTags := true
+	if generate, ok := GetMessageBoolExtension(msg, ext.E_XmlTags); ok {
+		generateXmlTags = generate
+	}
+
+	vanity.ForEachField([]*descriptor.DescriptorProto{msg}, func(field *descriptor.FieldDescriptorProto) {
+		if field.Options == nil {
+			field.Options = &descriptor.FieldOptions{}
+		}
+		deprecated := field.Options.Deprecated != nil && *field.Options.Deprecated == true
+
+		if field.Type != nil && *field.Type == descriptor.FieldDescriptorProto_TYPE_INT32 {
+			SetStringFieldOption(field, gogoproto.E_Casttype, "int")
+		}
+
+		if field.TypeName != nil && *field.TypeName == ".google.protobuf.Timestamp" {
+			vanity.SetBoolFieldOption(gogoproto.E_Stdtime, true)(field)
+		}
+
+		if goName, ok := GetFieldStringExtension(field, ext.E_Goname); ok {
+			SetStringFieldOption(field, gogoproto.E_Customname, goName)
+		} else if deprecated {
+			SetStringFieldOption(field, gogoproto.E_Customname, "Deprecated"+toCamelCase(*field.Name, true))
+		}
+
+		if val, ok := GetFieldBooleanExtension(field, ext.E_DeviceId); ok && val {
+			SetStringFieldOption(field, gogoproto.E_Customtype, "github.com/syncthing/syncthing/lib/protocol.DeviceID")
+		}
+
+		if jsonValue, ok := GetFieldStringExtension(field, ext.E_Json); ok {
+			SetStringFieldOption(field, gogoproto.E_Jsontag, jsonValue)
+		} else if deprecated {
+			SetStringFieldOption(field, gogoproto.E_Jsontag, "-")
+		} else {
+			SetStringFieldOption(field, gogoproto.E_Jsontag, toCamelCase(*field.Name, false))
+		}
+
+		current := ""
+		if v, ok := GetFieldStringExtension(field, gogoproto.E_Moretags); ok {
+			current = v
+		}
+
+		if generateXmlTags {
+			if len(current) > 0 {
+				current += " "
+			}
+			if xmlValue, ok := GetFieldStringExtension(field, ext.E_Xml); ok {
+				current += fmt.Sprintf(`xml:"%s"`, xmlValue)
+			} else {
+				xmlValue = toCamelCase(*field.Name, false)
+				// XML dictates element name within the collection, not collection name, so trim plural suffix.
+				if field.IsRepeated() {
+					if strings.HasSuffix(xmlValue, "ses") {
+						// addresses -> address
+						xmlValue = strings.TrimSuffix(xmlValue, "es")
+					} else {
+						// devices -> device
+						xmlValue = strings.TrimSuffix(xmlValue, "s")
+					}
+				}
+				if deprecated {
+					xmlValue += ",omitempty"
+				}
+				current += fmt.Sprintf(`xml:"%s"`, xmlValue)
+			}
+		}
+
+		if defaultValue, ok := GetFieldStringExtension(field, ext.E_Default); ok {
+			if len(current) > 0 {
+				current += " "
+			}
+			current += fmt.Sprintf(`default:"%s"`, defaultValue)
+		}
+
+		if restartValue, ok := GetFieldBooleanExtension(field, ext.E_Restart); ok {
+			if len(current) > 0 {
+				current += " "
+			}
+			current += fmt.Sprintf(`restart:"%t"`, restartValue)
+		}
+
+		SetStringFieldOption(field, gogoproto.E_Moretags, current)
+	})
+}

+ 39 - 8
script/protofmt.go → proto/scripts/protofmt.go

@@ -15,6 +15,7 @@ import (
 	"io"
 	"io"
 	"log"
 	"log"
 	"os"
 	"os"
+	"path/filepath"
 	"regexp"
 	"regexp"
 	"strings"
 	"strings"
 	"text/tabwriter"
 	"text/tabwriter"
@@ -22,24 +23,54 @@ import (
 
 
 func main() {
 func main() {
 	flag.Parse()
 	flag.Parse()
-	file := flag.Arg(0)
+	for _, arg := range flag.Args() {
+		matches, err := filepath.Glob(arg)
+		if err != nil {
+			log.Fatal(err)
+		}
+		for _, file := range matches {
+			if stat, err := os.Stat(file); err != nil {
+				log.Fatal(err)
+			} else if stat.IsDir() {
+				err := filepath.Walk(file, func(path string, info os.FileInfo, err error) error {
+					if err != nil {
+						return err
+					}
+					if filepath.Ext(path) == ".proto" {
+						return formatProtoFile(path)
+					}
+					return nil
+				})
+				if err != nil {
+					log.Fatal(err)
+				}
+			} else {
+				if err := formatProtoFile(file); err != nil {
+					log.Fatal(err)
+				}
+			}
+		}
+	}
+}
+
+func formatProtoFile(file string) error {
+	log.Println("Formatting", file)
 	in, err := os.Open(file)
 	in, err := os.Open(file)
 	if err != nil {
 	if err != nil {
-		log.Fatal(err)
+		return err
 	}
 	}
+	defer in.Close()
 	out, err := os.Create(file + ".tmp")
 	out, err := os.Create(file + ".tmp")
 	if err != nil {
 	if err != nil {
-		log.Fatal(err)
+		return err
 	}
 	}
-
+	defer out.Close()
 	if err := formatProto(in, out); err != nil {
 	if err := formatProto(in, out); err != nil {
-		log.Fatal(err)
+		return err
 	}
 	}
 	in.Close()
 	in.Close()
 	out.Close()
 	out.Close()
-	if err := os.Rename(file+".tmp", file); err != nil {
-		log.Fatal(err)
-	}
+	return os.Rename(file+".tmp", file)
 }
 }
 
 
 func formatProto(in io.Reader, out io.Writer) error {
 func formatProto(in io.Reader, out io.Writer) error {