查看源码 megaco_user 行为 (megaco v4.7)
Megaco 应用程序用户的回调模块
此模块定义了 Megaco 用户的回调行为。符合 megaco_user 要求的回调模块必须导出以下函数
- handle_connect/2,3
- handle_disconnect/3
- handle_syntax_error/3,4
- handle_message_error/3,4
- handle_trans_request/3,4
- handle_trans_long_request/3,4
- handle_trans_reply/4,5
- handle_trans_ack/4,5
- handle_unexpected_trans/3,4
- handle_trans_request_abort/4,5
- handle_segment_reply/5,6
它们的语义及其确切签名将在下面解释。
user_args
配置参数可用于扩展回调函数的参数列表。例如,handle_connect 函数默认接受两个参数
handle_connect(Handle, Version)
但是,如果 user_args
参数设置为更长的列表,例如 [SomePid,SomeTableRef]
,则回调函数应在参数列表的末尾添加这些(在这种情况下为两个)额外的参数
handle_connect(Handle, Version, SomePid, SomeTableRef)
注意
下面大多数函数都有一个可选的
Extra
参数(例如,handle_unexpected_trans/4)。只有在调用receive_message/5
或process_received_message/5
时,且Extra
参数不为ignore_extra
时,才会调用接受此参数的函数。
数据类型
action_request() = #'ActionRequest'{}
action_reply() = #'ActionReply'{}
error_desc() = #'ErrorDescriptor'{}
segment_no() = integer()
conn_handle() = #megaco_conn_handle{}
由 megaco:connect/4,5
最初返回的记录。它标识一个“虚拟”连接,并且可以在重新连接(断开连接 + 连接)后重复使用。
protocol_version() = integer()
是实际的协议版本。在大多数情况下,协议版本是从处理后的消息中检索的,但也有例外
- 当
handle_connect/2,3
由显式调用megaco:connect/4,5
触发时。 handle_disconnect/3
handle_syntax_error/3
在这些情况下,ProtocolVersion 默认版本是从静态连接配置中获取的
megaco:conn_info(ConnHandle, protocol_version)
.
概要
类型
-type megaco_timer() :: infinity | non_neg_integer() | #megaco_incr_timer{wait_for :: term(), factor :: term(), incr :: term(), max_retries :: term()}.
回调
-callback handle_connect(ConnHandle, ProtocolVersion) -> ok | error | {error, ErrorDescr} when ConnHandle :: conn_handle(), ProtocolVersion :: megaco_encoder:protocol_version(), ErrorDescr :: megaco_encoder:error_desc().
等效于 handle_connect/3
。
-callback handle_connect(ConnHandle, ProtocolVersion, Extra) -> ok | error | {error, ErrorDescr} when ConnHandle :: conn_handle(), ProtocolVersion :: megaco_encoder:protocol_version(), Extra :: term(), ErrorDescr :: megaco_encoder:error_desc().
当建立新连接时调用
连接可以通过显式调用 megaco:connect/4 或在首次调用 megaco:receive_message/3 时隐式建立。
通常,媒体网关 (MG) 会显式连接,而媒体网关控制器 (MGC) 会隐式连接。
在媒体网关控制器 (MGC) 端,可以通过返回 {error, ErrorDescr}
或仅返回 error
来拒绝连接请求(并向网关发送消息错误回复),这将生成一个代码为 402(未授权)且原因为“用户拒绝连接”的错误描述符(对于所有未知结果,例如退出信号或抛出也是如此)。
请参阅上面有关 handle_message_error/4
中的 Extra
参数的备注。
handle_connect/3
(带 Extra
)也可以作为调用 megaco:connect/5
函数的结果调用(如果该函数使用与 ignore_extra
不同的 Extra
参数调用)。
-callback handle_disconnect(ConnHandle, ProtocolVersion, Reason) -> megaco:void() when ConnHandle :: conn_handle(), ProtocolVersion :: megaco_encoder:protocol_version(), Reason :: term().
当连接被断开时调用
断开连接可以通过显式调用 megaco:disconnect/2 或在连接的控制进程死亡时隐式完成。
-callback handle_message_error(ConnHandle, ProtocolVersion, ErrorDescr) -> megaco:void() when ConnHandle :: conn_handle(), ProtocolVersion :: megaco_encoder:protocol_version(), ErrorDescr :: megaco_encoder:error_desc().
-callback handle_message_error(ConnHandle, ProtocolVersion, ErrorDescr, Extra) -> megaco:void() when ConnHandle :: conn_handle(), ProtocolVersion :: megaco_encoder:protocol_version(), ErrorDescr :: megaco_encoder:error_desc(), Extra :: term().
当接收到的消息仅包含错误而不是事务列表时调用。
传入消息由 megaco:receive_message/4 传递并成功解码。通常,消息包含事务列表,但它也可能在消息的顶层包含一个 ErrorDescriptor。
消息错误是在协议的另一端远程检测到的。你可能不想回复它,但它可能表明你有未完成的事务,这些事务不会收到任何响应(请求 -> 回复;回复 -> 确认)。
请参阅上面有关 handle_message_error/4
中的 Extra
参数的备注。
-callback handle_segment_reply(ConnHandle, ProtocolVersion, TransNo, SegNo, SegCompl) -> ok when ConnHandle :: conn_handle(), ProtocolVersion :: megaco_encoder:protocol_version(), TransNo :: integer(), SegNo :: integer(), SegCompl :: asn1_NOVALUE | 'NULL'.
-callback handle_segment_reply(ConnHandle, ProtocolVersion, TransNo, SegNo, SegCompl, Extra) -> ok when ConnHandle :: conn_handle(), ProtocolVersion :: megaco_encoder:protocol_version(), TransNo :: integer(), SegNo :: megaco_encoder:segment_no(), SegCompl :: asn1_NOVALUE | 'NULL', Extra :: term().
如果 segment_reply_ind 配置选项设置为 true,则当接收到分段回复时,将调用此函数。
这实际上是一个进度报告。
请参阅上面有关 handle_segment_reply/6
中的 Extra
参数的备注。
-callback handle_syntax_error(ReceiveHandle, ProtocolVersion, DefaultED) -> reply | {reply, ED} | no_reply | {no_reply, ED} when ReceiveHandle :: receive_handle(), ProtocolVersion :: megaco_encoder:protocol_version(), DefaultED :: megaco_encoder:error_desc(), ED :: megaco_encoder:error_desc().
-callback handle_syntax_error(ReceiveHandle, ProtocolVersion, DefaultED, Extra) -> reply | {reply, ED} | no_reply | {no_reply, ED} when ReceiveHandle :: receive_handle(), ProtocolVersion :: megaco_encoder:protocol_version(), DefaultED :: megaco_encoder:error_desc(), ED :: megaco_encoder:error_desc(), Extra :: term().
当接收到的消息存在语法错误时调用
传入消息由 megaco:receive_message/4 传递,通常会成功解码。但是,如果解码失败,则会调用此函数,以决定发起者是否应收到回复消息 (reply) 或是否应静默丢弃回复 (no_reply)。
语法错误是在协议的此端本地检测到的,并且可能有多种原因,例如,传输层发生故障、选择了错误的编码器/解码器、所选编码器/解码器配置错误等。
错误描述符默认为 DefaultED
,但可以通过返回 {reply,ED}
或 {no_reply,ED}
来覆盖它,而不是分别返回 reply
和 no_reply
。
任何其他返回值(包括退出信号或抛出)和 DefaultED
都将被使用。
请参阅上面关于 note 中 handle_syntax_error/4
的 Extra
参数的说明。
-callback handle_trans_ack(ConnHandle, ProtocolVersion, AckStatus, AckData) -> ok when ConnHandle :: conn_handle(), ProtocolVersion :: megaco_encoder:protocol_version(), AckStatus :: ok | {error, Reason}, AckData :: term(), Reason :: UserCancelReason | SendReason | OtherReason, UserCancelReason :: {user_cancel, ReasonForUserCancel}, ReasonForUserCancel :: term(), SendReason :: SendCancelledReason | SendFailedReason, SendCancelledReason :: {send_message_cancelled, ReasonForSendCancel}, ReasonForSendCancel :: term(), SendFailedReason :: {send_message_failed, ReasonForSendFailure}, ReasonForSendFailure :: term(), OtherReason :: term().
等效于 handle_trans_ack/5
。
-callback handle_trans_ack(ConnHandle, ProtocolVersion, AckStatus, AckData, Extra) -> ok when ConnHandle :: conn_handle(), ProtocolVersion :: megaco_encoder:protocol_version(), AckStatus :: ok | {error, Reason}, AckData :: term(), Extra :: term(), Reason :: UserCancelReason | SendReason | OtherReason, UserCancelReason :: {user_cancel, ReasonForUserCancel}, ReasonForUserCancel :: term(), SendReason :: SendCancelledReason | SendFailedReason, SendCancelledReason :: {send_message_cancelled, ReasonForSendCancel}, ReasonForSendCancel :: term(), SendFailedReason :: {send_message_failed, ReasonForSendFailure}, ReasonForSendFailure :: term(), OtherReason :: term().
可选地为事务确认调用
是否调用此函数取决于先前对 handle_trans_request/3 的调用的回复。handle_trans_request/3 函数可以决定返回 {handle_ack, ack_data()} 或 {handle_sloppy_ack, ack_data()},这意味着您需要立即确认回复,并且应调用此函数来处理确认。
此函数的 ack_data() 参数是 handle_trans_request/3 返回的 Erlang 项。
如果 AckStatus 为 ok,则表示这是对事务回复的真实确认。
如果 AckStatus 为 {error, Reason},则表示确认甚至回复(这是对回复的确认)都未送达,但没有必要再等待其到达。当发生以下情况时会出现这种情况:
reply_timer
-reply_timer
最终超时。回复发送失败 - 当 megaco 因任何原因无法发送回复时(请参阅 handle_trans_reply)。
取消 - 用户已明确取消等待 (megaco:cancel/2)。
请参阅上面关于 note 中 handle_trans_ack/5
的 Extra
参数的说明。
-callback handle_trans_long_request(ConnHandle, ProtocolVersion, ReqData) -> Reply when ConnHandle :: conn_handle(), ProtocolVersion :: megaco_encoder:protocol_version(), ReqData :: term(), Reply :: {AckAction, ActualReply} | {AckAction, ActualReply, SendOptions}, AckAction :: discard_ack | {handle_ack, AckData} | {handle_sloppy_ack, AckData}, ActualReply :: [megaco_encoder:action_reply()] | megaco_encoder:error_desc(), AckData :: term(), SendOptions :: [SendOption], SendOption :: {reply_timer, megaco_timer()} | {send_handle, term()} | {protocol_version, megaco_encoder:protocol_version()}.
-callback handle_trans_long_request(ConnHandle, ProtocolVersion, ReqData, Extra) -> Reply when ConnHandle :: conn_handle(), ProtocolVersion :: megaco_encoder:protocol_version(), ReqData :: term(), Extra :: term(), Reply :: {AckAction, ActualReply} | {AckAction, ActualReply, SendOptions}, AckAction :: discard_ack | {handle_ack, AckData} | {handle_sloppy_ack, AckData}, ActualReply :: [megaco_encoder:action_reply()] | megaco_encoder:error_desc(), AckData :: term(), SendOptions :: [SendOption], SendOption :: {reply_timer, megaco_timer()} | {send_handle, term()} | {protocol_version, megaco_encoder:protocol_version()}.
可选地为耗时的事务请求调用
是否调用此函数取决于先前对 handle_trans_request/3 的调用的回复。handle_trans_request/3 函数可以决定自己处理操作请求,或将处理委托给此函数。
此函数的 req_data() 参数是 handle_trans_request/3 返回的 Erlang 项。
任何其他返回值(包括退出信号或抛出)都将导致错误描述符,代码为 500(内部网关错误),模块名称(回调模块)作为原因。
请参阅上面关于 note 中 handle_trans_long_request/4
的 Extra
参数的说明。
-callback handle_trans_reply(ConnHandle, ProtocolVersion, UserReply, ReplyData) -> ok when ConnHandle :: conn_handle(), ProtocolVersion :: megaco_encoder:protocol_version(), UserReply :: Success | Failure, ReplyData :: term(), Success :: {ok, Result}, Result :: TransactionResult | SegmentResult, TransactionResult :: [megaco_encoder:action_reply()], SegmentResult :: {megaco_encoder:segment_no(), LastSegment, [megaco_encoder:action_reply()]}, Failure :: {error, Reason} | {error, ReplyNo, Reason}, Reason :: TransactionReason | SegmentReason | UserCancelReason | SendReason | OtherReason, TransactionReason :: megaco_encoder:error_desc(), SegmentReason :: {megaco_encoder:segment_no(), LastSegment, megaco_encoder:error_desc()}, OtherReason :: timeout | {segment_timeout, MissingSegments} | exceeded_recv_pending_limit | term(), LastSegment :: boolean(), MissingSegments :: [megaco_encoder:segment_no()], UserCancelReason :: {user_cancel, ReasonForUserCancel}, ReasonForUserCancel :: term(), SendReason :: SendCancelledReason | SendFailedReason, SendCancelledReason :: {send_message_cancelled, ReasonForSendCancel}, ReasonForSendCancel :: term(), SendFailedReason :: {send_message_failed, ReasonForSendFailure}, ReasonForSendFailure :: term(), ReplyNo :: pos_integer().
等效于 handle_trans_reply/5
。
-callback handle_trans_reply(ConnHandle, ProtocolVersion, UserReply, ReplyData, Extra) -> ok when ConnHandle :: conn_handle(), ProtocolVersion :: megaco_encoder:protocol_version(), UserReply :: Success | Failure, ReplyData :: term(), Extra :: term(), Success :: {ok, Result}, Result :: TransactionResult | SegmentResult, TransactionResult :: [megaco_encoder:action_reply()], SegmentResult :: {megaco_encoder:segment_no(), LastSegment, [megaco_encoder:action_reply()]}, Failure :: {error, Reason} | {error, ReplyNo, Reason}, Reason :: TransactionReason | SegmentReason | UserCancelReason | SendReason | OtherReason, TransactionReason :: megaco_encoder:error_desc(), SegmentReason :: {megaco_encoder:segment_no(), LastSegment, megaco_encoder:error_desc()}, OtherReason :: timeout | {segment_timeout, MissingSegments} | exceeded_recv_pending_limit | term(), LastSegment :: boolean(), MissingSegments :: [megaco_encoder:segment_no()], UserCancelReason :: {user_cancel, ReasonForUserCancel}, ReasonForUserCancel :: term(), SendReason :: SendCancelledReason | SendFailedReason, SendCancelledReason :: {send_message_cancelled, ReasonForSendCancel}, ReasonForSendCancel :: term(), SendFailedReason :: {send_message_failed, ReasonForSendFailure}, ReasonForSendFailure :: term(), ReplyNo :: pos_integer().
可选地为事务回复调用
事务请求的发送者可以选择决定,发起 Erlang 进程是应该同步等待(megaco:call/3
)回复,还是应该异步发送消息(megaco:cast/3
),并将回复的处理委托给此回调函数。
请注意,如果回复是分段的(拆分为几个较小的消息;段),则 UserReply 中还会包含一些额外的信息、段号以及是否已收到回复的所有段的指示。
ReplyData
默认为 megaco:lookup(ConnHandle, reply_data)
,但可以通过 megaco:cast/3
选项显式覆盖,以便转发有关发起进程的调用上下文的信息。
在 success()
中,UserReply
要么包含
- 可能包含错误指示的“ActionReply”记录的列表。
- 一个包含三个元素的元组:段号、
最后一段指示符
以及最后可能包含错误指示的“ActionReply”记录的列表。当然,这只有在回复是分段的情况下才有可能。
failure()
表示本地或外部错误,可以是以下之一
transaction_reason()
表示远程用户已回复显式的 transactionError。segment_reason()
表示远程用户已针对此段回复显式的 transactionError。当然,这只有在回复是分段的情况下才有可能。user_cancel_reason()
表示该请求已被用户取消。reason_for_user_cancel()
是在调用 cancel 函数时给出的原因。send_reason()
表示传输模块 send_message 函数未发送消息。原因可能是send_cancelled_reason()
- 消息发送被故意取消。reason_for_send_cancel()
是在 send_message 函数的cancel
返回中给出的原因。send_failed_reason()
- 尝试发送消息时发生错误。
other_reason()
表示其他一些错误,例如timeout
- 回复在请求计时器过期之前未能到达。{segment_timeout, missing_segments()}
- 在段计时器过期之前,未传递一个或多个段。exceeded_recv_pending_limit
- 此请求的挂起限制已超出。
请参阅上面关于 note 中 handle_trans_reply/5
的 Extra
参数的说明。
-callback handle_trans_request(ConnHandle, ProtocolVersion, ActionRequests) -> Pending | Reply | ignore_trans_request when ConnHandle :: conn_handle(), ProtocolVersion :: megaco_encoder:protocol_version(), ActionRequests :: [megaco_encoder:action_request()], Pending :: {pending, ReqData}, ReqData :: term(), Reply :: {AckAction, ActualReply} | {AckAction, ActualReply, SendOptions}, AckAction :: discard_ack | {handle_ack, AckData} | {handle_pending_ack, AckData} | {handle_sloppy_ack, AckData}, ActualReply :: [megaco_encoder:action_reply()] | megaco_encoder:error_desc(), AckData :: term(), SendOptions :: [SendOption], SendOption :: {reply_timer, megaco_timer()} | {send_handle, term()} | {protocol_version, integer()}.
-callback handle_trans_request(ConnHandle, ProtocolVersion, ActionRequests, Extra) -> Pending | Reply | ignore_trans_request when ConnHandle :: conn_handle(), ProtocolVersion :: megaco_encoder:protocol_version(), ActionRequests :: [megaco_encoder:action_request()], Extra :: term(), Pending :: {pending, ReqData}, ReqData :: term(), Reply :: {AckAction, ActualReply} | {AckAction, ActualReply, SendOptions}, AckAction :: discard_ack | {handle_ack, AckData} | {handle_pending_ack, AckData} | {handle_sloppy_ack, AckData}, ActualReply :: [megaco_encoder:action_reply()] | megaco_encoder:error_desc(), AckData :: term(), SendOptions :: [SendOption], SendOption :: {reply_timer, megaco_timer()} | {send_handle, term()} | {protocol_version, integer()}.
为每个事务请求调用
传入消息由 megaco:receive_message/4 传递并成功解码。通常,消息包含事务列表,并且对于消息中的每个 TransactionRequest 都会调用此函数。
此函数接收“ActionRequest”记录的列表,并具有三个主要选项
返回 ignore_trans_request
- 决定完全忽略这些操作请求。返回 pending()
- 决定这些操作请求的处理将花费很长时间,并且发起者应立即获得作为临时响应的“TransactionPending”回复。这些操作请求的实际处理应改为委托给 handle_trans_long_request/3 回调函数,并将 req_data() 作为其参数之一。返回 reply()
- 处理操作请求,并返回指示某些致命错误的 error_descr() 或操作回复列表(带通配符或不带通配符)。如果由于某种原因 megaco 无法传递回复,则此原因将通过调用回调函数 handle_trans_ack 传递给用户,除非
ack_action() = discard_ack
。ack_action() 是以下之一
discard_ack
- 表示您不关心是否确认回复。{handle_ack, ack_data()} | {handle_ack, ack_data(), send_options()}
- 表示您希望在另一方收到此事务回复时立即确认。当最终收到确认时,将调用 handle_trans_ack/4 回调函数,并将 ack_data() 作为其参数之一。ack_data() 可以是任何 Erlang 项。{handle_pending_ack, ack_data()} | {handle_pending_ack, ack_data(), send_options()}
- 这与上述效果相同,当且仅当 megaco 至少为该请求发送了一条挂起消息(在该请求的处理过程中)。如果没有发送挂起消息,则将不请求立即确认。请注意,仅当
sent_pending_limit
配置选项已设置为整数值时,此操作才会按指定方式工作。{handle_sloppy_ack, ack_data()}| {handle_sloppy_ack, ack_data(), send_options()}
- 表示您希望在某个时间收到确认。当最终收到确认时,将调用 handle_trans_ack/4 回调函数,并将 ack_data() 作为其参数之一。ack_data() 可以是任何 Erlang 项。
任何其他返回值(包括退出信号或抛出)都将导致错误描述符,代码为 500(内部网关错误),模块名称(回调模块)作为原因。
请参阅上面关于 note 中 handle_trans_request/4
的 Extra
参数的说明。
-callback handle_trans_request_abort(ConnHandle, ProtocolVersion, TransNo, Pid) -> ok when ConnHandle :: conn_handle(), ProtocolVersion :: megaco_encoder:protocol_version(), TransNo :: integer(), Pid :: undefined | pid().
-callback handle_trans_request_abort(ConnHandle, ProtocolVersion, TransNo, Pid, Extra) -> ok when ConnHandle :: conn_handle(), ProtocolVersion :: megaco_encoder:protocol_version(), TransNo :: integer(), Pid :: undefined | pid(), Extra :: term().
当事务请求被中止时调用
如果超出发起挂起限制,则调用此函数。这通常意味着请求花费了异常长的时间才能完成。
请参阅上面关于 note 中 handle_trans_request_abort/5
的 Extra
参数的说明。
-callback handle_unexpected_trans(ConnHandle, ProtocolVersion, Trans) -> ok when ConnHandle :: conn_handle(), ProtocolVersion :: megaco_encoder:protocol_version(), Trans :: megaco_encoder:transaction_pending() | megaco_encoder:transaction_reply() | megaco_encoder:transaction_response_ack().
-callback handle_unexpected_trans(ConnHandle, ProtocolVersion, Trans, Extra) -> ok when ConnHandle :: conn_handle(), ProtocolVersion :: megaco_encoder:protocol_version(), Trans :: megaco_encoder:transaction_pending() | megaco_encoder:transaction_reply() | megaco_encoder:transaction_response_ack(), Extra :: term().
当收到意外消息时调用
如果未及时收到对请求的回复,megaco 堆栈会从其表中删除有关该请求的所有信息。如果在此操作完成后回复到达,则应用程序无法知道将此消息发送到何处。通过在本地节点(具有链接的节点)上调用此函数,将消息传递给“用户”。
请参阅上面关于 note 中 handle_unexpected_trans/4
的 Extra
参数的说明。