/source/otp_src_R14B02/lib/megaco/src/engine/megaco_erl_dist_encoder.erl

https://github.com/remotesyssupport/omnibus · Erlang · 275 lines · 181 code · 41 blank · 53 comment · 5 complexity · cabb01707bd6339b4fa846d5845da4f2 MD5 · raw file

  1. %%
  2. %% %CopyrightBegin%
  3. %%
  4. %% Copyright Ericsson AB 2000-2009. All Rights Reserved.
  5. %%
  6. %% The contents of this file are subject to the Erlang Public License,
  7. %% Version 1.1, (the "License"); you may not use this file except in
  8. %% compliance with the License. You should have received a copy of the
  9. %% Erlang Public License along with this software. If not, it can be
  10. %% retrieved online at http://www.erlang.org/.
  11. %%
  12. %% Software distributed under the License is distributed on an "AS IS"
  13. %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  14. %% the License for the specific language governing rights and limitations
  15. %% under the License.
  16. %%
  17. %% %CopyrightEnd%
  18. %%
  19. %%
  20. %%----------------------------------------------------------------------
  21. %% Purpose: Externalize/internalize Megaco/H.248 messages
  22. %%----------------------------------------------------------------------
  23. -module(megaco_erl_dist_encoder).
  24. -behaviour(megaco_encoder).
  25. -export([encode_message/3, decode_message/3,
  26. decode_mini_message/3,
  27. encode_transaction/3,
  28. encode_action_requests/3,
  29. encode_action_request/3,
  30. encode_command_request/3,
  31. encode_action_reply/3
  32. ]).
  33. -export([version_of/2]).
  34. %% Backward compatible funcs:
  35. -export([encode_message/2, decode_message/2]).
  36. -include("megaco_message_internal.hrl").
  37. -define(MC_MOD, megaco_erl_dist_encoder_mc).
  38. %%----------------------------------------------------------------------
  39. %% Convert a 'MegacoMessage' record into a binary
  40. %% Return {ok, DeepIoList} | {error, Reason}
  41. %%----------------------------------------------------------------------
  42. encode_message(Config,
  43. #'MegacoMessage'{mess = #'Message'{version = V}} = MegaMsg) ->
  44. encode_message(Config, V, MegaMsg).
  45. encode_message([{version3, _}|EC], Vsn, MegaMsg) ->
  46. encode_message(EC, Vsn, MegaMsg);
  47. encode_message([megaco_compressed|Config], Vsn, MegaMsg)
  48. when is_record(MegaMsg, 'MegacoMessage') ->
  49. {ok, erlang:term_to_binary(?MC_MOD:encode(MegaMsg, Vsn), Config)};
  50. encode_message([{megaco_compressed, Mod}|Config], Vsn, MegaMsg)
  51. when is_atom(Mod) and is_record(MegaMsg, 'MegacoMessage') ->
  52. {ok, erlang:term_to_binary(Mod:encode(MegaMsg, Vsn), Config)};
  53. encode_message(Config, _Vsn, MegaMsg)
  54. when is_record(MegaMsg, 'MegacoMessage') ->
  55. {ok, erlang:term_to_binary(MegaMsg, Config)};
  56. encode_message(_Config, _Vsn, _MegaMsg) ->
  57. {error, not_a_megaco_message}.
  58. %%----------------------------------------------------------------------
  59. %% Convert a transaction record into a binary
  60. %% Return {ok, Bin} | {error, Reason}
  61. %%----------------------------------------------------------------------
  62. encode_transaction([{version3, _}|EC], Vsn, Trans) ->
  63. encode_transaction(EC, Vsn, Trans);
  64. encode_transaction([megaco_compressed|Config], _Vsn, Trans) ->
  65. {ok, erlang:term_to_binary(?MC_MOD:encode(Trans), Config)};
  66. encode_transaction([{megaco_compressed, Mod}|Config], _Vsn, Trans) ->
  67. {ok, erlang:term_to_binary(Mod:encode(Trans), Config)};
  68. encode_transaction(Config, _Vsn, Trans) ->
  69. {ok, erlang:term_to_binary(Trans, Config)}.
  70. %%----------------------------------------------------------------------
  71. %% Convert a list of ActionRequest record's into a binary
  72. %% Return {ok, Binary} | {error, Reason}
  73. %%----------------------------------------------------------------------
  74. encode_action_requests([{version3, _}|EC], Vsn, ActReqs) ->
  75. encode_action_requests(EC, Vsn, ActReqs);
  76. encode_action_requests([megaco_compressed|Config], Vsn, ActReqs0)
  77. when is_list(ActReqs0) ->
  78. ActReqs = [?MC_MOD:encode(AR, Vsn) || AR <- ActReqs0],
  79. {ok, erlang:term_to_binary(ActReqs, Config)};
  80. encode_action_requests([{megaco_compressed, Mod}|Config], Vsn, ActReqs0)
  81. when is_list(ActReqs0) ->
  82. ActReqs = [Mod:encode(AR, Vsn) || AR <- ActReqs0],
  83. {ok, erlang:term_to_binary(ActReqs, Config)};
  84. encode_action_requests(Config, _Vsn, ActReqs)
  85. when is_list(ActReqs) ->
  86. {ok, erlang:term_to_binary(ActReqs, Config)}.
  87. %%----------------------------------------------------------------------
  88. %% Convert a ActionRequest record into a binary
  89. %% Return {ok, Binary} | {error, Reason}
  90. %%----------------------------------------------------------------------
  91. encode_action_request([{version3, _}|EC], Vsn, ActReq) ->
  92. encode_action_request(EC, Vsn, ActReq);
  93. encode_action_request([megaco_compressed|Config], Vsn, ActReq)
  94. when is_tuple(ActReq) ->
  95. {ok, erlang:term_to_binary(?MC_MOD:encode(ActReq, Vsn), Config)};
  96. encode_action_request([{megaco_compressed, Mod}|Config], Vsn, ActReq)
  97. when is_tuple(ActReq) ->
  98. {ok, erlang:term_to_binary(Mod:encode(ActReq, Vsn), Config)};
  99. encode_action_request(Config, _Vsn, ActReq)
  100. when is_tuple(ActReq) ->
  101. {ok, erlang:term_to_binary(ActReq, Config)}.
  102. %%----------------------------------------------------------------------
  103. %% Convert a CommandRequest record into a binary
  104. %% Return {ok, DeepIoList} | {error, Reason}
  105. %%----------------------------------------------------------------------
  106. encode_command_request([{version3, _}|EC], Vsn, CmdReq) ->
  107. encode_command_request(EC, Vsn, CmdReq);
  108. encode_command_request([megaco_compressed|Config], Vsn, CmdReq)
  109. when is_tuple(CmdReq) ->
  110. {ok, erlang:term_to_binary(?MC_MOD:encode(CmdReq, Vsn), Config)};
  111. encode_command_request([{megaco_compressed, Mod}|Config], Vsn, CmdReq)
  112. when is_tuple(CmdReq) ->
  113. {ok, erlang:term_to_binary(Mod:encode(CmdReq, Vsn), Config)};
  114. encode_command_request(Config, _Vsn, CmdReq)
  115. when is_tuple(CmdReq) ->
  116. {ok, erlang:term_to_binary(CmdReq, Config)}.
  117. %%----------------------------------------------------------------------
  118. %% Convert a action reply into a binary
  119. %% Return {ok, DeepIoList} | {error, Reason}
  120. %%----------------------------------------------------------------------
  121. encode_action_reply([{version3, _}|EC], Vsn, ActRep) ->
  122. encode_action_reply(EC, Vsn, ActRep);
  123. encode_action_reply([megaco_compressed|Config], Vsn, ActRep)
  124. when is_tuple(ActRep) ->
  125. {ok, erlang:term_to_binary(?MC_MOD:encode(ActRep, Vsn), Config)};
  126. encode_action_reply([{megaco_compressed, Mod}|Config], Vsn, ActRep)
  127. when is_tuple(ActRep) ->
  128. {ok, erlang:term_to_binary(Mod:encode(ActRep, Vsn), Config)};
  129. encode_action_reply(Config, _Vsn, ActRep)
  130. when is_tuple(ActRep) ->
  131. {ok, erlang:term_to_binary(ActRep, Config)}.
  132. %%----------------------------------------------------------------------
  133. %% Get the megaco version of the message
  134. %% Return {ok, Version} | {error, Reason}
  135. %%----------------------------------------------------------------------
  136. version_of(Config, Bin) when is_binary(Bin) ->
  137. case decode_message(Config, 1, Bin) of
  138. {ok, M} ->
  139. V = (M#'MegacoMessage'.mess)#'Message'.version,
  140. {ok, V};
  141. Error ->
  142. Error
  143. end.
  144. decode_message(Config, Bin) ->
  145. decode_message(Config, 1, Bin).
  146. decode_message([{version3, _}|EC], V, Bin) ->
  147. decode_message(EC, V, Bin);
  148. decode_message([megaco_compressed = MC|_Config], Vsn, Bin) ->
  149. case catch erlang:binary_to_term(Bin) of
  150. Msg when is_tuple(Msg) ->
  151. case (?MC_MOD:decode(Msg, Vsn)) of
  152. MegaMsg when is_record(MegaMsg, 'MegacoMessage') ->
  153. {ok, dm(MegaMsg, MC, Vsn)};
  154. _ ->
  155. {error, {bad_message, Msg}}
  156. end;
  157. {'EXIT', _Reason} ->
  158. {error, bad_binary}
  159. end;
  160. decode_message([{megaco_compressed, Mod} = MC|_Config], Vsn, Bin)
  161. when is_atom(Mod) ->
  162. case catch erlang:binary_to_term(Bin) of
  163. Msg when is_tuple(Msg) ->
  164. case (Mod:decode(Msg, Vsn)) of
  165. MegaMsg when is_record(MegaMsg, 'MegacoMessage') ->
  166. {ok, dm(MegaMsg, MC, Vsn)};
  167. _ ->
  168. {error, {bad_message, Msg}}
  169. end;
  170. {'EXIT', _Reason} ->
  171. {error, bad_binary}
  172. end;
  173. decode_message(_Config, Vsn, Bin) ->
  174. case catch erlang:binary_to_term(Bin) of
  175. MegaMsg when is_record(MegaMsg, 'MegacoMessage') ->
  176. {ok, dm(MegaMsg, undefined, Vsn)};
  177. {'EXIT', _Reason} ->
  178. {error, bad_binary}
  179. end.
  180. decode_mini_message(EC, Vsn, Bin) when is_binary(Bin) ->
  181. decode_message(EC, Vsn, Bin).
  182. %% This crap is because the transactions or the action-requests
  183. %% might have been encoded separetely
  184. dm(#'MegacoMessage'{mess = Mess} = M, MC, Vsn) ->
  185. #'Message'{messageBody = Body} = Mess,
  186. case Body of
  187. {transactions, Transactions} ->
  188. Body2 = {transactions, dmt(Transactions, [], MC, Vsn)},
  189. Mess2 = Mess#'Message'{messageBody = Body2},
  190. M#'MegacoMessage'{mess = Mess2};
  191. _ ->
  192. M
  193. end.
  194. dmt([], Acc, _, _Vsn) ->
  195. lists:reverse(Acc);
  196. dmt([Trans0|Transactions], Acc, MC, Vsn) when is_binary(Trans0) ->
  197. Trans1 = erlang:binary_to_term(Trans0),
  198. Trans2 = dmt1(Trans1, MC, Vsn),
  199. dmt(Transactions, [Trans2|Acc], MC, Vsn);
  200. dmt([{Tag, Trans0}|Transactions], Acc, MC, Vsn) when is_binary(Trans0) ->
  201. Trans1 = erlang:binary_to_term(Trans0),
  202. Trans2 = dmt1(Trans1, MC, Vsn),
  203. dmt(Transactions, [{Tag, Trans2}|Acc], MC, Vsn);
  204. dmt([{transactionRequest,
  205. #'TransactionRequest'{actions = Acts0} = TR0}|Transactions],
  206. Acc, MC, Vsn)
  207. when is_binary(Acts0) ->
  208. Acts1 = erlang:binary_to_term(Acts0),
  209. Acts2 = dmt1(Acts1, MC, Vsn),
  210. TR1 = TR0#'TransactionRequest'{actions = Acts2},
  211. dmt(Transactions, [{transactionRequest, TR1}|Acc], MC, Vsn);
  212. dmt([{transactionRequest,
  213. #'TransactionRequest'{actions = Acts0} = TR0}|Transactions],
  214. Acc, MC, Vsn) ->
  215. Acts2 = [dmt2(AR, MC, Vsn) || AR <- Acts0],
  216. TR1 = TR0#'TransactionRequest'{actions = Acts2},
  217. dmt(Transactions, [{transactionRequest, TR1}|Acc], MC, Vsn);
  218. dmt([Trans|Transactions], Acc, MC, Vsn) ->
  219. dmt(Transactions, [Trans|Acc], MC, Vsn).
  220. dmt1(L, megaco_compressed, Vsn) when is_list(L) ->
  221. [?MC_MOD:decode(E, Vsn) || E <- L];
  222. dmt1(L, {megaco_compressed, Mod}, Vsn) when is_list(L) ->
  223. [Mod:decode(E, Vsn) || E <- L];
  224. dmt1(T, megaco_compressed, Vsn) when is_tuple(T) ->
  225. ?MC_MOD:decode(T, Vsn);
  226. dmt1(T, {megaco_compressed, Mod}, Vsn) when is_tuple(T) ->
  227. Mod:decode(T, Vsn);
  228. dmt1(Else, _, _Vsn) ->
  229. Else.
  230. dmt2(Bin, MC, Vsn) when is_binary(Bin) ->
  231. AR = erlang:binary_to_term(Bin),
  232. dmt1(AR, MC, Vsn);
  233. dmt2(AR, _MC, _Vsn) ->
  234. AR.