命名数据网络 | 名称(Name)
命名数据网络 | 名称(Name)
NDN 名称是 NDN 内容的层次名称,包含一系列名称组件。
名称 TLV 编码
我们使用一个两层嵌套的 TLV 来表示一个名称。外部 TLV 中的 NAME-TYPE 表示这是一个 Name。内部 TLV 应该是 NameComponent 元素,定义如下:
Name = NAME-TYPE TLV-LENGTH *NameComponent
NameComponent = GenericNameComponent /
ImplicitSha256DigestComponent /
ParametersSha256DigestComponent /
OtherTypeComponent
GenericNameComponent = GENERIC-NAME-COMPONENT-TYPE TLV-LENGTH *OCTET
ImplicitSha256DigestComponent = IMPLICIT-SHA256-DIGEST-COMPONENT-TYPE
TLV-LENGTH ; == 32
32OCTET
ParametersSha256DigestComponent = PARAMETERS-SHA256-DIGEST-COMPONENT-TYPE
TLV-LENGTH ; == 32
32OCTET
OtherTypeComponent = OTHER-TYPE-COMPONENT-TYPE ; any unassigned number in [1, 65535]
TLV-LENGTH
*OCTET
- GenericNameComponent 是一个泛型名称组件,对值的内容没有任何限制。
- ImplicitSha256DigestComponent 是一个隐式 SHA-256 摘要组件,它需要包含 32 个 8 字节的值。
- ParametersSha256DigestComponent 是一个携带 Interest 参数的 SHA-256 摘要的组件,它需要包含 32 个 8 字节的值。
除了上述组件类型之外,Name 还可以包含由 Name 组件分配策略 管理的其他组件类型。
Name 组件的 TLV-TYPE 必须在 [1,65535] 范围内。包含超出此范围的子元素的 Name 元素是无效的,数据包应该被丢弃。
NDN URI 方案
对于文本表示,通常使用 URI 表示 NDN 名称比较方便。
URI通用语法:RFC 3986
方案标识为 ndn。
授权组件(在熟悉的 http 和 ftp URI 方案中初始 // 之后的部分)与 NDN 无关。它不应该存在,如果存在则忽略它。
每个名称组件表示为 <type-number>=<escaped-value>,其中:
-
<type-number> 是组件的 TLV-TYPE,采用十进制格式,不带前导零。
-
<escaped-value> 是组件的 TLV-VALUE,根据以下规则转义:
-
通用 URI 无保留字符不进行转义。这些字符包括 US-ASCII 大小写字母(A-Z、A-Z)、数字(0-9)以及四个特殊字符:连字符(-)、句号(.)、下划线(_)和波浪号(~)。
-
所有其他字符都使用 URI 通用语法的百分比编码方法进行转义。
-
为了明确地表示与相对 URI 使用 . 和 .. 相冲突的名称组件,任何仅由零个或多个句点组成的组件都使用三个额外的句点进行编码。
-
例如,42=Hello%20world 表示 TLV-TYPE 42 和 TLV-VALUE “Hello world” 的名称组成部分。
为了更好的可读性,以下类型的名称组件有不同的 URI 表示:
- GenericNameComponent 可以省略它的 <type-number>= 前缀。例如,Hello%20world 相当于 8=Hello%20world。
- ImplicitSha256DigestComponent 可以表示为 sha256digest=<hex-value>。ParametersSha256DigestComponent 可以表示为 params-sha256=<hex-value>。
- sha256digest= 和 params-sha256= 前缀区分大小写。
- <hex-value> 是 TLV-VALUE,表示为 64 个十六进制数字序列。小写字母和大写字母都可以接受,但首选小写字母。
- 其他组件类型可能会以 <prefix>=<value> 的形式定义替代 URI 表示,其中:
- <prefix> 是一个非空字符串,以大写或小写字母开头,仅由通用 URI 无保留字符组成。
- <value> 是一个字符串,其解释根据前缀的不同而不同。
这种替代表示应该在 名称组件分配策略 中定义。
隐式摘要组件
每个数据包的全名包括一个逻辑最终隐式摘要组件,这使得每个数据包的名称是唯一的。隐式摘要(ImplicitSha256DigestComponent)可能作为 Interest 名称的最后一个组件出现在 Interest 中,以请求特定的数据包。当数据包在网络上传输时,ImplicitSha256DigestComponent 永远不会显式地包含在数据包中,如果需要,必须由所有节点根据数据包内容计算。
隐式摘要组件由整个数据包位的 SHA-256 摘要组成。将此摘要作为名称组件允许识别一个特定的数据包而不识别其他数据包。
参数摘要组件
参数摘要组件(ParametersSha256DigestComponent)包含对从 ApplicationParameters 元素开始并包括 ApplicationParameters 元素直到 Interest 结束的 Interest 部分计算的 SHA-256 摘要。此摘要为给定的一组参数提供了 Interest 名称的唯一性,并安全地确保检索到的数据包是根据正确的参数集生成的响应。
如果 Interest 包含 ApplicationParameters 元素,则该组件必须出现在 Interest 名称中。组件的位置由应用程序协议决定。通常,它应该在名称的末尾,但在版本号/段号之前。生产者应该根据收到的 Interest 的指定部分重新计算摘要,如果计算的摘要与名称中的参数摘要组件不匹配,则删除 Interest。
规范顺序
在 NDN 包处理的几个上下文中,有必要保持名称和名称组件的一致顺序。
各个名称组件之间的顺序定义如下:
-
如果组件 component1 和 component2 具有不同的类型,则
- 如果TLV-TYPE(component1) 的数值小于TLV-TYPE(component2) 的数值,则 component1 小于 component2。
NDN 规定:ImplicitSha256DigestComponent 的类型号小于任何其他有效名称组件的类型号。
- 如果组件具有相同的类型,则
- 如果a比b短(字节数更少),则 a 在 b 之前。
- 如果 a 和 b 具有相同的长度,则根据八位字节值的绝对值按字典顺序对它们进行比较(例如,基于 memcmp() 排序)。
对于名称,排序仅基于它们不同的第一个组件的排序。如果一个名称是另一个名称的适当前缀,则将其放在前面。
规范顺序可以通过直接比较 Name 字段的 TLV-VALUE 的连线编码来强制执行(即,排除 Name 元素本身的 TLV-TYPE 和 TLV-LENGTH):
int canonicalOrder(Name lhs, Name rhs)
{
int result = memcmp(lhs.value(), rhs.value(), min(lhs.value_size(), rhs.value_size()));
if (result == 0) {
result = lhs.value_size() - rhs.value_size();
}
return result;
}