summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJakob Borg <jakob@kastelo.net>2024-01-31 08:18:27 +0100
committerGitHub <noreply@github.com>2024-01-31 08:18:27 +0100
commitbda4016109a7492110ce8231d751521101af52f8 (patch)
tree808f9ddbfe56b1d3007e547bf73f8ebc285a3c38
parent8f5d07bd092990ceeb5d7f6b496e67ed5680a82f (diff)
lib/protocol: Refactor interface (#9375)
This is a refactor of the protocol/model interface to take the actual message as the parameter, instead of the broken-out fields: ```diff type Model interface { // An index was received from the peer device - Index(conn Connection, folder string, files []FileInfo) error + Index(conn Connection, idx *Index) error // An index update was received from the peer device - IndexUpdate(conn Connection, folder string, files []FileInfo) error + IndexUpdate(conn Connection, idxUp *IndexUpdate) error // A request was made by the peer device - Request(conn Connection, folder, name string, blockNo, size int32, offset int64, hash []byte, weakHash uint32, fromTemporary bool) (RequestResponse, error) + Request(conn Connection, req *Request) (RequestResponse, error) // A cluster configuration message was received - ClusterConfig(conn Connection, config ClusterConfig) error + ClusterConfig(conn Connection, config *ClusterConfig) error // The peer device closed the connection or an error occurred Closed(conn Connection, err error) // The peer device sent progress updates for the files it is currently downloading - DownloadProgress(conn Connection, folder string, updates []FileDownloadProgressUpdate) error + DownloadProgress(conn Connection, p *DownloadProgress) error } ``` (and changing the `ClusterConfig` to `*ClusterConfig` for symmetry; we'll be forced to use all pointers everywhere at some point anyway...) The reason for this is that I have another thing cooking which is a small troubleshooting change to check index consistency during transfer. This required adding a field or two to the index/indexupdate messages, and plumbing the extra parameters in umpteen changes is almost as big a diff as this is. I figured let's do it once and avoid having to do that in the future again... The rest of the diff falls out of the change above, much of it being in test code where we run these methods manually...
-rw-r--r--lib/model/fakeconns_test.go4
-rw-r--r--lib/model/folder_recvonly_test.go16
-rw-r--r--lib/model/folder_sendrecv_test.go2
-rw-r--r--lib/model/mocks/model.go132
-rw-r--r--lib/model/model.go84
-rw-r--r--lib/model/model_test.go94
-rw-r--r--lib/model/requests_test.go14
-rw-r--r--lib/model/testutils_test.go4
-rw-r--r--lib/protocol/benchmark_test.go14
-rw-r--r--lib/protocol/common_test.go28
-rw-r--r--lib/protocol/encryption.go50
-rw-r--r--lib/protocol/nativemodel_darwin.go22
-rw-r--r--lib/protocol/nativemodel_windows.go22
-rw-r--r--lib/protocol/protocol.go64
-rw-r--r--lib/protocol/protocol_test.go2
15 files changed, 259 insertions, 293 deletions
diff --git a/lib/model/fakeconns_test.go b/lib/model/fakeconns_test.go
index 9255d6eab..99179c6fe 100644
--- a/lib/model/fakeconns_test.go
+++ b/lib/model/fakeconns_test.go
@@ -160,7 +160,7 @@ func (f *fakeConnection) sendIndexUpdate() {
for i := range f.files {
toSend[i] = prepareFileInfoForIndex(f.files[i])
}
- f.model.IndexUpdate(f, f.folder, toSend)
+ f.model.IndexUpdate(f, &protocol.IndexUpdate{Folder: f.folder, Files: toSend})
}
func addFakeConn(m *testModel, dev protocol.DeviceID, folderID string) *fakeConnection {
@@ -168,7 +168,7 @@ func addFakeConn(m *testModel, dev protocol.DeviceID, folderID string) *fakeConn
fc.folder = folderID
m.AddConnection(fc, protocol.Hello{})
- m.ClusterConfig(fc, protocol.ClusterConfig{
+ m.ClusterConfig(fc, &protocol.ClusterConfig{
Folders: []protocol.Folder{
{
ID: folderID,
diff --git a/lib/model/folder_recvonly_test.go b/lib/model/folder_recvonly_test.go
index 72383bd62..b3c9800b3 100644
--- a/lib/model/folder_recvonly_test.go
+++ b/lib/model/folder_recvonly_test.go
@@ -45,7 +45,7 @@ func TestRecvOnlyRevertDeletes(t *testing.T) {
// Send and index update for the known stuff
- must(t, m.Index(conn, "ro", knownFiles))
+ must(t, m.Index(conn, &protocol.Index{Folder: "ro", Files: knownFiles}))
f.updateLocalsFromScanning(knownFiles)
size := globalSize(t, m, "ro")
@@ -122,7 +122,7 @@ func TestRecvOnlyRevertNeeds(t *testing.T) {
// Send and index update for the known stuff
- must(t, m.Index(conn, "ro", knownFiles))
+ must(t, m.Index(conn, &protocol.Index{Folder: "ro", Files: knownFiles}))
f.updateLocalsFromScanning(knownFiles)
// Scan the folder.
@@ -212,7 +212,7 @@ func TestRecvOnlyUndoChanges(t *testing.T) {
// Send an index update for the known stuff
- must(t, m.Index(conn, "ro", knownFiles))
+ must(t, m.Index(conn, &protocol.Index{Folder: "ro", Files: knownFiles}))
f.updateLocalsFromScanning(knownFiles)
// Scan the folder.
@@ -282,7 +282,7 @@ func TestRecvOnlyDeletedRemoteDrop(t *testing.T) {
// Send an index update for the known stuff
- must(t, m.Index(conn, "ro", knownFiles))
+ must(t, m.Index(conn, &protocol.Index{Folder: "ro", Files: knownFiles}))
f.updateLocalsFromScanning(knownFiles)
// Scan the folder.
@@ -347,7 +347,7 @@ func TestRecvOnlyRemoteUndoChanges(t *testing.T) {
// Send an index update for the known stuff
- must(t, m.Index(conn, "ro", knownFiles))
+ must(t, m.Index(conn, &protocol.Index{Folder: "ro", Files: knownFiles}))
f.updateLocalsFromScanning(knownFiles)
// Scan the folder.
@@ -402,7 +402,7 @@ func TestRecvOnlyRemoteUndoChanges(t *testing.T) {
return true
})
snap.Release()
- must(t, m.IndexUpdate(conn, "ro", files))
+ must(t, m.IndexUpdate(conn, &protocol.IndexUpdate{Folder: "ro", Files: files}))
// Ensure the pull to resolve conflicts (content identical) happened
must(t, f.doInSync(func() error {
@@ -470,7 +470,7 @@ func TestRecvOnlyRevertOwnID(t *testing.T) {
}()
// Receive an index update with an older version, but valid and then revert
- must(t, m.Index(conn, f.ID, []protocol.FileInfo{fi}))
+ must(t, m.Index(conn, &protocol.Index{Folder: f.ID, Files: []protocol.FileInfo{fi}}))
f.Revert()
select {
@@ -497,7 +497,7 @@ func TestRecvOnlyLocalChangeDoesNotCauseConflict(t *testing.T) {
// Send an index update for the known stuff
- must(t, m.Index(conn, "ro", knownFiles))
+ must(t, m.Index(conn, &protocol.Index{Folder: "ro", Files: knownFiles}))
f.updateLocalsFromScanning(knownFiles)
// Scan the folder.
diff --git a/lib/model/folder_sendrecv_test.go b/lib/model/folder_sendrecv_test.go
index 11b6e01f1..2c9d12866 100644
--- a/lib/model/folder_sendrecv_test.go
+++ b/lib/model/folder_sendrecv_test.go
@@ -1297,7 +1297,7 @@ func TestPullSymlinkOverExistingWindows(t *testing.T) {
if !ok {
t.Fatal("file missing")
}
- must(t, m.Index(conn, f.ID, []protocol.FileInfo{{Name: name, Type: protocol.FileInfoTypeSymlink, Version: file.Version.Update(device1.Short())}}))
+ must(t, m.Index(conn, &protocol.Index{Folder: f.ID, Files: []protocol.FileInfo{{Name: name, Type: protocol.FileInfoTypeSymlink, Version: file.Version.Update(device1.Short())}}}))
scanChan := make(chan string)
diff --git a/lib/model/mocks/model.go b/lib/model/mocks/model.go
index bfb7a07a4..2049b6567 100644
--- a/lib/model/mocks/model.go
+++ b/lib/model/mocks/model.go
@@ -50,11 +50,11 @@ type Model struct {
arg1 protocol.Connection
arg2 error
}
- ClusterConfigStub func(protocol.Connection, protocol.ClusterConfig) error
+ ClusterConfigStub func(protocol.Connection, *protocol.ClusterConfig) error
clusterConfigMutex sync.RWMutex
clusterConfigArgsForCall []struct {
arg1 protocol.Connection
- arg2 protocol.ClusterConfig
+ arg2 *protocol.ClusterConfig
}
clusterConfigReturns struct {
result1 error
@@ -198,12 +198,11 @@ type Model struct {
dismissPendingFolderReturnsOnCall map[int]struct {
result1 error
}
- DownloadProgressStub func(protocol.Connection, string, []protocol.FileDownloadProgressUpdate) error
+ DownloadProgressStub func(protocol.Connection, *protocol.DownloadProgress) error
downloadProgressMutex sync.RWMutex
downloadProgressArgsForCall []struct {
arg1 protocol.Connection
- arg2 string
- arg3 []protocol.FileDownloadProgressUpdate
+ arg2 *protocol.DownloadProgress
}
downloadProgressReturns struct {
result1 error
@@ -290,12 +289,11 @@ type Model struct {
result1 []*model.TreeEntry
result2 error
}
- IndexStub func(protocol.Connection, string, []protocol.FileInfo) error
+ IndexStub func(protocol.Connection, *protocol.Index) error
indexMutex sync.RWMutex
indexArgsForCall []struct {
arg1 protocol.Connection
- arg2 string
- arg3 []protocol.FileInfo
+ arg2 *protocol.Index
}
indexReturns struct {
result1 error
@@ -303,12 +301,11 @@ type Model struct {
indexReturnsOnCall map[int]struct {
result1 error
}
- IndexUpdateStub func(protocol.Connection, string, []protocol.FileInfo) error
+ IndexUpdateStub func(protocol.Connection, *protocol.IndexUpdate) error
indexUpdateMutex sync.RWMutex
indexUpdateArgsForCall []struct {
arg1 protocol.Connection
- arg2 string
- arg3 []protocol.FileInfo
+ arg2 *protocol.IndexUpdate
}
indexUpdateReturns struct {
result1 error
@@ -424,18 +421,11 @@ type Model struct {
result1 []db.FileInfoTruncated
result2 error
}
- RequestStub func(protocol.Connection, string, string, int32, int32, int64, []byte, uint32, bool) (protocol.RequestResponse, error)
+ RequestStub func(protocol.Connection, *protocol.Request) (protocol.RequestResponse, error)
requestMutex sync.RWMutex
requestArgsForCall []struct {
arg1 protocol.Connection
- arg2 string
- arg3 string
- arg4 int32
- arg5 int32
- arg6 int64
- arg7 []byte
- arg8 uint32
- arg9 bool
+ arg2 *protocol.Request
}
requestReturns struct {
result1 protocol.RequestResponse
@@ -733,12 +723,12 @@ func (fake *Model) ClosedArgsForCall(i int) (protocol.Connection, error) {
return argsForCall.arg1, argsForCall.arg2
}
-func (fake *Model) ClusterConfig(arg1 protocol.Connection, arg2 protocol.ClusterConfig) error {
+func (fake *Model) ClusterConfig(arg1 protocol.Connection, arg2 *protocol.ClusterConfig) error {
fake.clusterConfigMutex.Lock()
ret, specificReturn := fake.clusterConfigReturnsOnCall[len(fake.clusterConfigArgsForCall)]
fake.clusterConfigArgsForCall = append(fake.clusterConfigArgsForCall, struct {
arg1 protocol.Connection
- arg2 protocol.ClusterConfig
+ arg2 *protocol.ClusterConfig
}{arg1, arg2})
stub := fake.ClusterConfigStub
fakeReturns := fake.clusterConfigReturns
@@ -759,13 +749,13 @@ func (fake *Model) ClusterConfigCallCount() int {
return len(fake.clusterConfigArgsForCall)
}
-func (fake *Model) ClusterConfigCalls(stub func(protocol.Connection, protocol.ClusterConfig) error) {
+func (fake *Model) ClusterConfigCalls(stub func(protocol.Connection, *protocol.ClusterConfig) error) {
fake.clusterConfigMutex.Lock()
defer fake.clusterConfigMutex.Unlock()
fake.ClusterConfigStub = stub
}
-func (fake *Model) ClusterConfigArgsForCall(i int) (protocol.Connection, protocol.ClusterConfig) {
+func (fake *Model) ClusterConfigArgsForCall(i int) (protocol.Connection, *protocol.ClusterConfig) {
fake.clusterConfigMutex.RLock()
defer fake.clusterConfigMutex.RUnlock()
argsForCall := fake.clusterConfigArgsForCall[i]
@@ -1453,25 +1443,19 @@ func (fake *Model) DismissPendingFolderReturnsOnCall(i int, result1 error) {
}{result1}
}
-func (fake *Model) DownloadProgress(arg1 protocol.Connection, arg2 string, arg3 []protocol.FileDownloadProgressUpdate) error {
- var arg3Copy []protocol.FileDownloadProgressUpdate
- if arg3 != nil {
- arg3Copy = make([]protocol.FileDownloadProgressUpdate, len(arg3))
- copy(arg3Copy, arg3)
- }
+func (fake *Model) DownloadProgress(arg1 protocol.Connection, arg2 *protocol.DownloadProgress) error {
fake.downloadProgressMutex.Lock()
ret, specificReturn := fake.downloadProgressReturnsOnCall[len(fake.downloadProgressArgsForCall)]
fake.downloadProgressArgsForCall = append(fake.downloadProgressArgsForCall, struct {
arg1 protocol.Connection
- arg2 string
- arg3 []protocol.FileDownloadProgressUpdate
- }{arg1, arg2, arg3Copy})
+ arg2 *protocol.DownloadProgress
+ }{arg1, arg2})
stub := fake.DownloadProgressStub
fakeReturns := fake.downloadProgressReturns
- fake.recordInvocation("DownloadProgress", []interface{}{arg1, arg2, arg3Copy})
+ fake.recordInvocation("DownloadProgress", []interface{}{arg1, arg2})
fake.downloadProgressMutex.Unlock()
if stub != nil {
- return stub(arg1, arg2, arg3)
+ return stub(arg1, arg2)
}
if specificReturn {
return ret.result1
@@ -1485,17 +1469,17 @@ func (fake *Model) DownloadProgressCallCount() int {
return len(fake.downloadProgressArgsForCall)
}
-func (fake *Model) DownloadProgressCalls(stub func(protocol.Connection, string, []protocol.FileDownloadProgressUpdate) error) {
+func (fake *Model) DownloadProgressCalls(stub func(protocol.Connection, *protocol.DownloadProgress) error) {
fake.downloadProgressMutex.Lock()
defer fake.downloadProgressMutex.Unlock()
fake.DownloadProgressStub = stub
}
-func (fake *Model) DownloadProgressArgsForCall(i int) (protocol.Connection, string, []protocol.FileDownloadProgressUpdate) {
+func (fake *Model) DownloadProgressArgsForCall(i int) (protocol.Connection, *protocol.DownloadProgress) {
fake.downloadProgressMutex.RLock()
defer fake.downloadProgressMutex.RUnlock()
argsForCall := fake.downloadProgressArgsForCall[i]
- return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3
+ return argsForCall.arg1, argsForCall.arg2
}
func (fake *Model) DownloadProgressReturns(result1 error) {
@@ -1898,25 +1882,19 @@ func (fake *Model) GlobalDirectoryTreeReturnsOnCall(i int, result1 []*model.Tree
}{result1, result2}
}
-func (fake *Model) Index(arg1 protocol.Connection, arg2 string, arg3 []protocol.FileInfo) error {
- var arg3Copy []protocol.FileInfo
- if arg3 != nil {
- arg3Copy = make([]protocol.FileInfo, len(arg3))
- copy(arg3Copy, arg3)
- }
+func (fake *Model) Index(arg1 protocol.Connection, arg2 *protocol.Index) error {
fake.indexMutex.Lock()
ret, specificReturn := fake.indexReturnsOnCall[len(fake.indexArgsForCall)]
fake.indexArgsForCall = append(fake.indexArgsForCall, struct {
arg1 protocol.Connection
- arg2 string
- arg3 []protocol.FileInfo
- }{arg1, arg2, arg3Copy})
+ arg2 *protocol.Index
+ }{arg1, arg2})
stub := fake.IndexStub
fakeReturns := fake.indexReturns
- fake.recordInvocation("Index", []interface{}{arg1, arg2, arg3Copy})
+ fake.recordInvocation("Index", []interface{}{arg1, arg2})
fake.indexMutex.Unlock()
if stub != nil {
- return stub(arg1, arg2, arg3)
+ return stub(arg1, arg2)
}
if specificReturn {
return ret.result1
@@ -1930,17 +1908,17 @@ func (fake *Model) IndexCallCount() int {
return len(fake.indexArgsForCall)
}
-func (fake *Model) IndexCalls(stub func(protocol.Connection, string, []protocol.FileInfo) error) {
+func (fake *Model) IndexCalls(stub func(protocol.Connection, *protocol.Index) error) {
fake.indexMutex.Lock()
defer fake.indexMutex.Unlock()
fake.IndexStub = stub
}
-func (fake *Model) IndexArgsForCall(i int) (protocol.Connection, string, []protocol.FileInfo) {
+func (fake *Model) IndexArgsForCall(i int) (protocol.Connection, *protocol.Index) {
fake.indexMutex.RLock()
defer fake.indexMutex.RUnlock()
argsForCall := fake.indexArgsForCall[i]
- return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3
+ return argsForCall.arg1, argsForCall.arg2
}
func (fake *Model) IndexReturns(result1 error) {
@@ -1966,25 +1944,19 @@ func (fake *Model) IndexReturnsOnCall(i int, result1 error) {
}{result1}
}
-func (fake *Model) IndexUpdate(arg1 protocol.Connection, arg2 string, arg3 []protocol.FileInfo) error {
- var arg3Copy []protocol.FileInfo
- if arg3 != nil {
- arg3Copy = make([]protocol.FileInfo, len(arg3))
- copy(arg3Copy, arg3)
- }
+func (fake *Model) IndexUpdate(arg1 protocol.Connection, arg2 *protocol.IndexUpdate) error {
fake.indexUpdateMutex.Lock()
ret, specificReturn := fake.indexUpdateReturnsOnCall[len(fake.indexUpdateArgsForCall)]
fake.indexUpdateArgsForCall = append(fake.indexUpdateArgsForCall, struct {
arg1 protocol.Connection
- arg2 string
- arg3 []protocol.FileInfo
- }{arg1, arg2, arg3Copy})
+ arg2 *protocol.IndexUpdate
+ }{arg1, arg2})
stub := fake.IndexUpdateStub
fakeReturns := fake.indexUpdateReturns
- fake.recordInvocation("IndexUpdate", []interface{}{arg1, arg2, arg3Copy})
+ fake.recordInvocation("IndexUpdate", []interface{}{arg1, arg2})
fake.indexUpdateMutex.Unlock()
if stub != nil {
- return stub(arg1, arg2, arg3)
+ return stub(arg1, arg2)
}
if specificReturn {
return ret.result1
@@ -1998,17 +1970,17 @@ func (fake *Model) IndexUpdateCallCount() int {
return len(fake.indexUpdateArgsForCall)
}
-func (fake *Model) IndexUpdateCalls(stub func(protocol.Connection, string, []protocol.FileInfo) error) {
+func (fake *Model) IndexUpdateCalls(stub func(protocol.Connection, *protocol.IndexUpdate) error) {
fake.indexUpdateMutex.Lock()
defer fake.indexUpdateMutex.Unlock()
fake.IndexUpdateStub = stub
}
-func (fake *Model) IndexUpdateArgsForCall(i int) (protocol.Connection, string, []protocol.FileInfo) {
+func (fake *Model) IndexUpdateArgsForCall(i int) (protocol.Connection, *protocol.IndexUpdate) {
fake.indexUpdateMutex.RLock()
defer fake.indexUpdateMutex.RUnlock()
argsForCall := fake.indexUpdateArgsForCall[i]
- return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3
+ return argsForCall.arg1, argsForCall.arg2
}
func (fake *Model) IndexUpdateReturns(result1 error) {
@@ -2521,31 +2493,19 @@ func (fake *Model) RemoteNeedFolderFilesReturnsOnCall(i int, result1 []db.FileIn
}{result1, result2}
}
-func (fake *Model) Request(arg1 protocol.Connection, arg2 string, arg3 string, arg4 int32, arg5 int32, arg6 int64, arg7 []byte, arg8 uint32, arg9 bool) (protocol.RequestResponse, error) {
- var arg7Copy []byte
- if arg7 != nil {
- arg7Copy = make([]byte, len(arg7))
- copy(arg7Copy, arg7)
- }
+func (fake *Model) Request(arg1 protocol.Connection, arg2 *protocol.Request) (protocol.RequestResponse, error) {
fake.requestMutex.Lock()
ret, specificReturn := fake.requestReturnsOnCall[len(fake.requestArgsForCall)]
fake.requestArgsForCall = append(fake.requestArgsForCall, struct {
arg1 protocol.Connection
- arg2 string
- arg3 string
- arg4 int32
- arg5 int32
- arg6 int64
- arg7 []byte
- arg8 uint32
- arg9 bool
- }{arg1, arg2, arg3, arg4, arg5, arg6, arg7Copy, arg8, arg9})
+ arg2 *protocol.Request
+ }{arg1, arg2})
stub := fake.RequestStub
fakeReturns := fake.requestReturns
- fake.recordInvocation("Request", []interface{}{arg1, arg2, arg3, arg4, arg5, arg6, arg7Copy, arg8, arg9})
+ fake.recordInvocation("Request", []interface{}{arg1, arg2})
fake.requestMutex.Unlock()
if stub != nil {
- return stub(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)
+ return stub(arg1, arg2)
}
if specificReturn {
return ret.result1, ret.result2
@@ -2559,17 +2519,17 @@ func (fake *Model) RequestCallCount() int {
return len(fake.requestArgsForCall)
}
-func (fake *Model) RequestCalls(stub func(protocol.Connection, string, string, int32, int32, int64, []byte, uint32, bool) (protocol.RequestResponse, error)) {
+func (fake *Model) RequestCalls(stub func(protocol.Connection, *protocol.Request) (protocol.RequestResponse, error)) {
fake.requestMutex.Lock()
defer fake.requestMutex.Unlock()
fake.RequestStub = stub
}
-func (fake *Model) RequestArgsForCall(i int) (protocol.Connection, string, string, int32, int32, int64, []byte, uint32, bool) {
+func (fake *Model) RequestArgsForCall(i int) (protocol.Connection, *protocol.Request) {
fake.requestMutex.RLock()
defer fake.requestMutex.RUnlock()
argsForCall := fake.requestArgsForCall[i]
- return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4, argsForCall.arg5, argsForCall.arg6, argsForCall.arg7, argsForCall.arg8, argsForCall.arg9
+ return argsForCall.arg1, argsForCall.arg2
}
func (fake *Model) RequestReturns(result1 protocol.RequestResponse, result2 error) {
diff --git a/lib/model/model.go b/lib/model/model.go
index d2ea083d0..1607b379d 100644
--- a/lib/model/model.go
+++ b/lib/model/model.go
@@ -1133,14 +1133,14 @@ func (p *pager) done() bool {
// Index is called when a new device is connected and we receive their full index.
// Implements the protocol.Model interface.
-func (m *model) Index(conn protocol.Connection, folder string, fs []protocol.FileInfo) error {
- return m.handleIndex(conn, folder, fs, false)
+func (m *model) Index(conn protocol.Connection, idx *protocol.Index) error {
+ return m.handleIndex(conn, idx.Folder, idx.Files, false)
}
// IndexUpdate is called for incremental updates to connected devices' indexes.
// Implements the protocol.Model interface.
-func (m *model) IndexUpdate(conn protocol.Connection, folder string, fs []protocol.FileInfo) error {
- return m.handleIndex(conn, folder, fs, true)
+func (m *model) IndexUpdate(conn protocol.Connection, idxUp *protocol.IndexUpdate) error {
+ return m.handleIndex(conn, idxUp.Folder, idxUp.Files, true)
}
func (m *model) handleIndex(conn protocol.Connection, folder string, fs []protocol.FileInfo, update bool) error {
@@ -1182,7 +1182,7 @@ type ClusterConfigReceivedEventData struct {
Device protocol.DeviceID `json:"device"`
}
-func (m *model) ClusterConfig(conn protocol.Connection, cm protocol.ClusterConfig) error {
+func (m *model) ClusterConfig(conn protocol.Connection, cm *protocol.ClusterConfig) error {
deviceID := conn.DeviceID()
if cm.Secondary {
@@ -1632,7 +1632,7 @@ func (m *model) sendClusterConfig(ids []protocol.DeviceID) {
}
// handleIntroductions handles adding devices/folders that are shared by an introducer device
-func (m *model) handleIntroductions(introducerCfg config.DeviceConfiguration, cm protocol.ClusterConfig, folders map[string]config.FolderConfiguration, devices map[protocol.DeviceID]config.DeviceConfiguration) (map[string]config.FolderConfiguration, map[protocol.DeviceID]config.DeviceConfiguration, folderDeviceSet, bool) {
+func (m *model) handleIntroductions(introducerCfg config.DeviceConfiguration, cm *protocol.ClusterConfig, folders map[string]config.FolderConfiguration, devices map[protocol.DeviceID]config.DeviceConfiguration) (map[string]config.FolderConfiguration, map[protocol.DeviceID]config.DeviceConfiguration, folderDeviceSet, bool) {
changed := false
foldersDevices := make(folderDeviceSet)
@@ -1946,50 +1946,52 @@ func (r *requestResponse) Wait() {
// Request returns the specified data segment by reading it from local disk.
// Implements the protocol.Model interface.
-func (m *model) Request(conn protocol.Connection, folder, name string, _, size int32, offset int64, hash []byte, weakHash uint32, fromTemporary bool) (out protocol.RequestResponse, err error) {
- if size < 0 || offset < 0 {
+func (m *model) Request(conn protocol.Connection, req *protocol.Request) (out protocol.RequestResponse, err error) {
+ if req.Size < 0 || req.Offset < 0 {
return nil, protocol.ErrInvalid
}
deviceID := conn.DeviceID()
m.mut.RLock()
- folderCfg, ok := m.folderCfgs[folder]
- folderIgnores := m.folderIgnores[folder]
+ folderCfg, ok := m.folderCfgs[req.Folder]
+ folderIgnores := m.folderIgnores[req.Folder]
m.mut.RUnlock()
if !ok {
// The folder might be already unpaused in the config, but not yet
// in the model.
- l.Debugf("Request from %s for file %s in unstarted folder %q", deviceID.Short(), name, folder)
+ l.Debugf("Request from %s for file %s in unstarted folder %q", deviceID.Short(), req.Name, req.Folder)
return nil, protocol.ErrGeneric
}
if !folderCfg.SharedWith(deviceID) {
- l.Warnf("Request from %s for file %s in unshared folder %q", deviceID.Short(), name, folder)
+ l.Warnf("Request from %s for file %s in unshared folder %q", deviceID.Short(), req.Name, req.Folder)
return nil, protocol.ErrGeneric
}
if folderCfg.Paused {
- l.Debugf("Request from %s for file %s in paused folder %q", deviceID.Short(), name, folder)
+ l.Debugf("Request from %s for file %s in paused folder %q", deviceID.Short(), req.Name, req.Folder)
return nil, protocol.ErrGeneric
}
// Make sure the path is valid and in canonical form
- if name, err = fs.Canonicalize(name); err != nil {
- l.Debugf("Request from %s in folder %q for invalid filename %s", deviceID.Short(), folder, name)
+ if name, err := fs.Canonicalize(req.Name); err != nil {
+ l.Debugf("Request from %s in folder %q for invalid filename %s", deviceID.Short(), req.Folder, req.Name)
return nil, protocol.ErrGeneric
+ } else {
+ req.Name = name
}
if deviceID != protocol.LocalDeviceID {
- l.Debugf("%v REQ(in): %s: %q / %q o=%d s=%d t=%v", m, deviceID.Short(), folder, name, offset, size, fromTemporary)
+ l.Debugf("%v REQ(in): %s: %q / %q o=%d s=%d t=%v", m, deviceID.Short(), req.Folder, req.Name, req.Offset, req.Size, req.FromTemporary)
}
- if fs.IsInternal(name) {
- l.Debugf("%v REQ(in) for internal file: %s: %q / %q o=%d s=%d", m, deviceID.Short(), folder, name, offset, size)
+ if fs.IsInternal(req.Name) {
+ l.Debugf("%v REQ(in) for internal file: %s: %q / %q o=%d s=%d", m, deviceID.Short(), req.Folder, req.Name, req.Offset, req.Size)
return nil, protocol.ErrInvalid
}
- if folderIgnores.Match(name).IsIgnored() {
- l.Debugf("%v REQ(in) for ignored file: %s: %q / %q o=%d s=%d", m, deviceID.Short(), folder, name, offset, size)
+ if folderIgnores.Match(req.Name).IsIgnored() {
+ l.Debugf("%v REQ(in) for ignored file: %s: %q / %q o=%d s=%d", m, deviceID.Short(), req.Folder, req.Name, req.Offset, req.Size)
return nil, protocol.ErrInvalid
}
@@ -2001,7 +2003,7 @@ func (m *model) Request(conn protocol.Connection, folder, name string, _, size i
// The requestResponse releases the bytes to the buffer pool and the
// limiters when its Close method is called.
- res := newLimitedRequestResponse(int(size), limiter, m.globalRequestLimiter)
+ res := newLimitedRequestResponse(int(req.Size), limiter, m.globalRequestLimiter)
defer func() {
// Close it ourselves if it isn't returned due to an error
@@ -2015,40 +2017,40 @@ func (m *model) Request(conn protocol.Connection, folder, name string, _, size i
folderFs := folderCfg.Filesystem(nil)
- if err := osutil.TraversesSymlink(folderFs, filepath.Dir(name)); err != nil {
- l.Debugf("%v REQ(in) traversal check: %s - %s: %q / %q o=%d s=%d", m, err, deviceID.Short(), folder, name, offset, size)
+ if err := osutil.TraversesSymlink(folderFs, filepath.Dir(req.Name)); err != nil {
+ l.Debugf("%v REQ(in) traversal check: %s - %s: %q / %q o=%d s=%d", m, err, deviceID.Short(), req.Folder, req.Name, req.Offset, req.Size)
return nil, protocol.ErrNoSuchFile
}
// Only check temp files if the flag is set, and if we are set to advertise
// the temp indexes.
- if fromTemporary && !folderCfg.DisableTempIndexes {
- tempFn := fs.TempName(name)
+ if req.FromTemporary && !folderCfg.DisableTempIndexes {
+ tempFn := fs.TempName(req.Name)
if info, err := folderFs.Lstat(tempFn); err != nil || !info.IsRegular() {
// Reject reads for anything that doesn't exist or is something
// other than a regular file.
- l.Debugf("%v REQ(in) failed stating temp file (%v): %s: %q / %q o=%d s=%d", m, err, deviceID.Short(), folder, name, offset, size)
+ l.Debugf("%v REQ(in) failed stating temp file (%v): %s: %q / %q o=%d s=%d", m, err, deviceID.Short(), req.Folder, req.Name, req.Offset, req.Size)
return nil, protocol.ErrNoSuchFile
}
- _, err := readOffsetIntoBuf(folderFs, tempFn, offset, res.data)
- if err == nil && scanner.Validate(res.data, hash, weakHash) {
+ _, err := readOffsetIntoBuf(folderFs, tempFn, req.Offset, res.data)
+ if err == nil && scanner.Validate(res.data, req.Hash, req.WeakHash) {
return res, nil
}
// Fall through to reading from a non-temp file, just in case the temp
// file has finished downloading.
}
- if info, err := folderFs.Lstat(name); err != nil || !info.IsRegular() {
+ if info, err := folderFs.Lstat(req.Name); err != nil || !info.IsRegular() {
// Reject reads for anything that doesn't exist or is something
// other than a regular file.
- l.Debugf("%v REQ(in) failed stating file (%v): %s: %q / %q o=%d s=%d", m, err, deviceID.Short(), folder, name, offset, size)
+ l.Debugf("%v REQ(in) failed stating file (%v): %s: %q / %q o=%d s=%d", m, err, deviceID.Short(), req.Folder, req.Name, req.Offset, req.Size)
return nil, protocol.ErrNoSuchFile
}
- n, err := readOffsetIntoBuf(folderFs, name, offset, res.data)
+ n, err := readOffsetIntoBuf(folderFs, req.Name, req.Offset, res.data)
if fs.IsNotExist(err) {
- l.Debugf("%v REQ(in) file doesn't exist: %s: %q / %q o=%d s=%d", m, deviceID.Short(), folder, name, offset, size)
+ l.Debugf("%v REQ(in) file doesn't exist: %s: %q / %q o=%d s=%d", m, deviceID.Short(), req.Folder, req.Name, req.Offset, req.Size)
return nil, protocol.ErrNoSuchFile
} else if err == io.EOF {
// Read beyond end of file. This might indicate a problem, or it
@@ -2057,13 +2059,13 @@ func (m *model) Request(conn protocol.Connection, folder, name string, _, size i
// next step take care of it, by only hashing the part we actually
// managed to read.
} else if err != nil {
- l.Debugf("%v REQ(in) failed reading file (%v): %s: %q / %q o=%d s=%d", m, err, deviceID.Short(), folder, name, offset, size)
+ l.Debugf("%v REQ(in) failed reading file (%v): %s: %q / %q o=%d s=%d", m, err, deviceID.Short(), req.Folder, req.Name, req.Offset, req.Size)
return nil, protocol.ErrGeneric
}
- if folderCfg.Type != config.FolderTypeReceiveEncrypted && len(hash) > 0 && !scanner.Validate(res.data[:n], hash, weakHash) {
- m.recheckFile(deviceID, folder, name, offset, hash, weakHash)
- l.Debugf("%v REQ(in) failed validating data: %s: %q / %q o=%d s=%d", m, deviceID.Short(), folder, name, offset, size)
+ if folderCfg.Type != config.FolderTypeReceiveEncrypted && len(req.Hash) > 0 && !scanner.Validate(res.data[:n], req.Hash, req.WeakHash) {
+ m.recheckFile(deviceID, req.Folder, req.Name, req.Offset, req.Hash, req.WeakHash)
+ l.Debugf("%v REQ(in) failed validating data: %s: %q / %q o=%d s=%d", m, deviceID.Short(), req.Folder, req.Name, req.Offset, req.Size)
return nil, protocol.ErrNoSuchFile
}
@@ -2416,11 +2418,11 @@ func (m *model) promoteConnections() {
}
}
-func (m *model) DownloadProgress(conn protocol.Connection, folder string, updates []protocol.FileDownloadProgressUpdate) error {
+func (m *model) DownloadProgress(conn protocol.Connection, p *protocol.DownloadProgress) error {
deviceID := conn.DeviceID()
m.mut.RLock()
- cfg, ok := m.folderCfgs[folder]
+ cfg, ok := m.folderCfgs[p.Folder]
m.mut.RUnlock()
if !ok || cfg.DisableTempIndexes || !cfg.SharedWith(deviceID) {
@@ -2430,12 +2432,12 @@ func (m *model) DownloadProgress(conn protocol.Connection, folder string, update
m.mut.RLock()
downloads := m.deviceDownloads[deviceID]
m.mut.RUnlock()
- downloads.Update(folder, updates)
- state := downloads.GetBlockCounts(folder)
+ downloads.Update(p.Folder, p.Updates)
+ state := downloads.GetBlockCounts(p.Folder)
m.evLogger.Log(events.RemoteDownloadProgress, map[string]interface{}{
"device": deviceID.String(),
- "folder": folder,
+ "folder": p.Folder,
"state": state,
})
diff --git a/lib/model/model_test.go b/lib/model/model_test.go
index efc0ad4cf..0032790af 100644
--- a/lib/model/model_test.go
+++ b/lib/model/model_test.go
@@ -52,8 +52,8 @@ func newState(t testing.TB, cfg config.Configuration) (*testModel, context.Cance
return m, cancel
}
-func createClusterConfig(remote protocol.DeviceID, ids ...string) protocol.ClusterConfig {
- cc := protocol.ClusterConfig{
+func createClusterConfig(remote protocol.DeviceID, ids ...string) *protocol.ClusterConfig {
+ cc := &protocol.ClusterConfig{
Folders: make([]protocol.Folder, len(ids)),
}
for i, id := range ids {
@@ -65,7 +65,7 @@ func createClusterConfig(remote protocol.DeviceID, ids ...string) protocol.Clust
return addFolderDevicesToClusterConfig(cc, remote)
}
-func addFolderDevicesToClusterConfig(cc protocol.ClusterConfig, remote protocol.DeviceID) protocol.ClusterConfig {
+func addFolderDevicesToClusterConfig(cc *protocol.ClusterConfig, remote protocol.DeviceID) *protocol.ClusterConfig {
for i := range cc.Folders {
cc.Folders[i].Devices = []protocol.Device{
{ID: myID},
@@ -94,7 +94,7 @@ func TestRequest(t *testing.T) {
m.ScanFolder("default")
// Existing, shared file
- res, err := m.Request(device1Conn, "default", "foo", 0, 6, 0, nil, 0, false)
+ res, err := m.Request(device1Conn, &protocol.Request{Folder: "default", Name: "foo", Size: 6})
if err != nil {
t.Fatal(err)
}
@@ -104,35 +104,35 @@ func TestRequest(t *testing.T) {
}
// Existing, nonshared file
- _, err = m.Request(device2Conn, "default", "foo", 0, 6, 0, nil, 0, false)
+ _