[
https://issues.apache.org/jira/browse/SSHD-1181?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17360319#comment-17360319
]
Guillaume Nodet commented on SSHD-1181:
---------------------------------------
I've been able to reproduce the problem. The first thing was to change the
server side sftp code to send this EOF indicator when it makes sense. I should
be able to commit a fix with a test tomorrow.
> SFTP Get downloads empty file from servers which supports EOF indication
> after data
> -----------------------------------------------------------------------------------
>
> Key: SSHD-1181
> URL: https://issues.apache.org/jira/browse/SSHD-1181
> Project: MINA SSHD
> Issue Type: Bug
> Affects Versions: 2.6.0
> Reporter: Pavel Pohner
> Priority: Major
> Labels: SFTP, mina, sshd
>
> So, apparently there's a bug in Mina implementation when downloading the
> file, which is smaller than Mina's buffer (meaning it gets read in one
> iteration), from servers, which send EOF indicator at the end of data
> (https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#[section-9.3|https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-9.3]).
> The bug seems to be in setting up EOF indicator in
> {noformat}
> org.apache.sshd.sftp.client.impl.SftpInputStreamAsync#pollBuffer{noformat}
> prematurely (one iteration sooner), trace with me this example situation -
> download of the small file (14 B):
> At some point we arrive to mentioned function _pollBuffer()_, note that
> _this.pendingReads_ is set to 2. In first call of _pollBuffer()_ we go
> through this code on receiving SSH_FXP_DATA
> {code:java}
> if (type == SftpConstants.SSH_FXP_DATA) {
> int dlen = buf.getInt();
> int rpos = buf.rpos();
> buf.rpos(rpos + dlen);
> Boolean b = SftpHelper.getEndOfFileIndicatorValue(buf,
> client.getVersion());
> if ((b != null) && b.booleanValue()) {
> eofIndicator = true;
> }{code}
> Here, consider this situation, we're downloading file with 14B, remote server
> adds EOF indicator to the end of the data, so it makes 15B, let's add some
> necessary overhead (size etc.) which is, according to my experience, 13B, so
> we receive 15 + 13 = 28B into initial buffer.
> Now, if we populate these variables, _dlen_ = 14B (file size), _rpos_ = 13
> (overhead), and we set _buf.rpos_ to 27 (14 + 13), but _wpos_ is at the
> moment equal to 28B, as that's what we received. (We're not taking EOF into
> account here)
> Then the _SftpHelper.getEndOfFileIndicatorValue_ is called, which in it's
> implementation looks like this:
> {code:java}
> public static Boolean getEndOfFileIndicatorValue(Buffer buffer, int version) {
> return (version < SftpConstants.SFTP_V6) || (buffer.available() < 1) ?
> null : buffer.getBoolean();
> }
> {code}
> Pay attention to the _buffer.available()_ function as it's implemented like
> this:
> {code:java}
> public int available() {
> return wpos - rpos;
> }
> {code}
> therefore returning 1 (28 - 27), condition is then resolved in
> _SftpHelper.getEndOfFileIndicatorValue_ as a true and true is also returned
> to the _pollBuffer_ and _eofIndicator_ is set to true.
> If you'd keep tracing further, you'd find out that the buffer is then never
> read and returned from _SftpInputStreamAsync_ class, just because
> _eofIndicator_ was set sooner than it should have been.
>
>
--
This message was sent by Atlassian Jira
(v8.3.4#803005)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]