26
1
mirror of https://github.com/processone/ejabberd.git synced 2024-12-26 17:38:45 +01:00

Process bindings from multiple UACs correctly

This commit is contained in:
Evgeniy Khramtsov 2014-05-31 09:06:28 +04:00
parent da22da23cd
commit 86f2af6fdc

View File

@ -85,17 +85,9 @@ request(#sip{hdrs = Hdrs} = Req, SIPSock) ->
case register_session(US, SIPSock, CallID, CSeq, case register_session(US, SIPSock, CallID, CSeq,
ContactsWithExpires) of ContactsWithExpires) of
{ok, Res} -> {ok, Res} ->
if Res == updated -> ?INFO_MSG("~s SIP session for user ~s@~s from ~s",
?INFO_MSG("register SIP session for user " [Res, LUser, LServer,
"~s@~s from ~s", inet_parse:ntoa(PeerIP)]),
[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,
Cs = prepare_contacts_to_send(ContactsWithExpires), Cs = prepare_contacts_to_send(ContactsWithExpires),
mod_sip:make_response( mod_sip:make_response(
Req, Req,
@ -219,33 +211,36 @@ write_session(#sip_session{us = {U, S} = US, bindings = NewBindings}) ->
Err; Err;
(#binding{call_id = CallID, (#binding{call_id = CallID,
expires = Expires, expires = Expires,
cseq = CSeq} = Binding, {Add, Del}) -> cseq = CSeq} = Binding, {Add, Keep, Del}) ->
case find_binding(Binding, PrevBindings) of case find_binding(Binding, PrevBindings) of
{ok, #binding{call_id = CallID, cseq = PrevCSeq}} {ok, #binding{call_id = CallID, cseq = PrevCSeq}}
when PrevCSeq > CSeq -> when PrevCSeq > CSeq ->
{error, cseq_out_of_order}; {error, cseq_out_of_order};
{ok, PrevBinding} when Expires == 0 -> {ok, PrevBinding} when Expires == 0 ->
{Add, [PrevBinding|Del]}; {Add, Keep -- [PrevBinding], [PrevBinding|Del]};
{ok, _} -> {ok, PrevBinding} ->
{[Binding|Add], Del}; {[Binding|Add], Keep -- [PrevBinding], Del};
{error, notfound} when Expires == 0 -> {error, notfound} when Expires == 0 ->
{error, notfound}; {error, notfound};
{error, notfound} -> {error, notfound} ->
{[Binding|Add], Del} {[Binding|Add], Keep, Del}
end end
end, {[], []}, NewBindings), end, {[], PrevBindings, []}, NewBindings),
MaxSessions = ejabberd_sm:get_max_user_sessions(U, S), MaxSessions = ejabberd_sm:get_max_user_sessions(U, S),
case Res of case Res of
{error, Why} -> {error, Why} ->
{error, Why}; {error, Why};
{AddBindings, _} when length(AddBindings) > MaxSessions -> {AddBindings, KeepBindings, DelBindings} ->
MaxSessions = ejabberd_sm:get_max_user_sessions(U, S),
AllBindings = AddBindings ++ KeepBindings,
if length(AllBindings) > MaxSessions ->
{error, too_many_sessions}; {error, too_many_sessions};
{AddBindings, DelBindings} -> true ->
lists:foreach( lists:foreach(
fun(#binding{tref = TRef}) -> fun(#binding{tref = TRef}) ->
erlang:cancel_timer(TRef) erlang:cancel_timer(TRef)
end, DelBindings), end, DelBindings),
Bindings = lists:map( AddBindings1 = lists:map(
fun(#binding{tref = TRef, fun(#binding{tref = TRef,
expires = Expires} = Binding) -> expires = Expires} = Binding) ->
erlang:cancel_timer(TRef), erlang:cancel_timer(TRef),
@ -253,14 +248,20 @@ write_session(#sip_session{us = {U, S} = US, bindings = NewBindings}) ->
Expires * 1000, self(), US), Expires * 1000, self(), US),
Binding#binding{tref = NewTRef} Binding#binding{tref = NewTRef}
end, AddBindings), end, AddBindings),
case Bindings of AllBindings1 = AddBindings1 ++ KeepBindings,
case AllBindings1 of
[] -> [] ->
mnesia:dirty_delete(sip_session, US), mnesia:dirty_delete(sip_session, US),
{ok, deleted}; {ok, unregister};
_ -> _ ->
mnesia:dirty_write( mnesia:dirty_write(
#sip_session{us = US, bindings = Bindings}), #sip_session{us = US, bindings = AllBindings1}),
{ok, updated} if length(DelBindings) == length(NewBindings) ->
{ok, unregister};
true ->
{ok, register}
end
end
end end
end. end.