DHT扩展协议介绍
DHT扩展协议
该协议的目的是为bittorrent协议的扩展提供一个简单而精简的传输。支持此协议可以轻松添加新扩展,而不会干扰标准bittorrent协议或不支持此扩展或要添加的扩展的客户端。
要向您支持的其他客户端播发,将使用保留字节中的一位。
为扩展协议选择的位是右侧的位20(计数从0开始)。So(reserved_byte[5]&0x10)是用于检查客户端是否支持扩展消息传递的表达式。
一旦建立了对协议的支持,客户端应支持1条新消息:
name | id |
---|---|
extended | 20 |
此消息作为任何其他bittorrent消息发送,前缀长度为4字节,单个字节用于标识消息(在本例中,单个字节为20)。在消息有效负载的开头,是一个单字节消息标识符。此标识符可以引用不同的扩展消息,并且只指定了一个ID。如果ID为0,则消息为握手消息,如下所述。一般扩展消息的布局如下(包括bittorrent协议使用的消息头):
size | 描述 |
---|---|
uint32_t | 长度前缀。指定整个消息的字节数。(大端) |
uint8_t | bittorrent信息ID,=20 |
uint8_t | 扩展信息ID,0 = handshake, >0 = extended message as specified by the handshake. |
握手信息
握手消息的有效负载是一个b编码字典。字典中的所有项目都是可选的。客户端应忽略任何未知名称。字典的所有部分都区分大小写。这是字典中定义的项:
名称 | 描述 |
---|---|
m | 支持的扩展消息字典,它将扩展名映射到每个扩展消息的扩展消息ID。对这些ID的唯一要求是没有扩展消息共享相同的消息。将分机号码设置为零表示不支持/禁用该分机。客户端应该忽略它无法识别的任何扩展名。 扩展消息ID是用于向发送此握手的对等方发送扩展消息的ID。比如,ID是该特定对等方的本地ID。 |
以下是实现可能选择支持的一些其他项目:
名称 | 描述 |
---|---|
p | 本地TCP侦听端口。允许每一方了解另一方的TCP端口号。请注意,连接的接收端不需要发送此扩展消息,因为它的端口号是已知的。 |
v | 客户端名称和版本(作为utf-8字符串)。这是一种比依赖peer id编码更可靠的识别客户机的方法。 |
yourip | 一个字符串,包含该peer视为的ip地址的紧凑表示形式。例如,这是接收器的外部ip地址(不包括端口)。这可能是IPv4(4字节)或IPv6(16字节)地址。 |
ipv6 | 如果该peer具有IPv6接口,则这是该地址的紧凑表示形式(16字节)。客户端可能希望通过IPv6地址连接回。 |
ipv4 | 如果该peer具有IPv4接口,则这是该地址的紧凑表示形式(4字节)。客户端可能希望通过此接口连接回。 |
reqq | 整数,此客户端支持的未完成请求消息的数量,而不删除任何消息。libtorrent中的默认值是250。 |
握手字典还可以包括扩展的握手信息,例如支持加密的头或任何可以想象的东西。
握手消息的有效负载可能是什么样子的示例:
编码形式为:
1 |
|
为了确保扩展名不会发生错误冲突,它们应该以两个(或一个)字符代码作为前缀,用于标识引入扩展的客户机。这既适用于扩展消息的名称,也适用于顶级字典中的任何附加信息。除非本规范另有规定,否则所有单字节和双字节标识符均无效。
此消息应在标准bittorrent握手后立即发送给支持此扩展协议的任何对等方。在连接的生命周期内多次发送握手消息是有效的,不应断开发送客户端的连接。实现可以选择忽略后续握手消息(或其中的一部分)。
后续握手消息可用于启用/禁用扩展,而无需重新启动连接。如果对等方支持在运行时更改扩展,那么应该注意m字典是可添加的。它包含对扩展列表的实际更改就足够了。要在运行时禁用对LT_metadata的支持,而不影响任何其他扩展,应发送以下消息:d11:LT_metadatai0ee。如上所述,值0用于关闭扩展。
必须为每个对等方存储扩展ID,因为对于同一扩展,每个对等方可能有不同的ID。
本规范有意不指定任何扩展,例如对等交换或元数据交换。此协议只是bittorrent协议实际扩展的传输,上面示例中命名的扩展(如p)只是可能扩展的示例。
基本原理
在握手中定义扩展消息ID的原因是为了避免消息ID的全局注册。相反,扩展消息的名称需要唯一的名称,这在没有全局注册表的情况下更容易实现。约定是在扩展消息名称上使用两个字母的前缀,前缀将标识首先实现扩展消息的客户端。比如,LT_metadata由libtorrent实现,因此它具有LT前缀。
如果支持扩展的客户机可以决定它接收的消息的编号,这意味着它们是该客户机中的常量。比如,它们可以在switch语句中使用。另一端可以很容易地存储一个数组,该数组的ID为我们期望的每条消息的ID,并在每次发送扩展消息时使用该ID进行查找。
使用字典而不是数组(使用隐式分配给扩展的索引号)的原因是,如果客户机想要禁用某些扩展,ID号将发生变化,并且它将无法使用常量(因此,不能在交换机中使用常量)。如果消息ID将直接映射到bittorrent消息ID,那么还可以将握手中的扩展映射到具有固定消息ID的现有扩展。
使用单字节作为扩展消息标识符的原因是遵循bittorrent规范及其单字节消息标识符。这也被认为是足够的。它不会限制扩展的总数,只限制同时使用的扩展的数量。
标准化握手标识符使用单字节标识符的原因是1)主线DHT使用单字节标识符。2) 节省带宽。较长消息的唯一优点是,它使协议对人类更具可读性,但BT协议不是为人类可读的协议而设计的,所以为什么要麻烦呢。