Skip to content

Commit

Permalink
Merge branch 'WHISTLE-1241'
Browse files Browse the repository at this point in the history
Conflicts:
	ecallmgr/src/ecallmgr_call_control.erl
	ecallmgr/src/ecallmgr_fs_route.erl
  • Loading branch information
k-anderson committed Nov 16, 2012
2 parents b01e0d8 + c0410d2 commit 5b7b746
Show file tree
Hide file tree
Showing 40 changed files with 2,042 additions and 1,210 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
%%% @contributors
%%% Karl Anderson
%%%-------------------------------------------------------------------
-module(ecallmgr_util_sup).
-module(ecallmgr_auxiliary_sup).

-behaviour(supervisor).

Expand All @@ -16,10 +16,16 @@
-export([cache_proc/0]).
-export([init/1]).

-define(CHILD(N), {N, {wh_cache, start_link, [N]}, permanent, 5000, worker, [wh_cache]}).
-define(CHILDREN, [?ECALLMGR_UTIL_CACHE
,?ECALLMGR_REG_CACHE
,?ECALLMGR_CALL_CACHE
-define(CHILD(Name, Type), fun(N, cache) -> {N, {wh_cache, start_link, [N]}, permanent, 5000, worker, [wh_cache]};
(N, T) -> {N, {N, start_link, []}, permanent, 5000, T, [N]}
end(Name, Type)).

-define(CHILDREN, [{?ECALLMGR_UTIL_CACHE, cache}
,{?ECALLMGR_REG_CACHE, cache}
,{?ECALLMGR_CALL_CACHE, cache}
,{ecallmgr_query, worker}
,{ecallmgr_conference_listener, worker}
,{ecallmgr_originate_sup, supervisor}
]).

%% ===================================================================
Expand Down Expand Up @@ -59,6 +65,6 @@ init([]) ->
MaxSecondsBetweenRestarts = 10,

SupFlags = {RestartStrategy, MaxRestarts, MaxSecondsBetweenRestarts},
Children = [?CHILD(Name) || Name <- ?CHILDREN],
Children = [?CHILD(Name, Type) || {Name, Type} <- ?CHILDREN],

{ok, {SupFlags, Children}}.
8 changes: 4 additions & 4 deletions ecallmgr/src/ecallmgr_call_cdr.erl
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
,{<<"variable_progresssec">>, <<"Ringing-Seconds">>}
,{<<"variable_digits_dialed">>, <<"Digits-Dialed">>}
,{<<"ecallmgr">>, <<"Custom-Channel-Vars">>}
,{fun(P) -> ecallmgr_util:get_sip_request(P) end, <<"Request">>}
]).
-define(FS_TO_WHISTLE_OUTBOUND_MAP, [{<<"variable_sip_cid_type">>, <<"Caller-ID-Type">>}]).

Expand All @@ -60,22 +61,21 @@ create_cdr(EvtProp) ->

-spec add_values/3 :: (fs_to_whistle_map(), proplist(), proplist()) -> proplist().
add_values(Mappings, BaseProp, ChannelProp) ->
lists:foldl(fun({<<"ecallmgr">>, <<"Custom-Channel-Vars">>=WK}, WApi) ->
lists:foldl(fun({Fun, WK}, WApi) when is_function(Fun) ->
[{WK, Fun(ChannelProp)} | WApi];
({<<"ecallmgr">>, <<"Custom-Channel-Vars">>=WK}, WApi) ->
[{WK, wh_json:from_list(ecallmgr_util:custom_channel_vars(ChannelProp))} | WApi];

({<<"Event-Date-Timestamp">>=FSKey, WK}, WApi) ->
case props:get_value(FSKey, ChannelProp) of
undefined -> WApi;
V -> VUnix = wh_util:unix_seconds_to_gregorian_seconds(wh_util:microseconds_to_seconds(V)),
[{WK, wh_util:to_binary(VUnix)} | WApi]
end;

({FSKeys, WK}, WApi) when is_list(FSKeys) ->
case get_first_value(FSKeys, ChannelProp) of
undefined -> WApi;
V -> [{WK, V} | WApi]
end;

({FSKey, WK}, WApi) ->
case props:get_value(FSKey, ChannelProp) of
undefined -> WApi;
Expand Down
90 changes: 21 additions & 69 deletions ecallmgr/src/ecallmgr_call_command.erl
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ get_fs_app(Node, UUID, JObj, <<"record">>) ->
,get_terminators(wh_json:get_value(<<"Terminators">>, JObj))
]
end,
_ = set(Node, UUID, Vars),
_ = ecallmgr_util:set(Node, UUID, Vars),

MediaName = ecallmgr_util:recording_filename(wh_json:get_value(<<"Media-Name">>, JObj)),

Expand Down Expand Up @@ -175,7 +175,7 @@ get_fs_app(Node, UUID, JObj, <<"record_call">>) ->
,get_terminators(wh_json:get_value(<<"Terminators">>, JObj))
]
end,
_ = set(Node, UUID, Vars),
_ = ecallmgr_util:set(Node, UUID, Vars),

