Commit Graph

93 Commits

Author SHA1 Message Date
Cassondra Foesch afc8d7b11a no need to double type switch 2021-02-22 12:04:43 +00:00
Nicola Murino 5dbfeffd12 request-server: add StatVFS support 2021-02-10 19:13:19 +01:00
Cassondra Foesch d696bdb2ff add PosixRename optional support same as Lstat 2020-09-25 16:16:01 +00:00
Cassondra Foesch 8ae3feeb9f add NOTEs everywhere symlink target/linkpath vs sftp.Request.Filepath and sfftp.Request.Target come up 2020-09-24 15:20:10 +00:00
Fazlul Shahriar bbd5cf2737
Merge branch 'master' into plan9 2020-09-15 12:06:10 -04:00
Fazlul Shahriar 6120cae121
Fix build on Plan 9
All test are passing on Plan 9, and I've also verified
`examples/go-sftp-server` is working.
2020-09-10 18:18:22 -04:00
Nicola Murino ba3e280524 request-server: add lstat support
Add LstatFileLister, an optional interface for FileLister, if this
interface is implemented Lstat requests will call it otherwirse they
will be handled in the same way as Stat, as before
2020-09-06 08:26:58 +02:00
Nicola Murino 29c94d06cc request-server: simplify "Open" method handling 2020-09-03 18:17:31 +02:00
Nicola Murino 703dd9827c request-server: set request state only if there is no error 2020-09-03 16:40:14 +02:00
Nicola Murino 9284f1d6ac only check OpenFileWriter interface if Read flags is true
Improve memory handler and some test case
Improve nil check for Close and TransferError interfaces
2020-09-02 19:21:12 +02:00
Nicola Murino ea67d57ce5 request-server: implement Open method
add an optional interface to FileWriter to allow to open a file for both
writing and reading

Fixes #374
2020-08-30 10:40:22 +02:00
Cassondra Foesch c276d4b423 reorder writers over readers for Close() and transmitError() 2020-07-24 07:23:55 +00:00
Cassondra Foesch e56b4ff6ad Additional bug-fixes found looking at PR-361 2020-07-18 19:45:27 +00:00
Nicola Murino 3f969fcd59 add optional AllocationModeOptimized
after processing a packet we keep in memory the allocated slices and we reuse
them for new packets.
Slices are allocated in:

- recvPacket
- when we receive a sshFxpReadPacket (downloads)

The allocated slices have a fixed size = maxMsgLength.

Allocated slices are referenced to the request order id and are marked for reuse
after a request is served in maybeSendPackets.

The allocator is added to the packetManager struct and it is cleaned at the end
of the Serve() function.

This allocation mode is optional and disabled by default
2020-03-14 19:42:19 +01:00
Nicola Murino eeafeeff60 FxpReadPacket: add an helper method for slice allocation
This way we can use the same method in both server and request-server
2020-03-10 11:46:46 +01:00
Nicola Murino 44e44d716f fileget: allocate a slice with enough capacity
so a new allocation is not needed in MarshalBinary and sendPacket.

Here are some profiling results while downloading a file (file size is about 1GB),

before this patch:

1254.24MB 55.18% 55.18%  1254.24MB 55.18%  github.com/pkg/sftp.sshFxpDataPacket.MarshalBinary
  991.81MB 43.63% 98.81%   991.81MB 43.63%  github.com/pkg/sftp.fileget
       1MB 0.044% 98.86%  1255.24MB 55.22%  github.com/pkg/sftp.(*packetManager).maybeSendPackets
    0.50MB 0.022% 98.88%  1260.24MB 55.44%  github.com/pkg/sftp.(*packetManager).controller
         0     0% 98.88%   991.81MB 43.63%  github.com/pkg/sftp.(*Request).call
         0     0% 98.88%   993.31MB 43.70%  github.com/pkg/sftp.(*RequestServer).Serve.func1.1
         0     0% 98.88%   993.31MB 43.70%  github.com/pkg/sftp.(*RequestServer).packetWorker
         0     0% 98.88%  1254.24MB 55.18%  github.com/pkg/sftp.(*conn).sendPacket
         0     0% 98.88%  1254.24MB 55.18%  github.com/pkg/sftp.sendPacket

with this patch:

1209.48MB 98.46% 98.46%  1209.48MB 98.46%  github.com/pkg/sftp.fileget
       2MB  0.16% 98.63%     7.50MB  0.61%  github.com/pkg/sftp.recvPacket
         0     0% 98.63%        8MB  0.65%  github.com/drakkan/sftpgo/sftpd.Configuration.handleSftpConnection
         0     0% 98.63%  1209.48MB 98.46%  github.com/pkg/sftp.(*Request).call
         0     0% 98.63%        8MB  0.65%  github.com/pkg/sftp.(*RequestServer).Serve
         0     0% 98.63%  1209.98MB 98.50%  github.com/pkg/sftp.(*RequestServer).Serve.func1.1
         0     0% 98.63%  1209.98MB 98.50%  github.com/pkg/sftp.(*RequestServer).packetWorker
         0     0% 98.63%     7.50MB  0.61%  github.com/pkg/sftp.(*conn).recvPacket (inline)
