Skip to content

Commit

Permalink
WHISTLE-1121: updated specs, send execute resp to originate ready bef…
Browse files Browse the repository at this point in the history
…ore sending response to requesting app
  • Loading branch information
James Aimonetti committed Apr 12, 2012
1 parent 6181b03 commit 7ced45b
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 59 deletions.
4 changes: 3 additions & 1 deletion whistle_apps/apps/stepswitch/rebar.config
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
{erl_opts, [{parse_transform, switchblade_transform}, {d, debug}, debug_info]}. % uncomment to get debug messages, remove debug_info for production

{dialyzer_opts, [{warnings, [unmatched_returns, race_conditions, error_handling]}]}. % , underspecs
{lib_dirs, ["../../../lib"]}.
{cover_enabled, true}.
20 changes: 11 additions & 9 deletions whistle_apps/apps/stepswitch/src/stepswitch.erl
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
%%%-------------------------------------------------------------------
%%% @copyright (C) 2010-2011, VoIP INC
%%% @copyright (C) 2010-2012, VoIP INC
%%% @doc
%%% stepswitch routing WhApp
%%% @end
%%% @contributors
%%% Karl Anderson
%%% James Aimonetti
%%%-------------------------------------------------------------------
-module(stepswitch).

Expand All @@ -18,7 +21,7 @@
%%--------------------------------------------------------------------
-spec start_link/0 :: () -> startlink_ret().
start_link() ->
start_deps(),
_ = start_deps(),
stepswitch_sup:start_link().

%%--------------------------------------------------------------------
Expand All @@ -27,9 +30,9 @@ start_link() ->
%% Starts the app
%% @end
%%--------------------------------------------------------------------
-spec start/0 :: () -> ok.
-spec start/0 :: () -> 'ok'.
start() ->
start_deps(),
_ = start_deps(),
application:start(stepswitch).

%%--------------------------------------------------------------------
Expand All @@ -38,7 +41,7 @@ start() ->
%% Stop the app
%% @end
%%--------------------------------------------------------------------
-spec stop/0 :: () -> ok.
-spec stop/0 :: () -> 'ok'.
stop() ->
application:stop(stepswitch).

Expand All @@ -48,9 +51,8 @@ stop() ->
%% Ensures that all dependencies for this app are already running
%% @end
%%--------------------------------------------------------------------
-spec start_deps/0 :: () -> ok.
-spec start_deps/0 :: () -> 'ok'.
start_deps() ->
whistle_apps_deps:ensure(),
wh_util:ensure_started(sasl),
wh_util:ensure_started(crypto),
wh_util:ensure_started(whistle_amqp).
_ = [wh_util:ensure_started(App) || App <- [sasl, crypto, whistle_amqp]],
ok.
18 changes: 9 additions & 9 deletions whistle_apps/apps/stepswitch/src/stepswitch_inbound.erl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ init() ->

-spec handle_req/2 :: (wh_json:json_object(), proplist()) -> 'ok'.
handle_req(JObj, _Prop) ->
whapps_util:put_callid(JObj),
_ = whapps_util:put_callid(JObj),
case wh_json:get_ne_value([<<"Custom-Channel-Vars">>, <<"Account-ID">>], JObj) of
undefined ->
lager:debug("received new inbound dialplan route request"),
Expand Down Expand Up @@ -56,14 +56,14 @@ inbound_handler(JObj, Number) ->
get_dest_number(JObj) ->
{User, _} = whapps_util:get_destination(JObj, ?APP_NAME, <<"inbound_user_field">>),
case whapps_config:get_is_true(<<"stepswitch">>, <<"assume_inbound_e164">>) of
true ->
Number = assume_e164(User),
lager:debug("assuming number is e164, normalizing to ~s", [Number]),
Number;
_ ->
Number = wnm_util:to_e164(User),
lager:debug("converted number to e164: ~s", [Number]),
Number
true ->
Number = assume_e164(User),
lager:debug("assuming number is e164, normalizing to ~s", [Number]),
Number;
_ ->
Number = wnm_util:to_e164(User),
lager:debug("converted number to e164: ~s", [Number]),
Number
end.

