Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
SFTP: don't buffer up download requests (PuTTY doesn't)
- Loading branch information
1 parent
1dc39be
commit 333e2e4
Showing
1 changed file
with
8 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
333e2e4
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(#1425 is the inspiration for this change)
phpseclib implemented "parallel uploads" in 2010 in response to a post on the old (now defunct) support forum (topic_id=14936). "parallel downloads" were implemented in 2016 in the master branch in PR #945. The queue size was changed from 50 to 32 as a result of #1062 (also in 2016). The specific issue was in regards to downloading files and I made the change to make it consistent with what I observed PuTTY to be doing for downloads.
The thing is... PuTTY appears to be handling downloads and uploads differently whereas phpseclib is handling them the same (phpseclib is handling both as PuTTY handles downloads).
The idea of sending SSH_FXP_WRITE packets in batches of 50 came as a result of errors that would crop up in the files if > 50 packets were sent at a time. Quoting one of the responses to the original support forum ticket:
I am a little worried that removing this limit will re-introduce errors but (1) PuTTY does it without issue and (2) last time the request identifier was always set to 0 whereas this time (as of #1343) it's not so maybe that'll make a difference.
As for my comments on PuTTY's behavior... this can be observed by using psftp to download and upload a 1MB file. This can be done by first running the following command on the CLI:
From there you can do one of these commands:
A cursory examination of PuTTY's source code seems to confirm this behavior.
Downloads
psftp.c does
while (!xfer_done(xfer))
andxfer_download_queue(xfer)
:https://github.com/github/putty/blob/49fb598b0e78d09d6a2a42679ee0649df482090e/psftp.c#L428
xfer_download_queue
doeswhile (xfer->req_totalsize < xfer->req_maxsize && !xfer->eof && !xfer->err)
:https://github.com/github/putty/blob/49fb598b0e78d09d6a2a42679ee0649df482090e/sftp.c#L1158
xfer->req_totalsize
is incremented withxfer->req_totalsize += rr->len
andrr->len
, by default, is 32768.xfer->req_maxsize
is 1048576, as defined here:https://github.com/github/putty/blob/49fb598b0e78d09d6a2a42679ee0649df482090e/sftp.c#L1133
1048576 / 32768 is 32, so phpseclib's queue'ing up 32 read requests at a time is consistent with PuTTY's behavior.
Uploads
psftp.c does repeated calls to
xfer_upload_data(xfer, buffer, len)
whilexfer_upload_ready(xfer)
. Whenxfer_upload_data(xfer, buffer, len)
returns false it then receives the responses vis-a-visxfer_upload_gotpkt(xfer, pktin)
:https://github.com/github/putty/blob/49fb598b0e78d09d6a2a42679ee0649df482090e/psftp.c#L675
Here's
xfer_upload_ready
:sftp.h says the following of
sftp_sendbuffer
:https://github.com/github/putty/blob/49fb598b0e78d09d6a2a42679ee0649df482090e/sftp.h#L58
It's not actually clear to me how
sftp_sendbuffer
works but I'm kinda wondering if it may not be applicable for PHP. phpseclib uses fputs insend_binary_packet
.fputs
is an alias of fwrite, which "returns the number of bytes written". If the number of bytes written is not the length of the stringsend_binary_packet
returns false. So idk.