adjust strategy

Do you have a question? Post it now! No Registration Necessary.  Now with pictures!

Threaded View

I'm currently checking interoperation between the Erlang/OTP SSH
server and various SSH clients. The latest problem I've found was that
uploading of big files via SFTP from the Maverick SSH client library
(from didn't work. The root cause of the problem seems
to be that the Erlang server code used to send an
SSH_MSG_CHANNEL_WINDOW_ADJUST message for every received
SSH_MSG_CHANNEL_DATA message. However, the Maverick library seems to
fragment its SSH_FXP_WRITE messages into multiple SSH_MSG_CHANNEL_DATA
messages, usually one big (around 32KB) and a couple of small (less
then 100 bytes) messages. Consequently the Erlang server also sent a
couple of small adjust messages which somehow confused the Maverick
client to send only small messages and the whole upload didn't work.
I've changed the implementation in the Erlang server to only send an
adjust message if all fragments are received. This seems to work, but
I'm not sure if this is correct according to the specifications - is
it correct? SFTP version 3 is used in this communication.

By the way, which tools do you use for SSH testing? I'd love to check
the packets on the wire, but of course wireshark can't decode the SSH
packets for me.

Re: adjust strategy

Quoted text here. Click to load it

There's nothing wrong with that. It might sometimes be a bit
bandwidth-inefficient, but it's consistent with the spec.

Quoted text here. Click to load it

There's nothing wrong with this either.

Quoted text here. Click to load it

By 'didn't work', do you mean that something actually _failed_, or
just that the correct data was exchanged but only in extremely small
fragments leading to a very slow connection?

If the former, it sounds as if the client is actually broken, in the
sense that it is receiving a packet stream consistent with the spec
and not coping with it. Rather than trying to modify the server to
avoid triggering the client bug, you should find the client bug and
fix that.

Quoted text here. Click to load it

No. If the client wants to send an SFTP packet which is greater than
the SSH channel's window size, it MUST send no more than the first
windowful of data and then wait to receive a WINDOW_ADJUST before
sending any more. Therefore, you MUST be willing to send a
WINDOW_ADJUST in the middle of receiving an SFTP packet, if the
packet is large enough.

If you absolutely must solve this problem by fiddling with the
server's window adjust strategy rather than fixing the client to
cope with anything legal it receives, a simple option would be to
send WINDOW_ADJUST only once your window drops to half its original
size, which would mean you'd still send them in the middle of large
packets but wouldn't send too many very small ones.

I am surprised to hear that any implementation - client _or_ server
- has this much cross-talk between its ssh-connection layer and its
SFTP layer. Traditionally they're implemented with little or no
knowledge of each other: the SFTP layer formats its communication
into a byte stream containing SFTP packets stuck end-to-end, and
transmits that to the ssh-connection layer, which chooses
SSH_MSG_CHANNEL_DATA boundaries without reference to the SFTP packet
structure of the data it's dealing with. Similarly at the other end,
the ssh-connection layer receives SSH_MSG_CHANNEL_DATA messages,
sends back SSH_MSG_WINDOW_ADJUST when it thinks it's appropriate,
and passes the resulting byte stream on to the SFTP layer which will
then decode it into SFTP packets without generating any input into
the ssh-connection layer's window adjust strategy.

Quoted text here. Click to load it

Personally, I arrange that at least one of the implementations I'm
testing against each other contains a comprehensive debug dump
facility. Since one end of any connection I'm testing is invariably
PuTTY, I only had to go to the effort of doing this once.

I am continually amazed that other SSH implementations don't have
similar diagnostic facilities. I don't think I'd have been able to
survive without it for more than about half an hour without losing
my patience and writing one. (In fact, I didn't!)
Simon Tatham         "infinite loop _see_ loop, infinite"

Re: adjust strategy

Quoted text here. Click to load it

The server started to use 100% CPU and eventually the data transfer
stopped. I'm not sure that this was due to some timeout in an
application level above the SFTP layer - usually I stopped the
testcase, because the slowness is also unacceptable in this case.

Quoted text here. Click to load it

I only have access to the server source, that's why I tried to change
things there :-)

Quoted text here. Click to load it

So the current solution breaks the protocol. I'll look at this
solution, because I'd prefer not to break compatibility with other

Quoted text here. Click to load it

I'm working with an older version of the Erlang SSH server. The newer
one seems to be better separate the SSH and SFTP layers. Unfortunately
that doesn't work either (the upload stops after a while), but that's
another debugging session :-)

Site Timeline