%%--------------------------------------------------------------------
Expand Down
86 changes: 48 additions & 38 deletions whistle_apps/apps/stepswitch/src/stepswitch_outbound.erl
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@ init() ->
%% route
%% @end
%%--------------------------------------------------------------------
-spec handle_req/2 :: (wh_json:json_object(), proplist()) -> any().
-spec handle_req/3 :: (ne_binary(), wh_json:json_object(), proplist()) -> any().
handle_req(JObj, Props) ->
whapps_util:put_callid(JObj),
_ = whapps_util:put_callid(JObj),
true = wapi_offnet_resource:req_v(JObj),
lager:debug("received outbound request"),
handle_req(wh_json:get_value(<<"Resource-Type">>, JObj), JObj, Props).
Expand All @@ -58,24 +60,24 @@ handle_req(<<"originate">>, JObj, Props) ->
%%--------------------------------------------------------------------
%% @private
%% @doc
%%
%%
%% @end
%%--------------------------------------------------------------------
-spec attempt_to_fulfill_bridge_req/4 :: (ne_binary(), ne_binary(), wh_json:json_object(), proplist()) -> bridge_resp() | execute_ext_resp().
-spec attempt_to_fulfill_bridge_req/4 :: (ne_binary(), ne_binary(), wh_json:json_object(), proplist()) -> bridge_resp() | execute_ext_resp() | {'error', 'no_resources'}.
attempt_to_fulfill_bridge_req(Number, CtrlQ, JObj, Props) ->
Result = case stepswitch_util:lookup_number(Number) of
{ok, AccountId, false} ->
lager:debug("found local extension, keeping onnet"),
execute_local_extension(Number, AccountId, CtrlQ, JObj);
_ ->
Flags = wh_json:get_value(<<"Flags">>, JObj),
Resources = props:get_value(resources, Props),
Resources = props:get_value(resources, Props),
{Endpoints, IsEmergency} = find_endpoints(Number, Flags, Resources),
bridge_to_endpoints(Endpoints, IsEmergency, CtrlQ, JObj)
end,
case {Result, correct_shortdial(Number, JObj)} of
{{error, no_resources}, fail} -> Result;
{{error, no_resources}, CorrectedNumber} ->
{{error, no_resources}, CorrectedNumber} ->
lager:debug("found no resources for number as dialed, retrying number corrected for shortdial as ~s", [CorrectedNumber]),
attempt_to_fulfill_bridge_req(CorrectedNumber, CtrlQ, JObj, Props);
_Else -> Result
Expand All @@ -84,11 +86,11 @@ attempt_to_fulfill_bridge_req(Number, CtrlQ, JObj, Props) ->
-spec attempt_to_fulfill_originate_req/3 :: (ne_binary(), wh_json:json_object(), proplist()) -> originate_resp().
attempt_to_fulfill_originate_req(Number, JObj, Props) ->
Flags = wh_json:get_value(<<"Flags">>, JObj),
Resources = props:get_value(resources, Props),
Resources = props:get_value(resources, Props),
{Endpoints, _} = find_endpoints(Number, Flags, Resources),
case {originate_to_endpoints(Endpoints, JObj), correct_shortdial(Number, JObj)} of
{{error, no_resources}, fail} -> {error, no_resources};
{{error, no_resources}, CorrectedNumber} ->
{{error, no_resources}, CorrectedNumber} ->
lager:debug("found no resources for number as originated, retrying number corrected for shortdial as ~s", [CorrectedNumber]),
attempt_to_fulfill_originate_req(CorrectedNumber, JObj, Props);
{Result, _} -> Result
Expand Down Expand Up @@ -123,14 +125,14 @@ bridge_to_endpoints(Endpoints, IsEmergency, CtrlQ, JObj) ->
end,
lager:debug("set outbound caller id to ~s '~s'", [CIDNum, CIDName]),

