查看源代码 diameter_app 行为 (diameter v2.4.1)
Diameter 应用程序的回调模块。
由 diameter:start_service/2
启动的 Diameter 服务配置一个或多个 Diameter 应用程序,每个应用程序的配置指定一个回调来处理特定于该应用程序的消息。应用程序的消息和 AVP 定义在字典文件中,该文件的格式在 diameter_dict(4) 中进行了说明,而回调模块在此处进行了说明。回调模块实现了服务的 Diameter 应用程序特定功能。
回调模块必须导出下面文档中的所有函数。这些函数本身具有三种不同的类型
peer_up/3
和peer_down/3
表示与 Diameter 对等端的连接的建立或丢失。pick_peer/4
、prepare_request/3
、prepare_retransmit/3
、handle_answer/4
和handle_error/4
是(或可能是)在调用diameter:call/4
发送传出的 Diameter 请求消息时调用的结果。handle_request/3
是在响应传入的 Diameter 请求消息时调用的。
此处回调函数的参数数量假设没有额外的参数。所有函数还将传递在调用 diameter:start_service/2
配置回调模块本身时配置的任何额外参数,以及对于特定于调用的回调,传递给 diameter:call/4
的任何额外参数。
概要
类型
一个记录,包含本地 Diameter 节点和具有已建立传输连接的远程 Diameter 对等端的身份,以及由能力交换确定的能力。记录的每个字段都是一个二元组,由(本地)主机和(远程)对等端的值组成。可选或可能有多个值编码为值列表,强制值编码为裸值。
Diameter 消息的表示形式,传递给 diameter:call/4
或从 handle_request/3
回调返回。
传入和传出 Diameter 消息的容器,通过编码/解码和传输传递。除非另有说明,否则不应在返回值中设置字段。
表示 Diameter 对等连接的元组。
标识与 Diameter 对等端的传输连接的术语。
应用程序回调函数 peer_up/3
、peer_down/3
和(可选)pick_peer/4
维护的状态。初始状态在调用 diameter:start_service/2
时配置,该调用在服务上配置应用程序。返回状态的回调函数在通用的特定于服务的进程中评估,而那些不返回状态的回调函数在特定于请求的进程中评估。
回调
当从对等端收到应答消息时调用。返回值从 diameter:call/4
返回,除非指定了 detach
选项。
当在收到对传出请求的应答消息之前发生错误时调用。返回值从 diameter:call/4
返回,除非指定了 detach
选项。
当从对等端收到请求消息时调用。回调发生的应用程序(即,通过 diameter:start_service/2
配置的回调模块)由传入请求消息的标头中的应用程序标识符确定,选择的模块是声明自己定义了相关应用程序或中继应用程序的模块。
在先前调用 peer_up/3
之后,调用以指示本地 Erlang 节点上的对等连接不再可用。特别是,连接的 RFC 3539 监视状态机已离开 OKAY
状态,并且对等端将不再是 pick_peer/4
回调中的候选者。
调用以指示本地 Erlang 节点上对等连接的可用性。特别是,与对等端的能力交换已指示支持相关应用程序,连接的 RFC 3539 监视状态机已达到 OKAY
状态,并且可以发送和接收 Diameter 消息。
由于调用 diameter:call/4
而调用,以选择传出请求的目标对等端。返回值指示选择的对等端。
调用以返回用于编码和传输的请求。允许发送者使用所选对等端的能力来修改传出的请求。许多实现可能只想简单地返回 {send, Packet}
调用以返回用于编码和重新传输的请求。在对等连接丢失并选择了备用对等端的情况下,具有与 prepare_request/3
相同的作用,但是参数 packet() 是由初始 prepare_request/3
返回的。
类型
-type capabilities() :: #diameter_caps{origin_host :: term(), origin_realm :: term(), host_ip_address :: term(), vendor_id :: term(), product_name :: term(), origin_state_id :: term(), supported_vendor_id :: term(), auth_application_id :: term(), inband_security_id :: term(), acct_application_id :: term(), vendor_specific_application_id :: term(), firmware_revision :: term(), avp :: term()}.
一个记录,包含本地 Diameter 节点和具有已建立传输连接的远程 Diameter 对等端的身份,以及由能力交换确定的能力。记录的每个字段都是一个二元组,由(本地)主机和(远程)对等端的值组成。可选或可能有多个值编码为值列表,强制值编码为裸值。
-type message() :: diameter_codec:message().
Diameter 消息的表示形式,传递给 diameter:call/4
或从 handle_request/3
回调返回。
-type packet() :: diameter_codec:packet().
传入和传出 Diameter 消息的容器,通过编码/解码和传输传递。除非另有说明,否则不应在返回值中设置字段。
-type peer() :: {peer_ref(), capabilities()}.
表示 Diameter 对等连接的元组。
-type peer_ref() :: term().
标识与 Diameter 对等端的传输连接的术语。
-type state() :: term().
应用程序回调函数 peer_up/3
、peer_down/3
和(可选)pick_peer/4
维护的状态。初始状态在调用 diameter:start_service/2
时配置,该调用在服务上配置应用程序。返回状态的回调函数在通用的特定于服务的进程中评估,而那些不返回状态的回调函数在特定于请求的进程中评估。
回调
-callback handle_answer(Packet, Request, SvcName, Peer) -> Result when Packet :: packet(), Request :: message(), SvcName :: diameter:service_name(), Peer :: peer(), Result :: term().
当从对等端收到应答消息时调用。返回值从 diameter:call/4
返回,除非指定了 detach
选项。
解码后的应答记录和未解码的二进制文件分别位于参数 packet() 的 msg
和 bin
字段中。Request
是从 prepare_request/3
或 prepare_retransmit/3
返回的传出请求消息。
对于对 diameter:call/4
的任何给定调用,最多有一个 handle_answer/4
回调:任何重复的应答(由于重新传输或其他原因)都会被丢弃。同样,只会调用 handle_answer/4
或 handle_error/4
中的一个。
默认情况下,无法成功解码的传入应答消息会导致请求进程失败,从而导致 diameter:call/4
返回 {error, failure}
,除非指定了 detach
选项。特别是,在这种情况下没有 handle_error/4
回调。可以设置 diameter:application_opt() answer_errors
以更改此行为。
-callback handle_error(Reason, Request, SvcName, Peer) -> Result when Reason :: timeout | failover | term(), Request :: message(), SvcName :: diameter:service_name(), Peer :: peer(), Result :: term().
当在收到对传出请求的应答消息之前发生错误时调用。返回值从 diameter:call/4
返回,除非指定了 detach
选项。
Reason timeout
表示在相应的 diameter:call_opt() 中指定的时间内未收到应答消息。Reason failover
表示已发送请求的对等端的传输连接变得不可用,并且未选择备用对等端。
-callback handle_request(Packet, SvcName, Peer) -> Action when Packet :: packet(), SvcName :: term(), Peer :: peer(), Action :: Reply | {relay, [Opt]} | discard | {eval | eval_packet, Action, PostF}, Reply :: {reply, packet() | message()} | {answer_message, 3000..3999 | 5000..5999} | {protocol_error, 3000..3999}, Opt :: diameter:call_opt(), PostF :: diameter:eval().
当从对等端收到请求消息时调用。回调发生的应用程序(即,通过 diameter:start_service/2
配置的回调模块)由传入请求消息的标头中的应用程序标识符确定,选择的模块是声明自己定义了相关应用程序或中继应用程序的模块。
参数 packet() 具有以下签名。
#diameter_packet{header = #diameter_header{},
avps = [#diameter_avp{}],
msg = record() | undefined,
errors = [Unsigned32() | {Unsigned32(), #diameter_avp{}}],
bin = binary(),
transport_data = term()}
如果请求已在中继应用程序中接收,则 msg
字段将为 undefined
。否则,它包含表示请求的记录,如 diameter_dict(4) 中所述。
errors
字段指定在解码请求时发现的任何错误代码。这用于在返回的应答中设置 Result-Code 和/或 Failed-AVP,除非回调返回一个 #diameter_packet{}
,其 errors
字段设置为自己的非空列表,在这种情况下,将使用此列表,或者使用原子 false
来禁用 Result-Code 和 Failed-AVP 的任何设置。请注意,diameter 检测到的错误属于 3xxx 和 5xxx 系列,分别是协议错误和永久性故障。errors
列表为空,如果请求已在中继应用程序中接收。
transport_data
字段包含一个任意项,该项从相关的传输模块传递到 Diameter,或者如果传输模块没有指定数据,则为原子 undefined
。如果返回 message(),则该项会被保留,但必须在返回的 packet() 中显式设置。
每个可能的返回值的语义如下。
{reply,
packet()
|
message()
}
- 将指定的应答消息发送给对等方。对于 packet(),要发送的消息必须设置在msg
字段中,并且可以将header
字段设置为#diameter_header{}
以指定应该在传出的应答中保留的值,否则由 Diameter 设置适当的值。{answer_message, 3000..3999|5000..5999}
- 向对等方发送包含指定 Result-Code 的应答消息。等效于{reply, ['answer-message' | Avps]
其中
Avps
设置 Origin-Host、Origin-Realm、指定的 Result-Code 以及(如果请求包含)Session-Id AVP,并且可能包含如下所述的 Failed-AVP。返回 3xxx 或 5xxx 以外的值将导致相关的请求进程失败,如果对等连接配置了 RFC 3588 通用字典
diameter_gen_base_rfc3588
,则返回 5xxx 值也会导致失败。(因为 RFC 3588 只允许在应答消息中使用 3xxx 值。)当返回 5xxx 时,如果找到,则 Failed-AVP 将使用参数 packet() 的
errors
字段中第一个匹配的 Result-Code/AVP 对的 AVP 进行填充。如果这不合适,则应显式构造应答消息,并在reply
元组中返回。{relay, Opts}
- 将请求中继到另一个对等方,充当 Diameter 中继代理。如果检测到路由循环,则使用 3005 (DIAMETER_LOOP_DETECTED) 回答请求。否则,将 Route-Record AVP(包含发送对等方的 Origin-Host)添加到请求中,并且pick_peer/4
和后续回调的发生方式与显式调用diameter:call/4
时相同。传入请求的端到端标识符保留在中继请求的标头中。返回的
Opts
不应指定detach
。中继请求的后续handle_answer/4
回调必须返回其第一个参数,即包含应答消息的 packet()。请注意,可以指定extra
选项以提供参数,以便在需要时将中继情况与其他情况区分开来。任何其他返回值(例如,来自handle_error/4
回调的值)都会导致使用 3002 (DIAMETER_UNABLE_TO_DELIVER) 回答请求。discard
- 丢弃请求。不向对等方发送应答消息。{eval, Action, PostF}
- 处理请求,如同已返回Action
,然后在请求进程中评估PostF
。返回值被忽略。{eval_packet, Action, PostF}
- 与eval
类似,但在传输之前,在任何编码的#diameter_packet{}
上评估PostF
,其中bin
字段包含编码的二进制数据。返回值被忽略。{protocol_error, 3000..3999}
- 等效于{answer_message, 3000..3999}
。
注意
包含错误的请求可能由 Diameter 回答,而无需执行回调,具体取决于 diameter:application_opt()
request_errors
的值。
-callback peer_down(SvcName, Peer, State) -> NewState when SvcName :: diameter:service_name(), Peer :: peer(), State :: state(), NewState :: state().
在先前调用 peer_up/3
之后,调用以指示本地 Erlang 节点上的对等连接不再可用。特别是,连接的 RFC 3539 监视状态机已离开 OKAY
状态,并且对等端将不再是 pick_peer/4
回调中的候选者。
-callback peer_up(SvcName, Peer, State) -> NewState when SvcName :: diameter:service_name(), Peer :: peer(), State :: state(), NewState :: state().
调用以指示本地 Erlang 节点上对等连接的可用性。特别是,与对等端的能力交换已指示支持相关应用程序,连接的 RFC 3539 监视状态机已达到 OKAY
状态,并且可以发送和接收 Diameter 消息。
注意
看门狗状态机可以在不进行新的能力交换的情况下,从状态
SUSPECT
到达状态OKAY
。新的传输连接(和能力交换)会产生新的 peer_ref()。
注意
不要求回调在收到传入请求之前返回:
handle_request/3
回调必须独立于peer_up/3
和peer_down/3
进行处理。
-callback pick_peer(LocalCandidates, RemoteCandidates, SvcName, State) -> Selection | false when LocalCandidates :: [peer()], RemoteCandidates :: [peer()], SvcName :: diameter:service_name(), State :: state(), NewState :: state(), Selection :: {ok, Peer} | {Peer, NewState}, Peer :: peer() | false.
由于调用 diameter:call/4
而调用,以选择传出请求的目标对等端。返回值指示选择的对等端。
候选列表仅包含在能力交换期间声明支持相关 Diameter 应用程序、未被调用 diameter:call/4
的 filter
选项排除,并且其看门狗状态机处于 OKAY
状态的对等方。元素的顺序未指定,但任何其 Origin-Host 和 Origin-Realm 与传出请求匹配的对等方(在 diameter:call/4
的 {filter, {all, [host, realm]}}
选项的意义上)将放置在列表的开头。LocalCandidates
包含其传输进程位于本地 Erlang 节点上的对等方,而 RemoteCandidates
包含由具有相同名称的服务从其他节点传递的对等方。
返回 peer() 的回调将之后是 prepare_request/3
回调,并且如果后者指示应发送请求,则取决于是否从对等方收到应答消息,之后是 handle_answer/4
或 handle_error/4
。如果在 prepare_request/3
之后传输变得不可用,则可能会发生新的 pick_peer/4
回调以故障转移到备用对等方,之后 prepare_retransmit/3
将取代 prepare_request/3
来重新发送请求。无法保证选择备用对等方的 pick_peer/4
回调之后会进行任何其他回调,因为如果从先前选择的对等方收到应答,则会放弃向备用对等方重新传输。
返回值 false
和 {false, State}
(即 NewState = State
)是等效的,{ok, Peer}
和 {Peer, State}
也是等效的。
注意
diameter:service_opt()
use_shared_peers
确定服务是否使用从其他节点共享的对等方。如果不是,则RemoteCandidates
为空列表。
警告
仅当相关 Diameter 应用程序配置了 diameter:application_opt()
{call_mutates_state, true}
时,才允许返回值{Peer, NewState}
。否则,State
参数始终是在应用程序上配置的初始值,而不是peer_up/3
或peer_down/3
回调返回的任何后续值。
-callback prepare_request(Packet, SvcName, Peer) -> Action when Packet :: packet(), SvcName :: diameter:service_name(), Peer :: peer(), Action :: Send | Discard | {eval_packet, Action, PostF}, Send :: {send, packet() | message()}, Discard :: {discard, Reason :: term()} | discard, PostF :: diameter:eval().
调用以返回用于编码和传输的请求。允许发送者使用所选对等端的能力来修改传出的请求。许多实现可能只想简单地返回 {send, Packet}
返回的 packet() 应将要编码的请求设置在其 msg
字段中,并且可以设置 transport_data
字段以将信息传递给传输进程。传递给 diameter:call/4
的额外参数可用于将传输(或任何其他)数据传递给回调。
返回的 packet() 可以将 header
字段设置为 #diameter_header{}
以指定应在传出请求中保留的值,否则这些值将是 Packet
中包含的标头记录中的值。返回的 length
、cmd_code
或 application_id
将被忽略。
返回的 PostF
将在传输之前,在任何编码的 #diameter_packet{}
上进行评估,其中 bin
字段包含编码的二进制数据。返回值被忽略。
返回 {discard, Reason}
会导致请求中止,并且调用该回调的 diameter:call/4
会返回 {error, Reason}
。返回 discard
等效于返回 {discard, discarded}
。
-callback prepare_retransmit(Packet, SvcName, Peer) -> Action when Packet :: packet(), SvcName :: diameter:service_name(), Peer :: peer(), Action :: Send | Discard | {eval_packet, Action, PostF}, Send :: {send, packet() | message()}, Discard :: {discard, Reason :: term()} | discard, PostF :: diameter:eval().
调用以返回用于编码和重新传输的请求。在对等连接丢失并选择了备用对等端的情况下,具有与 prepare_request/3
相同的作用,但是参数 packet() 是由初始 prepare_request/3
返回的。
返回 {discard, Reason}
会导致请求中止,并使用 Reason
作为初始参数执行 handle_error/4
回调。返回 discard
等效于返回 {discard, discarded}
。