From 8925975c86a782abeb8b1ae795be062313daf170 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Fri, 23 May 2014 20:13:31 +0400 Subject: [PATCH] Fix proxying of ACK requests for 2xx responses --- src/mod_sip.erl | 21 +++++++---------- src/mod_sip_proxy.erl | 54 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 58 insertions(+), 17 deletions(-) diff --git a/src/mod_sip.erl b/src/mod_sip.erl index 8ed4ed8cf..4b733c623 100644 --- a/src/mod_sip.erl +++ b/src/mod_sip.erl @@ -12,7 +12,7 @@ -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, @@ -77,6 +77,13 @@ message_out(_, _) -> 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. @@ -251,18 +258,6 @@ process(Req, _) -> 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)}, diff --git a/src/mod_sip_proxy.erl b/src/mod_sip_proxy.erl index cae75bff8..b05c49061 100644 --- a/src/mod_sip_proxy.erl +++ b/src/mod_sip_proxy.erl @@ -12,7 +12,7 @@ -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, @@ -42,6 +42,19 @@ start_link(LServer, Opts) -> 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 %%%=================================================================== @@ -51,7 +64,7 @@ init([Host, Opts]) -> 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 = @@ -59,8 +72,9 @@ wait_for_request({#sip{type = request} = Req, TrID}, State) -> 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], @@ -234,6 +248,11 @@ add_via(#sip_socket{type = Transport}, LServer, #sip{hdrs = Hdrs} = Req) -> {<<"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, @@ -275,3 +294,30 @@ choose_best_response(#state{responses = Responses} = State) -> 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}.