FromURI = case catch whapps_config:get_atom(?APP_NAME, <<"format_from_uri">>, false) of
FromURI = case whapps_config:get_is_true(?APP_NAME, <<"format_from_uri">>, false) of
true ->
case {CIDNum, wh_json:get_value(<<"Account-Realm">>, JObj)} of
{undefined, _} -> undefined;
{_, undefined} -> undefined;
{FromNumber, FromRealm} -> <<"sip:", FromNumber/binary, "@", FromRealm/binary>>
end;
_ -> undefined
false -> undefined
end,
lager:debug("setting from-uri to ~s", [FromURI]),

Expand Down Expand Up @@ -178,14 +180,14 @@ originate_to_endpoints(Endpoints, JObj) ->

CIDNum = wh_json:get_value(<<"Outgoing-Caller-ID-Number">>, JObj),

FromURI = case catch whapps_config:get_atom(?APP_NAME, <<"format_from_uri">>, false) of
FromURI = case whapps_config:get_is_true(?APP_NAME, <<"format_from_uri">>, false) of
true ->
case {CIDNum, wh_json:get_value(<<"Account-Realm">>, JObj)} of
{undefined, _} -> undefined;
{_, undefined} -> undefined;
{FromNumber, FromRealm} -> <<"sip:", FromNumber/binary, "@", FromRealm/binary>>
end;
_ -> undefined
false -> undefined
end,

