0

我正在 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 获得了前两个权利,但随后失去了它......

现在我的第一个想法是我刚刚读错了 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 状态,它在所有客户端中都可以正常工作。但显然这无视规范,所以是个坏主意。

不幸的是,没有太多相关代码可以发布,因为这似乎是一个非常基本的问题。

任何想法或见解将不胜感激。在这一点上,我什至不在乎它是否是一个基本错误:)

4

1 回答 1

1

JavaScript 的位运算符仅适用于 32 位值。因此,您可以做的只是简单地使用乘法/除法,这就是我在ssh2的 sftpv3 客户端中所做的。

还要指出的是,(buf.readUInt32BE(0) << 8)只会将 4 个字节向左移动 1 个字节而不是 4 个字节,以便为 64 位整数的其他 4 个字节腾出空间。

于 2013-08-28T13:23:04.070 回答