node.js で SFTP サーバーを作成していますが、ファイルの読み取りという最後のハードルで奇妙な問題に遭遇しました。
こちらのバージョン 3 SFTP 仕様に従ってください: https://filezilla-project.org/specs/draft-ietf-secsh-filexfer-02.txt
OSXでFileZilla、Coda2、およびコマンドラインsftpを使用してサーバーをテストしてきました。それぞれ、64 ビット通信を含む読み取りまでのすべての機能で成功していますが、ファイルの読み取り時にそれぞれ異なる奇妙な動作を生成するようです。
仕様 (セクション 6.4) によると、SSH_FXP_READ は以下を提供する必要があります。
uint32 id <- request id
string handle <- file handle
uint64 offset
uint32 len
いずれも有効な ID とハンドルを使用しますが、オフセットと長さは別の問題です。簡単にするために、ここでは 2 バイトのハンドルのみを使用しています。
Coda Expected:
5 ff 0 30000
6 ff 30000 30000
7 ff 60000 30000
8 ff 90000 30000
etc until EOF
Coda Real:
5 ff 0 30000
6 ff 30000 30000
7 ff 27232 30000
8 ff 89872 30000
9 ff 87104 30000
10 ff 149872 30000
Coda は最初の 2 つは正解しましたが、その後は負けてしまいました...
今、私の最初の考えは、64ビットオフセットを間違って読んだだけだということでした:
(buf.readUInt32BE(0) << 32) + buf.readUInt32BE(4)
編集: ビットシフトの例を 8 から 32 に変更 (まだ機能していません)、node-bignum と node-int64 も同じ結果で試しました
ここでのJavascriptの53ビットの精度は、ファイルサイズに十分なはずですよね?
そこで、python unpack (">Q") で読み値を確認したところ、正しかった。それだけでなく、同じ 64 ビット ハンドラーが SSH_FXP_READDIR と SSH_FXP_STAT でファイル サイズを正常に通信しています。
それでは、別のクライアントを試してみましょう。それより悪いことはありませんか?
FileZilla は実際には最初のチャンクで長さを要求するのではなく、サーバーが最初のチャンクで返す長さを要求します。返されたデータの長さに関係なく、オフセットは 65536 バイト以上増加しているようです…</p>
私が考えることができる唯一のことは、64ビットバッファの読み取りは間違っているということですが、手動で読み取ることさえ間違っています:
<Buffer 00 00 00 00 00 00 75 30> Expected:30000 Got:30000
<Buffer 00 00 00 00 00 00 6a 60> Expected:60000 Got:27232
32 ビットを壊す前にエラーが発生しています。
ここで、オフセットと長さを完全に無視し、読み取り要求ごとにクライアントにファイルをチャンクでストリーミングし、完了時に EOF ステータスを提供すると、すべてのクライアントで正常に動作します。しかし、明らかにこれは仕様を無視しているため、悪い考えです。
残念ながら、これは非常に基本的な問題のように思われるため、投稿する関連コードはあまりありません。
どんなアイデアや洞察も大歓迎です。この時点で、それが初歩的な間違いであるかどうかさえ気にしません:)