lager:debug("setting from-uri to ~s", [FromURI]),
Expand Down Expand Up @@ -224,7 +226,7 @@ originate_to_endpoints(Endpoints, JObj) ->
%% @private
%% @doc
%% When the outbound number belongs to another account on the system
%% simply execute that callflow in the context of this call (think
%% simply execute that callflow in the context of this call (think
%% macro). This function will block until that callflow is complete.
%% @end
%%--------------------------------------------------------------------
Expand Down Expand Up @@ -259,18 +261,24 @@ execute_local_extension(Number, AccountId, CtrlQ, JObj) ->
%% Consume AMQP messages waiting for the originate response/error
%% @end
%%--------------------------------------------------------------------
-spec wait_for_originate/1 :: (ne_binary()) -> originate_resp().
-spec wait_for_originate/1 :: (ne_binary()) -> originate_resp() | {'error', 'no_resources'}.
wait_for_originate(MsgId) ->
receive
{#'basic.deliver'{}, #amqp_msg{props=#'P_basic'{content_type=CT}, payload=Payload}} ->
JObj = wh_json:decode(Payload, CT),
case get_event_type(JObj) of
case get_event_type(JObj) of
{<<"resource">>, <<"originate_resp">>, _} ->
{hangup_result(JObj), JObj};
{<<"error">>, <<"originate_resp">>, _} ->
{error, JObj};
{<<"dialplan">>, <<"originate_ready">>, _} ->
lager:debug("originate is ready"),
RespQ = wh_json:get_value(<<"Server-ID">>, JObj),
Resp = [{<<"Call-ID">>, wh_json:get_value(<<"Call-ID">>, JObj)}
,{<<"Msg-ID">>, wh_json:get_value(<<"Msg-ID">>, JObj)}
| wh_api:default_headers(?APP_NAME, ?APP_VERSION)],

wapi_dialplan:publish_originate_execute(RespQ, Resp),
{ready, JObj};
_ ->
wait_for_originate(MsgId)
Expand All @@ -290,7 +298,7 @@ wait_for_originate(MsgId) ->
%%--------------------------------------------------------------------
%% @private
%% @doc
%% Consume AMQP messages waiting for the channel to end or the
%% Consume AMQP messages waiting for the channel to end or the
%% execute extension to complete. However, if we receive a rate
%% response then set the CCVs accordingly.
%% @end
Expand All @@ -300,7 +308,7 @@ wait_for_execute_extension() ->
receive
{#'basic.deliver'{}, #amqp_msg{props=#'P_basic'{content_type=CT}, payload=Payload}} ->
JObj = wh_json:decode(Payload, CT),
case get_event_type(JObj) of
case get_event_type(JObj) of
{<<"call_event">>, <<"CHANNEL_DESTROY">>, _} ->
{hangup_result(JObj), JObj};
{<<"call_event">>, <<"CHANNEL_EXECUTE_COMPLETE">>, <<"execute_extension">>} ->
Expand All @@ -315,7 +323,7 @@ wait_for_execute_extension() ->
%%--------------------------------------------------------------------
%% @private
%% @doc
%% Consume AMQP messages waiting for the channel to end or the
%% Consume AMQP messages waiting for the channel to end or the
%% the bridge to complete. However, if we receive a rate
%% response then set the CCVs accordingly.
%% @end
Expand All @@ -326,7 +334,7 @@ wait_for_bridge(Timeout) ->
receive
{#'basic.deliver'{}, #amqp_msg{props=#'P_basic'{content_type=CT}, payload=Payload}} ->
JObj = wh_json:decode(Payload, CT),
case get_event_type(JObj) of
case get_event_type(JObj) of
{<<"error">>, <<"dialplan">>, _} ->
{error, JObj};
{<<"call_event">>, <<"CHANNEL_BRIDGE">>, _} ->
Expand Down Expand Up @@ -364,7 +372,7 @@ hangup_result(JObj) ->
true -> ok;
false -> fail
end.

%%--------------------------------------------------------------------
%% @private
%% @doc
Expand All @@ -376,14 +384,14 @@ hangup_result(JObj) ->
-spec create_queue/1 :: (wh_json:json_object()) -> ne_binary().
create_queue(JObj) ->
Q = amqp_util:new_queue(),
amqp_util:basic_consume(Q),
wapi_call:bind_q(Q, [{restrict_to, [events]}
,{callid, get(callid)}
]),
wapi_self:bind_q(Q, []),
lager:debug("consuming call events"),
request_rating(JObj),
Q.

ok = amqp_util:basic_consume(Q),
ok = wapi_call:bind_q(Q, [{restrict_to, [events]}
,{callid, get(callid)}
]),
ok = wapi_self:bind_q(Q, []),
ok = request_rating(JObj),
Q.

%%--------------------------------------------------------------------
%% @private
Expand All @@ -393,18 +401,19 @@ create_queue(JObj) ->
%%--------------------------------------------------------------------
-spec request_rating/1 :: (wh_json:json_object()) -> 'ok'.
request_rating(JObj) ->
whapps_util:put_callid(JObj),
_ = wh_util:put_callid(JObj),
CallID = wh_json:get_value(<<"Call-ID">>, JObj),
lager:debug("sending rate request"),
Req = [{<<"To-DID">>, wh_json:get_value(<<"To-DID">>, JObj)}
,{<<"From-DID">>, wh_json:get_value(<<"From-DID">>, JObj)}
,{<<"Call-ID">>, get(callid)}
,{<<"Call-ID">>, CallID}
,{<<"Control-Queue">>, wh_json:get_value(<<"Control-Queue">>, JObj)}
,{<<"Account-ID">>, wh_json:get_value(<<"Account-ID">>, JObj)}
,{<<"Options">>, wh_json:get_value(<<"Flags">>, JObj, [])}
,{<<"Direction">>, <<"outbound">>}
| wh_api:default_headers(?APP_NAME, ?APP_VERSION)
],
wapi_call:publish_rate_req(get(callid), [KV || {_,V}=KV <- Req, V =/= undefined]).
wapi_call:publish_rate_req(CallID, [KV || {_,V}=KV <- Req, V =/= undefined]).

%%--------------------------------------------------------------------
%% @private
Expand All @@ -413,24 +422,25 @@ request_rating(JObj) ->
%% us in a case clause to determine the appropriate action.
%% @end
%%--------------------------------------------------------------------
-spec get_event_type/1 :: (wh_json:json_object()) -> {binary(), binary(), undefined | binary()}.
-spec get_event_type/1 :: (wh_json:json_object()) -> {binary(), binary(), binary()}.
get_event_type(JObj) ->
{ wh_json:get_value(<<"Event-Category">>, JObj, <<>>)
,wh_json:get_value(<<"Event-Name">>, JObj, <<>>)
,wh_json:get_value(<<"Application-Name">>, JObj, <<>>) }.
,wh_json:get_value(<<"Application-Name">>, JObj, <<>>)
}.

%%--------------------------------------------------------------------
%% @private
%% @doc
%% Filter the given resources by any flags required and rules that match
%% this number. Then sort them by weight and build the Endpoints
%% this number. Then sort them by weight and build the Endpoints
%% component of a Whistle dialplan bridge API.
%% @end
%%--------------------------------------------------------------------
-spec find_endpoints/3 :: (ne_binary(), [] | [ne_binary(),...], endpoints()) -> {proplist(), boolean()}.
find_endpoints(Number, Flags, Resources) ->
Endpoints = case Flags of
'undefined' ->
'undefined' ->
stepswitch_util:evaluate_number(Number, Resources);
Flags ->
_ = [lager:debug("resource must have ~s flag", [F]) || F <- Flags],
Expand Down Expand Up @@ -483,7 +493,7 @@ build_endpoints([{_, GracePeriod, Number, Gateways, _}|T], Delay, Acc0) ->
%%--------------------------------------------------------------------
%% @private
%% @doc
%%
%%
%% @end
%%--------------------------------------------------------------------
-spec build_endpoint/3 :: (ne_binary(), #gateway{}, non_neg_integer()) -> wh_json:json_object().
Expand Down Expand Up @@ -517,7 +527,7 @@ build_endpoint(Number, Gateway, _Delay) ->
%% create and send a Whistle offnet resource response
%% @end
%%--------------------------------------------------------------------
-spec response/2 :: (bridge_resp() | execute_ext_resp() | originate_resp(), wh_json:json_object()) -> proplist().
-spec response/2 :: ({'error', 'no_resources'} | bridge_resp() | execute_ext_resp() | originate_resp(), wh_json:json_object()) -> proplist().
response({ok, Resp}, JObj) ->
lager:debug("outbound request successfully completed"),
[{<<"Call-ID">>, wh_json:get_value(<<"Call-ID">>, JObj)}
Expand Down Expand Up @@ -579,8 +589,8 @@ response({error, Error}, JObj) ->
%%--------------------------------------------------------------------
%% @private
%% @doc
%% if the given number is shorter then a known caller id then try
%% to pad the front of the dialed number with values from the
%% if the given number is shorter then a known caller id then try
%% to pad the front of the dialed number with values from the
%% callerid.
%% @end
%%--------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion whistle_apps/src/whapps_call.erl
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,7 @@ kvs_update_counter(Key, Number, #whapps_call{kvs=Dict}=Call) ->
-spec flush/0 :: () -> 'ok'.
flush() ->
{ok, Cache} = whistle_apps_sup:whapps_call_cache_proc(),
wh_cache:local_flush(Cache).
wh_cache:flush_local(Cache).

-spec cache/1 :: (whapps_call:call()) -> 'ok'.
-spec cache/2 :: (whapps_call:call(), pos_integer()) -> 'ok'.
Expand Down
2 changes: 1 addition & 1 deletion whistle_apps/src/whapps_conference.erl
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ kvs_update_counter(Key, Number, #whapps_conference{kvs=Dict}=Conference) ->
-spec flush/0 :: () -> 'ok'.
flush() ->
{ok, Cache} = whistle_apps_sup:whapps_call_cache_proc(),
wh_cache:local_flush(Cache).
wh_cache:flush_local(Cache).

-spec cache/1 :: (conference()) -> 'ok'.
-spec cache/2 :: (conference(), pos_integer()) -> 'ok'.
Expand Down

0 comments on commit 7ced45b

Please sign in to comment.