%% UUID start path/to/media limit
RecArg = binary_to_list(list_to_binary([
Expand Down Expand Up @@ -291,7 +291,7 @@ get_fs_app(Node, UUID, _JObj, <<"receive_fax">>) ->
Vars = [{<<"fax_enable_t38_request">>, <<"true">>}
,{<<"fax_enable_t38">>, <<"true">>}
],
_ = set(Node, UUID, Vars),
_ = ecallmgr_util:set(Node, UUID, Vars),

[{<<"playback">>, <<"silence_stream://2000">>}
,{<<"rxfax">>, ecallmgr_util:fax_filename(UUID)}
Expand Down Expand Up @@ -502,7 +502,7 @@ get_fs_app(Node, UUID, JObj, <<"execute_extension">>) ->
true -> DP;
false ->
ChannelVars = wh_json:to_proplist(CCVs),
[{"application", <<"set ", (get_fs_kv(K, V, UUID))/binary>>}
[{"application", <<"set ", (ecallmgr_util:get_fs_kv(K, V, UUID))/binary>>}
|| {K, V} <- ChannelVars] ++ DP
end
end
Expand Down Expand Up @@ -576,10 +576,10 @@ get_fs_app(Node, UUID, JObj, <<"set">>) ->
false -> {'error', <<"set failed to execute as JObj did not validate">>};
true ->
ChannelVars = wh_json:to_proplist(wh_json:get_value(<<"Custom-Channel-Vars">>, JObj, wh_json:new())),
_ = set(Node, UUID, ChannelVars),
_ = ecallmgr_util:set(Node, UUID, ChannelVars),

CallVars = wh_json:to_proplist(wh_json:get_value(<<"Custom-Call-Vars">>, JObj, wh_json:new())),
_ = [ export(Node, UUID, get_fs_kv(K, V, UUID)) || {K, V} <- CallVars],
_ = [ ecallmgr_util:export(Node, UUID, ecallmgr_util:get_fs_kv(K, V, UUID)) || {K, V} <- CallVars],

{<<"set">>, noop}
end;
Expand All @@ -600,7 +600,7 @@ get_fs_app(Node, UUID, JObj, <<"redirect">>) ->
true ->
_ = case wh_json:get_value(<<"Redirect-Server">>, JObj) of
undefined -> ok;
Server -> set(Node, UUID, <<"sip_rh_X-Redirect-Server=", Server/binary>>)
Server -> ecallmgr_util:set(Node, UUID, <<"sip_rh_X-Redirect-Server=", Server/binary>>)
end,
{<<"redirect">>, wh_json:get_value(<<"Redirect-Contact">>, JObj, <<>>)}
end;
Expand All @@ -626,43 +626,30 @@ get_fs_app(_Node, _UUID, _JObj, _App) ->
%%--------------------------------------------------------------------
%% @private
%% @doc
%% set channel and call variables in FreeSWITCH
%%
%% @end
%%--------------------------------------------------------------------
-spec get_fs_kv/3 :: (ne_binary(), ne_binary(), ne_binary()) -> binary().
get_fs_kv(<<"Hold-Media">>, Media, UUID) ->
list_to_binary(["hold_music="
,wh_util:to_list(ecallmgr_util:media_path(Media, extant, UUID, wh_json:new()))
]);
get_fs_kv(Key, Val, _) ->
case lists:keyfind(Key, 1, ?SPECIAL_CHANNEL_VARS) of
false ->
list_to_binary([?CHANNEL_VAR_PREFIX, wh_util:to_list(Key), "=", wh_util:to_list(Val)]);
{_, Prefix} ->
list_to_binary([Prefix, "=", wh_util:to_list(Val)])
end.

-spec get_call_pickup_app/4 :: (atom(), ne_binary(), wh_json:json_object(), ne_binary()) ->
{ne_binary(), ne_binary()}.
get_call_pickup_app(Node, UUID, JObj, Target) ->
_ = case wh_json:is_true(<<"Park-After-Pickup">>, JObj, false) of
false -> export(Node, UUID, <<"park_after_bridge=false">>);
false -> ecallmgr_util:export(Node, UUID, <<"park_after_bridge=false">>);
true ->
_ = set(Node, Target, <<"park_after_bridge=true">>),
set(Node, UUID, <<"park_after_bridge=true">>)
_ = ecallmgr_util:set(Node, Target, <<"park_after_bridge=true">>),
ecallmgr_util:set(Node, UUID, <<"park_after_bridge=true">>)
end,

_ = case wh_json:is_true(<<"Continue-On-Fail">>, JObj, true) of
false -> export(Node, UUID, <<"continue_on_fail=false">>);
true -> export(Node, UUID, <<"continue_on_fail=true">>)
false -> ecallmgr_util:export(Node, UUID, <<"continue_on_fail=false">>);
true -> ecallmgr_util:export(Node, UUID, <<"continue_on_fail=true">>)
end,

_ = case wh_json:is_true(<<"Continue-On-Cancel">>, JObj, true) of
false -> export(Node, UUID, <<"continue_on_cancel=false">>);
true -> export(Node, UUID, <<"continue_on_cancel=true">>)
false -> ecallmgr_util:export(Node, UUID, <<"continue_on_cancel=false">>);
true -> ecallmgr_util:export(Node, UUID, <<"continue_on_cancel=true">>)
end,

_ = export(Node, UUID, <<"failure_causes=NORMAL_CLEARING,ORIGINATOR_CANCEL,CRASH">>),
_ = ecallmgr_util:export(Node, UUID, <<"failure_causes=NORMAL_CLEARING,ORIGINATOR_CANCEL,CRASH">>),

{<<"call_pickup">>, <<UUID/binary, " ", Target/binary>>}.

Expand Down Expand Up @@ -735,42 +722,7 @@ get_terminators(Ts) ->
-spec set_terminators/3 :: (atom(), ne_binary(), 'undefined' | binary() | list()) -> ecallmgr_util:send_cmd_ret().
set_terminators(Node, UUID, Ts) ->
{K, V} = get_terminators(Ts),
set(Node, UUID, <<K/binary, "=", V/binary>>).

%%--------------------------------------------------------------------
%% @private
%% @doc
%% @end
%%--------------------------------------------------------------------
-spec set/3 :: (atom(), ne_binary(), wh_proplist() | ne_binary()) -> ecallmgr_util:send_cmd_ret().
set(Node, UUID, [{K, V}]) ->
set(Node, UUID, get_fs_kv(K, V, UUID));
set(Node, UUID, [{_, _}|_]=Props) ->
Multiset = lists:foldl(fun({K, V}, Acc) ->
<<"|", (get_fs_kv(K, V, UUID))/binary, Acc/binary>>
end, <<>>, Props),
ecallmgr_util:send_cmd(Node, UUID, "multiset", <<"^^", Multiset/binary>>);
set(Node, UUID, Arg) ->
case wh_util:to_binary(Arg) of
<<"hold_music=", _/binary>> ->
ecallmgr_fs_nodes:channel_set_import_moh(Node, UUID, false);
_Else -> ok
end,
ecallmgr_util:send_cmd(Node, UUID, "set", Arg).

%%--------------------------------------------------------------------
%% @private
%% @doc
%% @end
%%--------------------------------------------------------------------
-spec export/3 :: (atom(), ne_binary(), binary()) -> ecallmgr_util:send_cmd_ret().
export(Node, UUID, Arg) ->
case wh_util:to_binary(Arg) of
<<"hold_music=", _/binary>> ->
ecallmgr_fs_nodes:channel_set_import_moh(Node, UUID, false);
_Else -> ok
end,
ecallmgr_util:send_cmd(Node, UUID, "export", wh_util:to_list(Arg)).
ecallmgr_util:set(Node, UUID, <<K/binary, "=", V/binary>>).

%%--------------------------------------------------------------------
%% @private
Expand Down Expand Up @@ -898,7 +850,7 @@ play(Node, UUID, JObj) ->
,get_terminators(wh_json:get_value(<<"Terminators">>, JObj))
]
end,
_ = set(Node, UUID, Vars),
_ = ecallmgr_util:set(Node, UUID, Vars),

F = ecallmgr_util:media_path(wh_json:get_value(<<"Media-Name">>, JObj), new, UUID, JObj, ?ECALLMGR_CALL_CACHE),

Expand All @@ -915,9 +867,9 @@ tts_flite(Node, UUID, JObj) ->

lager:debug("tts_flite voice: ~s", [TTSVoice]),

_ = set(Node, UUID, [{<<"tts_engine">>, <<"flite">>}
,{<<"tts_voice">>, TTSVoice}
]),
_ = ecallmgr_util:set(Node, UUID, [{<<"tts_engine">>, <<"flite">>}
,{<<"tts_voice">>, TTSVoice}
]),
{<<"speak">>, wh_json:get_value(<<"Text">>, JObj)}.

-spec tts_flite_voice/1 :: (api_binary()) -> ne_binary().
Expand Down
94 changes: 56 additions & 38 deletions ecallmgr/src/ecallmgr_call_control.erl
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,18 @@

%% API
-export([start_link/3, stop/1]).
-export([handle_call_command/2, handle_conference_command/2, handle_call_events/2]).
-export([queue_name/1, callid/1, node/1, hostname/1]).
-export([handle_call_command/2]).
-export([handle_conference_command/2]).
-export([handle_call_events/2]).
-export([queue_name/1]).
-export([callid/1]).
-export([node/1]).
-export([hostname/1]).
-export([event_execute_complete/3]).
-export([add_leg/1, rm_leg/1]).
-export([other_legs/1
,update_node/2
,control_procs/1
]).
-export([transferer/2, transferee/2]).

%% gen_listener callbacks
-export([init/1
Expand Down Expand Up @@ -163,19 +166,6 @@ other_legs(Srv) ->
event_execute_complete(Srv, CallId, App) ->
gen_listener:cast(Srv, {event_execute_complete, CallId, App, wh_json:new()}).

-spec add_leg/1 :: (wh_proplist()) -> 'ok'.
add_leg(Props) ->
%% if there is a Other-Leg-Unique-ID then that MAY refer to a leg managed
%% by call_control, if so add the leg to it
case props:get_value(<<"Other-Leg-Unique-ID">>, Props) of
undefined -> ok;
CallId ->
_ = [gen_listener:cast(Srv, {add_leg, wh_json:from_list(Props)})
|| Srv <- gproc:lookup_pids({p, l, {call_control, CallId}})
],
ok
end.

-spec update_node/2 :: (atom(), ne_binary() | [pid(),...] | []) -> 'ok'.
update_node(Node, CallId) when is_binary(CallId) ->
update_node(Node, gproc:lookup_pids({p, l, {call_control, CallId}}));
Expand All @@ -187,27 +177,6 @@ update_node(Node, Pids) when is_list(Pids) ->
control_procs(CallId) ->
gproc:lookup_pids({p, l, {call_control, CallId}}).

-spec rm_leg/1 :: (wh_proplist()) -> 'ok'.
rm_leg(Props) ->
%% if there is a Other-Leg-Unique-ID then that MAY refer to a leg managed
%% by call_control, if so remove the leg from it
case props:get_value(<<"Other-Leg-Unique-ID">>, Props) of
undefined -> ok;
CallId ->
_ = [gen_listener:cast(Srv, {rm_leg, wh_json:from_list(Props)})
|| Srv <- gproc:lookup_pids({p, l, {call_control, CallId}})
],
ok
end.

-spec transferer/2 :: (pid(), proplist()) -> 'ok'.
transferer(Srv, Props) ->
gen_listener:cast(Srv, {transferer, wh_json:from_list(Props)}).

-spec transferee/2 :: (pid(), proplist()) -> 'ok'.
transferee(Srv, Props) ->
gen_listener:cast(Srv, {transferee, wh_json:from_list(Props)}).

-spec handle_call_command/2 :: (wh_json:json_object(), proplist()) -> 'ok'.
handle_call_command(JObj, Props) ->
Srv = props:get_value(server, Props),
Expand Down Expand Up @@ -257,6 +226,41 @@ handle_call_events(JObj, Props) ->
ok
end.

handle_channel_create(Props, _Node, CallId) ->
case props:get_value(<<"Other-Leg-Unique-ID">>, Props) =:= CallId of
false -> ok;
true ->
gen_listener:cast(self(), {add_leg, wh_json:from_list(Props)})
end.

handle_channel_destroy(Props, _Node, CallId) ->
case props:get_value(<<"Other-Leg-Unique-ID">>, Props) =:= CallId of
false -> ok;
true ->
gen_listener:cast(self(), {rm_leg, wh_json:from_list(Props)})
end.

handle_transfer(Props, _Node, CallId) ->
Transferer = case props:get_value(<<"Transferor-Direction">>, Props) of
<<"inbound">> ->
props:get_value(<<"Transferor-UUID">>, Props);
_ ->
props:get_value(<<"Transferee-UUID">>, Props)
end,
case Transferer =:= CallId of
false -> ok;
true ->
gen_listener:cast(self(), {transferer, wh_json:from_list(Props)})
end,
case
props:get_value(<<"Type">>, Props) =:= <<"BLIND_TRANSFER">>
andalso props:get_value(<<"Replaces">>, Props) =:= CallId
of
false -> ok;
true ->
gen_listener:cast(self(), {transferee, wh_json:from_list(Props)})
end.

%%%===================================================================
%%% gen_listener callbacks
%%%===================================================================
Expand All @@ -278,6 +282,7 @@ init([Node, CallId, WhAppQ]) ->
erlang:monitor_node(Node, true),
gproc:reg({p, l, call_control}),
gproc:reg({p, l, {call_control, CallId}}),
bind_to_events(freeswitch:version(Node), Node),
TRef = erlang:send_after(?SANITY_CHECK_PERIOD, self(), {sanity_check}),
{ok, #state{node=Node
,callid=CallId
Expand All @@ -289,6 +294,11 @@ init([Node, CallId, WhAppQ]) ->
}
}.

bind_to_events(_, Node) ->
gproc:reg({p, l, {call_event, Node, <<"CHANNEL_CREATE">>}}),
gproc:reg({p, l, {call_event, Node, <<"CHANNEL_DESTROY">>}}),
gproc:reg({p, l, {call_event, Node, <<"sofia::transfer">>}}).

%%--------------------------------------------------------------------
%% @private
%% @doc
Expand Down Expand Up @@ -560,6 +570,14 @@ handle_cast(_, State) ->
%% {stop, Reason, State}
%% @end
%%--------------------------------------------------------------------
handle_info({event, [_ | Props]}, #state{node=Node, callid=CallId}=State) ->
case props:get_value(<<"Event-Subclass">>, Props, props:get_value(<<"Event-Name">>, Props)) of
<<"CHANNEL_DESTROY">> -> handle_channel_destroy(Props, Node, CallId);
<<"CHANNEL_CREATE">> -> handle_channel_create(Props, Node, CallId);
<<"sofia::transfer">> -> handle_transfer(Props, Node, CallId);
_ -> ok
end,
{noreply, State};
handle_info({nodedown, Node}, #state{node=Node
,is_node_up=true
}=State) ->
Expand Down
Loading

0 comments on commit 5b7b746

Please sign in to comment.