Skip to content

Instantly share code, notes, and snippets.

@rpl
Created December 28, 2009 21:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rpl/264946 to your computer and use it in GitHub Desktop.
Save rpl/264946 to your computer and use it in GitHub Desktop.
%% yate_decode: yate message decoding experimental erlang module.
%%
%% Copyright (C) 2009 - Alca Società Cooperativa <info@alcacoop.it>
%%
%% Author: Luca Greco <luca.greco@alcacoop.it>
%%
%% This program is free software: you can redistribute it and/or modify
%% it under the terms of the GNU Lesser General Public License as published by
%% the Free Software Foundation, either version 3 of the License, or
%% (at your option) any later version.
%%
%% This program is distributed in the hope that it will be useful,
%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
%% General Public License for more details.
%%
%% You should have received a copy of the GNU Lessel General Public License
%% along with this program. If not, see <http://www.gnu.org/licenses/>.
-module(yate_decode).
-compile(export_all).
%%% NOTE: decode message type and call specialized attributes parsing functions
binary_to_term(<<"Error in: ", Msg/binary>>) ->
{ error, Msg };
binary_to_term(<<"%%<install:", Rest/binary>>) ->
{ answer, install, parse_install_answer_attributes(Rest) };
binary_to_term(<<"%%<uninstall:", Rest/binary>>) ->
{ answer, uninstall, parse_uninstall_answer_attributes(Rest) };
binary_to_term(<<"%%<watch:", Rest/binary>>) ->
{ answer, watch, parse_watch_answer_attributes(Rest) };
binary_to_term(<<"%%<unwatch:", Rest/binary>>) ->
{ answer, unwatch, parse_unwatch_answer_attributes(Rest) };
binary_to_term(<<"%%<setlocal:", Rest/binary>>) ->
{ answer, setlocal, parse_setlocal_answer_attributes(Rest) };
binary_to_term(<<"%%<message:", Rest/binary>>) ->
[ EventAttrs, MsgParams ] = parse_message_answer_attributes(Rest),
{ answer, message, EventAttrs, MsgParams };
binary_to_term(<<"%%>message:", Rest/binary>>) ->
[ EventAttrs, MsgParams ] = parse_message_incoming_attributes(Rest),
{ incoming, message, EventAttrs, MsgParams };
binary_to_term(_Unknown) ->
{ unknown_event }.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% NOTE: private specialized attributes parsing functions
%%% on error throws
%%% { invalid_data, { data, Data }, { where, File, Line } }
%%% unimplemented features throws
%%% { not_implemented, {data, Rest}, { where, ?FILE, ?LINE } }
%%%
%%% IMPLEMENTATION NOTES:
% throw({ not_implemented, {data, Rest}, { where, ?FILE, ?LINE } }).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
parse_install_answer_attributes(Rest) when is_binary(Rest) ->
case string:tokens(binary_to_list(Rest), ":") of
[ Priority, Name, Success ] -> [ { priority, Priority }, { name, Name }, { success, Success } ];
_Any -> throw({ invalid_data, {data, _Any}, { where, ?FILE, ?LINE } })
end.
parse_uninstall_answer_attributes(Rest) when is_binary(Rest) ->
case string:tokens(binary_to_list(Rest), ":") of
[ Name, Success ] -> [ { name, Name }, { success, Success } ];
_Any -> throw({ invalid_data, {data, _Any}, { where, ?FILE, ?LINE } })
end.
parse_watch_answer_attributes(Rest) when is_binary(Rest) ->
case string:tokens(binary_to_list(Rest), ":") of
[ Name, Success ] -> [ { name, Name }, { success, Success } ];
_Any -> throw({ invalid_data, {data, _Any}, { where, ?FILE, ?LINE } })
end.
parse_unwatch_answer_attributes(Rest) when is_binary(Rest) ->
case string:tokens(binary_to_list(Rest), ":") of
[ Name, Success ] -> [ { name, Name }, { success, Success } ];
_Any -> throw({ invalid_data, {data, _Any}, { where, ?FILE, ?LINE } })
end.
parse_setlocal_answer_attributes(Rest) when is_binary(Rest) ->
case string:tokens(binary_to_list(Rest), ":") of
[ Name, Value, Success ] -> [ { name, Name }, { value, Value }, { success, Success } ];
_Any -> throw({ invalid_data, {data, _Any}, { where, ?FILE, ?LINE } })
end.
%%% %%<message:<id>:<processed>:[<name>]:<retvalue>[:<key>=<value>...]
parse_message_answer_attributes(Rest) when is_binary(Rest) ->
case string:tokens(binary_to_list(Rest), ":") of
[ Id, Processed, Name, RetVal | RawMsgParams ] ->
Attrs = [ { id, Id }, { processed, Processed }, { name, Name }, { retval, RetVal }],
MsgParams = parse_message_parameters(RawMsgParams),
[Attrs, MsgParams];
_Any -> throw({ invalid_data, {data, _Any}, { where, ?FILE, ?LINE } })
end.
%%% %%>message:<id>:<time>:<name>:<retvalue>[:<key>=<value>...]
parse_message_incoming_attributes(Rest) when is_binary(Rest) ->
case string:tokens(binary_to_list(Rest), ":") of
[ Id, Time, Name, RetVal | RawMsgParams ] ->
Attrs = [ { id, Id }, { time, Time }, { name, Name }, { retval, RetVal }],
MsgParams = parse_message_parameters(RawMsgParams),
[Attrs, MsgParams];
_Any -> throw({ invalid_data, {data, _Any}, { where, ?FILE, ?LINE } })
end.
parse_message_parameters([H|T] = RawMsgParams) when is_list(RawMsgParams) ->
MsgParam = case string:tokens(H, "=") of
[Key, Value] ->
{ list_to_atom(Key), Value };
_Any -> throw({ invalid_data, {data, _Any}, { where, ?FILE, ?LINE } })
end,
[MsgParam | parse_message_parameters(T)];
parse_message_parameters([]) ->
[].
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment