all: Store pending devices and folders in database (fixes #7178) (#6443)

This commit is contained in:
André Colomb 2020-12-17 19:54:31 +01:00 committed by GitHub
parent 4470cd5aaa
commit 7502997e7e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 1259 additions and 383 deletions

View File

@ -131,6 +131,23 @@ func dump(ldb backend.Backend) {
fmt.Printf(" V:%v\n", v) fmt.Printf(" V:%v\n", v)
} }
case db.KeyTypePendingFolder:
device := binary.BigEndian.Uint32(key[1:])
folder := string(key[5:])
var of db.ObservedFolder
of.Unmarshal(it.Value())
fmt.Printf("[pendingFolder] D:%d F:%s V:%v\n", device, folder, of)
case db.KeyTypePendingDevice:
device := "<invalid>"
dev, err := protocol.DeviceIDFromBytes(key[1:])
if err == nil {
device = dev.String()
}
var od db.ObservedDevice
od.Unmarshal(it.Value())
fmt.Printf("[pendingDevice] D:%v V:%v\n", device, od)
default: default:
fmt.Printf("[??? %d]\n %x\n %x\n", key[0], key, it.Value()) fmt.Printf("[??? %d]\n %x\n %x\n", key[0], key, it.Value())
} }

View File

@ -190,7 +190,7 @@
<!-- Panel: New Device --> <!-- Panel: New Device -->
<div ng-repeat="pendingDevice in config.pendingDevices" class="row"> <div ng-repeat="(deviceID, pendingDevice) in pendingDevices" class="row">
<div class="col-md-12"> <div class="col-md-12">
<div class="panel panel-warning"> <div class="panel panel-warning">
<div class="panel-heading"> <div class="panel-heading">
@ -202,17 +202,17 @@
</div> </div>
<div class="panel-body"> <div class="panel-body">
<p> <p>
<span translate translate-value-device="{{ pendingDevice.deviceID }}" translate-value-address="{{ pendingDevice.address }}" translate-value-name="{{ pendingDevice.name }}"> <span translate translate-value-device="{{ deviceID }}" translate-value-address="{{ pendingDevice.address }}" translate-value-name="{{ pendingDevice.name }}">
Device "{%name%}" ({%device%} at {%address%}) wants to connect. Add new device? Device "{%name%}" ({%device%} at {%address%}) wants to connect. Add new device?
</span> </span>
</p> </p>
</div> </div>
<div class="panel-footer clearfix"> <div class="panel-footer clearfix">
<div class="pull-right"> <div class="pull-right">
<button type="button" class="btn btn-sm btn-success" ng-click="addDevice(pendingDevice.deviceID, pendingDevice.name)"> <button type="button" class="btn btn-sm btn-success" ng-click="addDevice(deviceID, pendingDevice.name)">
<span class="fas fa-plus"></span>&nbsp;<span translate>Add Device</span> <span class="fas fa-plus"></span>&nbsp;<span translate>Add Device</span>
</button> </button>
<button type="button" class="btn btn-sm btn-danger" ng-click="ignoreDevice(pendingDevice)"> <button type="button" class="btn btn-sm btn-danger" ng-click="ignoreDevice(deviceID, pendingDevice)">
<span class="fas fa-times"></span>&nbsp;<span translate>Ignore</span> <span class="fas fa-times"></span>&nbsp;<span translate>Ignore</span>
</button> </button>
</div> </div>
@ -222,8 +222,8 @@
</div> </div>
<!-- Panel: New Folder --> <!-- Panel: New Folder -->
<div ng-repeat="device in config.devices"> <div ng-repeat="(folderID, pendingFolder) in pendingFolders">
<div ng-repeat="pendingFolder in device.pendingFolders" class="row reject"> <div ng-repeat="(deviceID, offeringDevice) in pendingFolder.offeredBy" class="row reject">
<div class="col-md-12"> <div class="col-md-12">
<div class="panel panel-warning"> <div class="panel panel-warning">
<div class="panel-heading"> <div class="panel-heading">
@ -231,32 +231,32 @@
<div class="panel-icon"> <div class="panel-icon">
<span class="fas fa-folder"></span> <span class="fas fa-folder"></span>
</div> </div>
<span translate ng-if="!folders[pendingFolder.id]">New Folder</span> <span translate ng-if="!folders[folderID]">New Folder</span>
<span translate ng-if="folders[pendingFolder.id]">Share Folder</span> <span translate ng-if="folders[folderID]">Share Folder</span>
<span class="pull-right">{{ pendingFolder.time | date:"yyyy-MM-dd HH:mm:ss" }}</span> <span class="pull-right">{{ offeringDevice.time | date:"yyyy-MM-dd HH:mm:ss" }}</span>
</h3> </h3>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<p> <p>
<span ng-if="pendingFolder.label.length == 0" translate translate-value-device="{{ deviceName(devices[device.deviceID]) }}" translate-value-folder="{{ pendingFolder.id }}"> <span ng-if="offeringDevice.label.length == 0" translate translate-value-device="{{ deviceName(devices[deviceID]) }}" translate-value-folder="{{ folderID }}">
{%device%} wants to share folder "{%folder%}". {%device%} wants to share folder "{%folder%}".
</span> </span>
<span ng-if="pendingFolder.label.length != 0" translate translate-value-device="{{ deviceName(devices[device.deviceID]) }}" translate-value-folder="{{ pendingFolder.id }}" translate-value-folderlabel="{{ pendingFolder.label }}"> <span ng-if="offeringDevice.label.length != 0" translate translate-value-device="{{ deviceName(devices[deviceID]) }}" translate-value-folder="{{ folderID }}" translate-value-folderlabel="{{ offeringDevice.label }}">
{%device%} wants to share folder "{%folderlabel%}" ({%folder%}). {%device%} wants to share folder "{%folderlabel%}" ({%folder%}).
</span> </span>
<span translate ng-if="folders[pendingFolder.id]">Share this folder?</span> <span translate ng-if="folders[folderID]">Share this folder?</span>
<span translate ng-if="!folders[pendingFolder.id]">Add new folder?</span> <span translate ng-if="!folders[folderID]">Add new folder?</span>
</p> </p>
</div> </div>
<div class="panel-footer clearfix"> <div class="panel-footer clearfix">
<div class="pull-right"> <div class="pull-right">
<button type="button" class="btn btn-sm btn-success" ng-click="addFolderAndShare(pendingFolder.id, pendingFolder.label, device.deviceID)" ng-if="!folders[pendingFolder.id]"> <button type="button" class="btn btn-sm btn-success" ng-click="addFolderAndShare(folderID, offeringDevice.label, deviceID)" ng-if="!folders[folderID]">
<span class="fas fa-check"></span>&nbsp;<span translate>Add</span> <span class="fas fa-check"></span>&nbsp;<span translate>Add</span>
</button> </button>
<button type="button" class="btn btn-sm btn-success" ng-click="shareFolderWithDevice(pendingFolder.id, device.deviceID)" ng-if="folders[pendingFolder.id]"> <button type="button" class="btn btn-sm btn-success" ng-click="shareFolderWithDevice(folderID, deviceID)" ng-if="folders[folderID]">
<span class="fas fa-check"></span>&nbsp;<span translate>Share</span> <span class="fas fa-check"></span>&nbsp;<span translate>Share</span>
</button> </button>
<button type="button" class="btn btn-sm btn-danger" ng-click="ignoreFolder(device.deviceID, pendingFolder)"> <button type="button" class="btn btn-sm btn-danger" ng-click="ignoreFolder(deviceID, folderID, offeringDevice)">
<span class="fas fa-times"></span>&nbsp;<span translate>Ignore</span> <span class="fas fa-times"></span>&nbsp;<span translate>Ignore</span>
</button> </button>
</div> </div>

View File

@ -38,6 +38,8 @@ angular.module('syncthing.core')
$scope.upgradeInfo = null; $scope.upgradeInfo = null;
$scope.deviceStats = {}; $scope.deviceStats = {};
$scope.folderStats = {}; $scope.folderStats = {};
$scope.pendingDevices = {};
$scope.pendingFolders = {};
$scope.progress = {}; $scope.progress = {};
$scope.version = {}; $scope.version = {};
$scope.needed = {} $scope.needed = {}
@ -242,6 +244,34 @@ angular.module('syncthing.core')
} }
}); });
$scope.$on(Events.DEVICE_REJECTED, function (event, arg) {
var pendingDevice = {
time: arg.time,
name: arg.data.name,
address: arg.data.address
};
console.log("rejected device:", arg.data.device, pendingDevice);
$scope.pendingDevices[arg.data.device] = pendingDevice;
});
$scope.$on(Events.FOLDER_REJECTED, function (event, arg) {
var offeringDevice = {
time: arg.time,
label: arg.data.folderLabel
};
console.log("rejected folder", arg.data.folder, "from device:", arg.data.device, offeringDevice);
var pendingFolder = $scope.pendingFolders[arg.data.folder];
if (pendingFolder === undefined) {
pendingFolder = {
offeredBy: {}
};
}
pendingFolder.offeredBy[arg.data.device] = offeringDevice;
$scope.pendingFolders[arg.data.folder] = pendingFolder;
});
$scope.$on('ConfigLoaded', function () { $scope.$on('ConfigLoaded', function () {
if ($scope.config.options.urAccepted === 0) { if ($scope.config.options.urAccepted === 0) {
// If usage reporting has been neither accepted nor declined, // If usage reporting has been neither accepted nor declined,
@ -391,6 +421,7 @@ angular.module('syncthing.core')
}); });
}); });
refreshCluster();
refreshNoAuthWarning(); refreshNoAuthWarning();
setDefaultTheme(); setDefaultTheme();
@ -455,6 +486,16 @@ angular.module('syncthing.core')
} }
} }
function refreshCluster() {
$http.get(urlbase + '/cluster/pending/devices').success(function (data) {
$scope.pendingDevices = data;
console.log("refreshCluster devices", data);
}).error($scope.emitHTTPError);
$http.get(urlbase + '/cluster/pending/folders').success(function (data) {
$scope.pendingFolders = data;
console.log("refreshCluster folders", data);
}).error($scope.emitHTTPError);
}
function refreshDiscoveryCache() { function refreshDiscoveryCache() {
$http.get(urlbase + '/system/discovery').success(function (data) { $http.get(urlbase + '/system/discovery').success(function (data) {
@ -1012,7 +1053,6 @@ angular.module('syncthing.core')
// loop through all devices // loop through all devices
var deviceCount = 0; var deviceCount = 0;
var pendingFolders = 0;
for (var id in $scope.devices) { for (var id in $scope.devices) {
var status = $scope.deviceStatus({ var status = $scope.deviceStatus({
deviceID: id deviceID: id
@ -1028,14 +1068,11 @@ angular.module('syncthing.core')
deviceCount--; deviceCount--;
break; break;
} }
pendingFolders += $scope.devices[id].pendingFolders.length;
deviceCount++; deviceCount++;
} }
// enumerate notifications // enumerate notifications
if ($scope.openNoAuth || !$scope.configInSync || $scope.errorList().length > 0 || !online || ( if ($scope.openNoAuth || !$scope.configInSync || $scope.errorList().length > 0 || !online || Object.keys($scope.pendingDevices).length > 0 || Object.keys($scope.pendingFolders).length > 0) {
!isEmptyObject($scope.config) && ($scope.config.pendingDevices.length > 0 || pendingFolders > 0)
)) {
notifyCount++; notifyCount++;
} }
@ -1476,7 +1513,6 @@ angular.module('syncthing.core')
_addressesStr: 'dynamic', _addressesStr: 'dynamic',
compression: 'metadata', compression: 'metadata',
introducer: false, introducer: false,
pendingFolders: [],
ignoredFolders: [] ignoredFolders: []
}; };
$scope.editingExisting = false; $scope.editingExisting = false;
@ -1549,11 +1585,12 @@ angular.module('syncthing.core')
$scope.saveConfig(); $scope.saveConfig();
}; };
$scope.ignoreDevice = function (pendingDevice) { $scope.ignoreDevice = function (deviceID, pendingDevice) {
pendingDevice = angular.copy(pendingDevice); var ignoredDevice = angular.copy(pendingDevice);
ignoredDevice.deviceID = deviceID;
// Bump time // Bump time
pendingDevice.time = (new Date()).toISOString(); ignoredDevice.time = (new Date()).toISOString();
$scope.config.remoteIgnoredDevices.push(pendingDevice); $scope.config.remoteIgnoredDevices.push(ignoredDevice);
$scope.saveConfig(); $scope.saveConfig();
}; };
@ -1954,13 +1991,16 @@ angular.module('syncthing.core')
}); });
}; };
$scope.ignoreFolder = function (device, pendingFolder) { $scope.ignoreFolder = function (device, folderID, offeringDevice) {
pendingFolder = angular.copy(pendingFolder); var ignoredFolder = {
// Bump time id: folderID,
pendingFolder.time = (new Date()).toISOString(); label: offeringDevice.label,
// Bump time
time: (new Date()).toISOString()
}
if (device in $scope.devices) { if (id in $scope.devices) {
$scope.devices[device].ignoredFolders.push(pendingFolder); $scope.devices[id].ignoredFolders.push(ignoredFolder);
$scope.saveConfig(); $scope.saveConfig();
} }
}; };

View File

@ -237,36 +237,38 @@ func (s *service) Serve(ctx context.Context) error {
restMux := httprouter.New() restMux := httprouter.New()
// The GET handlers // The GET handlers
restMux.HandlerFunc(http.MethodGet, "/rest/db/completion", s.getDBCompletion) // [device] [folder] restMux.HandlerFunc(http.MethodGet, "/rest/cluster/pending/devices", s.getPendingDevices) // -
restMux.HandlerFunc(http.MethodGet, "/rest/db/file", s.getDBFile) // folder file restMux.HandlerFunc(http.MethodGet, "/rest/cluster/pending/folders", s.getPendingFolders) // [device]
restMux.HandlerFunc(http.MethodGet, "/rest/db/ignores", s.getDBIgnores) // folder restMux.HandlerFunc(http.MethodGet, "/rest/db/completion", s.getDBCompletion) // [device] [folder]
restMux.HandlerFunc(http.MethodGet, "/rest/db/need", s.getDBNeed) // folder [perpage] [page] restMux.HandlerFunc(http.MethodGet, "/rest/db/file", s.getDBFile) // folder file
restMux.HandlerFunc(http.MethodGet, "/rest/db/remoteneed", s.getDBRemoteNeed) // device folder [perpage] [page] restMux.HandlerFunc(http.MethodGet, "/rest/db/ignores", s.getDBIgnores) // folder
restMux.HandlerFunc(http.MethodGet, "/rest/db/localchanged", s.getDBLocalChanged) // folder restMux.HandlerFunc(http.MethodGet, "/rest/db/need", s.getDBNeed) // folder [perpage] [page]
restMux.HandlerFunc(http.MethodGet, "/rest/db/status", s.getDBStatus) // folder restMux.HandlerFunc(http.MethodGet, "/rest/db/remoteneed", s.getDBRemoteNeed) // device folder [perpage] [page]
restMux.HandlerFunc(http.MethodGet, "/rest/db/browse", s.getDBBrowse) // folder [prefix] [dirsonly] [levels] restMux.HandlerFunc(http.MethodGet, "/rest/db/localchanged", s.getDBLocalChanged) // folder
restMux.HandlerFunc(http.MethodGet, "/rest/folder/versions", s.getFolderVersions) // folder restMux.HandlerFunc(http.MethodGet, "/rest/db/status", s.getDBStatus) // folder
restMux.HandlerFunc(http.MethodGet, "/rest/folder/errors", s.getFolderErrors) // folder restMux.HandlerFunc(http.MethodGet, "/rest/db/browse", s.getDBBrowse) // folder [prefix] [dirsonly] [levels]
restMux.HandlerFunc(http.MethodGet, "/rest/folder/pullerrors", s.getFolderErrors) // folder (deprecated) restMux.HandlerFunc(http.MethodGet, "/rest/folder/versions", s.getFolderVersions) // folder
restMux.HandlerFunc(http.MethodGet, "/rest/events", s.getIndexEvents) // [since] [limit] [timeout] [events] restMux.HandlerFunc(http.MethodGet, "/rest/folder/errors", s.getFolderErrors) // folder
restMux.HandlerFunc(http.MethodGet, "/rest/events/disk", s.getDiskEvents) // [since] [limit] [timeout] restMux.HandlerFunc(http.MethodGet, "/rest/folder/pullerrors", s.getFolderErrors) // folder (deprecated)
restMux.HandlerFunc(http.MethodGet, "/rest/stats/device", s.getDeviceStats) // - restMux.HandlerFunc(http.MethodGet, "/rest/events", s.getIndexEvents) // [since] [limit] [timeout] [events]
restMux.HandlerFunc(http.MethodGet, "/rest/stats/folder", s.getFolderStats) // - restMux.HandlerFunc(http.MethodGet, "/rest/events/disk", s.getDiskEvents) // [since] [limit] [timeout]
restMux.HandlerFunc(http.MethodGet, "/rest/svc/deviceid", s.getDeviceID) // id restMux.HandlerFunc(http.MethodGet, "/rest/stats/device", s.getDeviceStats) // -
restMux.HandlerFunc(http.MethodGet, "/rest/svc/lang", s.getLang) // - restMux.HandlerFunc(http.MethodGet, "/rest/stats/folder", s.getFolderStats) // -
restMux.HandlerFunc(http.MethodGet, "/rest/svc/report", s.getReport) // - restMux.HandlerFunc(http.MethodGet, "/rest/svc/deviceid", s.getDeviceID) // id
restMux.HandlerFunc(http.MethodGet, "/rest/svc/random/string", s.getRandomString) // [length] restMux.HandlerFunc(http.MethodGet, "/rest/svc/lang", s.getLang) // -
restMux.HandlerFunc(http.MethodGet, "/rest/system/browse", s.getSystemBrowse) // current restMux.HandlerFunc(http.MethodGet, "/rest/svc/report", s.getReport) // -
restMux.HandlerFunc(http.MethodGet, "/rest/system/connections", s.getSystemConnections) // - restMux.HandlerFunc(http.MethodGet, "/rest/svc/random/string", s.getRandomString) // [length]
restMux.HandlerFunc(http.MethodGet, "/rest/system/discovery", s.getSystemDiscovery) // - restMux.HandlerFunc(http.MethodGet, "/rest/system/browse", s.getSystemBrowse) // current
restMux.HandlerFunc(http.MethodGet, "/rest/system/error", s.getSystemError) // - restMux.HandlerFunc(http.MethodGet, "/rest/system/connections", s.getSystemConnections) // -
restMux.HandlerFunc(http.MethodGet, "/rest/system/ping", s.restPing) // - restMux.HandlerFunc(http.MethodGet, "/rest/system/discovery", s.getSystemDiscovery) // -
restMux.HandlerFunc(http.MethodGet, "/rest/system/status", s.getSystemStatus) // - restMux.HandlerFunc(http.MethodGet, "/rest/system/error", s.getSystemError) // -
restMux.HandlerFunc(http.MethodGet, "/rest/system/upgrade", s.getSystemUpgrade) // - restMux.HandlerFunc(http.MethodGet, "/rest/system/ping", s.restPing) // -
restMux.HandlerFunc(http.MethodGet, "/rest/system/version", s.getSystemVersion) // - restMux.HandlerFunc(http.MethodGet, "/rest/system/status", s.getSystemStatus) // -
restMux.HandlerFunc(http.MethodGet, "/rest/system/debug", s.getSystemDebug) // - restMux.HandlerFunc(http.MethodGet, "/rest/system/upgrade", s.getSystemUpgrade) // -
restMux.HandlerFunc(http.MethodGet, "/rest/system/log", s.getSystemLog) // [since] restMux.HandlerFunc(http.MethodGet, "/rest/system/version", s.getSystemVersion) // -
restMux.HandlerFunc(http.MethodGet, "/rest/system/log.txt", s.getSystemLogTxt) // [since] restMux.HandlerFunc(http.MethodGet, "/rest/system/debug", s.getSystemDebug) // -
restMux.HandlerFunc(http.MethodGet, "/rest/system/log", s.getSystemLog) // [since]
restMux.HandlerFunc(http.MethodGet, "/rest/system/log.txt", s.getSystemLogTxt) // [since]
// The POST handlers // The POST handlers
restMux.HandlerFunc(http.MethodPost, "/rest/db/prio", s.postDBPrio) // folder file [perpage] [page] restMux.HandlerFunc(http.MethodPost, "/rest/db/prio", s.postDBPrio) // folder file [perpage] [page]
@ -620,6 +622,33 @@ func (s *service) whenDebugging(h http.Handler) http.Handler {
}) })
} }
func (s *service) getPendingDevices(w http.ResponseWriter, r *http.Request) {
devices, err := s.model.PendingDevices()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
sendJSON(w, devices)
}
func (s *service) getPendingFolders(w http.ResponseWriter, r *http.Request) {
qs := r.URL.Query()
device := qs.Get("device")
deviceID, err := protocol.DeviceIDFromString(device)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
folders, err := s.model.PendingFolders(deviceID)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
sendJSON(w, folders)
}
func (s *service) restPing(w http.ResponseWriter, r *http.Request) { func (s *service) restPing(w http.ResponseWriter, r *http.Request) {
sendJSON(w, map[string]string{"ping": "pong"}) sendJSON(w, map[string]string{"ping": "pong"})
} }

