aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mod_sip_proxy.erl26
-rw-r--r--src/mod_sip_registrar.erl81
2 files changed, 59 insertions, 48 deletions
diff --git a/src/mod_sip_proxy.erl b/src/mod_sip_proxy.erl
index 7a10671e4..16c45df5c 100644
--- a/src/mod_sip_proxy.erl
+++ b/src/mod_sip_proxy.erl
@@ -47,9 +47,9 @@ route(Req, LServer, Opts) ->
case connect(Req1, add_certfile(LServer, Opts)) of
{ok, SIPSocketsWithURIs} ->
lists:foreach(
- fun({SIPSocket, URI}) ->
+ fun({SIPSocket, _URI}) ->
Req2 = add_via(SIPSocket, LServer, Req1),
- esip:send(SIPSocket, Req2#sip{uri = URI})
+ esip:send(SIPSocket, Req2)
end, SIPSocketsWithURIs);
_ ->
error
@@ -72,9 +72,10 @@ wait_for_request({#sip{type = request} = Req, TrID}, State) ->
fun(_SIPSocketWithURI, {error, _} = Err) ->
Err;
({SIPSocket, URI}, #state{tr_ids = TrIDs} = AccState) ->
- Req2 = add_record_route(SIPSocket, State#state.host, Req1),
+ Req2 = add_record_route_and_set_uri(
+ URI, State#state.host, Req1),
Req3 = add_via(SIPSocket, State#state.host, Req2),
- case esip:request(SIPSocket, Req3#sip{uri = URI},
+ case esip:request(SIPSocket, Req3,
{?MODULE, route, [self()]}) of
{ok, ClientTrID} ->
NewTrIDs = [ClientTrID|TrIDs],
@@ -248,10 +249,19 @@ 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}.
+add_record_route_and_set_uri(URI, LServer, #sip{hdrs = Hdrs} = Req) ->
+ case is_request_within_dialog(Req) of
+ false ->
+ RR_URI = #uri{host = LServer, params = [{<<"lr">>, <<"">>}]},
+ Hdrs1 = [{'record-route', [{<<>>, RR_URI, []}]}|Hdrs],
+ Req#sip{uri = URI, hdrs = Hdrs1};
+ true ->
+ Req
+ end.
+
+is_request_within_dialog(#sip{hdrs = Hdrs}) ->
+ {_, _, Params} = esip:get_hdr('to', Hdrs),
+ esip:has_param(<<"tag">>, Params).
get_configured_vias(LServer) ->
gen_mod:get_module_opt(
diff --git a/src/mod_sip_registrar.erl b/src/mod_sip_registrar.erl
index 5080cf4a7..2102af851 100644
--- a/src/mod_sip_registrar.erl
+++ b/src/mod_sip_registrar.erl
@@ -85,17 +85,9 @@ request(#sip{hdrs = Hdrs} = Req, SIPSock) ->
case register_session(US, SIPSock, CallID, CSeq,
ContactsWithExpires) of
{ok, Res} ->
- if Res == updated ->
- ?INFO_MSG("register SIP session for user "
- "~s@~s from ~s",
- [LUser, LServer,
- inet_parse:ntoa(PeerIP)]);
- Res == deleted ->
- ?INFO_MSG("unregister SIP session for user "
- "~s@~s from ~s",
- [LUser, LServer,
- inet_parse:ntoa(PeerIP)])
- end,
+ ?INFO_MSG("~s SIP session for user ~s@~s from ~s",
+ [Res, LUser, LServer,
+ inet_parse:ntoa(PeerIP)]),
Cs = prepare_contacts_to_send(ContactsWithExpires),
mod_sip:make_response(
Req,
@@ -219,48 +211,57 @@ write_session(#sip_session{us = {U, S} = US, bindings = NewBindings}) ->
Err;
(#binding{call_id = CallID,
expires = Expires,
- cseq = CSeq} = Binding, {Add, Del}) ->
+ cseq = CSeq} = Binding, {Add, Keep, Del}) ->
case find_binding(Binding, PrevBindings) of
{ok, #binding{call_id = CallID, cseq = PrevCSeq}}
when PrevCSeq > CSeq ->
{error, cseq_out_of_order};
{ok, PrevBinding} when Expires == 0 ->
- {Add, [PrevBinding|Del]};
- {ok, _} ->
- {[Binding|Add], Del};
+ {Add, Keep -- [PrevBinding], [PrevBinding|Del]};
+ {ok, PrevBinding} ->
+ {[Binding|Add], Keep -- [PrevBinding], Del};
{error, notfound} when Expires == 0 ->
{error, notfound};
{error, notfound} ->
- {[Binding|Add], Del}
+ {[Binding|Add], Keep, Del}
end
- end, {[], []}, NewBindings),
+ end, {[], PrevBindings, []}, NewBindings),
MaxSessions = ejabberd_sm:get_max_user_sessions(U, S),
case Res of
{error, Why} ->
{error, Why};
- {AddBindings, _} when length(AddBindings) > MaxSessions ->
- {error, too_many_sessions};
- {AddBindings, DelBindings} ->
- lists:foreach(
- fun(#binding{tref = TRef}) ->
- erlang:cancel_timer(TRef)
- end, DelBindings),
- Bindings = lists:map(
- fun(#binding{tref = TRef,
- expires = Expires} = Binding) ->
- erlang:cancel_timer(TRef),
- NewTRef = erlang:start_timer(
- Expires * 1000, self(), US),
- Binding#binding{tref = NewTRef}
- end, AddBindings),
- case Bindings of
- [] ->
- mnesia:dirty_delete(sip_session, US),
- {ok, deleted};
- _ ->
- mnesia:dirty_write(
- #sip_session{us = US, bindings = Bindings}),
- {ok, updated}
+ {AddBindings, KeepBindings, DelBindings} ->
+ MaxSessions = ejabberd_sm:get_max_user_sessions(U, S),
+ AllBindings = AddBindings ++ KeepBindings,
+ if length(AllBindings) > MaxSessions ->
+ {error, too_many_sessions};
+ true ->
+ lists:foreach(
+ fun(#binding{tref = TRef}) ->
+ erlang:cancel_timer(TRef)
+ end, DelBindings),
+ AddBindings1 = lists:map(
+ fun(#binding{tref = TRef,
+ expires = Expires} = Binding) ->
+ erlang:cancel_timer(TRef),
+ NewTRef = erlang:start_timer(
+ Expires * 1000, self(), US),
+ Binding#binding{tref = NewTRef}
+ end, AddBindings),
+ AllBindings1 = AddBindings1 ++ KeepBindings,
+ case AllBindings1 of
+ [] ->
+ mnesia:dirty_delete(sip_session, US),
+ {ok, unregister};
+ _ ->
+ mnesia:dirty_write(
+ #sip_session{us = US, bindings = AllBindings1}),
+ if length(DelBindings) == length(NewBindings) ->
+ {ok, unregister};
+ true ->
+ {ok, register}
+ end
+ end
end
end.