/day3/yate_decode.erl

https://github.com/rpl/learning-erlang-experiments · Erlang · 123 lines · 74 code · 14 blank · 35 comment · 0 complexity · 49f308f89f794bf177f65c9677b82920 MD5 · raw file

  1. %% yate_decode: yate message decoding experimental erlang module.
  2. %%
  3. %% Copyright (C) 2009 - Alca Società Cooperativa <info@alcacoop.it>
  4. %%
  5. %% Author: Luca Greco <luca.greco@alcacoop.it>
  6. %%
  7. %% This program is free software: you can redistribute it and/or modify
  8. %% it under the terms of the GNU Lesser General Public License as published by
  9. %% the Free Software Foundation, either version 3 of the License, or
  10. %% (at your option) any later version.
  11. %%
  12. %% This program is distributed in the hope that it will be useful,
  13. %% but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. %% General Public License for more details.
  16. %%
  17. %% You should have received a copy of the GNU Lessel General Public License
  18. %% along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. -module(yate_decode).
  20. -compile(export_all).
  21. -include("yate.hrl").
  22. %%% NOTE: decode message type and call specialized attributes parsing functions
  23. binary_to_term(Raw = <<"Error in: ", Msg/binary>>) when is_binary(Raw) ->
  24. #yate_event{ direction=incoming, type=error, attrs=[{msg, binary_to_list(Msg)}] };
  25. binary_to_term(Raw = <<"%%<install:", Rest/binary>>) when is_binary(Raw) ->
  26. #yate_event{ direction=answer, type=install, attrs=decode_install_answer_attributes(Rest) };
  27. binary_to_term(Raw = <<"%%<uninstall:", Rest/binary>>) when is_binary(Raw) ->
  28. #yate_event{ direction=answer, type=uninstall, attrs=decode_uninstall_answer_attributes(Rest) };
  29. binary_to_term(Raw = <<"%%<watch:", Rest/binary>>) when is_binary(Raw) ->
  30. #yate_event{ direction=answer, type=watch, attrs=decode_watch_answer_attributes(Rest) };
  31. binary_to_term(Raw = <<"%%<unwatch:", Rest/binary>>) when is_binary(Raw) ->
  32. #yate_event{ direction=answer, type=unwatch, attrs=decode_unwatch_answer_attributes(Rest) };
  33. binary_to_term(Raw = <<"%%<setlocal:", Rest/binary>>) when is_binary(Raw) ->
  34. #yate_event{ direction=answer, type=setlocal, attrs=decode_setlocal_answer_attributes(Rest) };
  35. binary_to_term(Raw = <<"%%<message:", Rest/binary>>) when is_binary(Raw) ->
  36. [ EventAttrs, MsgParams ] = decode_message_answer_attributes(Rest),
  37. #yate_event{ direction=answer, type=message, attrs=EventAttrs, params=MsgParams };
  38. binary_to_term(Raw = <<"%%>message:", Rest/binary>>) when is_binary(Raw) ->
  39. [ EventAttrs, MsgParams ] = decode_message_incoming_attributes(Rest),
  40. #yate_event{ direction=incoming, type=message, attrs=EventAttrs, params=MsgParams };
  41. binary_to_term(_Unknown) when is_binary(_Unknown) ->
  42. ?THROW_YATE_EXCEPTION(unknown_event, "Invalid Engine YATE Event", _Unknown);
  43. binary_to_term(_Unknown) ->
  44. ?THROW_YATE_EXCEPTION(invalid_engine_yate_event, "Needs binary data", _Unknown).
  45. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  46. %%% TODO: 'binary:split' seems to be more efficient way to split a binary string
  47. %%% http://www.erlang.org/eeps/eep-0009.html
  48. %%% http://stackoverflow.com/questions/428124/how-can-i-split-a-binary-in-erlang
  49. %%% NOTE: private specialized attributes parsing functions
  50. %%% on error throws
  51. %%% { invalid_data, { data, Data }, { where, File, Line } }
  52. %%% unimplemented features throws
  53. %%% { not_implemented, {data, Rest}, { where, ?FILE, ?LINE } }
  54. %%%
  55. %%% IMPLEMENTATION NOTES:
  56. % throw({ not_implemented, {data, Rest}, { where, ?FILE, ?LINE } }).
  57. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  58. decode_install_answer_attributes(Rest) when is_binary(Rest) ->
  59. case string:tokens(binary_to_list(Rest), ":") of
  60. [ Priority, Name, Success ] -> [ { priority, Priority }, { name, Name }, { success, Success } ];
  61. _Any -> ?THROW_YATE_EXCEPTION(invalid_data, "Error parsing install answer attributes", _Any)
  62. %% throw({ invalid_data, {data, _Any}, { where, ?FILE, ?LINE } })
  63. end.
  64. decode_uninstall_answer_attributes(Rest) when is_binary(Rest) ->
  65. case string:tokens(binary_to_list(Rest), ":") of
  66. [ Name, Success ] -> [ { name, Name }, { success, Success } ];
  67. _Any -> ?THROW_YATE_EXCEPTION(invalid_data, "Error parsing install answer attributes", _Any)
  68. end.
  69. decode_watch_answer_attributes(Rest) when is_binary(Rest) ->
  70. case string:tokens(binary_to_list(Rest), ":") of
  71. [ Name, Success ] -> [ { name, Name }, { success, Success } ];
  72. _Any -> ?THROW_YATE_EXCEPTION(invalid_data, "Error parsing install answer attributes", _Any)
  73. end.
  74. decode_unwatch_answer_attributes(Rest) when is_binary(Rest) ->
  75. case string:tokens(binary_to_list(Rest), ":") of
  76. [ Name, Success ] -> [ { name, Name }, { success, Success } ];
  77. _Any -> ?THROW_YATE_EXCEPTION(invalid_data, "Error parsing install answer attributes", _Any)
  78. end.
  79. decode_setlocal_answer_attributes(Rest) when is_binary(Rest) ->
  80. case string:tokens(binary_to_list(Rest), ":") of
  81. [ Name, Value, Success ] -> [ { name, Name }, { value, Value }, { success, Success } ];
  82. _Any -> ?THROW_YATE_EXCEPTION(invalid_data, "Error parsing install answer attributes", _Any)
  83. end.
  84. %%% %%<message:<id>:<processed>:[<name>]:<retvalue>[:<key>=<value>...]
  85. decode_message_answer_attributes(Rest) when is_binary(Rest) ->
  86. case string:tokens(binary_to_list(Rest), ":") of
  87. [ Id, Processed, Name, RetVal | RawMsgParams ] ->
  88. Attrs = [ { id, Id }, { processed, Processed }, { name, Name }, { retval, RetVal }],
  89. MsgParams = decode_message_parameters(RawMsgParams),
  90. [Attrs, MsgParams];
  91. _Any -> ?THROW_YATE_EXCEPTION(invalid_data, "Error parsing install answer attributes", _Any)
  92. end.
  93. %%% %%>message:<id>:<time>:<name>:<retvalue>[:<key>=<value>...]
  94. decode_message_incoming_attributes(Rest) when is_binary(Rest) ->
  95. case string:tokens(binary_to_list(Rest), ":") of
  96. [ Id, Time, Name, RetVal | RawMsgParams ] ->
  97. Attrs = [ { id, Id }, { time, Time }, { name, Name }, { retval, RetVal }],
  98. MsgParams = decode_message_parameters(RawMsgParams),
  99. [Attrs, MsgParams];
  100. _Any -> ?THROW_YATE_EXCEPTION(invalid_data, "Error parsing install answer attributes", _Any)
  101. end.
  102. decode_message_parameters([H|T] = RawMsgParams) when is_list(RawMsgParams) ->
  103. MsgParam = case string:tokens(H, "=") of
  104. [Key, Value] -> { list_to_atom(Key), Value };
  105. _Any -> ?THROW_YATE_EXCEPTION(invalid_data, "Error parsing install answer attributes", _Any)
  106. end,
  107. [MsgParam | decode_message_parameters(T)];
  108. decode_message_parameters([]) ->
  109. [].