View File

@ -130,6 +130,10 @@ func (c *mockedConfig) IgnoredDevice(id protocol.DeviceID) bool {
return false return false
} }
func (c *mockedConfig) IgnoredDevices() []config.ObservedDevice {
return nil
}
func (c *mockedConfig) IgnoredFolder(device protocol.DeviceID, folder string) bool { func (c *mockedConfig) IgnoredFolder(device protocol.DeviceID, folder string) bool {
return false return false
} }

View File

@ -125,6 +125,14 @@ func (m *mockedModel) State(folder string) (string, time.Time, error) {
func (m *mockedModel) UsageReportingStats(r *contract.Report, version int, preview bool) { func (m *mockedModel) UsageReportingStats(r *contract.Report, version int, preview bool) {
} }
func (m *mockedModel) PendingDevices() (map[protocol.DeviceID]db.ObservedDevice, error) {
return nil, nil
}
func (m *mockedModel) PendingFolders(device protocol.DeviceID) (map[string]db.PendingFolder, error) {
return nil, nil
}
func (m *mockedModel) FolderErrors(folder string) ([]model.FileError, error) { func (m *mockedModel) FolderErrors(folder string) ([]model.FileError, error) {
return nil, nil return nil, nil
} }

View File

@ -204,9 +204,6 @@ func (cfg Configuration) Copy() Configuration {
newCfg.IgnoredDevices = make([]ObservedDevice, len(cfg.IgnoredDevices)) newCfg.IgnoredDevices = make([]ObservedDevice, len(cfg.IgnoredDevices))
copy(newCfg.IgnoredDevices, cfg.IgnoredDevices) copy(newCfg.IgnoredDevices, cfg.IgnoredDevices)
newCfg.PendingDevices = make([]ObservedDevice, len(cfg.PendingDevices))
copy(newCfg.PendingDevices, cfg.PendingDevices)
return newCfg return newCfg
} }
@ -235,9 +232,7 @@ func (cfg *Configuration) prepare(myID protocol.DeviceID) error {
guiPWIsSet := cfg.GUI.User != "" && cfg.GUI.Password != "" guiPWIsSet := cfg.GUI.User != "" && cfg.GUI.Password != ""
cfg.Options.prepare(guiPWIsSet) cfg.Options.prepare(guiPWIsSet)
ignoredDevices := cfg.prepareIgnoredDevices(existingDevices) cfg.prepareIgnoredDevices(existingDevices)
cfg.preparePendingDevices(existingDevices, ignoredDevices)
cfg.removeDeprecatedProtocols() cfg.removeDeprecatedProtocols()
@ -354,31 +349,6 @@ func (cfg *Configuration) prepareIgnoredDevices(existingDevices map[protocol.Dev
return ignoredDevices return ignoredDevices
} }
func (cfg *Configuration) preparePendingDevices(existingDevices, ignoredDevices map[protocol.DeviceID]bool) {
// The list of pending devices should not contain devices that were added manually, nor should it contain
// ignored devices.
// Sort by time, so that in case of duplicates latest "time" is used.
sort.Slice(cfg.PendingDevices, func(i, j int) bool {
return cfg.PendingDevices[i].Time.Before(cfg.PendingDevices[j].Time)
})
newPendingDevices := cfg.PendingDevices[:0]
nextPendingDevice:
for _, pendingDevice := range cfg.PendingDevices {
if !existingDevices[pendingDevice.ID] && !ignoredDevices[pendingDevice.ID] {
// Deduplicate
for _, existingPendingDevice := range newPendingDevices {
if existingPendingDevice.ID == pendingDevice.ID {
continue nextPendingDevice
}
}
newPendingDevices = append(newPendingDevices, pendingDevice)
}
}
cfg.PendingDevices = newPendingDevices
}
func (cfg *Configuration) removeDeprecatedProtocols() { func (cfg *Configuration) removeDeprecatedProtocols() {
// Deprecated protocols are removed from the list of listeners and // Deprecated protocols are removed from the list of listeners and
// device addresses. So far just kcp*. // device addresses. So far just kcp*.

View File

@ -24,14 +24,14 @@ var _ = math.Inf
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
type Configuration struct { type Configuration struct {
Version int `protobuf:"varint,1,opt,name=version,proto3,casttype=int" json:"version" xml:"version,attr"` 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"` 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"` 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"` 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"` 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"` 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"` 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"` DeprecatedPendingDevices []ObservedDevice `protobuf:"bytes,8,rep,name=pending_devices,json=pendingDevices,proto3" json:"-" xml:"pendingDevice,omitempty"` // Deprecated: Do not use.
} }
func (m *Configuration) Reset() { *m = Configuration{} } func (m *Configuration) Reset() { *m = Configuration{} }
@ -74,42 +74,43 @@ func init() {
func init() { proto.RegisterFile("lib/config/config.proto", fileDescriptor_baadf209193dc627) } func init() { proto.RegisterFile("lib/config/config.proto", fileDescriptor_baadf209193dc627) }
var fileDescriptor_baadf209193dc627 = []byte{ var fileDescriptor_baadf209193dc627 = []byte{
// 547 bytes of a gzipped FileDescriptorProto // 575 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x93, 0x4f, 0x8b, 0xd3, 0x40, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x93, 0x4d, 0x8b, 0xd3, 0x5e,
0x18, 0xc6, 0x13, 0xbb, 0xdb, 0xba, 0xd9, 0x7f, 0x90, 0x15, 0x4d, 0x55, 0x32, 0x75, 0xa8, 0x52, 0x14, 0xc6, 0x93, 0x7f, 0x3b, 0xed, 0x7f, 0x32, 0x6f, 0x10, 0x45, 0x53, 0x5f, 0x72, 0x6b, 0xa8,
0x45, 0xbb, 0xb0, 0x5e, 0xc4, 0x9b, 0xb5, 0xb8, 0x14, 0x05, 0x65, 0x60, 0x45, 0xbd, 0x48, 0xdb, 0x52, 0x65, 0xec, 0xc0, 0xb8, 0x11, 0x77, 0xd6, 0xe2, 0x58, 0x14, 0x1c, 0x02, 0x23, 0xea, 0x46,
0xcc, 0xa6, 0x03, 0xed, 0x4c, 0x49, 0xd2, 0xb2, 0x7e, 0x0b, 0xf1, 0x13, 0x78, 0xf5, 0x1b, 0xf8, 0xda, 0xe6, 0x4e, 0x7a, 0xa1, 0xcd, 0x0d, 0xc9, 0x4d, 0x99, 0xf9, 0x08, 0xee, 0xc4, 0x4f, 0xe0,
0x11, 0x7a, 0x6b, 0x8f, 0x9e, 0x06, 0xb6, 0xbd, 0xf5, 0x98, 0xa3, 0x27, 0x99, 0x7f, 0xdd, 0x44, 0xd6, 0x6f, 0xd2, 0x5d, 0xbb, 0x70, 0xe1, 0xea, 0xc2, 0xb4, 0xbb, 0x2c, 0xb3, 0x74, 0x25, 0xf7,
0xa2, 0xa7, 0xe6, 0x7d, 0x9f, 0xe7, 0xf9, 0xbd, 0x2f, 0x6f, 0x13, 0xe7, 0xd6, 0x90, 0xf4, 0x8e, 0xad, 0x26, 0x10, 0x5d, 0x35, 0xe7, 0x3c, 0xcf, 0xf9, 0x9d, 0xc3, 0xd3, 0xc4, 0xb8, 0x39, 0x41,
0xfb, 0x8c, 0x9e, 0x93, 0x50, 0xff, 0x34, 0xc7, 0x11, 0x4b, 0x98, 0x5b, 0x56, 0xd5, 0xed, 0x7a, 0xc3, 0xa3, 0x11, 0x0e, 0xce, 0x91, 0x2f, 0x7f, 0x3a, 0x61, 0x84, 0x09, 0x36, 0x6b, 0xa2, 0xba,
0xc6, 0x70, 0xce, 0x86, 0x01, 0x8e, 0x54, 0x31, 0x89, 0xba, 0x09, 0x61, 0x54, 0xb9, 0x73, 0xae, 0xd5, 0xca, 0x19, 0xce, 0xf1, 0xc4, 0x83, 0x91, 0x28, 0x92, 0x68, 0x40, 0x10, 0x0e, 0x84, 0xbb,
0x00, 0x4f, 0x49, 0x1f, 0x17, 0xb9, 0xee, 0x65, 0x5c, 0xe1, 0x84, 0x14, 0x59, 0x60, 0xc6, 0x32, 0xe0, 0xf2, 0xe0, 0x0c, 0x8d, 0x60, 0x99, 0xeb, 0x5e, 0xce, 0xe5, 0x27, 0xa8, 0xcc, 0xe2, 0xe4,
0x0c, 0xba, 0xe3, 0x22, 0xcf, 0xfd, 0x8c, 0x87, 0x8d, 0x85, 0x10, 0x17, 0xd9, 0xaa, 0x59, 0x5b, 0x2c, 0x13, 0x6f, 0x10, 0x96, 0x79, 0xee, 0xe7, 0x3c, 0x38, 0x64, 0x42, 0x5c, 0x66, 0x6b, 0xe4,
0x2f, 0xc6, 0xd1, 0x14, 0x07, 0x5a, 0xda, 0xc1, 0x17, 0x89, 0x7a, 0x84, 0x3f, 0xcb, 0xce, 0xfe, 0x6d, 0xc3, 0x18, 0x46, 0x33, 0xe8, 0x49, 0x69, 0x1b, 0x5e, 0x10, 0xf1, 0xe8, 0xfc, 0xa8, 0x19,
0xcb, 0x6c, 0xda, 0x45, 0x4e, 0x65, 0x8a, 0xa3, 0x98, 0x30, 0xea, 0xd9, 0x35, 0xbb, 0xb1, 0xdd, 0x7b, 0x2f, 0xf2, 0xd3, 0xa6, 0x6b, 0xd4, 0x67, 0x30, 0x8a, 0x11, 0x0e, 0x2c, 0xbd, 0xa9, 0xb7,
0x7a, 0xb6, 0xe6, 0xc0, 0xb4, 0x52, 0x0e, 0xdc, 0x8b, 0xd1, 0xf0, 0x39, 0xd4, 0xf5, 0xe3, 0x6e, 0xb7, 0xba, 0x4f, 0x53, 0x0a, 0x54, 0x2b, 0xa3, 0xc0, 0xbc, 0x98, 0x4e, 0x9e, 0x39, 0xb2, 0x3e,
0x92, 0x44, 0xf0, 0x37, 0x07, 0x25, 0x42, 0x93, 0xf5, 0xbc, 0xbe, 0x97, 0xed, 0x23, 0x93, 0x72, 0x1c, 0x10, 0x12, 0x39, 0xbf, 0x28, 0xa8, 0xa0, 0x80, 0xa4, 0x8b, 0xd6, 0x6e, 0xbe, 0xef, 0xaa,
0xdf, 0x3b, 0x15, 0x75, 0xbc, 0xd8, 0xbb, 0x56, 0x2b, 0x35, 0x76, 0x4f, 0xee, 0x34, 0xf5, 0xb5, 0x29, 0xf3, 0x9d, 0x51, 0x17, 0xe1, 0xc5, 0xd6, 0x7f, 0xcd, 0x4a, 0x7b, 0xe7, 0xf8, 0x76, 0x47,
0x5f, 0xc9, 0x76, 0x6e, 0x83, 0x16, 0x98, 0x71, 0x60, 0x89, 0xa1, 0x3a, 0x93, 0x72, 0xb0, 0x27, 0xa6, 0xfd, 0x92, 0xb7, 0x0b, 0x17, 0x74, 0xc1, 0x9c, 0x02, 0x8d, 0x2d, 0x95, 0x33, 0x19, 0x05,
0x87, 0xaa, 0x1a, 0x22, 0x23, 0x08, 0xae, 0x3a, 0x77, 0xec, 0x95, 0xf2, 0xdc, 0xb6, 0x6c, 0xff, 0xbb, 0x7c, 0xa9, 0xa8, 0x1d, 0x57, 0x09, 0x8c, 0x2b, 0xe2, 0x8e, 0xad, 0x4a, 0x91, 0xdb, 0xe3,
0x83, 0xab, 0x33, 0x1b, 0xae, 0xaa, 0x21, 0x32, 0x82, 0x8b, 0x9c, 0x52, 0x38, 0x21, 0xde, 0x56, 0xed, 0xbf, 0x70, 0xe5, 0xcc, 0x86, 0x2b, 0x6a, 0xc7, 0x55, 0x82, 0xe9, 0x1a, 0x15, 0x3f, 0x41,
0xcd, 0x6e, 0xec, 0x9e, 0x78, 0x86, 0x79, 0x7a, 0xd6, 0xc9, 0x03, 0x1f, 0x08, 0xe0, 0x92, 0x83, 0x56, 0xb5, 0xa9, 0xb7, 0x77, 0x8e, 0x2d, 0xc5, 0x3c, 0x39, 0xeb, 0x17, 0x81, 0x0f, 0x18, 0x70,
0xd2, 0xe9, 0x59, 0x67, 0xcd, 0x81, 0xc8, 0xa4, 0x1c, 0xec, 0x48, 0x66, 0x38, 0x21, 0xf0, 0xdb, 0x45, 0x41, 0xe5, 0xe4, 0xac, 0x9f, 0x52, 0xc0, 0x66, 0x32, 0x0a, 0xb6, 0x39, 0xd3, 0x4f, 0x90,
0xa2, 0x2e, 0x24, 0x24, 0x04, 0xf7, 0xa3, 0xb3, 0x25, 0xfe, 0x51, 0x6f, 0x5b, 0x42, 0xab, 0x06, 0xf3, 0x75, 0xd9, 0x62, 0x92, 0xcb, 0x04, 0xf3, 0x83, 0x51, 0x65, 0xff, 0xa8, 0xb5, 0xc5, 0xa1,
0xfa, 0xa6, 0xfd, 0xe2, 0x5d, 0x9e, 0xfa, 0x48, 0x53, 0xb7, 0x84, 0xb4, 0xe6, 0x40, 0xc6, 0x52, 0x0d, 0x05, 0x7d, 0xd3, 0x7b, 0x7e, 0x5a, 0xa4, 0x3e, 0x92, 0xd4, 0x2a, 0x93, 0x52, 0x0a, 0xf8,
0x0e, 0x1c, 0xc9, 0x15, 0x85, 0x00, 0x4b, 0x15, 0x49, 0xcd, 0xfd, 0xe0, 0x54, 0xf4, 0x8b, 0xe0, 0x58, 0x46, 0x81, 0xc1, 0xb9, 0xac, 0x60, 0x60, 0xae, 0xba, 0x5c, 0x33, 0xdf, 0x1b, 0x75, 0xf9,
0x95, 0x25, 0xfd, 0xae, 0xa1, 0xbf, 0x55, 0xed, 0xfc, 0x80, 0x9a, 0xb9, 0x83, 0x0e, 0xa5, 0x1c, 0x22, 0x58, 0x35, 0x4e, 0xbf, 0xa3, 0xe8, 0x6f, 0x45, 0xbb, 0xb8, 0xa0, 0xa9, 0x72, 0x90, 0x43,
0xec, 0x4b, 0xb6, 0xae, 0x21, 0x32, 0x8a, 0xfb, 0xc3, 0x76, 0x0e, 0x49, 0x48, 0x59, 0x84, 0x83, 0x19, 0x05, 0x7b, 0x9c, 0x2d, 0x6b, 0xc7, 0x55, 0x8a, 0xf9, 0x5d, 0x37, 0x0e, 0x90, 0x1f, 0xe0,
0xcf, 0xe6, 0xd2, 0x15, 0x79, 0xe9, 0x9b, 0x9b, 0x11, 0xfa, 0xdd, 0x52, 0x17, 0x6f, 0x0d, 0x34, 0x08, 0x7a, 0x9f, 0x54, 0xd2, 0x75, 0x9e, 0xf4, 0x8d, 0xcd, 0x0a, 0xf9, 0x6e, 0x89, 0xc4, 0xbb,
0xfc, 0x46, 0x84, 0x47, 0x2c, 0xc1, 0x1d, 0x15, 0x6e, 0x6f, 0x2e, 0x5e, 0x95, 0x93, 0x0a, 0x44, 0x63, 0x09, 0xbf, 0x1e, 0xc1, 0x29, 0x26, 0xb0, 0x2f, 0x86, 0x7b, 0x9b, 0xc4, 0x1b, 0x7c, 0x53,
0xb8, 0x9e, 0xd7, 0x8f, 0x0a, 0xfa, 0xe9, 0xbc, 0x5e, 0xc8, 0x42, 0x07, 0x24, 0x57, 0xbb, 0xd4, 0x89, 0xe8, 0xa4, 0x8b, 0xd6, 0xb5, 0x92, 0x7e, 0xb6, 0x68, 0x95, 0xb2, 0xdc, 0x7d, 0x54, 0xa8,
0x39, 0x1c, 0x63, 0x1a, 0x10, 0x1a, 0x6e, 0x56, 0xbd, 0xfe, 0xdf, 0x55, 0x9f, 0xe8, 0x55, 0x0f, 0xcd, 0xcf, 0xba, 0x71, 0x10, 0xc2, 0xc0, 0x43, 0x81, 0xbf, 0xb9, 0xf5, 0xff, 0x7f, 0xde, 0xfa,
0x74, 0xec, 0x6a, 0xc9, 0x23, 0xb9, 0x64, 0xae, 0x0d, 0xd1, 0x5f, 0xb6, 0xd6, 0xeb, 0xd9, 0xa5, 0x4a, 0x26, 0x6d, 0xf5, 0x60, 0x18, 0xc1, 0xd1, 0x80, 0x40, 0xef, 0x54, 0x00, 0x24, 0x33, 0xa5,
0x6f, 0x2d, 0x2e, 0x7d, 0x6b, 0xb6, 0xf4, 0xed, 0xc5, 0xd2, 0xb7, 0xbf, 0xae, 0x7c, 0xeb, 0xfb, 0x40, 0x7f, 0x9c, 0x51, 0x70, 0x97, 0x1f, 0x1d, 0xe6, 0xb5, 0x43, 0x3c, 0x45, 0x04, 0x4e, 0x43,
0xca, 0xb7, 0x17, 0x2b, 0xdf, 0xfa, 0xb5, 0xf2, 0xad, 0x4f, 0x0f, 0x43, 0x92, 0x0c, 0x26, 0xbd, 0x72, 0xe9, 0x58, 0xba, 0xbb, 0x5f, 0xd0, 0xe2, 0xee, 0xeb, 0xf9, 0x95, 0xad, 0x2d, 0xaf, 0x6c,
0x66, 0x9f, 0x8d, 0x8e, 0xe3, 0x2f, 0xb4, 0x9f, 0x0c, 0x08, 0x0d, 0x33, 0x4f, 0x57, 0x5f, 0x68, 0x6d, 0xbe, 0xb2, 0xf5, 0xe5, 0xca, 0xd6, 0xbf, 0xac, 0x6d, 0xed, 0xdb, 0xda, 0xd6, 0x97, 0x6b,
0xaf, 0x2c, 0x3f, 0xc7, 0xa7, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0xcb, 0xcf, 0x98, 0x86, 0x91, 0x5b, 0xfb, 0xb9, 0xb6, 0xb5, 0x8f, 0x0f, 0x7d, 0x44, 0xc6, 0xc9, 0xb0, 0x33, 0xc2, 0xd3, 0xa3,
0x04, 0x00, 0x00, 0xf8, 0x32, 0x18, 0x91, 0x31, 0x0a, 0xfc, 0xdc, 0xd3, 0x9f, 0xaf, 0x77, 0x58, 0xe3, 0x9f, 0xea,
0x93, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x97, 0x39, 0xe5, 0x72, 0xad, 0x04, 0x00, 0x00,
} }
func (m *Configuration) Marshal() (dAtA []byte, err error) { func (m *Configuration) Marshal() (dAtA []byte, err error) {
@ -132,10 +133,10 @@ func (m *Configuration) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i _ = i
var l int var l int
_ = l _ = l
if len(m.PendingDevices) > 0 { if len(m.DeprecatedPendingDevices) > 0 {
for iNdEx := len(m.PendingDevices) - 1; iNdEx >= 0; iNdEx-- { for iNdEx := len(m.DeprecatedPendingDevices) - 1; iNdEx >= 0; iNdEx-- {
{ {
size, err := m.PendingDevices[iNdEx].MarshalToSizedBuffer(dAtA[:i]) size, err := m.DeprecatedPendingDevices[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -270,8 +271,8 @@ func (m *Configuration) ProtoSize() (n int) {
n += 1 + l + sovConfig(uint64(l)) n += 1 + l + sovConfig(uint64(l))
} }
} }
if len(m.PendingDevices) > 0 { if len(m.DeprecatedPendingDevices) > 0 {
for _, e := range m.PendingDevices { for _, e := range m.DeprecatedPendingDevices {
l = e.ProtoSize() l = e.ProtoSize()
n += 1 + l + sovConfig(uint64(l)) n += 1 + l + sovConfig(uint64(l))
} }
@ -536,7 +537,7 @@ func (m *Configuration) Unmarshal(dAtA []byte) error {
iNdEx = postIndex iNdEx = postIndex
case 8: case 8:
if wireType != 2 { if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field PendingDevices", wireType) return fmt.Errorf("proto: wrong wireType = %d for field DeprecatedPendingDevices", wireType)
} }
var msglen int var msglen int
for shift := uint(0); ; shift += 7 { for shift := uint(0); ; shift += 7 {
@ -563,8 +564,8 @@ func (m *Configuration) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.PendingDevices = append(m.PendingDevices, ObservedDevice{}) m.DeprecatedPendingDevices = append(m.DeprecatedPendingDevices, ObservedDevice{})
if err := m.PendingDevices[len(m.PendingDevices)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { if err := m.DeprecatedPendingDevices[len(m.DeprecatedPendingDevices)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex

View File

@ -142,7 +142,6 @@ func TestDeviceConfig(t *testing.T) {
Compression: protocol.CompressionMetadata, Compression: protocol.CompressionMetadata,
AllowedNetworks: []string{}, AllowedNetworks: []string{},
IgnoredFolders: []ObservedFolder{}, IgnoredFolders: []ObservedFolder{},
PendingFolders: []ObservedFolder{},
}, },
{ {
DeviceID: device4, DeviceID: device4,
@ -151,7 +150,6 @@ func TestDeviceConfig(t *testing.T) {
Compression: protocol.CompressionMetadata, Compression: protocol.CompressionMetadata,
AllowedNetworks: []string{}, AllowedNetworks: []string{},
IgnoredFolders: []ObservedFolder{}, IgnoredFolders: []ObservedFolder{},
PendingFolders: []ObservedFolder{},
}, },
} }
expectedDeviceIDs := []protocol.DeviceID{device1, device4} expectedDeviceIDs := []protocol.DeviceID{device1, device4}
@ -248,21 +246,18 @@ func TestDeviceAddressesDynamic(t *testing.T) {
Addresses: []string{"dynamic"}, Addresses: []string{"dynamic"},
AllowedNetworks: []string{}, AllowedNetworks: []string{},
IgnoredFolders: []ObservedFolder{}, IgnoredFolders: []ObservedFolder{},
PendingFolders: []ObservedFolder{},
}, },
device2: { device2: {
DeviceID: device2, DeviceID: device2,
Addresses: []string{"dynamic"}, Addresses: []string{"dynamic"},
AllowedNetworks: []string{}, AllowedNetworks: []string{},
IgnoredFolders: []ObservedFolder{}, IgnoredFolders: []ObservedFolder{},
PendingFolders: []ObservedFolder{},
}, },
device3: { device3: {
DeviceID: device3, DeviceID: device3,
Addresses: []string{"dynamic"}, Addresses: []string{"dynamic"},
AllowedNetworks: []string{}, AllowedNetworks: []string{},
IgnoredFolders: []ObservedFolder{}, IgnoredFolders: []ObservedFolder{},
PendingFolders: []ObservedFolder{},
}, },
device4: { device4: {
DeviceID: device4, DeviceID: device4,
@ -271,7 +266,6 @@ func TestDeviceAddressesDynamic(t *testing.T) {
Compression: protocol.CompressionMetadata, Compression: protocol.CompressionMetadata,
AllowedNetworks: []string{}, AllowedNetworks: []string{},
IgnoredFolders: []ObservedFolder{}, IgnoredFolders: []ObservedFolder{},
PendingFolders: []ObservedFolder{},
}, },
} }
@ -295,7 +289,6 @@ func TestDeviceCompression(t *testing.T) {
Compression: protocol.CompressionMetadata, Compression: protocol.CompressionMetadata,
AllowedNetworks: []string{}, AllowedNetworks: []string{},
IgnoredFolders: []ObservedFolder{}, IgnoredFolders: []ObservedFolder{},
PendingFolders: []ObservedFolder{},
}, },
device2: { device2: {
DeviceID: device2, DeviceID: device2,
@ -303,7 +296,6 @@ func TestDeviceCompression(t *testing.T) {
Compression: protocol.CompressionMetadata, Compression: protocol.CompressionMetadata,
AllowedNetworks: []string{}, AllowedNetworks: []string{},
IgnoredFolders: []ObservedFolder{}, IgnoredFolders: []ObservedFolder{},
PendingFolders: []ObservedFolder{},
}, },
device3: { device3: {
DeviceID: device3, DeviceID: device3,
@ -311,7 +303,6 @@ func TestDeviceCompression(t *testing.T) {
Compression: protocol.CompressionNever, Compression: protocol.CompressionNever,
AllowedNetworks: []string{}, AllowedNetworks: []string{},
IgnoredFolders: []ObservedFolder{}, IgnoredFolders: []ObservedFolder{},
PendingFolders: []ObservedFolder{},
}, },
device4: { device4: {
DeviceID: device4, DeviceID: device4,
@ -320,7 +311,6 @@ func TestDeviceCompression(t *testing.T) {
Compression: protocol.CompressionMetadata, Compression: protocol.CompressionMetadata,
AllowedNetworks: []string{}, AllowedNetworks: []string{},
IgnoredFolders: []ObservedFolder{}, IgnoredFolders: []ObservedFolder{},
PendingFolders: []ObservedFolder{},
}, },
} }
@ -343,21 +333,18 @@ func TestDeviceAddressesStatic(t *testing.T) {
Addresses: []string{"tcp://192.0.2.1", "tcp://192.0.2.2"}, Addresses: []string{"tcp://192.0.2.1", "tcp://192.0.2.2"},
AllowedNetworks: []string{}, AllowedNetworks: []string{},
IgnoredFolders: []ObservedFolder{}, IgnoredFolders: []ObservedFolder{},
PendingFolders: []ObservedFolder{},
}, },
device2: { device2: {
DeviceID: device2, DeviceID: device2,
Addresses: []string{"tcp://192.0.2.3:6070", "tcp://[2001:db8::42]:4242"}, Addresses: []string{"tcp://192.0.2.3:6070", "tcp://[2001:db8::42]:4242"},
AllowedNetworks: []string{}, AllowedNetworks: []string{},
IgnoredFolders: []ObservedFolder{}, IgnoredFolders: []ObservedFolder{},
PendingFolders: []ObservedFolder{},
}, },
device3: { device3: {
DeviceID: device3, DeviceID: device3,
Addresses: []string{"tcp://[2001:db8::44]:4444", "tcp://192.0.2.4:6090"}, Addresses: []string{"tcp://[2001:db8::44]:4444", "tcp://192.0.2.4:6090"},
AllowedNetworks: []string{}, AllowedNetworks: []string{},
IgnoredFolders: []ObservedFolder{}, IgnoredFolders: []ObservedFolder{},
PendingFolders: []ObservedFolder{},
}, },
device4: { device4: {
DeviceID: device4, DeviceID: device4,
@ -366,7 +353,6 @@ func TestDeviceAddressesStatic(t *testing.T) {
Compression: protocol.CompressionMetadata, Compression: protocol.CompressionMetadata,
AllowedNetworks: []string{}, AllowedNetworks: []string{},
IgnoredFolders: []ObservedFolder{}, IgnoredFolders: []ObservedFolder{},
PendingFolders: []ObservedFolder{},
}, },
} }
@ -1097,10 +1083,6 @@ func TestDeviceConfigObservedNotNil(t *testing.T) {
if dev.IgnoredFolders == nil { if dev.IgnoredFolders == nil {
t.Errorf("Ignored folders nil") t.Errorf("Ignored folders nil")
} }
if dev.PendingFolders == nil {
t.Errorf("Pending folders nil")
}
} }
} }

View File

@ -33,8 +33,6 @@ func (cfg DeviceConfiguration) Copy() DeviceConfiguration {
copy(c.AllowedNetworks, cfg.AllowedNetworks) copy(c.AllowedNetworks, cfg.AllowedNetworks)
c.IgnoredFolders = make([]ObservedFolder, len(cfg.IgnoredFolders)) c.IgnoredFolders = make([]ObservedFolder, len(cfg.IgnoredFolders))
copy(c.IgnoredFolders, cfg.IgnoredFolders) copy(c.IgnoredFolders, cfg.IgnoredFolders)
c.PendingFolders = make([]ObservedFolder, len(cfg.PendingFolders))
copy(c.PendingFolders, cfg.PendingFolders)
return c return c
} }
@ -47,19 +45,12 @@ func (cfg *DeviceConfiguration) prepare(sharedFolders []string) {
} }
ignoredFolders := deduplicateObservedFoldersToMap(cfg.IgnoredFolders) ignoredFolders := deduplicateObservedFoldersToMap(cfg.IgnoredFolders)
pendingFolders := deduplicateObservedFoldersToMap(cfg.PendingFolders)
for id := range ignoredFolders {
delete(pendingFolders, id)
}
for _, sharedFolder := range sharedFolders { for _, sharedFolder := range sharedFolders {
delete(ignoredFolders, sharedFolder) delete(ignoredFolders, sharedFolder)
delete(pendingFolders, sharedFolder)
} }
cfg.IgnoredFolders = sortedObservedFolderSlice(ignoredFolders) cfg.IgnoredFolders = sortedObservedFolderSlice(ignoredFolders)
cfg.PendingFolders = sortedObservedFolderSlice(pendingFolders)
} }
func (cfg *DeviceConfiguration) IgnoredFolder(folder string) bool { func (cfg *DeviceConfiguration) IgnoredFolder(folder string) bool {

View File

@ -40,7 +40,7 @@ type DeviceConfiguration struct {
MaxSendKbps int `protobuf:"varint,12,opt,name=max_send_kbps,json=maxSendKbps,proto3,casttype=int" json:"maxSendKbps" xml:"maxSendKbps"` 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"` 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"` 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"` DeprecatedPendingFolders []ObservedFolder `protobuf:"bytes,15,rep,name=pending_folders,json=pendingFolders,proto3" json:"-" xml:"pendingFolder,omitempty"` // Deprecated: Do not use.
MaxRequestKiB int `protobuf:"varint,16,opt,name=max_request_kib,json=maxRequestKib,proto3,casttype=int" json:"maxRequestKiB" xml:"maxRequestKiB"` MaxRequestKiB int `protobuf:"varint,16,opt,name=max_request_kib,json=maxRequestKib,proto3,casttype=int" json:"maxRequestKiB" xml:"maxRequestKiB"`
Untrusted bool `protobuf:"varint,17,opt,name=untrusted,proto3" json:"untrusted" xml:"untrusted"` Untrusted bool `protobuf:"varint,17,opt,name=untrusted,proto3" json:"untrusted" xml:"untrusted"`
RemoteGUIPort int `protobuf:"varint,18,opt,name=remote_gui_port,json=remoteGuiPort,proto3,casttype=int" json:"remoteGUIPort" xml:"remoteGUIPort"` RemoteGUIPort int `protobuf:"varint,18,opt,name=remote_gui_port,json=remoteGuiPort,proto3,casttype=int" json:"remoteGUIPort" xml:"remoteGUIPort"`
@ -88,69 +88,71 @@ func init() {
} }
var fileDescriptor_744b782bd13071dd = []byte{ var fileDescriptor_744b782bd13071dd = []byte{
// 980 bytes of a gzipped FileDescriptorProto // 1009 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x55, 0x31, 0x6f, 0xdb, 0x46, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x55, 0xbd, 0x6f, 0xdb, 0x46,
0x18, 0x15, 0xeb, 0xc4, 0xb6, 0x68, 0xcb, 0xb2, 0x68, 0xc4, 0x61, 0x0c, 0x44, 0x27, 0xb0, 0x1a, 0x1c, 0x15, 0xeb, 0xc4, 0xb6, 0xce, 0x96, 0x65, 0xd3, 0x88, 0xc3, 0x18, 0x88, 0x4e, 0x50, 0x35,
0x14, 0x34, 0x95, 0x0b, 0xb7, 0x93, 0xd1, 0x16, 0x28, 0x13, 0xb4, 0x35, 0x8c, 0x26, 0xe9, 0x15, 0x28, 0x68, 0x22, 0x17, 0x6e, 0x27, 0xa3, 0x2d, 0x50, 0xc6, 0x68, 0x63, 0x18, 0x4d, 0xdc, 0x2b,
0x5d, 0xbc, 0xb0, 0x24, 0xef, 0xac, 0x1c, 0x2c, 0xf2, 0x58, 0xf2, 0xa8, 0x48, 0x40, 0x87, 0x8e, 0xba, 0x78, 0x61, 0x49, 0xde, 0x59, 0x39, 0x58, 0xfc, 0x28, 0x79, 0x54, 0x2c, 0xa0, 0x43, 0xc7,
0x1d, 0x3a, 0x14, 0x59, 0xbb, 0x14, 0x1d, 0x0a, 0xb4, 0xbf, 0xc4, 0x9b, 0x35, 0x16, 0x1d, 0x0e, 0x16, 0xe8, 0x50, 0x64, 0xed, 0x52, 0x74, 0xe8, 0xd0, 0xff, 0xa3, 0x80, 0x37, 0x6b, 0x2c, 0x3a,
0x88, 0xbd, 0x71, 0xe4, 0x98, 0xa9, 0xb8, 0x23, 0x45, 0x91, 0x74, 0x5c, 0x04, 0xe8, 0x76, 0xf7, 0x1c, 0x10, 0x7b, 0xe3, 0xc8, 0x31, 0x53, 0x71, 0x47, 0x8a, 0x3a, 0xca, 0x71, 0x50, 0x20, 0xdb,
0xde, 0xbb, 0xf7, 0xee, 0xfb, 0xf4, 0x9d, 0xa8, 0xf6, 0xc7, 0xc4, 0xd9, 0x77, 0xa9, 0x7f, 0x4a, 0xdd, 0x7b, 0xef, 0xde, 0xef, 0x83, 0xbf, 0x3b, 0x82, 0xee, 0x90, 0x3a, 0x3b, 0x6e, 0xe0, 0x9f,
0x46, 0xfb, 0x08, 0x4f, 0x88, 0x8b, 0xb3, 0x4d, 0x1c, 0xda, 0x8c, 0x50, 0x7f, 0x18, 0x84, 0x94, 0xd0, 0xc1, 0x0e, 0x26, 0x23, 0xea, 0x92, 0x7c, 0x93, 0x44, 0x36, 0xa3, 0x81, 0xdf, 0x0f, 0xa3,
0x51, 0x6d, 0x35, 0x03, 0xf7, 0x76, 0x85, 0x5a, 0x42, 0x2e, 0x1d, 0xef, 0x3b, 0x38, 0xc8, 0xf8, 0x80, 0x05, 0xfa, 0x62, 0x0e, 0x6e, 0x6f, 0x09, 0xb5, 0x84, 0xdc, 0x60, 0xb8, 0xe3, 0x90, 0x30,
0xbd, 0x7b, 0x25, 0x17, 0xea, 0x44, 0x38, 0x9c, 0x60, 0x94, 0x53, 0x4d, 0x3c, 0x65, 0xd9, 0xd2, 0xe7, 0xb7, 0xef, 0x29, 0x2e, 0x81, 0x13, 0x93, 0x68, 0x44, 0x70, 0x41, 0xd5, 0xc9, 0x19, 0xcb,
0xf8, 0x73, 0x5b, 0xdd, 0x79, 0x2c, 0x33, 0x1e, 0x95, 0x33, 0xb4, 0xbf, 0x14, 0xb5, 0x99, 0x65, 0x97, 0x9d, 0xbf, 0xd7, 0xc1, 0xe6, 0xbe, 0x8c, 0xf1, 0x58, 0x8d, 0xa1, 0xff, 0xa5, 0x81, 0x7a,
0x5b, 0x04, 0xe9, 0x4a, 0x4f, 0x19, 0x6c, 0x9a, 0x3f, 0x2b, 0xe7, 0x1c, 0x34, 0xfe, 0xe1, 0xe0, 0x1e, 0xdb, 0xa2, 0xd8, 0xd0, 0xda, 0x5a, 0x6f, 0xd5, 0xfc, 0x45, 0x3b, 0xe7, 0xb0, 0xf6, 0x2f,
0xa3, 0x11, 0x61, 0xcf, 0x63, 0x67, 0xe8, 0x52, 0x6f, 0x3f, 0x9a, 0xf9, 0x2e, 0x7b, 0x4e, 0xfc, 0x87, 0x1f, 0x0f, 0x28, 0x7b, 0x9e, 0x38, 0x7d, 0x37, 0xf0, 0x76, 0xe2, 0xb1, 0xef, 0xb2, 0xe7,
0x51, 0x69, 0x55, 0xbe, 0xd1, 0x30, 0x73, 0x3f, 0x7a, 0x7c, 0xc9, 0xc1, 0xfa, 0x62, 0x9d, 0x70, 0xd4, 0x1f, 0x28, 0x2b, 0x35, 0xa3, 0x7e, 0xee, 0x7e, 0xb0, 0x7f, 0xc9, 0xe1, 0xf2, 0x74, 0x9d,
0xb0, 0x8e, 0xf2, 0x75, 0xca, 0x41, 0x6b, 0xea, 0x8d, 0x0f, 0x0d, 0x82, 0x1e, 0xda, 0x8c, 0x85, 0x72, 0xb8, 0x8c, 0x8b, 0x75, 0xc6, 0x61, 0xe3, 0xcc, 0x1b, 0xee, 0x75, 0x28, 0x7e, 0x68, 0x33,
0x46, 0x72, 0xd1, 0x5f, 0xcb, 0xd7, 0xe9, 0x45, 0xbf, 0xd0, 0xfd, 0x34, 0xef, 0x2b, 0x2f, 0xe7, 0x16, 0x75, 0xd2, 0x8b, 0xee, 0x52, 0xb1, 0xce, 0x2e, 0xba, 0xa5, 0xee, 0xa7, 0x49, 0x57, 0x7b,
0xfd, 0xc2, 0x03, 0x2e, 0x18, 0xa4, 0x3d, 0x53, 0x6f, 0xf9, 0xb6, 0x87, 0xf5, 0x77, 0x7a, 0xca, 0x39, 0xe9, 0x96, 0x1e, 0x68, 0xca, 0x60, 0xfd, 0x08, 0xdc, 0xf2, 0x6d, 0x8f, 0x18, 0xef, 0xb5,
0xa0, 0x69, 0x7e, 0x9c, 0x70, 0x20, 0xf7, 0x29, 0x07, 0xf7, 0xa4, 0xb3, 0xd8, 0x48, 0xbf, 0x87, 0xb5, 0x5e, 0xdd, 0xfc, 0x24, 0xe5, 0x50, 0xee, 0x33, 0x0e, 0xef, 0x49, 0x67, 0xb1, 0x91, 0x7e,
0xd4, 0x23, 0x0c, 0x7b, 0x01, 0x9b, 0x89, 0x94, 0x9d, 0x37, 0xe0, 0x50, 0x9e, 0xd4, 0xa6, 0x6a, 0x0f, 0x03, 0x8f, 0x32, 0xe2, 0x85, 0x6c, 0x2c, 0xa2, 0x6c, 0xbe, 0x01, 0x47, 0xf2, 0xa4, 0x7e,
0xd3, 0x46, 0x28, 0xc4, 0x51, 0x84, 0x23, 0x7d, 0xa5, 0xb7, 0x32, 0x68, 0x9a, 0x27, 0x09, 0x07, 0x06, 0xea, 0x36, 0xc6, 0x11, 0x89, 0x63, 0x12, 0x1b, 0x0b, 0xed, 0x85, 0x5e, 0xdd, 0x3c, 0x4e,
0x4b, 0x30, 0xe5, 0xe0, 0x81, 0xf4, 0xce, 0x91, 0x92, 0x73, 0x0f, 0xe1, 0x53, 0x3b, 0x1e, 0xb3, 0x39, 0x9c, 0x81, 0x19, 0x87, 0x0f, 0xa4, 0x77, 0x81, 0x28, 0xce, 0x6d, 0x4c, 0x4e, 0xec, 0x64,
0x43, 0x03, 0xcd, 0x7c, 0xdb, 0x23, 0xae, 0xc8, 0xea, 0x5c, 0xd3, 0xbd, 0xbe, 0xe8, 0xaf, 0xe5, 0xc8, 0xf6, 0x3a, 0x78, 0xec, 0xdb, 0x1e, 0x75, 0x45, 0xac, 0x8d, 0x6b, 0xba, 0xd7, 0x17, 0xdd,
0x02, 0xb8, 0xf4, 0xd5, 0x26, 0xea, 0x86, 0x4b, 0xbd, 0x40, 0xec, 0x08, 0xf5, 0xf5, 0x5b, 0x3d, 0xa5, 0x42, 0x80, 0x66, 0xbe, 0xfa, 0x08, 0xac, 0xb8, 0x81, 0x17, 0x8a, 0x1d, 0x0d, 0x7c, 0xe3,
0x65, 0xb0, 0x75, 0x70, 0x67, 0x58, 0xb4, 0xf3, 0xd1, 0x92, 0x34, 0x3f, 0x49, 0x38, 0x28, 0xab, 0x56, 0x5b, 0xeb, 0xad, 0xed, 0xde, 0xe9, 0x97, 0xed, 0x7c, 0x3c, 0x23, 0xcd, 0x4f, 0x53, 0x0e,
0x53, 0x0e, 0x76, 0xe5, 0xa5, 0x4a, 0x58, 0xd1, 0xd3, 0xed, 0x3a, 0x08, 0xcb, 0x47, 0x35, 0xac, 0x55, 0x75, 0xc6, 0xe1, 0x96, 0x4c, 0x4a, 0xc1, 0xca, 0x9e, 0xae, 0xcf, 0x83, 0x48, 0x3d, 0xaa,
0x36, 0x5d, 0x1c, 0x32, 0x4b, 0x36, 0xf2, 0xb6, 0x6c, 0xe4, 0x97, 0xe2, 0x67, 0x12, 0xe0, 0x93, 0x13, 0x50, 0x77, 0x49, 0xc4, 0x2c, 0xd9, 0xc8, 0xdb, 0xb2, 0x91, 0x4f, 0xc4, 0x67, 0x12, 0xe0,
0xac, 0x99, 0xf7, 0x33, 0xef, 0x1c, 0x78, 0x43, 0x43, 0xef, 0xde, 0xc0, 0xc1, 0xc2, 0x45, 0x3b, 0xd3, 0xbc, 0x99, 0xf7, 0x73, 0xef, 0x02, 0x78, 0x43, 0x43, 0xef, 0xde, 0xc0, 0xa1, 0xd2, 0x45,
0x51, 0x55, 0xe2, 0xb3, 0x90, 0xa2, 0xd8, 0xc5, 0xa1, 0xbe, 0xda, 0x53, 0x06, 0xeb, 0xe6, 0x61, 0x3f, 0x06, 0x80, 0xfa, 0x2c, 0x0a, 0x70, 0xe2, 0x92, 0xc8, 0x58, 0x6c, 0x6b, 0xbd, 0x65, 0x73,
0xc2, 0x41, 0x09, 0x4d, 0x39, 0xb8, 0x93, 0x0d, 0x44, 0x01, 0x15, 0x45, 0xb4, 0x6b, 0x18, 0x2c, 0x2f, 0xe5, 0x50, 0x41, 0x33, 0x0e, 0xef, 0xe4, 0x03, 0x51, 0x42, 0x65, 0x11, 0xcd, 0x39, 0x0c,
0x9d, 0xd3, 0x7e, 0x57, 0xd4, 0xbd, 0xe8, 0x8c, 0x04, 0xd6, 0x02, 0x13, 0x93, 0x6c, 0x85, 0xd8, 0x29, 0xe7, 0xf4, 0x3f, 0x34, 0xb0, 0x1d, 0x9f, 0xd2, 0xd0, 0x9a, 0x62, 0x62, 0x92, 0xad, 0x88,
0xa3, 0x13, 0x7b, 0x1c, 0xe9, 0x6b, 0x32, 0x0c, 0x25, 0x1c, 0xe8, 0x42, 0x75, 0x54, 0x12, 0xc1, 0x78, 0xc1, 0xc8, 0x1e, 0xc6, 0xc6, 0x92, 0x0c, 0x86, 0x53, 0x0e, 0x0d, 0xa1, 0x3a, 0x50, 0x44,
0x5c, 0x93, 0x72, 0xf0, 0xae, 0x8c, 0xbe, 0x49, 0x50, 0x5c, 0xe4, 0xfe, 0x7f, 0x2a, 0xe0, 0x8d, 0xa8, 0xd0, 0x64, 0x1c, 0xbe, 0x2f, 0x43, 0xdf, 0x24, 0x28, 0x13, 0xb9, 0xff, 0x56, 0x05, 0xba,
0x09, 0xda, 0x1f, 0x8a, 0xda, 0x2a, 0xee, 0x8c, 0x2c, 0x67, 0xa6, 0xaf, 0xcb, 0xc7, 0xf5, 0xe3, 0x31, 0x82, 0xfe, 0xa7, 0x06, 0x1a, 0x65, 0xce, 0xd8, 0x72, 0xc6, 0xc6, 0xb2, 0xbc, 0x5c, 0x3f,
0xff, 0x7a, 0x5c, 0x09, 0x07, 0x9b, 0x4b, 0x57, 0x73, 0x96, 0x72, 0x70, 0xb7, 0xda, 0x43, 0x64, 0xbe, 0xd3, 0xe5, 0x4a, 0x39, 0x5c, 0x9d, 0xb9, 0x9a, 0xe3, 0x8c, 0xc3, 0xbb, 0xd5, 0x1e, 0x62,
0xce, 0x8a, 0xcb, 0x77, 0xae, 0xa1, 0xe2, 0x71, 0xc1, 0x8a, 0x83, 0x76, 0xa0, 0xae, 0x06, 0x76, 0x73, 0x5c, 0x26, 0xbf, 0x71, 0x0d, 0x15, 0x97, 0x0b, 0x55, 0x1c, 0xf4, 0x5d, 0xb0, 0x18, 0xda,
0x1c, 0x61, 0xa4, 0x37, 0x65, 0xe3, 0xf6, 0x12, 0x0e, 0x72, 0x24, 0xe5, 0x60, 0x53, 0xba, 0x67, 0x49, 0x4c, 0xb0, 0x51, 0x97, 0x8d, 0xdb, 0x4e, 0x39, 0x2c, 0x90, 0x8c, 0xc3, 0x55, 0xe9, 0x9e,
0x5b, 0x03, 0xe6, 0xb8, 0xf6, 0x83, 0xba, 0x6d, 0x8f, 0xc7, 0xf4, 0x05, 0x46, 0x96, 0x8f, 0xd9, 0x6f, 0x3b, 0xa8, 0xc0, 0xf5, 0x1f, 0xc0, 0xba, 0x3d, 0x1c, 0x06, 0x2f, 0x08, 0xb6, 0x7c, 0xc2,
0x0b, 0x1a, 0x9e, 0x45, 0xba, 0x2a, 0x5f, 0xcf, 0xd7, 0x09, 0x07, 0xed, 0x9c, 0x7b, 0x92, 0x53, 0x5e, 0x04, 0xd1, 0x69, 0x6c, 0x00, 0x79, 0x7b, 0xbe, 0x4e, 0x39, 0x6c, 0x16, 0xdc, 0xd3, 0x82,
0x29, 0x07, 0xdd, 0xec, 0x0d, 0x55, 0xf0, 0xea, 0x4c, 0xe9, 0x37, 0x91, 0xb0, 0x6e, 0xa7, 0x7d, 0xca, 0x38, 0x6c, 0xe5, 0x77, 0xa8, 0x82, 0x57, 0x67, 0xca, 0xb8, 0x89, 0x44, 0xf3, 0x76, 0xfa,
0xa7, 0xee, 0xd8, 0x31, 0xa3, 0x96, 0xed, 0xba, 0x38, 0x60, 0xd6, 0x29, 0x1d, 0x23, 0x1c, 0x46, 0x77, 0x60, 0xd3, 0x4e, 0x58, 0x60, 0xd9, 0xae, 0x4b, 0x42, 0x66, 0x9d, 0x04, 0x43, 0x4c, 0xa2,
0xfa, 0x86, 0xbc, 0xfe, 0x07, 0x09, 0x07, 0x1d, 0x41, 0x7f, 0x26, 0xd9, 0xcf, 0x33, 0xb2, 0xe8, 0xd8, 0x58, 0x91, 0xe9, 0x7f, 0x98, 0x72, 0xb8, 0x21, 0xe8, 0xcf, 0x25, 0xfb, 0x45, 0x4e, 0x96,
0xd3, 0x35, 0xc6, 0x80, 0xd7, 0xd5, 0xda, 0x53, 0xb5, 0xe5, 0xd9, 0x53, 0x2b, 0xc2, 0x3e, 0xb2, 0x7d, 0xba, 0xc6, 0x74, 0xd0, 0x75, 0xb5, 0xfe, 0x0c, 0x34, 0x3c, 0xfb, 0xcc, 0x8a, 0x89, 0x8f,
0xce, 0x9c, 0x20, 0xd2, 0x37, 0x7b, 0xca, 0xe0, 0xb6, 0xf9, 0x9e, 0x78, 0x87, 0x9e, 0x3d, 0xfd, 0xad, 0x53, 0x27, 0x8c, 0x8d, 0xd5, 0xb6, 0xd6, 0xbb, 0x6d, 0x7e, 0x20, 0xee, 0xa1, 0x67, 0x9f,
0x06, 0xfb, 0xe8, 0xd8, 0x09, 0x84, 0x6b, 0x47, 0xba, 0x96, 0x30, 0xe3, 0x35, 0x07, 0x2b, 0xc4, 0x7d, 0x43, 0x7c, 0x7c, 0xe8, 0x84, 0xc2, 0x75, 0x43, 0xba, 0x2a, 0x58, 0xe7, 0x35, 0x87, 0x0b,
0x67, 0xb0, 0x2c, 0x5c, 0x18, 0x86, 0xd8, 0x9d, 0x64, 0x86, 0xad, 0x8a, 0x21, 0xc4, 0xee, 0xa4, 0xd4, 0x67, 0x48, 0x15, 0x4e, 0x0d, 0x23, 0xe2, 0x8e, 0x72, 0xc3, 0x46, 0xc5, 0x10, 0x11, 0x77,
0x6e, 0xb8, 0xc0, 0x2a, 0x86, 0x0b, 0x50, 0xf3, 0xd5, 0x36, 0x19, 0xf9, 0x34, 0xc4, 0xa8, 0xa8, 0x34, 0x6f, 0x38, 0xc5, 0x2a, 0x86, 0x53, 0x50, 0xf7, 0x41, 0x93, 0x0e, 0xfc, 0x20, 0x22, 0xb8,
0x7f, 0xab, 0xb7, 0x32, 0xd8, 0x38, 0xd8, 0x1d, 0x66, 0xdf, 0x82, 0xe1, 0xd3, 0xfc, 0x5b, 0x90, 0xac, 0x7f, 0xad, 0xbd, 0xd0, 0x5b, 0xd9, 0xdd, 0xea, 0xe7, 0xff, 0x82, 0xfe, 0xb3, 0xe2, 0x5f,
0xd5, 0x64, 0xbe, 0x2f, 0xc6, 0x2e, 0xe1, 0x60, 0x2b, 0x3f, 0xb6, 0x6c, 0xcc, 0x4e, 0x36, 0x40, 0x90, 0xd7, 0x64, 0x3e, 0x12, 0x63, 0x97, 0x72, 0xb8, 0x56, 0x1c, 0x9b, 0x35, 0x66, 0x33, 0x1f,
0x65, 0xd8, 0x80, 0x35, 0x99, 0xc8, 0x0b, 0xb0, 0x8f, 0x88, 0x3f, 0x2a, 0xf2, 0xda, 0x6f, 0x97, 0x20, 0x15, 0xee, 0xa0, 0x39, 0x99, 0xfe, 0xb3, 0x06, 0x9a, 0x21, 0xf1, 0x31, 0xf5, 0x07, 0x65,
0x97, 0x1f, 0xab, 0xe7, 0x55, 0x60, 0x03, 0xd6, 0x64, 0xda, 0xaf, 0x8a, 0xda, 0xce, 0x3a, 0xf6, 0xc0, 0xe6, 0x5b, 0x03, 0x3e, 0x11, 0x01, 0x2f, 0x39, 0x34, 0xf6, 0x49, 0x18, 0x11, 0xd7, 0x66,
0x7d, 0x8c, 0x23, 0x66, 0x9d, 0x11, 0x47, 0xdf, 0x96, 0x3d, 0x8b, 0x2e, 0x39, 0x68, 0x7d, 0x25, 0x04, 0x1f, 0xe5, 0x06, 0x85, 0x67, 0xca, 0xa1, 0xf6, 0xa8, 0x7c, 0x6e, 0x42, 0x95, 0x53, 0x46,
0x5a, 0x21, 0x99, 0x63, 0x62, 0x26, 0x1c, 0xb4, 0xbc, 0x32, 0x50, 0x84, 0x54, 0xd0, 0x45, 0x23, 0xc3, 0xd0, 0xd0, 0x5a, 0x85, 0x8b, 0xf5, 0xdf, 0x34, 0xd0, 0xcc, 0xbb, 0xf9, 0x7d, 0x42, 0x62,
0x93, 0x8b, 0x7e, 0x4d, 0x5e, 0x07, 0x5e, 0xce, 0xfb, 0xd5, 0x04, 0x58, 0xe1, 0x1d, 0xed, 0x53, 0x66, 0x9d, 0x52, 0xc7, 0x58, 0x97, 0xfd, 0x8c, 0x2f, 0x39, 0x6c, 0x7c, 0x25, 0xda, 0x24, 0x99,
0xb5, 0x19, 0xfb, 0x2c, 0x8c, 0x23, 0x86, 0x91, 0xde, 0x91, 0x73, 0xd7, 0x13, 0x9f, 0x8d, 0x02, 0x43, 0x6a, 0xa6, 0x1c, 0x36, 0x3c, 0x15, 0x28, 0x0b, 0xae, 0xa0, 0xd3, 0x26, 0xa7, 0x17, 0xdd,
0x4c, 0x39, 0x68, 0xcb, 0x1b, 0x14, 0x88, 0x01, 0x97, 0xac, 0xac, 0x4e, 0xfc, 0x5f, 0x31, 0x6c, 0x39, 0xf9, 0x3c, 0xf0, 0x72, 0xd2, 0xad, 0x46, 0x40, 0x15, 0xde, 0xd1, 0x3f, 0x03, 0xf5, 0xc4,
0x8d, 0x62, 0x62, 0x05, 0x34, 0x64, 0xba, 0xb6, 0xac, 0x0e, 0x4a, 0xea, 0x8b, 0x6f, 0x8f, 0x9e, 0x67, 0x51, 0x12, 0x33, 0x82, 0x8d, 0x0d, 0x39, 0x93, 0x6d, 0xf1, 0x4b, 0x29, 0xc1, 0x8c, 0xc3,
0xd1, 0x90, 0x89, 0xea, 0xc2, 0x32, 0x50, 0x54, 0x57, 0x41, 0xcb, 0xd5, 0x55, 0xe5, 0x75, 0x40, 0xa6, 0xcc, 0xa0, 0x44, 0x3a, 0x68, 0xc6, 0xca, 0xea, 0xc4, 0x5b, 0xc6, 0x88, 0x35, 0x48, 0xa8,
0x54, 0x57, 0x49, 0x80, 0x0b, 0x3e, 0x26, 0x62, 0x6b, 0x1e, 0x9f, 0xbf, 0xea, 0x36, 0xe6, 0xaf, 0x15, 0x06, 0x11, 0x33, 0xf4, 0x59, 0x75, 0x48, 0x52, 0x5f, 0x7e, 0x7b, 0x70, 0x14, 0x44, 0x4c,
0xba, 0x8d, 0xf3, 0xcb, 0xae, 0x32, 0xbf, 0xec, 0x2a, 0xbf, 0x5c, 0x75, 0x1b, 0xbf, 0x5d, 0x75, 0x54, 0x17, 0xa9, 0x40, 0x59, 0x5d, 0x05, 0x55, 0xab, 0xab, 0xca, 0xe7, 0x01, 0x51, 0x5d, 0x25,
0x95, 0xf9, 0x55, 0xb7, 0xf1, 0xf7, 0x55, 0xb7, 0x71, 0xf2, 0xe0, 0x2d, 0xfe, 0xbb, 0xb2, 0xb1, 0x02, 0x9a, 0xf2, 0x09, 0x15, 0x5b, 0xf3, 0xf0, 0xfc, 0x55, 0xab, 0x36, 0x79, 0xd5, 0xaa, 0x9d,
0x70, 0x56, 0xe5, 0x7f, 0xd8, 0x87, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0xe9, 0x0e, 0x8a, 0x12, 0x5f, 0xb6, 0xb4, 0xc9, 0x65, 0x4b, 0xfb, 0xf5, 0xaa, 0x55, 0xfb, 0xfd, 0xaa, 0xa5, 0x4d, 0xae,
0xed, 0x08, 0x00, 0x00, 0x5a, 0xb5, 0x7f, 0xae, 0x5a, 0xb5, 0xe3, 0x07, 0xff, 0xe3, 0x5d, 0xcb, 0x27, 0xc6, 0x59, 0x94,
0xef, 0xdb, 0x47, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0x1d, 0x01, 0x84, 0xd4, 0x09, 0x09, 0x00,
0x00,
} }
func (m *DeviceConfiguration) Marshal() (dAtA []byte, err error) { func (m *DeviceConfiguration) Marshal() (dAtA []byte, err error) {
@ -199,10 +201,10 @@ func (m *DeviceConfiguration) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i-- i--
dAtA[i] = 0x80 dAtA[i] = 0x80
} }
if len(m.PendingFolders) > 0 { if len(m.DeprecatedPendingFolders) > 0 {
for iNdEx := len(m.PendingFolders) - 1; iNdEx >= 0; iNdEx-- { for iNdEx := len(m.DeprecatedPendingFolders) - 1; iNdEx >= 0; iNdEx-- {
{ {
size, err := m.PendingFolders[iNdEx].MarshalToSizedBuffer(dAtA[:i]) size, err := m.DeprecatedPendingFolders[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -405,8 +407,8 @@ func (m *DeviceConfiguration) ProtoSize() (n int) {
n += 1 + l + sovDeviceconfiguration(uint64(l)) n += 1 + l + sovDeviceconfiguration(uint64(l))
} }
} }
if len(m.PendingFolders) > 0 { if len(m.DeprecatedPendingFolders) > 0 {
for _, e := range m.PendingFolders { for _, e := range m.DeprecatedPendingFolders {
l = e.ProtoSize() l = e.ProtoSize()
n += 1 + l + sovDeviceconfiguration(uint64(l)) n += 1 + l + sovDeviceconfiguration(uint64(l))
} }
@ -825,7 +827,7 @@ func (m *DeviceConfiguration) Unmarshal(dAtA []byte) error {
iNdEx = postIndex iNdEx = postIndex
case 15: case 15:
if wireType != 2 { if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field PendingFolders", wireType) return fmt.Errorf("proto: wrong wireType = %d for field DeprecatedPendingFolders", wireType)
} }
var msglen int var msglen int
for shift := uint(0); ; shift += 7 { for shift := uint(0); ; shift += 7 {
@ -852,8 +854,8 @@ func (m *DeviceConfiguration) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.PendingFolders = append(m.PendingFolders, ObservedFolder{}) m.DeprecatedPendingFolders = append(m.DeprecatedPendingFolders, ObservedFolder{})
if err := m.PendingFolders[len(m.PendingFolders)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { if err := m.DeprecatedPendingFolders[len(m.DeprecatedPendingFolders)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex

View File

@ -9,7 +9,6 @@ package config
import ( import (
"os" "os"
"sync/atomic" "sync/atomic"
"time"
"github.com/syncthing/syncthing/lib/events" "github.com/syncthing/syncthing/lib/events"
"github.com/syncthing/syncthing/lib/osutil" "github.com/syncthing/syncthing/lib/osutil"
@ -85,8 +84,7 @@ type Wrapper interface {
SetDevice(DeviceConfiguration) (Waiter, error) SetDevice(DeviceConfiguration) (Waiter, error)
SetDevices([]DeviceConfiguration) (Waiter, error) SetDevices([]DeviceConfiguration) (Waiter, error)
AddOrUpdatePendingDevice(device protocol.DeviceID, name, address string) IgnoredDevices() []ObservedDevice
AddOrUpdatePendingFolder(id, label string, device protocol.DeviceID)
IgnoredDevice(id protocol.DeviceID) bool IgnoredDevice(id protocol.DeviceID) bool
IgnoredFolder(device protocol.DeviceID, folder string) bool IgnoredFolder(device protocol.DeviceID, folder string) bool
@ -428,6 +426,15 @@ func (w *wrapper) IgnoredDevice(id protocol.DeviceID) bool {
return false return false
} }
// IgnoredDevices returns a slice of ignored devices.
func (w *wrapper) IgnoredDevices() []ObservedDevice {
w.mut.Lock()
defer w.mut.Unlock()
res := make([]ObservedDevice, len(w.cfg.IgnoredDevices))
copy(res, w.cfg.IgnoredDevices)
return res
}
// IgnoredFolder returns whether or not share attempts for the given // IgnoredFolder returns whether or not share attempts for the given
// folder should be silently ignored. // folder should be silently ignored.
func (w *wrapper) IgnoredFolder(device protocol.DeviceID, folder string) bool { func (w *wrapper) IgnoredFolder(device protocol.DeviceID, folder string) bool {
@ -495,49 +502,3 @@ func (w *wrapper) RequiresRestart() bool {
func (w *wrapper) setRequiresRestart() { func (w *wrapper) setRequiresRestart() {
atomic.StoreUint32(&w.requiresRestart, 1) atomic.StoreUint32(&w.requiresRestart, 1)
} }
func (w *wrapper) AddOrUpdatePendingDevice(device protocol.DeviceID, name, address string) {
w.mut.Lock()
defer w.mut.Unlock()
for i := range w.cfg.PendingDevices {
if w.cfg.PendingDevices[i].ID == device {
w.cfg.PendingDevices[i].Time = time.Now().Round(time.Second)
w.cfg.PendingDevices[i].Name = name
w.cfg.PendingDevices[i].Address = address
return
}
}
w.cfg.PendingDevices = append(w.cfg.PendingDevices, ObservedDevice{
Time: time.Now().Round(time.Second),
ID: device,
Name: name,
Address: address,
})
}
func (w *wrapper) AddOrUpdatePendingFolder(id, label string, device protocol.DeviceID) {
w.mut.Lock()
defer w.mut.Unlock()
for i := range w.cfg.Devices {
if w.cfg.Devices[i].DeviceID == device {
for j := range w.cfg.Devices[i].PendingFolders {
if w.cfg.Devices[i].PendingFolders[j].ID == id {
w.cfg.Devices[i].PendingFolders[j].Label = label
w.cfg.Devices[i].PendingFolders[j].Time = time.Now().Round(time.Second)
return
}
}
w.cfg.Devices[i].PendingFolders = append(w.cfg.Devices[i].PendingFolders, ObservedFolder{
Time: time.Now().Round(time.Second),
ID: id,
Label: label,
})
return
}
}
panic("bug: adding pending folder for non-existing device")
}

View File

@ -68,6 +68,12 @@ const (
// KeyTypeVersion <version hash> = Vector // KeyTypeVersion <version hash> = Vector
KeyTypeVersion byte = 15 KeyTypeVersion byte = 15
// KeyTypePendingFolder <int32 device ID> <folder ID as string> = ObservedFolder
KeyTypePendingFolder byte = 16
// KeyTypePendingDevice <device ID in wire format> = ObservedDevice
KeyTypePendingDevice byte = 17
) )
type keyer interface { type keyer interface {
@ -108,6 +114,14 @@ type keyer interface {
// Version vectors // Version vectors
GenerateVersionKey(key []byte, hash []byte) versionKey GenerateVersionKey(key []byte, hash []byte) versionKey
// Pending (unshared) folders and devices
GeneratePendingFolderKey(key, device, folder []byte) (pendingFolderKey, error)
FolderFromPendingFolderKey(key []byte) []byte
DeviceFromPendingFolderKey(key []byte) ([]byte, bool)
GeneratePendingDeviceKey(key, device []byte) pendingDeviceKey
DeviceFromPendingDeviceKey(key []byte) []byte
} }
// defaultKeyer implements our key scheme. It needs folder and device // defaultKeyer implements our key scheme. It needs folder and device
@ -341,6 +355,41 @@ func (k versionKey) Hash() []byte {
return k[keyPrefixLen:] return k[keyPrefixLen:]
} }
type pendingFolderKey []byte
func (k defaultKeyer) GeneratePendingFolderKey(key, device, folder []byte) (pendingFolderKey, error) {
deviceID, err := k.deviceIdx.ID(device)
if err != nil {
return nil, err
}
key = resize(key, keyPrefixLen+keyDeviceLen+len(folder))
key[0] = KeyTypePendingFolder
binary.BigEndian.PutUint32(key[keyPrefixLen:], deviceID)
copy(key[keyPrefixLen+keyDeviceLen:], folder)
return key, nil
}
func (k defaultKeyer) FolderFromPendingFolderKey(key []byte) []byte {
return key[keyPrefixLen+keyDeviceLen:]
}
func (k defaultKeyer) DeviceFromPendingFolderKey(key []byte) ([]byte, bool) {
return k.deviceIdx.Val(binary.BigEndian.Uint32(key[keyPrefixLen:]))
}
type pendingDeviceKey []byte
func (k defaultKeyer) GeneratePendingDeviceKey(key, device []byte) pendingDeviceKey {
key = resize(key, keyPrefixLen+len(device))
key[0] = KeyTypePendingDevice
copy(key[keyPrefixLen:], device)
return key
}
func (k defaultKeyer) DeviceFromPendingDeviceKey(key []byte) []byte {
return key[keyPrefixLen:]
}
// resize returns a byte slice of the specified size, reusing bs if possible // resize returns a byte slice of the specified size, reusing bs if possible
func resize(bs []byte, size int) []byte { func resize(bs []byte, size int) []byte {
if cap(bs) < size { if cap(bs) < size {

172
lib/db/observed.go Normal file
View File

@ -0,0 +1,172 @@
// 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/.
package db
import (
"time"
"github.com/syncthing/syncthing/lib/protocol"
)
func (db *Lowlevel) AddOrUpdatePendingDevice(device protocol.DeviceID, name, address string) error {
key := db.keyer.GeneratePendingDeviceKey(nil, device[:])
od := ObservedDevice{
Time: time.Now().Round(time.Second),
Name: name,
Address: address,
}
bs, err := od.Marshal()
if err != nil {
return err
}
return db.Put(key, bs)
}
func (db *Lowlevel) RemovePendingDevice(device protocol.DeviceID) {
key := db.keyer.GeneratePendingDeviceKey(nil, device[:])
if err := db.Delete(key); err != nil {
l.Warnf("Failed to remove pending device entry: %v", err)
}
}
// PendingDevices enumerates all entries. Invalid ones are dropped from the database
// after a warning log message, as a side-effect.
func (db *Lowlevel) PendingDevices() (map[protocol.DeviceID]ObservedDevice, error) {
iter, err := db.NewPrefixIterator([]byte{KeyTypePendingDevice})
if err != nil {
return nil, err
}
defer iter.Release()
res := make(map[protocol.DeviceID]ObservedDevice)
for iter.Next() {
keyDev := db.keyer.DeviceFromPendingDeviceKey(iter.Key())
deviceID, err := protocol.DeviceIDFromBytes(keyDev)
var od ObservedDevice
if err != nil {
goto deleteKey
}
if err = od.Unmarshal(iter.Value()); err != nil {
goto deleteKey
}
res[deviceID] = od
continue
deleteKey:
// Deleting invalid entries is the only possible "repair" measure and
// appropriate for the importance of pending entries. They will come back
// soon if still relevant.
l.Infof("Invalid pending device entry, deleting from database: %x", iter.Key())
if err := db.Delete(iter.Key()); err != nil {
return nil, err
}
}
return res, nil
}
func (db *Lowlevel) AddOrUpdatePendingFolder(id, label string, device protocol.DeviceID) error {
key, err := db.keyer.GeneratePendingFolderKey(nil, device[:], []byte(id))
if err != nil {
return err
}
of := ObservedFolder{
Time: time.Now().Round(time.Second),
Label: label,
}
bs, err := of.Marshal()
if err != nil {
return err
}
return db.Put(key, bs)
}
// RemovePendingFolderForDevice removes entries for specific folder / device combinations.
func (db *Lowlevel) RemovePendingFolderForDevice(id string, device protocol.DeviceID) {
key, err := db.keyer.GeneratePendingFolderKey(nil, device[:], []byte(id))
if err != nil {
return
}
if err := db.Delete(key); err != nil {
l.Warnf("Failed to remove pending folder entry: %v", err)
}
}
// RemovePendingFolder removes all entries matching a specific folder ID.
func (db *Lowlevel) RemovePendingFolder(id string) {
iter, err := db.NewPrefixIterator([]byte{KeyTypePendingFolder})
if err != nil {
l.Infof("Could not iterate through pending folder entries: %v", err)
return
}
defer iter.Release()
for iter.Next() {
if id != string(db.keyer.FolderFromPendingFolderKey(iter.Key())) {
continue
}
if err := db.Delete(iter.Key()); err != nil {
l.Warnf("Failed to remove pending folder entry: %v", err)
}
}
}
// Consolidated information about a pending folder
type PendingFolder struct {
OfferedBy map[protocol.DeviceID]ObservedFolder `json:"offeredBy"`
}
func (db *Lowlevel) PendingFolders() (map[string]PendingFolder, error) {
return db.PendingFoldersForDevice(protocol.EmptyDeviceID)
}
// PendingFoldersForDevice enumerates only entries matching the given device ID, unless it
// is EmptyDeviceID. Invalid ones are dropped from the database after a warning log
// message, as a side-effect.
func (db *Lowlevel) PendingFoldersForDevice(device protocol.DeviceID) (map[string]PendingFolder, error) {
var err error
prefixKey := []byte{KeyTypePendingFolder}
if device != protocol.EmptyDeviceID {
prefixKey, err = db.keyer.GeneratePendingFolderKey(nil, device[:], nil)
if err != nil {
return nil, err
}
}
iter, err := db.NewPrefixIterator(prefixKey)
if err != nil {
return nil, err
}
defer iter.Release()
res := make(map[string]PendingFolder)
for iter.Next() {
keyDev, ok := db.keyer.DeviceFromPendingFolderKey(iter.Key())
deviceID, err := protocol.DeviceIDFromBytes(keyDev)
var of ObservedFolder
var folderID string
if !ok || err != nil {
goto deleteKey
}
if folderID = string(db.keyer.FolderFromPendingFolderKey(iter.Key())); len(folderID) < 1 {
goto deleteKey
}
if err = of.Unmarshal(iter.Value()); err != nil {
goto deleteKey
}
if _, ok := res[folderID]; !ok {
res[folderID] = PendingFolder{
OfferedBy: map[protocol.DeviceID]ObservedFolder{},
}
}
res[folderID].OfferedBy[deviceID] = of
continue
deleteKey:
// Deleting invalid entries is the only possible "repair" measure and
// appropriate for the importance of pending entries. They will come back
// soon if still relevant.
l.Infof("Invalid pending folder entry, deleting from database: %x", iter.Key())
if err := db.Delete(iter.Key()); err != nil {
return nil, err
}
}
return res, nil
}

View File

@ -7,18 +7,22 @@ import (
fmt "fmt" fmt "fmt"
_ "github.com/gogo/protobuf/gogoproto" _ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto" 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_lib_protocol "github.com/syncthing/syncthing/lib/protocol"
protocol "github.com/syncthing/syncthing/lib/protocol" protocol "github.com/syncthing/syncthing/lib/protocol"
_ "github.com/syncthing/syncthing/proto/ext" _ "github.com/syncthing/syncthing/proto/ext"
io "io" io "io"
math "math" math "math"
math_bits "math/bits" math_bits "math/bits"
time "time"
) )
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal var _ = proto.Marshal
var _ = fmt.Errorf var _ = fmt.Errorf
var _ = math.Inf var _ = math.Inf
var _ = time.Kitchen
// This is a compile-time assertion to ensure that this generated file // This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against. // is compatible with the proto package it is being compiled against.
@ -395,6 +399,83 @@ func (m *VersionListDeprecated) XXX_DiscardUnknown() {
var xxx_messageInfo_VersionListDeprecated proto.InternalMessageInfo var xxx_messageInfo_VersionListDeprecated proto.InternalMessageInfo
type ObservedFolder struct {
Time time.Time `protobuf:"bytes,1,opt,name=time,proto3,stdtime" json:"time" xml:"time"`
Label string `protobuf:"bytes,2,opt,name=label,proto3" json:"label" xml:"label"`
}
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_5465d80e8cba02e3, []int{9}
}
func (m *ObservedFolder) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *ObservedFolder) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_ObservedFolder.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *ObservedFolder) XXX_Merge(src proto.Message) {
xxx_messageInfo_ObservedFolder.Merge(m, src)
}
func (m *ObservedFolder) XXX_Size() int {
return m.ProtoSize()
}
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"`
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name" xml:"name"`
Address string `protobuf:"bytes,3,opt,name=address,proto3" json:"address" xml:"address"`
}
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_5465d80e8cba02e3, []int{10}
}
func (m *ObservedDevice) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *ObservedDevice) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_ObservedDevice.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *ObservedDevice) XXX_Merge(src proto.Message) {
xxx_messageInfo_ObservedDevice.Merge(m, src)
}
func (m *ObservedDevice) XXX_Size() int {
return m.ProtoSize()
}
func (m *ObservedDevice) XXX_DiscardUnknown() {
xxx_messageInfo_ObservedDevice.DiscardUnknown(m)
}
var xxx_messageInfo_ObservedDevice proto.InternalMessageInfo
func init() { func init() {
proto.RegisterType((*FileVersion)(nil), "db.FileVersion") proto.RegisterType((*FileVersion)(nil), "db.FileVersion")
proto.RegisterType((*VersionList)(nil), "db.VersionList") proto.RegisterType((*VersionList)(nil), "db.VersionList")
@ -405,93 +486,103 @@ func init() {
proto.RegisterType((*CountsSet)(nil), "db.CountsSet") proto.RegisterType((*CountsSet)(nil), "db.CountsSet")
proto.RegisterType((*FileVersionDeprecated)(nil), "db.FileVersionDeprecated") proto.RegisterType((*FileVersionDeprecated)(nil), "db.FileVersionDeprecated")
proto.RegisterType((*VersionListDeprecated)(nil), "db.VersionListDeprecated") proto.RegisterType((*VersionListDeprecated)(nil), "db.VersionListDeprecated")
proto.RegisterType((*ObservedFolder)(nil), "db.ObservedFolder")
proto.RegisterType((*ObservedDevice)(nil), "db.ObservedDevice")
} }
func init() { proto.RegisterFile("lib/db/structs.proto", fileDescriptor_5465d80e8cba02e3) } func init() { proto.RegisterFile("lib/db/structs.proto", fileDescriptor_5465d80e8cba02e3) }
var fileDescriptor_5465d80e8cba02e3 = []byte{ var fileDescriptor_5465d80e8cba02e3 = []byte{
// 1289 bytes of a gzipped FileDescriptorProto // 1415 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0xcf, 0x6f, 0xdc, 0x44, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x57, 0xcf, 0x6f, 0xdb, 0xc6,
0x14, 0x5e, 0x67, 0x7f, 0x64, 0x77, 0x76, 0x93, 0x36, 0x2e, 0xad, 0x4c, 0x81, 0x9d, 0x65, 0x9a, 0x12, 0x36, 0x2d, 0xf9, 0x87, 0x56, 0xb2, 0x13, 0x33, 0x2f, 0x01, 0x9f, 0xdf, 0x7b, 0x5a, 0xbd,
0x4a, 0x0b, 0x48, 0x1b, 0x29, 0x55, 0x2b, 0x54, 0x09, 0xaa, 0xba, 0x51, 0xdb, 0x54, 0xa5, 0x45, 0x8d, 0x03, 0xa8, 0x2d, 0x20, 0x03, 0x0e, 0x62, 0x14, 0x01, 0xda, 0x20, 0x8c, 0xe1, 0xc4, 0x41,
0x93, 0xaa, 0x20, 0x2e, 0xab, 0xb5, 0x77, 0x92, 0x58, 0x75, 0xec, 0xc5, 0xe3, 0x34, 0xdd, 0xde, 0x9a, 0x14, 0xeb, 0x20, 0x2d, 0x7a, 0x11, 0xf8, 0x63, 0x2d, 0x13, 0xa1, 0x48, 0x95, 0x4b, 0xdb,
0xb8, 0x20, 0x71, 0x43, 0x15, 0x07, 0x84, 0x10, 0xea, 0x89, 0x3f, 0x81, 0xbf, 0xa1, 0xc7, 0x1c, 0x51, 0x6e, 0xbd, 0x14, 0xe8, 0x2d, 0x08, 0x7a, 0x28, 0x8a, 0xa2, 0xc8, 0xa9, 0x7f, 0x42, 0xff,
0x11, 0x07, 0x4b, 0x4d, 0x2e, 0xb0, 0xc7, 0x3d, 0x21, 0x4e, 0x68, 0xde, 0x8c, 0xc7, 0xb3, 0x8d, 0x82, 0x1e, 0x72, 0xf4, 0xb1, 0xe8, 0x81, 0x45, 0xec, 0x4b, 0xab, 0xa3, 0x4e, 0x45, 0x4f, 0xc5,
0x8a, 0xda, 0x92, 0x9b, 0xdf, 0xf7, 0xbe, 0xf7, 0x6c, 0xbf, 0xf9, 0xde, 0x9b, 0x87, 0xde, 0x0a, 0xce, 0x2e, 0x97, 0x54, 0x8c, 0x14, 0x49, 0xea, 0x1b, 0xe7, 0x9b, 0x6f, 0x46, 0xe4, 0xec, 0x37,
0x03, 0x6f, 0x65, 0xe8, 0xad, 0xf0, 0x34, 0xd9, 0xf5, 0x53, 0xde, 0x1b, 0x25, 0x71, 0x1a, 0xdb, 0xb3, 0x23, 0xf4, 0xaf, 0x30, 0x70, 0x57, 0x7d, 0x77, 0x95, 0xa7, 0xc9, 0x9e, 0x97, 0xf2, 0xce,
0x73, 0x43, 0xef, 0xec, 0xb9, 0x84, 0x8d, 0x62, 0xbe, 0x02, 0x80, 0xb7, 0xbb, 0xb9, 0xb2, 0x15, 0x20, 0x89, 0xd3, 0xd8, 0x9c, 0xf6, 0xdd, 0xe5, 0x8b, 0x09, 0x1b, 0xc4, 0x7c, 0x15, 0x00, 0x77,
0x6f, 0xc5, 0x60, 0xc0, 0x93, 0x24, 0x9e, 0x3d, 0x23, 0xc2, 0xe1, 0xd1, 0x8f, 0xc3, 0x15, 0x8f, 0x6f, 0x67, 0xb5, 0x17, 0xf7, 0x62, 0x30, 0xe0, 0x49, 0x12, 0x97, 0x71, 0x2f, 0x8e, 0x7b, 0x21,
0x8d, 0x14, 0xde, 0x60, 0x8f, 0x52, 0xf9, 0x48, 0x7e, 0x99, 0x43, 0xcd, 0xeb, 0x41, 0xc8, 0xee, 0x2b, 0x58, 0x69, 0xd0, 0x67, 0x3c, 0x75, 0xfa, 0x03, 0x45, 0xb8, 0x20, 0xf2, 0xc3, 0xa3, 0x17,
0xb3, 0x84, 0x07, 0x71, 0x64, 0xdf, 0x46, 0xf3, 0x0f, 0xe5, 0xa3, 0x63, 0x75, 0xac, 0x6e, 0x73, 0x87, 0xab, 0x2e, 0xcb, 0xf1, 0x1a, 0x7b, 0x94, 0xca, 0x47, 0xf2, 0xfd, 0x34, 0xaa, 0x6f, 0x06,
0xf5, 0x64, 0x2f, 0x4f, 0xd0, 0xbb, 0xcf, 0xfc, 0x34, 0x4e, 0xdc, 0xce, 0xb3, 0x0c, 0x97, 0x26, 0x21, 0x7b, 0xc0, 0x12, 0x1e, 0xc4, 0x91, 0x79, 0x07, 0xcd, 0xed, 0xcb, 0x47, 0xcb, 0x68, 0x19,
0x19, 0xce, 0x89, 0xd3, 0x0c, 0x2f, 0x3c, 0xda, 0x09, 0x2f, 0x13, 0x65, 0x13, 0x9a, 0x7b, 0xec, 0xed, 0xfa, 0xda, 0xd9, 0x4e, 0x9e, 0xa0, 0xf3, 0x80, 0x79, 0x69, 0x9c, 0xd8, 0xad, 0xe7, 0x19,
0x4b, 0x68, 0x7e, 0xc8, 0x42, 0x96, 0xb2, 0xa1, 0x33, 0xd7, 0xb1, 0xba, 0x75, 0xf7, 0x5d, 0x11, 0x9e, 0x1a, 0x65, 0x38, 0x27, 0x8e, 0x33, 0xbc, 0xf0, 0xa8, 0x1f, 0x5e, 0x25, 0xca, 0x26, 0x34,
0xa7, 0x20, 0x1d, 0xa7, 0x6c, 0x42, 0x73, 0x8f, 0x7d, 0x51, 0xc4, 0x3d, 0x0c, 0x7c, 0xc6, 0x9d, 0xf7, 0x98, 0xeb, 0x68, 0xce, 0x67, 0x21, 0x4b, 0x99, 0x6f, 0x4d, 0xb7, 0x8c, 0xf6, 0xbc, 0xfd,
0x72, 0xa7, 0xdc, 0x6d, 0xb9, 0xef, 0xc8, 0x38, 0x80, 0xa6, 0x19, 0x6e, 0xa9, 0x38, 0x61, 0x43, 0x5f, 0x11, 0xa7, 0x20, 0x1d, 0xa7, 0x6c, 0x42, 0x73, 0x8f, 0x79, 0x45, 0xc4, 0xed, 0x07, 0x1e,
0x18, 0x38, 0x6c, 0x8a, 0x4e, 0x04, 0xd1, 0xc3, 0x41, 0x18, 0x0c, 0xfb, 0x79, 0x78, 0x05, 0xc2, 0xe3, 0x56, 0xa5, 0x55, 0x69, 0x37, 0xec, 0xff, 0xc8, 0x38, 0x80, 0xc6, 0x19, 0x6e, 0xa8, 0x38,
0x3f, 0x98, 0x64, 0x78, 0x51, 0xb9, 0xd6, 0x74, 0x96, 0x53, 0x90, 0x65, 0x06, 0x26, 0xf4, 0x05, 0x61, 0x43, 0x18, 0x38, 0x4c, 0x8a, 0xce, 0x04, 0xd1, 0xbe, 0x13, 0x06, 0x7e, 0x37, 0x0f, 0xaf,
0x1a, 0xf9, 0xc6, 0x42, 0x4d, 0x55, 0x9c, 0xdb, 0x01, 0x4f, 0xed, 0x10, 0xd5, 0xd5, 0xdf, 0x71, 0x42, 0xf8, 0x3b, 0xa3, 0x0c, 0x2f, 0x2a, 0xd7, 0x86, 0xce, 0x72, 0x0e, 0xb2, 0x4c, 0xc0, 0x84,
0xc7, 0xea, 0x94, 0xbb, 0xcd, 0xd5, 0x13, 0xbd, 0xa1, 0xd7, 0x33, 0x6a, 0xe8, 0x5e, 0x11, 0x05, 0xbe, 0x44, 0x23, 0x5f, 0x18, 0xa8, 0xae, 0x8a, 0x73, 0x27, 0xe0, 0xa9, 0x19, 0xa2, 0x79, 0xf5,
0x3a, 0xc8, 0x70, 0x93, 0x0e, 0xf6, 0x14, 0xc6, 0x27, 0x19, 0xd6, 0x71, 0x47, 0x0a, 0xf6, 0x64, 0x75, 0xdc, 0x32, 0x5a, 0x95, 0x76, 0x7d, 0xed, 0x4c, 0xc7, 0x77, 0x3b, 0xa5, 0x1a, 0xda, 0xd7,
0x7f, 0xd9, 0xe4, 0x52, 0xcd, 0xbc, 0x5c, 0xf9, 0xf1, 0x29, 0x2e, 0x91, 0xbf, 0x11, 0x5a, 0x12, 0x44, 0x81, 0x8e, 0x32, 0x5c, 0xa7, 0xce, 0x81, 0xc2, 0xf8, 0x28, 0xc3, 0x3a, 0xee, 0x44, 0xc1,
0x2f, 0x58, 0x8f, 0x36, 0xe3, 0x7b, 0xc9, 0x6e, 0xe4, 0x0f, 0x44, 0x91, 0x3e, 0x44, 0x95, 0x68, 0x9e, 0x1e, 0xae, 0x94, 0xb9, 0x54, 0x33, 0xaf, 0x56, 0xbf, 0x79, 0x86, 0xa7, 0xc8, 0x1f, 0x08,
0xb0, 0xc3, 0xe0, 0x9c, 0x1a, 0xee, 0x99, 0x49, 0x86, 0xc1, 0x9e, 0x66, 0x18, 0x41, 0x76, 0x61, 0x2d, 0x89, 0x1f, 0xd8, 0x8a, 0x76, 0xe2, 0xfb, 0xc9, 0x5e, 0xe4, 0x39, 0xa2, 0x48, 0xef, 0xa2,
0x10, 0x0a, 0x98, 0xe0, 0xf2, 0xe0, 0x31, 0x73, 0xca, 0x1d, 0xab, 0x5b, 0x96, 0x5c, 0x61, 0x6b, 0x6a, 0xe4, 0xf4, 0x19, 0x9c, 0x53, 0xcd, 0xbe, 0x30, 0xca, 0x30, 0xd8, 0xe3, 0x0c, 0x23, 0xc8,
0xae, 0x30, 0x08, 0x05, 0xcc, 0xbe, 0x82, 0xd0, 0x4e, 0x3c, 0x0c, 0x36, 0x03, 0x36, 0xec, 0x73, 0x2e, 0x0c, 0x42, 0x01, 0x13, 0x5c, 0x1e, 0x3c, 0x66, 0x56, 0xa5, 0x65, 0xb4, 0x2b, 0x92, 0x2b,
0xa7, 0x0a, 0x11, 0x9d, 0x49, 0x86, 0x1b, 0x39, 0xba, 0x31, 0xcd, 0xf0, 0x09, 0x08, 0xd3, 0x08, 0x6c, 0xcd, 0x15, 0x06, 0xa1, 0x80, 0x99, 0xd7, 0x10, 0xea, 0xc7, 0x7e, 0xb0, 0x13, 0x30, 0xbf,
0xa1, 0x85, 0xd7, 0xfe, 0xcd, 0x42, 0x4d, 0x9d, 0xc1, 0x1b, 0x3b, 0xad, 0x8e, 0xd5, 0xad, 0xb8, 0xcb, 0xad, 0x19, 0x88, 0x68, 0x8d, 0x32, 0x5c, 0xcb, 0xd1, 0xed, 0x71, 0x86, 0xcf, 0x40, 0x98,
0x3f, 0x58, 0xa2, 0x2c, 0x7f, 0x64, 0xf8, 0xc2, 0x56, 0x90, 0x6e, 0xef, 0x7a, 0x3d, 0x3f, 0xde, 0x46, 0x08, 0x2d, 0xbc, 0xe6, 0x8f, 0x06, 0xaa, 0xeb, 0x0c, 0xee, 0xd0, 0x6a, 0xb4, 0x8c, 0x76,
0x59, 0xe1, 0xe3, 0xc8, 0x4f, 0xb7, 0x83, 0x68, 0xcb, 0x78, 0x32, 0x45, 0xdb, 0xdb, 0xd8, 0x8e, 0xd5, 0xfe, 0xda, 0x10, 0x65, 0xf9, 0x25, 0xc3, 0x97, 0x7b, 0x41, 0xba, 0xbb, 0xe7, 0x76, 0xbc,
0x93, 0x74, 0x7d, 0x6d, 0x92, 0x61, 0xfd, 0x51, 0xee, 0x78, 0x9a, 0xe1, 0x93, 0x33, 0xef, 0x77, 0xb8, 0xbf, 0xca, 0x87, 0x91, 0x97, 0xee, 0x06, 0x51, 0xaf, 0xf4, 0x54, 0x16, 0x6d, 0x67, 0x7b,
0xc7, 0xe4, 0xa7, 0xfd, 0xe5, 0x37, 0x49, 0x4c, 0x8d, 0xb4, 0xa6, 0xf8, 0x1b, 0xff, 0x5f, 0xfc, 0x37, 0x4e, 0xd2, 0xad, 0x8d, 0x51, 0x86, 0xf5, 0x4b, 0xd9, 0xc3, 0x71, 0x86, 0xcf, 0x4e, 0xfc,
0x97, 0x51, 0x9d, 0xb3, 0xaf, 0x77, 0x59, 0xe4, 0x33, 0x07, 0x41, 0x15, 0xdb, 0x42, 0x05, 0x39, 0xbe, 0x3d, 0x24, 0xdf, 0x1e, 0xae, 0xbc, 0x4d, 0x62, 0x5a, 0x4a, 0x5b, 0x16, 0x7f, 0xed, 0x9f,
0x36, 0xcd, 0xf0, 0xa2, 0xac, 0xbd, 0x02, 0x08, 0xd5, 0x3e, 0xfb, 0x2e, 0x5a, 0xe4, 0xe3, 0x9d, 0x8b, 0xff, 0x2a, 0x9a, 0xe7, 0xec, 0xf3, 0x3d, 0x16, 0x79, 0xcc, 0x42, 0x50, 0xc5, 0xa6, 0x50,
0x30, 0x88, 0x1e, 0xf4, 0xd3, 0x41, 0xb2, 0xc5, 0x52, 0x67, 0x09, 0x4e, 0xb9, 0x3b, 0xc9, 0xf0, 0x41, 0x8e, 0x8d, 0x33, 0xbc, 0x28, 0x6b, 0xaf, 0x00, 0x42, 0xb5, 0xcf, 0xbc, 0x87, 0x16, 0xf9,
0x82, 0xf2, 0xdc, 0x03, 0x87, 0xd6, 0xf1, 0x0c, 0x4a, 0xe8, 0x2c, 0xcb, 0xbe, 0x86, 0x9a, 0x5e, 0xb0, 0x1f, 0x06, 0xd1, 0xc3, 0x6e, 0xea, 0x24, 0x3d, 0x96, 0x5a, 0x4b, 0x70, 0xca, 0xed, 0x51,
0x18, 0xfb, 0x0f, 0x78, 0x7f, 0x7b, 0xc0, 0xb7, 0x1d, 0xbb, 0x63, 0x75, 0x5b, 0x2e, 0x11, 0x65, 0x86, 0x17, 0x94, 0xe7, 0x3e, 0x38, 0xb4, 0x8e, 0x27, 0x50, 0x42, 0x27, 0x59, 0xe6, 0x0d, 0x54,
0x95, 0xf0, 0xcd, 0x01, 0xdf, 0xd6, 0x65, 0x2d, 0x20, 0x42, 0x0d, 0xbf, 0xfd, 0x29, 0x6a, 0xb0, 0x77, 0xc3, 0xd8, 0x7b, 0xc8, 0xbb, 0xbb, 0x0e, 0xdf, 0xb5, 0xcc, 0x96, 0xd1, 0x6e, 0xd8, 0x44,
0xc8, 0x4f, 0xc6, 0x23, 0xd1, 0xd0, 0xa7, 0x20, 0x05, 0x08, 0x43, 0x83, 0x5a, 0x18, 0x1a, 0x21, 0x94, 0x55, 0xc2, 0xb7, 0x1c, 0xbe, 0xab, 0xcb, 0x5a, 0x40, 0x84, 0x96, 0xfc, 0xe6, 0x87, 0xa8,
0xb4, 0xf0, 0xda, 0x2e, 0xaa, 0xa4, 0xe3, 0x11, 0x83, 0x59, 0xb0, 0xb8, 0x7a, 0xa6, 0x28, 0xae, 0xc6, 0x22, 0x2f, 0x19, 0x0e, 0x44, 0x43, 0x9f, 0x83, 0x14, 0x20, 0x0c, 0x0d, 0x6a, 0x61, 0x68,
0x16, 0xf7, 0x78, 0xc4, 0xa4, 0x3a, 0x05, 0x4f, 0xab, 0x53, 0x18, 0x84, 0x02, 0x66, 0x5f, 0x47, 0x84, 0xd0, 0xc2, 0x6b, 0xda, 0xa8, 0x9a, 0x0e, 0x07, 0x0c, 0x66, 0xc1, 0xe2, 0xda, 0x85, 0xa2,
0xcd, 0x11, 0x4b, 0x76, 0x02, 0x2e, 0x5b, 0xb0, 0xd2, 0xb1, 0xba, 0x0b, 0xee, 0xf2, 0x24, 0xc3, 0xb8, 0x5a, 0xdc, 0xc3, 0x01, 0x93, 0xea, 0x14, 0x3c, 0xad, 0x4e, 0x61, 0x10, 0x0a, 0x98, 0xb9,
0x26, 0x3c, 0xcd, 0xf0, 0x12, 0x44, 0x1a, 0x18, 0xa1, 0x26, 0xc3, 0xbe, 0x65, 0x68, 0x34, 0xe2, 0x89, 0xea, 0x03, 0x96, 0xf4, 0x03, 0x2e, 0x5b, 0xb0, 0xda, 0x32, 0xda, 0x0b, 0xf6, 0xca, 0x28,
0x4e, 0xb3, 0x63, 0x75, 0xab, 0x30, 0x27, 0xb4, 0x20, 0xee, 0xf0, 0x23, 0x3a, 0xbb, 0xc3, 0xc9, 0xc3, 0x65, 0x78, 0x9c, 0xe1, 0x25, 0x88, 0x2c, 0x61, 0x84, 0x96, 0x19, 0xe6, 0xed, 0x92, 0x46,
0x3f, 0x19, 0x2e, 0x07, 0x51, 0x4a, 0x0d, 0x9a, 0xbd, 0x89, 0x64, 0x95, 0xfa, 0xd0, 0x63, 0x0b, 0x23, 0x6e, 0xd5, 0x5b, 0x46, 0x7b, 0x06, 0xe6, 0x84, 0x16, 0xc4, 0x5d, 0x7e, 0x42, 0x67, 0x77,
0x90, 0xea, 0xc6, 0x41, 0x86, 0x5b, 0x74, 0xb0, 0xe7, 0x0a, 0xc7, 0x46, 0xf0, 0x98, 0x89, 0x42, 0x39, 0xf9, 0x33, 0xc3, 0x95, 0x20, 0x4a, 0x69, 0x89, 0x66, 0xee, 0x20, 0x59, 0xa5, 0x2e, 0xf4,
0x79, 0xb9, 0xa1, 0x0b, 0xa5, 0x91, 0x3c, 0xf1, 0x93, 0xfd, 0xe5, 0x99, 0x30, 0x5a, 0x04, 0xd9, 0xd8, 0x02, 0xa4, 0xba, 0x79, 0x94, 0xe1, 0x06, 0x75, 0x0e, 0x6c, 0xe1, 0xd8, 0x0e, 0x1e, 0x33,
0x6b, 0xa8, 0x19, 0xc6, 0xfe, 0x20, 0xec, 0x6f, 0x86, 0x83, 0x2d, 0xee, 0xfc, 0x39, 0x0f, 0x3f, 0x51, 0x28, 0x37, 0x37, 0x74, 0xa1, 0x34, 0x92, 0x27, 0x7e, 0x7a, 0xb8, 0x32, 0x11, 0x46, 0x8b,
0x0f, 0xa7, 0x08, 0xf8, 0x75, 0x01, 0xeb, 0x8f, 0x2e, 0x20, 0x42, 0x0d, 0xbf, 0x7d, 0x13, 0xb5, 0x20, 0x73, 0x03, 0xd5, 0xc3, 0xd8, 0x73, 0xc2, 0xee, 0x4e, 0xe8, 0xf4, 0xb8, 0xf5, 0xdb, 0x1c,
0x94, 0x44, 0xa5, 0x16, 0xfe, 0x9a, 0x87, 0x93, 0x84, 0x1a, 0x2a, 0x87, 0x52, 0xc3, 0x92, 0xa9, 0x7c, 0x3c, 0x9c, 0x22, 0xe0, 0x9b, 0x02, 0xd6, 0x2f, 0x5d, 0x40, 0x84, 0x96, 0xfc, 0xe6, 0x2d,
0x6c, 0x29, 0x07, 0x93, 0x61, 0x8e, 0xf7, 0xda, 0xeb, 0x8c, 0x77, 0x8a, 0xe6, 0xd5, 0x94, 0x75, 0xd4, 0x50, 0x12, 0x95, 0x5a, 0xf8, 0x7d, 0x0e, 0x4e, 0x12, 0x6a, 0xa8, 0x1c, 0x4a, 0x0d, 0x4b,
0xe6, 0x21, 0xee, 0xe3, 0x83, 0x0c, 0x23, 0x3a, 0xd8, 0x5b, 0x97, 0xa8, 0xc8, 0xa2, 0x08, 0x3a, 0x65, 0x65, 0x4b, 0x39, 0x94, 0x19, 0xe5, 0xf1, 0x3e, 0xfb, 0x26, 0xe3, 0x9d, 0xa2, 0x39, 0x35,
0x8b, 0xb2, 0xc5, 0xac, 0x34, 0x98, 0x34, 0xe7, 0x89, 0x8e, 0x89, 0xe2, 0xbe, 0x29, 0x8d, 0x3a, 0x65, 0xad, 0x39, 0x88, 0x7b, 0xff, 0x28, 0xc3, 0x88, 0x3a, 0x07, 0x5b, 0x12, 0x15, 0x59, 0x14,
0xa4, 0x86, 0x8e, 0x89, 0xe2, 0xcf, 0x67, 0xc4, 0x21, 0x3b, 0x66, 0x06, 0x25, 0x74, 0x96, 0xa5, 0x41, 0x67, 0x51, 0xb6, 0x98, 0x95, 0x25, 0x26, 0xcd, 0x79, 0xa2, 0x63, 0xa2, 0xb8, 0x5b, 0x96,
0x46, 0xef, 0x17, 0xa8, 0x01, 0x47, 0x01, 0xb3, 0xff, 0x16, 0xaa, 0xc9, 0x6e, 0x50, 0x93, 0xff, 0xc6, 0x3c, 0xa4, 0x86, 0x8e, 0x89, 0xe2, 0x8f, 0x27, 0xc4, 0x21, 0x3b, 0x66, 0x02, 0x25, 0x74,
0x54, 0xa1, 0x60, 0x20, 0x09, 0x09, 0xbb, 0xef, 0xa9, 0x09, 0xa1, 0xa8, 0xd3, 0x0c, 0x37, 0x8b, 0x92, 0xa5, 0x46, 0xef, 0x27, 0xa8, 0x06, 0x47, 0x01, 0xb3, 0xff, 0x36, 0x9a, 0x95, 0xdd, 0xa0,
0x93, 0x26, 0x54, 0xc1, 0xe4, 0x57, 0x0b, 0x9d, 0x5e, 0x8f, 0x86, 0x41, 0xc2, 0xfc, 0x54, 0xd5, 0x26, 0xff, 0xb9, 0x42, 0xc1, 0x40, 0x12, 0x12, 0xb6, 0xff, 0xa7, 0x26, 0x84, 0xa2, 0x8e, 0x33,
0x93, 0xf1, 0xbb, 0x51, 0x38, 0x3e, 0x9e, 0x56, 0x3d, 0xb6, 0x43, 0x26, 0x3f, 0x57, 0x50, 0xed, 0x5c, 0x2f, 0x4e, 0x9a, 0x50, 0x05, 0x93, 0x1f, 0x0c, 0x74, 0x7e, 0x2b, 0xf2, 0x83, 0x84, 0x79,
0x5a, 0xbc, 0x1b, 0xa5, 0xdc, 0xbe, 0x88, 0xaa, 0x9b, 0x41, 0xc8, 0x38, 0x5c, 0x39, 0x55, 0x17, 0xa9, 0xaa, 0x27, 0xe3, 0xf7, 0xa2, 0x70, 0x78, 0x3a, 0xad, 0x7a, 0x6a, 0x87, 0x4c, 0xbe, 0xab,
0x4f, 0x32, 0x2c, 0x01, 0xfd, 0x93, 0x60, 0xe9, 0x1e, 0x91, 0x4e, 0xfb, 0x33, 0xd4, 0x94, 0xff, 0xa2, 0xd9, 0x1b, 0xf1, 0x5e, 0x94, 0x72, 0xf3, 0x0a, 0x9a, 0xd9, 0x09, 0x42, 0xc6, 0xe1, 0xca,
0x19, 0x27, 0x01, 0xe3, 0xd0, 0xfd, 0x55, 0xf7, 0x23, 0xf1, 0x25, 0x06, 0xac, 0xbf, 0xc4, 0xc0, 0x99, 0xb1, 0xf1, 0x28, 0xc3, 0x12, 0xd0, 0x1f, 0x09, 0x96, 0xee, 0x11, 0xe9, 0x34, 0x3f, 0x42,
0x74, 0x22, 0x93, 0x68, 0x5f, 0x45, 0x75, 0x35, 0xdb, 0x38, 0xdc, 0x67, 0x55, 0xf7, 0x3c, 0xcc, 0x75, 0xf9, 0x9d, 0x71, 0x12, 0x30, 0x0e, 0xdd, 0x3f, 0x63, 0xbf, 0x27, 0xde, 0xa4, 0x04, 0xeb,
0x55, 0x85, 0x15, 0x73, 0x55, 0x01, 0x3a, 0x8b, 0xa6, 0xd8, 0x9f, 0x14, 0xc2, 0xad, 0x40, 0x86, 0x37, 0x29, 0x61, 0x3a, 0x51, 0x99, 0x68, 0x5e, 0x47, 0xf3, 0x6a, 0xb6, 0x71, 0xb8, 0xcf, 0x66,
0x73, 0xff, 0x25, 0xdc, 0x3c, 0x5e, 0xeb, 0xb7, 0x87, 0xaa, 0xde, 0x38, 0x65, 0xf9, 0xe5, 0xe8, 0xec, 0x4b, 0x30, 0x57, 0x15, 0x56, 0xcc, 0x55, 0x05, 0xe8, 0x2c, 0x9a, 0x62, 0x7e, 0x50, 0x08,
0x88, 0x3a, 0x00, 0x50, 0x1c, 0xb6, 0xb0, 0x08, 0x95, 0xe8, 0xcc, 0x4d, 0x50, 0x7b, 0xcd, 0x9b, 0xb7, 0x0a, 0x19, 0x2e, 0xfe, 0x9d, 0x70, 0xf3, 0x78, 0xad, 0xdf, 0x0e, 0x9a, 0x71, 0x87, 0x29,
0x60, 0x03, 0x35, 0xe4, 0x2e, 0xd3, 0x0f, 0x86, 0x70, 0x09, 0xb4, 0xdc, 0x4b, 0x07, 0x19, 0xae, 0xcb, 0x2f, 0x47, 0x4b, 0xd4, 0x01, 0x80, 0xe2, 0xb0, 0x85, 0x45, 0xa8, 0x44, 0x27, 0x6e, 0x82,
0xcb, 0xfd, 0x04, 0x6e, 0xc6, 0xba, 0x24, 0xac, 0x0f, 0x75, 0xa2, 0x1c, 0x10, 0xdd, 0xa2, 0x99, 0xd9, 0x37, 0xbc, 0x09, 0xb6, 0x51, 0x4d, 0xee, 0x32, 0xdd, 0xc0, 0x87, 0x4b, 0xa0, 0x61, 0xaf,
0x54, 0xf3, 0x84, 0xc4, 0xcc, 0x41, 0x62, 0xbf, 0xc9, 0x1c, 0x51, 0x0d, 0xf2, 0xad, 0x85, 0x1a, 0x1f, 0x65, 0x78, 0x5e, 0xee, 0x27, 0x70, 0x33, 0xce, 0x4b, 0xc2, 0x96, 0xaf, 0x13, 0xe5, 0x80,
0x52, 0x1e, 0x1b, 0x2c, 0xb5, 0xaf, 0xa2, 0x9a, 0x0f, 0x86, 0xea, 0x10, 0x24, 0x76, 0x23, 0xe9, 0xe8, 0x16, 0xcd, 0xa4, 0x9a, 0x27, 0x24, 0x56, 0x1e, 0x24, 0xe6, 0xdb, 0xcc, 0x11, 0xd5, 0x20,
0x2e, 0x1a, 0x43, 0x32, 0x74, 0xad, 0xc0, 0x24, 0x54, 0xc1, 0x62, 0xa8, 0xf8, 0x09, 0x1b, 0xe4, 0x5f, 0x1a, 0xa8, 0x26, 0xe5, 0xb1, 0xcd, 0x52, 0xf3, 0x3a, 0x9a, 0xf5, 0xc0, 0x50, 0x1d, 0x82,
0x3b, 0x63, 0x59, 0x0e, 0x15, 0x05, 0xe9, 0xb3, 0x51, 0x36, 0xa1, 0xb9, 0x87, 0x7c, 0x37, 0x87, 0xc4, 0x6e, 0x24, 0xdd, 0x45, 0x63, 0x48, 0x86, 0xae, 0x15, 0x98, 0x84, 0x2a, 0x58, 0x0c, 0x15,
0x4e, 0x1b, 0x5b, 0xd8, 0x1a, 0x1b, 0x25, 0x4c, 0x2e, 0x4a, 0xc7, 0xbb, 0xd3, 0xae, 0xa2, 0x9a, 0x2f, 0x61, 0x4e, 0xbe, 0x33, 0x56, 0xe4, 0x50, 0x51, 0x90, 0x3e, 0x1b, 0x65, 0x13, 0x9a, 0x7b,
0xac, 0x23, 0x7c, 0x5e, 0xcb, 0x3d, 0x2b, 0x7e, 0x49, 0x22, 0x47, 0x36, 0x53, 0x85, 0x8b, 0x7f, 0xc8, 0x57, 0xd3, 0xe8, 0x7c, 0x69, 0x0b, 0xdb, 0x60, 0x83, 0x84, 0xc9, 0x45, 0xe9, 0x74, 0x77,
0xca, 0x07, 0x5e, 0xb9, 0x18, 0x94, 0x2f, 0x1b, 0x71, 0xc5, 0x50, 0xbb, 0x34, 0xab, 0xd3, 0x57, 0xda, 0x35, 0x34, 0x2b, 0xeb, 0x08, 0xaf, 0xd7, 0xb0, 0x97, 0xc5, 0x27, 0x49, 0xe4, 0xc4, 0x66,
0x1d, 0xb0, 0x64, 0x0f, 0x9d, 0x36, 0x76, 0x56, 0xa3, 0x14, 0x5f, 0x1e, 0xd9, 0x5e, 0xdf, 0x7e, 0xaa, 0x70, 0xf1, 0x4d, 0xf9, 0xc0, 0xab, 0x14, 0x83, 0xf2, 0x55, 0x23, 0xae, 0x18, 0x6a, 0xeb,
0x61, 0x7b, 0x2d, 0xc8, 0xee, 0xfb, 0xaa, 0x28, 0x2f, 0x5f, 0x5c, 0x5f, 0xdc, 0x54, 0xdd, 0x1b, 0x93, 0x3a, 0x7d, 0xdd, 0x01, 0x4b, 0x0e, 0xd0, 0xf9, 0xd2, 0xce, 0x5a, 0x2a, 0xc5, 0xa7, 0x27,
0xcf, 0x9e, 0xb7, 0x4b, 0xfb, 0xcf, 0xdb, 0xa5, 0x67, 0x07, 0x6d, 0x6b, 0xff, 0xa0, 0x6d, 0x7d, 0xb6, 0xd7, 0x7f, 0xbf, 0xb4, 0xbd, 0x16, 0x64, 0xfb, 0xff, 0xaa, 0x28, 0xaf, 0x5e, 0x5c, 0x4f,
0x7f, 0xd8, 0x2e, 0x3d, 0x3d, 0x6c, 0x5b, 0xfb, 0x87, 0xed, 0xd2, 0xef, 0x87, 0xed, 0xd2, 0x57, 0x6c, 0xaa, 0x4f, 0x0c, 0xb4, 0x78, 0xcf, 0xe5, 0x2c, 0xd9, 0x67, 0xfe, 0x66, 0x1c, 0xfa, 0x2c,
0xe7, 0x5f, 0x61, 0x49, 0x1b, 0x7a, 0x5e, 0x0d, 0x4e, 0xe8, 0xc2, 0xbf, 0x01, 0x00, 0x00, 0xff, 0x31, 0xef, 0xa2, 0xaa, 0xf8, 0x5f, 0xa2, 0x4a, 0xbf, 0xdc, 0x91, 0x7f, 0x5a, 0x3a, 0xf9, 0x9f,
0xff, 0xfc, 0x01, 0x79, 0xc2, 0x02, 0x0d, 0x00, 0x00, 0x96, 0xce, 0xfd, 0xfc, 0x4f, 0x8b, 0xdd, 0x54, 0xbf, 0x07, 0xfc, 0xe2, 0xf2, 0x0f, 0xfa, 0x8c,
0x3c, 0xf9, 0x15, 0x1b, 0x14, 0x70, 0xd1, 0x7c, 0xa1, 0xe3, 0xb2, 0x10, 0xca, 0x5f, 0x93, 0xcd,
0x07, 0x80, 0x16, 0x14, 0x58, 0x84, 0x4a, 0x94, 0xfc, 0x54, 0x7a, 0x25, 0xd9, 0x0a, 0xa7, 0xfe,
0x4a, 0xf9, 0x26, 0x3e, 0xfd, 0x1a, 0x9b, 0xf8, 0x3a, 0x9a, 0x73, 0x7c, 0x3f, 0x61, 0x5c, 0x0e,
0xaf, 0x9a, 0x3c, 0x52, 0x05, 0xe9, 0x02, 0x2b, 0x9b, 0xd0, 0xdc, 0x63, 0xdf, 0x7c, 0xfe, 0xa2,
0x39, 0x75, 0xf8, 0xa2, 0x39, 0xf5, 0xfc, 0xa8, 0x69, 0x1c, 0x1e, 0x35, 0x8d, 0x27, 0xc7, 0xcd,
0xa9, 0x67, 0xc7, 0x4d, 0xe3, 0xf0, 0xb8, 0x39, 0xf5, 0xf3, 0x71, 0x73, 0xea, 0xb3, 0x4b, 0xaf,
0xb1, 0xfe, 0xfa, 0xae, 0x3b, 0x0b, 0x9f, 0x79, 0xf9, 0xaf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x9e,
0xa0, 0xbe, 0xf2, 0x7d, 0x0e, 0x00, 0x00,
} }
func (m *FileVersion) Marshal() (dAtA []byte, err error) { func (m *FileVersion) Marshal() (dAtA []byte, err error) {
@ -1031,6 +1122,89 @@ func (m *VersionListDeprecated) MarshalToSizedBuffer(dAtA []byte) (int, error) {
return len(dAtA) - i, nil return len(dAtA) - i, nil
} }
func (m *ObservedFolder) Marshal() (dAtA []byte, err error) {
size := m.ProtoSize()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *ObservedFolder) MarshalTo(dAtA []byte) (int, error) {
size := m.ProtoSize()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *ObservedFolder) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.Label) > 0 {
i -= len(m.Label)
copy(dAtA[i:], m.Label)
i = encodeVarintStructs(dAtA, i, uint64(len(m.Label)))
i--
dAtA[i] = 0x12
}
n4, err4 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):])
if err4 != nil {
return 0, err4
}
i -= n4
i = encodeVarintStructs(dAtA, i, uint64(n4))
i--
dAtA[i] = 0xa
return len(dAtA) - i, nil
}
func (m *ObservedDevice) Marshal() (dAtA []byte, err error) {
size := m.ProtoSize()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *ObservedDevice) MarshalTo(dAtA []byte) (int, error) {
size := m.ProtoSize()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *ObservedDevice) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.Address) > 0 {
i -= len(m.Address)
copy(dAtA[i:], m.Address)
i = encodeVarintStructs(dAtA, i, uint64(len(m.Address)))
i--
dAtA[i] = 0x1a
}
if len(m.Name) > 0 {
i -= len(m.Name)
copy(dAtA[i:], m.Name)
i = encodeVarintStructs(dAtA, i, uint64(len(m.Name)))
i--
dAtA[i] = 0x12
}
n5, err5 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):])
if err5 != nil {
return 0, err5
}
i -= n5
i = encodeVarintStructs(dAtA, i, uint64(n5))
i--
dAtA[i] = 0xa
return len(dAtA) - i, nil
}
func encodeVarintStructs(dAtA []byte, offset int, v uint64) int { func encodeVarintStructs(dAtA []byte, offset int, v uint64) int {
offset -= sovStructs(v) offset -= sovStructs(v)
base := offset base := offset
@ -1270,6 +1444,40 @@ func (m *VersionListDeprecated) ProtoSize() (n int) {
return n return n
} }
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 + sovStructs(uint64(l))
l = len(m.Label)
if l > 0 {
n += 1 + l + sovStructs(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 + sovStructs(uint64(l))
l = len(m.Name)
if l > 0 {
n += 1 + l + sovStructs(uint64(l))
}
l = len(m.Address)
if l > 0 {
n += 1 + l + sovStructs(uint64(l))
}
return n
}
func sovStructs(x uint64) (n int) { func sovStructs(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7 return (math_bits.Len64(x|1) + 6) / 7
} }
@ -2797,6 +3005,274 @@ func (m *VersionListDeprecated) Unmarshal(dAtA []byte) error {
} }
return nil return nil
} }
func (m *ObservedFolder) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowStructs
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: ObservedFolder: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: ObservedFolder: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowStructs
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthStructs
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthStructs
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Label", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowStructs
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthStructs
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthStructs
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Label = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipStructs(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthStructs
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthStructs
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *ObservedDevice) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowStructs
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: ObservedDevice: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: ObservedDevice: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowStructs
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthStructs
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthStructs
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowStructs
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthStructs
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthStructs
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Name = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowStructs
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthStructs
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthStructs
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Address = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipStructs(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthStructs
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthStructs
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipStructs(dAtA []byte) (n int, err error) { func skipStructs(dAtA []byte) (n int, err error) {
l := len(dAtA) l := len(dAtA)
iNdEx := 0 iNdEx := 0

View File

@ -105,6 +105,9 @@ type Model interface {
FolderStatistics() (map[string]stats.FolderStatistics, error) FolderStatistics() (map[string]stats.FolderStatistics, error)
UsageReportingStats(report *contract.Report, version int, preview bool) UsageReportingStats(report *contract.Report, version int, preview bool)
PendingDevices() (map[protocol.DeviceID]db.ObservedDevice, error)
PendingFolders(device protocol.DeviceID) (map[string]db.PendingFolder, error)
StartDeadlockDetector(timeout time.Duration) StartDeadlockDetector(timeout time.Duration)
GlobalDirectoryTree(folder, prefix string, levels int, dirsonly bool) map[string]interface{} GlobalDirectoryTree(folder, prefix string, levels int, dirsonly bool) map[string]interface{}
} }
@ -255,8 +258,10 @@ func NewModel(cfg config.Wrapper, id protocol.DeviceID, clientName, clientVersio
func (m *model) serve(ctx context.Context) error { func (m *model) serve(ctx context.Context) error {
// Add and start folders // Add and start folders
cacheIgnoredFiles := m.cfg.Options().CacheIgnoredFiles cacheIgnoredFiles := m.cfg.Options().CacheIgnoredFiles
clusterConfigDevices := make(deviceIDSet, len(m.cfg.Devices())) existingDevices := m.cfg.Devices()
for _, folderCfg := range m.cfg.Folders() { existingFolders := m.cfg.Folders()
clusterConfigDevices := make(deviceIDSet, len(existingDevices))
for _, folderCfg := range existingFolders {
if folderCfg.Paused { if folderCfg.Paused {
folderCfg.CreateRoot() folderCfg.CreateRoot()
continue continue
@ -264,6 +269,10 @@ func (m *model) serve(ctx context.Context) error {
m.newFolder(folderCfg, cacheIgnoredFiles) m.newFolder(folderCfg, cacheIgnoredFiles)
clusterConfigDevices.add(folderCfg.DeviceIDs()) clusterConfigDevices.add(folderCfg.DeviceIDs())
} }
ignoredDevices := observedDeviceSet(m.cfg.IgnoredDevices())
m.cleanPending(existingDevices, existingFolders, ignoredDevices, nil)
m.resendClusterConfig(clusterConfigDevices.AsSlice()) m.resendClusterConfig(clusterConfigDevices.AsSlice())
m.cfg.Subscribe(m) m.cfg.Subscribe(m)
@ -1251,9 +1260,10 @@ func (m *model) ccHandleFolders(folders []protocol.Folder, deviceCfg config.Devi
l.Infof("Ignoring folder %s from device %s since we are configured to", folder.Description(), deviceID) l.Infof("Ignoring folder %s from device %s since we are configured to", folder.Description(), deviceID)
continue continue
} }
m.cfg.AddOrUpdatePendingFolder(folder.ID, folder.Label, deviceID) if err := m.db.AddOrUpdatePendingFolder(folder.ID, folder.Label, deviceID); err != nil {
l.Warnf("Failed to persist pending folder entry to database: %v", err)
}
indexSenders.addPending(cfg, ccDeviceInfos[folder.ID]) indexSenders.addPending(cfg, ccDeviceInfos[folder.ID])
changed = true
m.evLogger.Log(events.FolderRejected, map[string]string{ m.evLogger.Log(events.FolderRejected, map[string]string{
"folder": folder.ID, "folder": folder.ID,
"folderLabel": folder.Label, "folderLabel": folder.Label,
@ -1989,8 +1999,9 @@ func (m *model) OnHello(remoteID protocol.DeviceID, addr net.Addr, hello protoco
cfg, ok := m.cfg.Device(remoteID) cfg, ok := m.cfg.Device(remoteID)
if !ok { if !ok {
m.cfg.AddOrUpdatePendingDevice(remoteID, hello.DeviceName, addr.String()) if err := m.db.AddOrUpdatePendingDevice(remoteID, hello.DeviceName, addr.String()); err != nil {
_ = m.cfg.Save() // best effort l.Warnf("Failed to persist pending device entry to database: %v", err)
}
m.evLogger.Log(events.DeviceRejected, map[string]string{ m.evLogger.Log(events.DeviceRejected, map[string]string{
"name": hello.DeviceName, "name": hello.DeviceName,
"device": remoteID.String(), "device": remoteID.String(),
@ -2577,12 +2588,14 @@ func (m *model) CommitConfiguration(from, to config.Configuration) bool {
} }
} }
removedFolders := make(map[string]struct{})
for folderID, fromCfg := range fromFolders { for folderID, fromCfg := range fromFolders {
toCfg, ok := toFolders[folderID] toCfg, ok := toFolders[folderID]
if !ok { if !ok {
// The folder was removed. // The folder was removed.
m.removeFolder(fromCfg) m.removeFolder(fromCfg)
clusterConfigDevices.add(fromCfg.DeviceIDs()) clusterConfigDevices.add(fromCfg.DeviceIDs())
removedFolders[fromCfg.ID] = struct{}{}
continue continue
} }
@ -2647,6 +2660,7 @@ func (m *model) CommitConfiguration(from, to config.Configuration) bool {
m.evLogger.Log(events.DeviceResumed, map[string]string{"device": deviceID.String()}) m.evLogger.Log(events.DeviceResumed, map[string]string{"device": deviceID.String()})
} }
} }
// Clean up after removed devices
removedDevices := make([]protocol.DeviceID, 0, len(fromDevices)) removedDevices := make([]protocol.DeviceID, 0, len(fromDevices))
m.fmut.Lock() m.fmut.Lock()
for deviceID := range fromDevices { for deviceID := range fromDevices {
@ -2671,6 +2685,9 @@ func (m *model) CommitConfiguration(from, to config.Configuration) bool {
// Generating cluster-configs acquires fmut -> must happen outside of pmut. // Generating cluster-configs acquires fmut -> must happen outside of pmut.
m.resendClusterConfig(clusterConfigDevices.AsSlice()) m.resendClusterConfig(clusterConfigDevices.AsSlice())
ignoredDevices := observedDeviceSet(to.IgnoredDevices)
m.cleanPending(toDevices, toFolders, ignoredDevices, removedFolders)
m.globalRequestLimiter.setCapacity(1024 * to.Options.MaxConcurrentIncomingRequestKiB()) m.globalRequestLimiter.setCapacity(1024 * to.Options.MaxConcurrentIncomingRequestKiB())
m.folderIOLimiter.setCapacity(to.Options.MaxFolderConcurrency()) m.folderIOLimiter.setCapacity(to.Options.MaxFolderConcurrency())
@ -2685,6 +2702,59 @@ func (m *model) CommitConfiguration(from, to config.Configuration) bool {
return true return true
} }
func (m *model) cleanPending(existingDevices map[protocol.DeviceID]config.DeviceConfiguration, existingFolders map[string]config.FolderConfiguration, ignoredDevices deviceIDSet, removedFolders map[string]struct{}) {
pendingFolders, err := m.db.PendingFolders()
if err != nil {
l.Infof("Could not iterate through pending folder entries for cleanup: %v", err)
// Continue with pending devices below, loop is skipped.
}
for folderID, pf := range pendingFolders {
if _, ok := removedFolders[folderID]; ok {
// Forget pending folder device associations for recently removed
// folders as well, assuming the folder is no longer of interest
// at all (but might become pending again).
l.Debugf("Discarding pending removed folder %v from all devices", folderID)
m.db.RemovePendingFolder(folderID)
continue
}
for deviceID := range pf.OfferedBy {
if dev, ok := existingDevices[deviceID]; !ok {
l.Debugf("Discarding pending folder %v from unknown device %v", folderID, deviceID)
m.db.RemovePendingFolderForDevice(folderID, deviceID)
continue
} else if dev.IgnoredFolder(folderID) {
l.Debugf("Discarding now ignored pending folder %v for device %v", folderID, deviceID)
m.db.RemovePendingFolderForDevice(folderID, deviceID)
continue
}
if folderCfg, ok := existingFolders[folderID]; ok {
if folderCfg.SharedWith(deviceID) {
l.Debugf("Discarding now shared pending folder %v for device %v", folderID, deviceID)
m.db.RemovePendingFolderForDevice(folderID, deviceID)
}
}
}
}
pendingDevices, err := m.db.PendingDevices()
if err != nil {
l.Infof("Could not iterate through pending device entries for cleanup: %v", err)
return
}
for deviceID := range pendingDevices {
if _, ok := ignoredDevices[deviceID]; ok {
l.Debugf("Discarding now ignored pending device %v", deviceID)
m.db.RemovePendingDevice(deviceID)
continue
}
if _, ok := existingDevices[deviceID]; ok {
l.Debugf("Discarding now added pending device %v", deviceID)
m.db.RemovePendingDevice(deviceID)
continue
}
}
}
// checkFolderRunningLocked returns nil if the folder is up and running and a // checkFolderRunningLocked returns nil if the folder is up and running and a
// descriptive error if not. // descriptive error if not.
// Need to hold (read) lock on m.fmut when calling this. // Need to hold (read) lock on m.fmut when calling this.
@ -2703,6 +2773,18 @@ func (m *model) checkFolderRunningLocked(folder string) error {
return errFolderNotRunning return errFolderNotRunning
} }
// PendingDevices lists unknown devices that tried to connect.
func (m *model) PendingDevices() (map[protocol.DeviceID]db.ObservedDevice, error) {
return m.db.PendingDevices()
}
// PendingFolders lists folders that we don't yet share with the offering devices. It
// returns the entries grouped by folder and filters for a given device unless the
// argument is specified as EmptyDeviceID.
func (m *model) PendingFolders(device protocol.DeviceID) (map[string]db.PendingFolder, error) {
return m.db.PendingFoldersForDevice(device)
}
// mapFolders returns a map of folder ID to folder configuration for the given // mapFolders returns a map of folder ID to folder configuration for the given
// slice of folder configurations. // slice of folder configurations.
func mapFolders(folders []config.FolderConfiguration) map[string]config.FolderConfiguration { func mapFolders(folders []config.FolderConfiguration) map[string]config.FolderConfiguration {
@ -2723,6 +2805,14 @@ func mapDevices(devices []protocol.DeviceID) map[protocol.DeviceID]struct{} {
return m return m
} }
func observedDeviceSet(devices []config.ObservedDevice) deviceIDSet {
res := make(deviceIDSet, len(devices))
for _, dev := range devices {
res[dev.ID] = struct{}{}
}
return res
}
func readOffsetIntoBuf(fs fs.Filesystem, file string, offset int64, buf []byte) error { func readOffsetIntoBuf(fs fs.Filesystem, file string, offset int64, buf []byte) error {
fd, err := fs.Open(file) fd, err := fs.Open(file)
if err != nil { if err != nil {

View File

@ -4323,6 +4323,78 @@ func TestCCFolderNotRunning(t *testing.T) {
} }
} }
func TestPendingFolder(t *testing.T) {
w, _ := tmpDefaultWrapper()
m := setupModel(w)
defer cleanupModel(m)
waiter, err := w.SetDevice(config.DeviceConfiguration{DeviceID: device2})
if err != nil {
t.Fatal(err)
}
waiter.Wait()
pfolder := "default"
if err := m.db.AddOrUpdatePendingFolder(pfolder, pfolder, device2); err != nil {
t.Fatal(err)
}
deviceFolders, err := m.PendingFolders(protocol.EmptyDeviceID)
if err != nil {
t.Fatal(err)
} else if pf, ok := deviceFolders[pfolder]; !ok {
t.Errorf("folder %v not pending", pfolder)
} else if _, ok := pf.OfferedBy[device2]; !ok {
t.Errorf("folder %v not pending for device %v", pfolder, device2)
} else if len(pf.OfferedBy) > 1 {
t.Errorf("folder %v pending for too many devices %v", pfolder, pf.OfferedBy)
}
device3, err := protocol.DeviceIDFromString("AIBAEAQ-CAIBAEC-AQCAIBA-EAQCAIA-BAEAQCA-IBAEAQC-CAIBAEA-QCAIBA7")
waiter, err = w.SetDevice(config.DeviceConfiguration{DeviceID: device3})
if err != nil {
t.Fatal(err)
}
waiter.Wait()
if err := m.db.AddOrUpdatePendingFolder(pfolder, pfolder, device3); err != nil {
t.Fatal(err)
}
deviceFolders, err = m.PendingFolders(device2)
if err != nil {
t.Fatal(err)
} else if pf, ok := deviceFolders[pfolder]; !ok {
t.Errorf("folder %v not pending when filtered", pfolder)
} else if _, ok := pf.OfferedBy[device2]; !ok {
t.Errorf("folder %v not pending for device %v when filtered", pfolder, device2)
} else if _, ok := pf.OfferedBy[device3]; ok {
t.Errorf("folder %v pending for device %v, but not filtered out", pfolder, device3)
}
waiter, err = w.RemoveDevice(device3)
if err != nil {
t.Fatal(err)
}
waiter.Wait()
deviceFolders, err = m.PendingFolders(protocol.EmptyDeviceID)
if err != nil {
t.Fatal(err)
} else if pf, ok := deviceFolders[pfolder]; !ok {
t.Errorf("folder %v not pending", pfolder)
} else if _, ok := pf.OfferedBy[device3]; ok {
t.Errorf("folder %v pending for removed device %v", pfolder, device3)
}
waiter, err = w.RemoveFolder(pfolder)
if err != nil {
t.Fatal(err)
}
waiter.Wait()
deviceFolders, err = m.PendingFolders(protocol.EmptyDeviceID)
if err != nil {
t.Fatal(err)
} else if _, ok := deviceFolders[pfolder]; ok {
t.Errorf("folder %v still pending after local removal", pfolder)
}
}
func equalStringsInAnyOrder(a, b []string) bool { func equalStringsInAnyOrder(a, b []string) bool {
if len(a) != len(b) { if len(a) != len(b) {
return false return false

View File

@ -19,5 +19,5 @@ message Configuration {
LDAPConfiguration ldap = 5 [(ext.goname) = "LDAP"]; LDAPConfiguration ldap = 5 [(ext.goname) = "LDAP"];
OptionsConfiguration options = 6; OptionsConfiguration options = 6;
repeated ObservedDevice ignored_devices = 7 [(ext.json) = "remoteIgnoredDevices", (ext.xml) = "remoteIgnoredDevice"]; repeated ObservedDevice ignored_devices = 7 [(ext.json) = "remoteIgnoredDevices", (ext.xml) = "remoteIgnoredDevice"];
repeated ObservedDevice pending_devices = 8; repeated ObservedDevice pending_devices = 8 [deprecated=true];
} }

View File

@ -22,7 +22,7 @@ message DeviceConfiguration {
int32 max_send_kbps = 12; int32 max_send_kbps = 12;
int32 max_recv_kbps = 13; int32 max_recv_kbps = 13;
repeated ObservedFolder ignored_folders = 14; repeated ObservedFolder ignored_folders = 14;
repeated ObservedFolder pending_folders = 15; repeated ObservedFolder pending_folders = 15 [deprecated = true];
int32 max_request_kib = 16 [(ext.goname) = "MaxRequestKiB", (ext.xml) = "maxRequestKiB", (ext.json) = "maxRequestKiB"]; int32 max_request_kib = 16 [(ext.goname) = "MaxRequestKiB", (ext.xml) = "maxRequestKiB", (ext.json) = "maxRequestKiB"];
bool untrusted = 17; bool untrusted = 17;
int32 remote_gui_port = 18 [(ext.goname) = "RemoteGUIPort", (ext.xml) = "remoteGUIPort", (ext.json) = "remoteGUIPort"]; int32 remote_gui_port = 18 [(ext.goname) = "RemoteGUIPort", (ext.xml) = "remoteGUIPort", (ext.json) = "remoteGUIPort"];

View File

@ -3,6 +3,7 @@ syntax = "proto3";
package db; package db;
import "repos/protobuf/gogoproto/gogo.proto"; import "repos/protobuf/gogoproto/gogo.proto";
import "google/protobuf/timestamp.proto";
import "lib/protocol/bep.proto"; import "lib/protocol/bep.proto";
import "ext.proto"; import "ext.proto";
@ -88,3 +89,14 @@ message VersionListDeprecated {
option (gogoproto.goproto_stringer) = false; option (gogoproto.goproto_stringer) = false;
repeated FileVersionDeprecated versions = 1; repeated FileVersionDeprecated versions = 1;
} }
message ObservedFolder {
google.protobuf.Timestamp time = 1 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false];
string label = 2;
}
message ObservedDevice {
google.protobuf.Timestamp time = 1 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false];
string name = 2;
string address = 3;
}