Commit Graph

36 Commits

Author SHA1 Message Date
Cassondra Foesch d9ce3caa72 convert uses of uint8 instead of fxp to fxp 2025-05-30 13:30:46 +00:00
Cassondra Foesch f1b135a6f5 invert if-blocks to reduce indention levels 2025-05-23 10:25:23 +00:00
Cassondra Foesch 18192955ef fix ssh subsystem request invocation 2025-05-23 09:21:31 +00:00
Erik Unger 3aa53a572f sendPacket with context 2023-11-13 09:13:33 +01:00
Joe Tsai e9377c8373 Properly handle io.EOF error conditions when reading
Previously, the Server.Serve method would never return nil,
because the infinite for-loop handling request packets would
only break if reading a packet reported an error.
A common termination condition is when the underlying connection
is closed and recvPacket returns io.EOF.
In which case Serve should ignore io.EOF and
treat it as a normal shutdown.

However, this means that recvPacket must correctly handle io.EOF
such that it never reports io.EOF if a packet is partially read.
There are two calls to io.ReadFull in recvPacket.
The first call correctly forwards an io.EOF error
if no additional bytes of the next packet are read.
However, the second call incorrectly forwards io.EOF
when no bytes of the payload could be read.
This is incorrect since we already read the length and
should convert the io.EOF into an io.ErrUnexpectedEOF.
2023-08-09 16:35:43 -07:00
Cassondra Foesch cc19e20d72 more context for EOF during client setup 2022-06-29 12:13:03 +00:00
Sebastien Rosset (serosset) 3b8042dfc0 Use go errors instead of github.com/pkg/errors 2021-06-04 14:18:41 -07:00
Nicola Murino f5f52ff56b
Merge pull request #419 from greatroar/fix-recv-panic
Fix panic when connection dropped in the middle of the sid
2021-03-23 21:49:58 +01:00
Cassondra Foesch f1e28f8a88 Improve benchmarks and errors 2021-03-17 11:03:51 +00:00
greatroar 053574d9eb Fix panic when connection dropped in the middle of the sid 2021-03-15 18:01:38 +01:00
Cassondra Foesch 861a8eaf5c pointer receivers and statusFromError(uint32, error) 2021-02-22 12:11:42 +00:00
Cassondra Foesch 1d73fd92d5 fix typo, error message is now two-way greppable 2021-02-22 12:04:43 +00:00
Cassondra Foesch 5d0d479f46 The SSH_FX_CONNECTION_LOST exists precisely for this 2021-02-22 12:04:43 +00:00
Cassondra Foesch 79ae5c2d53 a new server disconnect error point rather than EOF 2021-02-22 12:04:43 +00:00
Cassondra Foesch ac6027de63 numerous subtle race conditions resolved in clientConn 2021-02-22 12:04:43 +00:00
Cassondra Foesch 2aa3f7e910 don't broadcast anything other than disconnect to clients 2020-11-04 10:02:59 +01:00
Nicola Murino 1f178f9671 the allocator can now be enabled per request
Other minor changes as per review comments
2020-03-18 09:36:07 +01: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
John Eikenberry c31b3c3b22 fix connection close race
Need to prevent Close from being called at the same time. The lock
already existed, but was only used in one place where it should be
applied generally.
2020-03-07 15:05:46 -08:00
Taizeng Wu 5cd7f324f9 Use channel to implement a simple way to wait 2018-12-05 16:30:09 +08:00
Taizeng Wu 3a53acc96b Reimplement Wait method to make it can be called concurrently from multiple goroutines 2018-12-05 14:47:03 +08:00
Taizeng Wu fbf9e05c66 Add Wait method to detect underlying SFTP connection closed
Closes #278
2018-12-03 17:46:45 +08:00
John Eikenberry 22e9c1ccc0 set inflight chan buffer to 2 for deadlock
It is possible for dispatchRequest and broadcastErr to both send a
result down the inflight[] channel which has a buffer of 1, so would
work for one of them then block on the other. If broadcastErr went
first, then dispatchRequest would block causing the client to hang.
2018-02-06 16:43:44 -08:00
Pavel Borzenkov cb456b384c Fix race between client's close and write
After commit 506f3a7 which removed clientConn mutex around
conn.sendPacket, it is now possible for conn.Close and conn.Write to
race (https://travis-ci.org/pkg/sftp/jobs/219048782#L1838). The problem
is really hard to reproduce, but I believe this patch fixes it.

Now clientConn.Mutex protects 'inflight' map only, and conn.Mutex
serializes connection writes/close.

Signed-off-by: Pavel Borzenkov <pavel.borzenkov@gmail.com>
2017-04-08 20:29:37 -07:00
Pavel Borzenkov 506f3a7848 Fix deadlock when using Client + Service over io.Pipe
Client + Server might deadlock while being connected via io.Pipe with
high request concurrency. The scenario is as follows:

  - Server is trying to send reply to a previous client's packet and is
    waiting on Pipe's condvar for the client to read it:

 3  0x0000000000460e39 in sync.(*Cond).Wait
    at /usr/lib/go/src/sync/cond.go:57
 4  0x0000000000464519 in io.(*pipe).write
    at /usr/lib/go/src/io/pipe.go:90
 5  0x0000000000464a4c in io.(*PipeWriter).Write
    at /usr/lib/go/src/io/pipe.go:157
 6  0x00000000007a0b66 in go.(*struct { io.Reader; io.WriteCloser }).Write
    at <autogenerated>:246
 7  0x0000000000790cf6 in github.com/pkg/sftp.(*conn).Write
    at <autogenerated>:3
 8  0x000000000073a68d in github.com/pkg/sftp.sendPacket
    at ./packet.go:130
 9  0x000000000073338c in github.com/pkg/sftp.(*conn).sendPacket
    at ./conn.go:31
10  0x00000000007374b4 in github.com/pkg/sftp.(*packetManager).maybeSendPackets
    at ./packet-manager.go:87

  - Client is sending a new packet and is waiting on Pipe's condvar for
    the server to read it, while holding clientConn mutex:

 5  0x0000000000464a4c in io.(*PipeWriter).Write
    at /usr/lib/go/src/io/pipe.go:157
 6  0x0000000000790cf6 in github.com/pkg/sftp.(*conn).Write
    at <autogenerated>:3
 7  0x000000000073a68d in github.com/pkg/sftp.sendPacket
    at ./packet.go:130
 8  0x000000000073338c in github.com/pkg/sftp.(*conn).sendPacket
    at ./conn.go:31
 9  0x0000000000733bfb in github.com/pkg/sftp.(*clientConn).dispatchRequest
    at ./conn.go:105
10  0x0000000000733a0b in github.com/pkg/sftp.(*clientConn).sendPacket
    at ./conn.go:97

  - Client's receive loop is processing a reply from the server and is
    trying to acquire clientConn mutex:

4  0x000000000046108d in sync.(*Mutex).Lock
   at /usr/lib/go/src/sync/mutex.go:87
5  0x00000000007336cb in github.com/pkg/sftp.(*clientConn).recv
   at ./conn.go:69
6  0x000000000073350d in github.com/pkg/sftp.(*clientConn).loop
   at ./conn.go:49
7  0x000000000045ab51 in runtime.goexit
   at /usr/lib/go/src/runtime/asm_amd64.s:2197

In this scenario neither server nor client can progress. Fix this by
releasing clienConn mutex *before* trying to send the packet.

Signed-off-by: Pavel Borzenkov <pavel.borzenkov@gmail.com>
2017-04-05 14:15:57 -07:00
John Eikenberry 89c474ca1d new name for id (now ider) interface
more in line with go naming scheme for interfaces
better greppability
2017-03-23 16:15:04 -07:00
John Eikenberry 14f0a222dd Tests to replicate deadlock bug in Write/ReadFrom
github issue #145

A deadlock will occur in cases when using client.Write or client.ReadFrom,
it has 2 network issues in a row, and it is starting a new loop to send
more concurrent packets.
2017-02-13 00:32:33 -08:00
John Eikenberry bf1c2bb001 add lock on connection close to prevent race
Notably fixes occasional failures of TestServerRoughDisconnect due to
the race.

fixes #153
2017-01-31 16:24:31 -08:00
Dave Cheney 3a7eae5fbb Introduce serverConn (#119) 2016-06-15 21:08:29 +10:00
Dave Cheney ea1a7bcdfc conn: seperate io.Reader and io.WriteCloser (#118)
Reading and Writing are less coupled in the sftp client and server than
they may be over a traditional ReadWriter. This mirrors the full duplex
/ half close nature of a TCP connection.

In essence conn.Reader cannot be closed locally, it can only close in
response to the remote side using conn.WriteCloser.Close(), or a network
error, which is effectively the same thing.

Make this behaviour super clear by no longer smooshing the type into a
ReadWriteCloser.
2016-06-15 20:19:51 +10:00
Dave Cheney 9d52a809ce Always close client conn when clientConn.recv exits (#117)
If recv has exited then nobody will retrive the response, so
make sure we cannot send anything by shutting down the Write side of the
connection.
2016-06-15 20:04:26 +10:00
Dave Cheney 1a25dc501f rename sendRequest to sendPacket
clientConn.sendPacket now obscures clientConn.conn.sendPacket with a
diferent signature.
2016-06-15 18:57:05 +10:00
Dave Cheney 0847713e96 Migrate sendRequest to clientConn 2016-06-15 18:30:05 +10:00
Dave Cheney c91ab27c13 Move client.Close to clientConn.Close 2016-06-15 18:23:51 +10:00
Dave Cheney 9184483985 Introduce clientConn
clientConn embeds a conn and adds the basic loop/recv methods.
2016-06-15 18:08:04 +10:00
Dave Cheney 7d4fc94878 Introduce sftp.conn type to handle common send/recv behaviour (#113)
Introduce sftp.conn type to bind packet send/recv to a
io.ReadWriteCloser.
2016-06-15 11:50:02 +10:00