-behaviour(esip).
%% API
--export([start/2, stop/1, prepare_request/1, make_response/2, at_my_host/1]).
+-export([start/2, stop/1, make_response/2, is_my_host/1, at_my_host/1]).
%% esip_callbacks
-export([data_in/2, data_out/2, message_in/2, message_out/2,
response(_Resp, _SIPSock) ->
ok.
+request(#sip{method = <<"ACK">>} = Req, SIPSock) ->
+ case action(Req, SIPSock) of
+ {relay, LServer} ->
+ mod_sip_proxy:route(Req, LServer, []);
+ _ ->
+ error
+ end;
request(_Req, _SIPSock) ->
error.
make_response(Req, #sip{type = response, status = 405,
hdrs = [{'allow', allow()}]}).
-prepare_request(#sip{hdrs = Hdrs1} = Req) ->
- MF = esip:get_hdr('max-forwards', Hdrs1),
- Hdrs2 = esip:set_hdr('max-forwards', MF-1, Hdrs1),
- Hdrs3 = lists:filter(
- fun({'proxy-authorization', {_, Params}}) ->
- Realm = esip:unquote(esip:get_param(<<"realm">>, Params)),
- not is_my_host(jlib:nameprep(Realm));
- (_) ->
- true
- end, Hdrs2),
- Req#sip{hdrs = Hdrs3}.
-
make_auth_hdr(LServer) ->
Realm = jlib:nameprep(LServer),
{<<"Digest">>, [{<<"realm">>, esip:quote(Realm)},
-behaviour(?GEN_FSM).
%% API
--export([start/2, start_link/2, route/4]).
+-export([start/2, start_link/2, route/3, route/4]).
%% gen_fsm callbacks
-export([init/1, wait_for_request/2, wait_for_response/2,
route(SIPMsg, _SIPSock, TrID, Pid) ->
?GEN_FSM:send_event(Pid, {SIPMsg, TrID}).
+route(Req, LServer, Opts) ->
+ Req1 = prepare_request(LServer, Req),
+ case connect(Req1, add_certfile(LServer, Opts)) of
+ {ok, SIPSockets} ->
+ lists:foreach(
+ fun(SIPSocket) ->
+ Req2 = add_via(SIPSocket, LServer, Req1),
+ esip:send(SIPSocket, Req2)
+ end, SIPSockets);
+ _ ->
+ error
+ end.
+
%%%===================================================================
%%% gen_fsm callbacks
%%%===================================================================
wait_for_request({#sip{type = request} = Req, TrID}, State) ->
Opts = State#state.opts,
- Req1 = mod_sip:prepare_request(Req),
+ Req1 = prepare_request(State#state.host, Req),
case connect(Req1, Opts) of
{ok, SIPSockets} ->
NewState =
fun(_SIPSocket, {error, _} = Err) ->
Err;
(SIPSocket, #state{tr_ids = TrIDs} = AccState) ->
- Req2 = add_via(SIPSocket, State#state.host, Req1),
- case esip:request(SIPSocket, Req2,
+ Req2 = add_record_route(SIPSocket, State#state.host, Req1),
+ Req3 = add_via(SIPSocket, State#state.host, Req2),
+ case esip:request(SIPSocket, Req3,
{?MODULE, route, [self()]}) of
{ok, ClientTrID} ->
NewTrIDs = [ClientTrID|TrIDs],
{<<"rport">>, <<"">>}]},
Req#sip{hdrs = [{'via', [Via]}|Hdrs]}.
+add_record_route(_SIPSocket, LServer, #sip{hdrs = Hdrs} = Req) ->
+ URI = #uri{host = LServer, params = [{<<"lr">>, <<"">>}]},
+ Hdrs1 = [{'record-route', [{<<>>, URI, []}]}|Hdrs],
+ Req#sip{hdrs = Hdrs1}.
+
get_configured_vias(LServer) ->
gen_mod:get_module_opt(
LServer, ?MODULE, via,
ok
end
end.
+
+prepare_request(Host, #sip{hdrs = Hdrs} = Req) ->
+ Hdrs1 = lists:flatmap(
+ fun({Hdr, HdrList}) when Hdr == 'route';
+ Hdr == 'record-route' ->
+ case lists:filter(
+ fun({_, #uri{user = <<"">>, host = Host1}, _}) ->
+ Host1 /= Host
+ end, HdrList) of
+ [] ->
+ [];
+ HdrList1 ->
+ [{Hdr, HdrList1}]
+ end;
+ (Hdr) ->
+ [Hdr]
+ end, Hdrs),
+ MF = esip:get_hdr('max-forwards', Hdrs1),
+ Hdrs2 = esip:set_hdr('max-forwards', MF-1, Hdrs1),
+ Hdrs3 = lists:filter(
+ fun({'proxy-authorization', {_, Params}}) ->
+ Realm = esip:unquote(esip:get_param(<<"realm">>, Params)),
+ not mod_sip:is_my_host(jlib:nameprep(Realm));
+ (_) ->
+ true
+ end, Hdrs2),
+ Req#sip{hdrs = Hdrs3}.