4.内部形式及其编码 | 4. Internal form and its encodings
4内部形式及其编码
此版本的堆栈符合:
- Megaco / H.248版本1(RFC3525)根据实施者指南版本10-13更新。
- 根据Draft-ietf-megaco-h248v2-04定义的Megaco / H.248版本2根据实施者指南版本10-13更新。
- 由ITU H.248.1(09/2005)定义的Megaco / H.248第3版.4.1消息的内部形式对于二进制和文本编码,我们使用相同的内部形式。我们的Megaco / H.248消息的内部形式受ASN.1编码器/解码器使用的内部格式的严重影响:
- “序列”表示为列表。
- “CHOICE”表示为大小为2的标记元组。
- “序列”表示为记录,定义为“megaco/include/meaco”。[医]讯息[医]v1.hrl“。
- “可选”表示为默认为'asn1_NOVALUE'的记录中的普通字段,表示该字段没有值。
- “八进制字符串”表示为无符号整数的列表。
- “枚举”表示为单个原子。
- “位字符串”表示为原子列表。
- “BOOLEAN”表示为原子“真”或“假”。
- “整数”表示为整数。
- “IA5String”表示为整数列表,其中每个整数是相应字符的ASCII值。
- “NULL”被表示为原子'NULL'。
为了充分理解内部形式,您必须掌握Megaco / H.248协议的ASN.1规范,并应用上述规则。请参阅Erlang / OTP中ASN.1编译器的文档,了解ASN.1和相应内部表单之间映射语义的更多细节。
注意到'TerminationId'记录没有用在内部表格中。它已被替换为megaco_term_id记录(在“megaco / include / megaco.hrl”中定义)。
4.2不同的编码
Megaco / H.248标准定义了纯文本编码和二进制编码(ASN.1 BER),并且我们实现了两者的编码器和解码器。实际上我们提供五种不同的编码/解码模块。
在文本编码中,实现者可以选择使用短和长关键字的组合。也可以添加空格以提高可读性。我们对短信使用术语“紧凑”(compact),用尽可能短的关键字和没有可选的空格,术语“漂亮”(pretty)表示使用长关键字和缩进样式,如Megaco / H.248规范中的文本示例)。
下面是一个文本消息的示例,它给出了文本消息的漂亮版本和紧凑版本之间的区别。第一,漂亮的缩进版本,有长的关键字:
MEGACO/1 [124.124.124.222]
Transaction = 9998 {
Context = - {
ServiceChange = ROOT {
Services {
Method = Restart,
ServiceChangeAddress = 55555,
Profile = ResGW/1,
Reason = "901 Cold Boot"
}
}
}
}
然后是紧凑的版本,没有缩进和简短的关键字:
!/1 [124.124.124.222]
T=9998{C=-{SC=ROOT{SV{MT=RS,AD=55555,PF=ResGW/1,RE="901 Cold Boot"}}}}
以及程序员对同一条消息的看法。首先构造一个ActionRequest记录列表,然后使用API中的一个Send函数发送它:
Prof = #'ServiceChangeProfile'{profileName = "resgw", version = 1},
Parm = #'ServiceChangeParm'{serviceChangeMethod = restart,
serviceChangeAddress = {portNumber, 55555},
serviceChangeReason = "901 Cold Boot",
serviceChangeProfile = Prof},
Req = #'ServiceChangeRequest'{terminationID = [?megaco_root_termination_id],
serviceChangeParms = Parm},
Actions = [#'ActionRequest'{contextId = ?megaco_null_context_id,
commandRequests = {serviceChangeReq, Req}}],
megaco:call(ConnHandle, Actions, Config).
最后打印出整个内部形式:
{'MegacoMessage',
asn1_NOVALUE,
{'Message',
1,
{ip4Address,{'IP4Address', [124,124,124,222], asn1_NOVALUE}},
{transactions,
[
{transactionRequest,
{'TransactionRequest',
9998,
[{'ActionRequest',
0,
asn1_NOVALUE,
asn1_NOVALUE,
[
{'CommandRequest',
{serviceChangeReq,
{'ServiceChangeRequest',
[
{megaco_term_id, false, ["root"]}],
{'ServiceChangeParm',
restart,
{portNumber, 55555},
asn1_NOVALUE,
{'ServiceChangeProfile', "resgw", version = 1},
"901 MG Cold Boot",
asn1_NOVALUE,
asn1_NOVALUE,
asn1_NOVALUE
}
}
},
asn1_NOVALUE,
asn1_NOVALUE
}
]
}
]
}
}
]
}
}
}
提供了下列编码模块:
- megaco_pretty_text_encoder - 将消息编码为漂亮的文本格式,对漂亮和紧凑的文本进行解码。
- megaco_compact_text_encoder - 将消息编码为紧凑文本格式,可以同时对紧凑文本进行解码。
- megaco_binary_encoder - 编码/解码ASN.1 BER消息。该编码器实现了最快的BER编码器/解码器。推荐的二进制编码。
- megaco_ber_encoder - 编码/解码ASN.1 BER消息。
- megaco_per_encoder - 编码/解码ASN.1 PER消息。注意这种格式不包含在Megaco标准中。
- megaco_erl_dist_encoder - 将消息编码为Erlangs分发格式。它比较冗长,但编码和解码速度很快。注意这种格式不包含在Megaco标准中。
4.3配置Erlang分配编码模块
megaco_erl_dist_encoder模块的encoding_config可能是以下其中一个:
[]
- 将消息编码为标准分发格式。它比较冗长,但编码和解码速度很快。
[megaco_compressed]
- 在内部转换后将消息编码为标准分发格式。它不那么冗长,但是编码和解码的总时间会稍微慢一些(参见performance
本章了解更多信息)。
[{megaco_compressed, Module}]
- 以与megaco_compressed配置参数相同的方式工作,只有在这里用户提供他们自己的压缩模块。该模块必须执行该megaco_edist_compress
行为。
[compressed]
- 将消息编码为标准分发格式的压缩格式。它不那么冗长,但编码和解码将会更慢。
4.4文本编码模块的配置
当使用文本编码时,实际上有两种不同的配置控制使用什么软件:
[]
- 空列表表示应使用erlang扫描器。
[{flex, port()}]
- 解码时使用柔性扫描仪(不针对SMP进行优化)。查看initial configuration
更多信息。
[{flex, ports()}]
- 解码时使用柔性扫描器(针对SMP进行了优化)。参见initial configuration
更多信息。Flex扫描仪是一种Megaco扫描仪,写成驱动程序链接(C语言)。有两种方法可以实现这一点:
- 让Megaco堆栈启动Flex扫描器(加载驱动程序)。
为了实现这一点,必须配置Megaco堆栈:
- Add the `{scanner, flex}` (or similar) directive to an Erlang system config file for the megaco app (see [`initial configuration`](megaco_run#initial_config) chapter for details).
- Retrieve the encoding-config using the [`system_info`](megaco#system_info) function (with `Item = text_config`).
- Update the receive handle with the encoding-config (the `encoding_config` field). 这样做的好处是,Megaco负责司机和港口的启动、持有和监督。Megaco客户端%28用户%29启动Flex扫描仪%28加载驱动程序%29。
启动柔性扫描仪时,会创建链接到驱动程序的端口。这个端口必须由一个进程拥有。这个过程不能死。如果有,端口也将终止。为此:
- Create a permanent process. Make sure this process is supervised (so that if it does die, this will be noticed).
- Let this process start the flex scanner by calling the `megaco_flex_scanner:start/0,1` function.
- Retrieve the encoding-config and when initiating the `megaco_receive_handle`, set the field `encoding_config` accordingly.
- Pass the `megaco_receive_handle` to the transport module.
4.5二进制编码模块的配置
使用二进制编码时,需要指定终结ID的结构。
[native]
-跳过转换阶段,即解码后的消息%28s%29将不会转换为我们的内部形式。
[integer()]
- 包含每个级别的大小(位数)的列表。例如:[3,8,5,8]
。
- integer() - 一个字节(8位)级别的数量。NB这当前转换为以前的配置。例如:3([8,8,8]).4.6处理MEGACO versionsSince实现的版本3,在这个版本中的Megaco应用的,是初步的,有必要有一种方法来处理不同的版本3的实施方式。出于这个原因,编码配置选项{version3, version3()}已被引入。此选项,如果存在的话,必须先在编码配置列表。如果找到,版本1和2编解码器会忽略此选项。version3() - > prev3a | prev3b | prev3c | V3
prev3a
初稿第3版,基于TD-33
prev3b
初稿第3版,基于TD-33,但文本编码更新为最终解决方案contextProperty
(与v2向后兼容)。
prev3c
初步版本3,基于v3标准的最终版本,但是不包括
段数%21
v3
完整版3.包括分割。这是默认的版本3变体(即,如果版本3消息要被编码/解码并且没有找到版本3编码配置,则假定为v3
)。有两种方式来处理不同的megaco编码版本。使用动态版本检测
(仅适用于传入消息)或通过连接信息中的显式版本
设置。对于传入消息:
- 动态版本检测
将megaco_receive_handle中的协议版本设置为dynamic
(这是默认值)。
这适用于那些支持版本,当前文本
和ber_bin(megaco_binary_encoder
和megaco_ber_bin_encoder
)的部分解码的编解码器。
这样解码器将检测使用哪个版本,然后使用正确的解码器。
- 显式版本显式设置megaco_receive_handle中的实际协议版本。从版本1开始。执行初始服务更改并协商了版本2时,请将传输进程的megaco_receive_handle(control_pid)升级到版本2.请参阅
megaco_tcp
和megaco_udp
。请注意,如果udp
使用相同的传输过程,则可用于多个连接。这可能使升级变得不可能。对于不支持的版本部分解码的编解码器,目前megaco_ber_encoder
,megaco_per_encoder
和megaco_per_bin_encoder
,dynamic
将恢复到版本1.对于传出消息:
- 更新连接信息协议[医]版本。
- 通过将项目添加
{protocol_version, integer()}
到选项来覆盖发送消息时的协议版本。参见call
或cast
。
请注意,这不会影响由堆栈自动发送的消息。他们使用连接信息的protocol_version。
4.7编码器回调函数
编码器回调接口由megaco_encoder
行为定义,请参阅megaco_encoder
。