mirror of
https://github.com/octoleo/syncthing.git
synced 2024-12-22 10:58:57 +00:00
Use protocol provided buffers for requests (fixes #1157)
This commit is contained in:
parent
b63351074c
commit
1977c526e4
@ -705,19 +705,19 @@ func (m *Model) Close(device protocol.DeviceID, err error) {
|
|||||||
|
|
||||||
// Request returns the specified data segment by reading it from local disk.
|
// Request returns the specified data segment by reading it from local disk.
|
||||||
// Implements the protocol.Model interface.
|
// Implements the protocol.Model interface.
|
||||||
func (m *Model) Request(deviceID protocol.DeviceID, folder, name string, offset int64, size int, hash []byte, flags uint32, options []protocol.Option) ([]byte, error) {
|
func (m *Model) Request(deviceID protocol.DeviceID, folder, name string, offset int64, hash []byte, flags uint32, options []protocol.Option, buf []byte) error {
|
||||||
if offset < 0 || size < 0 {
|
if offset < 0 {
|
||||||
return nil, protocol.ErrNoSuchFile
|
return protocol.ErrNoSuchFile
|
||||||
}
|
}
|
||||||
|
|
||||||
if !m.folderSharedWith(folder, deviceID) {
|
if !m.folderSharedWith(folder, deviceID) {
|
||||||
l.Warnf("Request from %s for file %s in unshared folder %q", deviceID, name, folder)
|
l.Warnf("Request from %s for file %s in unshared folder %q", deviceID, name, folder)
|
||||||
return nil, protocol.ErrNoSuchFile
|
return protocol.ErrNoSuchFile
|
||||||
}
|
}
|
||||||
|
|
||||||
if flags != 0 {
|
if flags != 0 {
|
||||||
// We don't currently support or expect any flags.
|
// We don't currently support or expect any flags.
|
||||||
return nil, fmt.Errorf("protocol error: unknown flags 0x%x in Request message", flags)
|
return fmt.Errorf("protocol error: unknown flags 0x%x in Request message", flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that the requested file exists in the local model. We only need
|
// Verify that the requested file exists in the local model. We only need
|
||||||
@ -739,7 +739,7 @@ func (m *Model) Request(deviceID protocol.DeviceID, folder, name string, offset
|
|||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
l.Warnf("Request from %s for file %s in nonexistent folder %q", deviceID, name, folder)
|
l.Warnf("Request from %s for file %s in nonexistent folder %q", deviceID, name, folder)
|
||||||
return nil, protocol.ErrNoSuchFile
|
return protocol.ErrNoSuchFile
|
||||||
}
|
}
|
||||||
|
|
||||||
// This call is really expensive for large files, as we load the full
|
// This call is really expensive for large files, as we load the full
|
||||||
@ -747,21 +747,21 @@ func (m *Model) Request(deviceID protocol.DeviceID, folder, name string, offset
|
|||||||
// space for, read, and deserialize.
|
// space for, read, and deserialize.
|
||||||
lf, ok := folderFiles.Get(protocol.LocalDeviceID, name)
|
lf, ok := folderFiles.Get(protocol.LocalDeviceID, name)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, protocol.ErrNoSuchFile
|
return protocol.ErrNoSuchFile
|
||||||
}
|
}
|
||||||
|
|
||||||
if lf.IsInvalid() || lf.IsDeleted() {
|
if lf.IsInvalid() || lf.IsDeleted() {
|
||||||
if debug {
|
if debug {
|
||||||
l.Debugf("%v REQ(in): %s: %q / %q o=%d s=%d; invalid: %v", m, deviceID, folder, name, offset, size, lf)
|
l.Debugf("%v REQ(in): %s: %q / %q o=%d s=%d; invalid: %v", m, deviceID, folder, name, offset, len(buf), lf)
|
||||||
}
|
}
|
||||||
return nil, protocol.ErrInvalid
|
return protocol.ErrInvalid
|
||||||
}
|
}
|
||||||
|
|
||||||
if offset > lf.Size() {
|
if offset > lf.Size() {
|
||||||
if debug {
|
if debug {
|
||||||
l.Debugf("%v REQ(in; nonexistent): %s: %q o=%d s=%d", m, deviceID, name, offset, size)
|
l.Debugf("%v REQ(in; nonexistent): %s: %q o=%d s=%d", m, deviceID, name, offset, len(buf))
|
||||||
}
|
}
|
||||||
return nil, protocol.ErrNoSuchFile
|
return protocol.ErrNoSuchFile
|
||||||
}
|
}
|
||||||
|
|
||||||
m.rvmut.Lock()
|
m.rvmut.Lock()
|
||||||
@ -792,7 +792,7 @@ func (m *Model) Request(deviceID protocol.DeviceID, folder, name string, offset
|
|||||||
}
|
}
|
||||||
|
|
||||||
if debug && deviceID != protocol.LocalDeviceID {
|
if debug && deviceID != protocol.LocalDeviceID {
|
||||||
l.Debugf("%v REQ(in): %s: %q / %q o=%d s=%d", m, deviceID, folder, name, offset, size)
|
l.Debugf("%v REQ(in): %s: %q / %q o=%d s=%d", m, deviceID, folder, name, offset, len(buf))
|
||||||
}
|
}
|
||||||
m.fmut.RLock()
|
m.fmut.RLock()
|
||||||
fn := filepath.Join(m.folderCfgs[folder].Path(), name)
|
fn := filepath.Join(m.folderCfgs[folder].Path(), name)
|
||||||
@ -803,7 +803,7 @@ func (m *Model) Request(deviceID protocol.DeviceID, folder, name string, offset
|
|||||||
if info, err := os.Lstat(fn); err == nil && info.Mode()&os.ModeSymlink != 0 {
|
if info, err := os.Lstat(fn); err == nil && info.Mode()&os.ModeSymlink != 0 {
|
||||||
target, _, err := symlinks.Read(fn)
|
target, _, err := symlinks.Read(fn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
reader = strings.NewReader(target)
|
reader = strings.NewReader(target)
|
||||||
} else {
|
} else {
|
||||||
@ -811,19 +811,18 @@ func (m *Model) Request(deviceID protocol.DeviceID, folder, name string, offset
|
|||||||
// at any moment.
|
// at any moment.
|
||||||
reader, err = os.Open(fn)
|
reader, err = os.Open(fn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer reader.(*os.File).Close()
|
defer reader.(*os.File).Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := make([]byte, size)
|
|
||||||
_, err = reader.ReadAt(buf, offset)
|
_, err = reader.ReadAt(buf, offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return buf, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Model) CurrentFolderFile(folder string, file string) (protocol.FileInfo, bool) {
|
func (m *Model) CurrentFolderFile(folder string, file string) (protocol.FileInfo, bool) {
|
||||||
|
@ -99,8 +99,11 @@ func TestRequest(t *testing.T) {
|
|||||||
m.ServeBackground()
|
m.ServeBackground()
|
||||||
m.ScanFolder("default")
|
m.ScanFolder("default")
|
||||||
|
|
||||||
|
bs := make([]byte, protocol.BlockSize)
|
||||||
|
|
||||||
// Existing, shared file
|
// Existing, shared file
|
||||||
bs, err := m.Request(device1, "default", "foo", 0, 6, nil, 0, nil)
|
bs = bs[:6]
|
||||||
|
err := m.Request(device1, "default", "foo", 0, nil, 0, nil, bs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
@ -109,58 +112,35 @@ func TestRequest(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Existing, nonshared file
|
// Existing, nonshared file
|
||||||
bs, err = m.Request(device2, "default", "foo", 0, 6, nil, 0, nil)
|
err = m.Request(device2, "default", "foo", 0, nil, 0, nil, bs)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("Unexpected nil error on insecure file read")
|
t.Error("Unexpected nil error on insecure file read")
|
||||||
}
|
}
|
||||||
if bs != nil {
|
|
||||||
t.Errorf("Unexpected non nil data on insecure file read: %q", string(bs))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nonexistent file
|
// Nonexistent file
|
||||||
bs, err = m.Request(device1, "default", "nonexistent", 0, 6, nil, 0, nil)
|
err = m.Request(device1, "default", "nonexistent", 0, nil, 0, nil, bs)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("Unexpected nil error on insecure file read")
|
t.Error("Unexpected nil error on insecure file read")
|
||||||
}
|
}
|
||||||
if bs != nil {
|
|
||||||
t.Errorf("Unexpected non nil data on insecure file read: %q", string(bs))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shared folder, but disallowed file name
|
// Shared folder, but disallowed file name
|
||||||
bs, err = m.Request(device1, "default", "../walk.go", 0, 6, nil, 0, nil)
|
err = m.Request(device1, "default", "../walk.go", 0, nil, 0, nil, bs)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("Unexpected nil error on insecure file read")
|
t.Error("Unexpected nil error on insecure file read")
|
||||||
}
|
}
|
||||||
if bs != nil {
|
|
||||||
t.Errorf("Unexpected non nil data on insecure file read: %q", string(bs))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Larger block than available
|
|
||||||
bs, err = m.Request(device1, "default", "foo", 0, 42, nil, 0, nil)
|
|
||||||
if err == nil {
|
|
||||||
t.Error("Unexpected nil error on insecure file read")
|
|
||||||
}
|
|
||||||
if bs != nil {
|
|
||||||
t.Errorf("Unexpected non nil data on insecure file read: %q", string(bs))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Negative offset
|
// Negative offset
|
||||||
bs, err = m.Request(device1, "default", "foo", -4, 6, nil, 0, nil)
|
err = m.Request(device1, "default", "foo", -4, nil, 0, nil, bs[:0])
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("Unexpected nil error on insecure file read")
|
t.Error("Unexpected nil error on insecure file read")
|
||||||
}
|
}
|
||||||
if bs != nil {
|
|
||||||
t.Errorf("Unexpected non nil data on insecure file read: %q", string(bs))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Negative size
|
// Larger block than available
|
||||||
bs, err = m.Request(device1, "default", "foo", 4, -4, nil, 0, nil)
|
bs = bs[:42]
|
||||||
|
err = m.Request(device1, "default", "foo", 0, nil, 0, nil, bs)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("Unexpected nil error on insecure file read")
|
t.Error("Unexpected nil error on insecure file read")
|
||||||
}
|
}
|
||||||
if bs != nil {
|
|
||||||
t.Errorf("Unexpected non nil data on insecure file read: %q", string(bs))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func genFiles(n int) []protocol.FileInfo {
|
func genFiles(n int) []protocol.FileInfo {
|
||||||
|
Loading…
Reference in New Issue
Block a user