2020-03-09 19:22:48 +01:00
Tommie Gannert 2c24eaad1c Implement the hardlink@openssh.com extension.
Both client and server. This is documented in

  https://github.com/openssh/openssh-portable/blob/master/PROTOCOL

Draft 7 of SFTP added support for SSH_FXP_LINK which supports both
symlinks and hardlinks, but unfortunately OpenSSH doesn't support
that:

  https://tools.ietf.org/html/draft-ietf-secsh-filexfer-07#section-7.7

Adding support for this as an option would be a nice extension to
this.
2019-08-25 20:16:37 -07:00
John Eikenberry 7f106a3327 change fstat to not reuse request object
When fstat is called it now uses the handle to get the opened request,
pulls the filepath from that and creates a new request for the fstat
call. This eliminates the need to change the Method on the request
object and furthers the goal of eliminating post-creation mutation of
the request object to open up the possibility to eliminate or at least
reduce the use of the global request lock.
2019-01-29 14:49:22 -08:00
John Eikenberry c71cbb17d3 'open' directory on opendir packet
Just like with files, the call to the hander to create the Lister is
done when the OPENDIR packet is received. This eliminates the need for
the lock in the filelist() method and opens the path for eliminating
more locks.
2019-01-29 14:49:22 -08:00
John Eikenberry 0a96e0de8a initial test of opening 'file' on open packet
Testing feasibility of creating the reader/writer when first receiving
the Open packet instead of waiting for the Get/Put.

This work is meant to make the Request locks easier to manage and
ultimately reducing/eliminating them as much as possible.
2019-01-29 14:49:22 -08:00
John Eikenberry c9d56c8108 fix race condition in fileget/fileput
This fixes the concurrent access/locking race in both fileget and
fileput when accessing the saved readerAt/writerAt. It eliminates the
dedicated functions and moves the access/locking inline where they were
called to make it clearer.

Thanks to Marshall Brekka (@marshallbrekka) for the original bug report
and outline for the fix.
2018-09-17 11:44:35 -07:00
John Eikenberry 54893da9f3 fix issue with reusing opendir file handle
Methods (Stat, Readlink) that only work on sigle file no longer keep any
list state. Only the List method now keeps the list progress state.

Fixes #256
2018-06-05 18:34:17 -07:00
John Eikenberry 218c0d4148 Opendir return an error status when not found
The initial Opendir packet is supposed to repond with an error status if
the directory wasn't found. It was just returning a handle without
checking, now it does a Stat on the path and only returns the handle if
the Stat is successful and it indicates it is a directory, otherwise it
returns an error.
2018-05-26 13:59:55 -07:00
John Eikenberry f01c3557dc Be sure to cancel context when Close is called.
When I moved the context below the close calls to fix the issue with
cancel interfering with file finalizing, I didn't take into account
the returns. The context cancel needed to be done regardless which this
does by moving it into a defer.
2018-05-26 13:55:29 -07:00
sig 2375ad2cff set flags and attrs for fsetstat packet type in filecmd 2018-05-10 16:09:50 -07:00
John Eikenberry e5e5f4de7e Fix issue with filelist returning to soon.
Don't return until FileLister returns io.EOF and 0 results. Fixes issue
where FileLister would return 0 results in one batch, but still have
more results to go.

Fixes #240
2018-05-10 10:54:29 -07:00
John Eikenberry 43ec6c679d request.close should close files before cancel
File reading/writeing might block on close until finished. If the
context's cancel is run first it can cancel the session before that
finishes. So the context's cancel should always be run last.
2018-03-19 16:09:31 -07:00
John Eikenberry 353daee2bc better request copy code
With state's lock as a pointer, we can use the `*r = *r2` statement for
copying which is much more concise and future proof.
2018-02-06 12:22:08 -08:00
John Eikenberry 50208af173 refactor state lock to allow request copying
This refactors Request.state's lock use and converts it into a pointer
to allow for cleaner copying and better organization.
2018-02-06 11:59:15 -08:00
John Eikenberry b00841bcd7 create master/parent context in the server session
Create a master Context in the per-session ReqeustServer.Serve method
that is then used as the parent for all Context's created in that
server. Its cancelFunc is then always called when Serve exits. This is
in line which out the http.serve code works.

Each Request gets a child WithCancel context created in the
requestFromPacket call. This Context is still closed on request.close().
2018-02-05 14:10:05 -08:00
Allan Feid 87f773b0e3 Add context to request lifecycle 2018-02-05 12:46:27 -08:00
John Eikenberry 01df3f4dbd remove old comment 2018-01-09 10:58:58 -08:00
John Eikenberry 65c300dda8 remove some redundant code 2018-01-07 17:34:08 -08:00
John Eikenberry aae30a2509 factor out unnecessary data structure
packet_data structure was a leftover from previous code and it is no
longer necessary as the packets are available to use. I kept
packetData() to simplify grabing the data off the packets.
2018-01-06 16:12:05 -08:00
John Eikenberry 9ff3538709 store open packet's pflags to request.Flags 2018-01-05 17:55:57 -08:00
John Eikenberry fa2d0c3125 respect create flag in open packet
When the SSH_FXP_OPEN packet has the SSH_FXF_CREAT pflag set the file
should get created even if no data is sent. We do this by having the
Open method call through to the FilePut Handler with empty packet data.

Fixes #214
2017-12-23 19:14:16 -08:00
John Eikenberry a6c60b2061 Split setFileState into separate, typed functions.
Fixes #215 where the user had an object that was their reader and writer
and thing wouldn't work right.
2017-12-23 16:50:46 -08:00
John Eikenberry 8722020a70 simpify Request struct and Method updating
In #192 we normalized all Request use to have pointer receivers. This
simplified reasoning and allowed for a simpler Request struct. This
change completes that work by eliminating the need for the
state/stackLock pointers and also removes the need for a new Request
each packet, reducing the pressure on the GC.

The main bit is that the RequestServer.openRequests[] map now stores Request
pointers and it only creates new Requests (replacing the mapped entry) when the
Method changes. It never updates/modifies an existing Request and the packet to
Method mapping is now all in place place (requestMethod).
2017-12-23 16:34:22 -08:00
Mayank Agarwal 1816888769 fix(request-server): handle file close error 2017-12-12 23:35:18 +05:30
John Eikenberry 87518d071d remove vestigial packets channel from request
Request object had a packet channel where it stored packets for
read/write/readdir handling. It was required in an earlier version of
the code (that was refactored before merging) and never got cleaned up.

This removes that channel and just passes the packet through the methods
instead. This is much simpler and would have eliminated the chance of
issue #195. It also looks like it should allow for a few more
simplifications as well.
2017-08-22 19:24:14 -07:00
John Eikenberry 98dd8fc859 remove dead end-of-dir code 2017-08-22 17:32:37 -07:00
John Eikenberry 19d66c2d96 change request.handle() to request.callHandler()
Handle was already used for sftp's session 'handle' which is the name
used in the other code and sftp specs.
2017-08-20 17:51:45 -07:00
John Eikenberry 6eeffbb805 don't use read locks when making a change 2017-08-20 17:38:09 -07:00
John Eikenberry 4c02ab5a94 Merge branch 'master' into master 2017-08-20 17:18:07 -07:00
John Eikenberry aedf9a737a Fix #192 all Request methods use pointer recivers
Prevents subtle copy bugs and made the 1 required Request copy explicit.
2017-08-20 17:03:15 -07:00
John Eikenberry cffd2fabb0 Fix #195 Handler wrappers deal with errors
TLDR; have the Handler wrappers generate the response packets for the
errors instead of returning the errors.

Errors from the handers was returned up the stack to the request-server
handler call. In cases of errors the packet for the error was then
generated using the passed in packet (the incoming packet).

For file read/write/list operations the incoming packet data (includeing
ID) is put in a queue/channel so that it can be handled by the same file
handling code returned by the handler.

Due to gorouting scheduling, in some cases the packets in the channel
won't line up with the incoming packets. That is the worker that took an
incoming packet with one ID might respond with a packet with a different
ID. This doesn't matter as the reply order of packets doesn't matter.

BUT when this response packet that doesn't match IDs with the incoming
packet system returns an error, it uses the incoming packets ID to
generate the error packet. So the error response would use that ID and
the packet from the queue, once processed, would also use that ID
(because on success  it uses the ID from the packet in the queue).

This patch fixes the issue by having the code that works with the
packets, either incoming or from the queue, generate the error packet.
So there is no chance of them getting out of sync.
2017-08-20 16:15:01 -07:00
John Eikenberry bd3f00a6ea Merge pull request #194 from pkg/move-handle-ptr-request
Move Request.handle to *Request
2017-08-20 15:09:04 -07:00
Martin Garton 725c3d861f Fix #196; Increase offset correctly
If a ListerAt implementation chooses to return fewer than MaxFileList
entries, the next offset it increased by MaxFileList in any case and so
we get unwanted results.  Instead, increase the offset by the correct
number as returned by ListAt.
2017-08-16 15:53:40 +01:00
sandreas 653e2f1043 Merge branch 'master' into master 2017-08-13 17:00:45 +02:00
andreas 4d7bb970c4 Resolved conflict with SftpServerWorkerCount
Splitted cleanPath into cleanPacketPath and cleanPath for better handling of slashes in file paths
Added test for cleanPath func
Removed code duplication => filepath.ToSlash(filepath.Clean(...)) => cleanPath(...)
Fixed tests for runLs to match year or time
Renamed constants to fit hound rules
2017-08-13 14:00:08 +02:00