mirror of
https://github.com/processone/ejabberd.git
synced 2024-07-04 23:15:31 +02:00
Fix mod_ack, make it work with both oor and normal clients.
If the client is able to go to oor, mod_ack must made it do so. If the client is not able to to go oor mode, mod_ack must stop the c2s session, and wait for it to really terminate before continuing (to avoid race conditions, see EJABS-1677). Conflicts: src/ejabberd_c2s.erl src/mod_ack.erl src/mod_ping.erl
This commit is contained in:
parent
99610c3357
commit
02eeebd41a
|
@ -35,7 +35,7 @@
|
||||||
-behaviour(?GEN_FSM).
|
-behaviour(?GEN_FSM).
|
||||||
|
|
||||||
%% External exports
|
%% External exports
|
||||||
-export([start/2, stop/1, start_link/3, send_text/2,
|
-export([start/2, stop_or_detach/1, start_link/3, send_text/2,
|
||||||
send_element/2, socket_type/0, get_presence/1,
|
send_element/2, socket_type/0, get_presence/1,
|
||||||
get_aux_field/2, set_aux_field/3, del_aux_field/2,
|
get_aux_field/2, set_aux_field/3, del_aux_field/2,
|
||||||
get_subscription/2, broadcast/4, get_subscribed/1]).
|
get_subscription/2, broadcast/4, get_subscribed/1]).
|
||||||
|
@ -44,10 +44,13 @@
|
||||||
-export([add_rosteritem/3, del_rosteritem/2]).
|
-export([add_rosteritem/3, del_rosteritem/2]).
|
||||||
|
|
||||||
%% gen_fsm callbacks
|
%% gen_fsm callbacks
|
||||||
-export([init/1, wait_for_stream/2, wait_for_auth/2,
|
-export([init/1, wait_for_stream/2, wait_for_stream/3,
|
||||||
wait_for_feature_request/2, wait_for_bind/2,
|
wait_for_auth/2, wait_for_auth/3,
|
||||||
wait_for_session/2, wait_for_sasl_response/2,
|
wait_for_feature_request/2, wait_for_feature_request/3,
|
||||||
session_established/2, handle_event/3,
|
wait_for_bind/2, wait_for_bind/3,
|
||||||
|
wait_for_session/2, wait_for_session/3,
|
||||||
|
wait_for_sasl_response/2, wait_for_sasl_response/3,
|
||||||
|
session_established/2, session_established/3, handle_event/3,
|
||||||
handle_sync_event/4, code_change/4, handle_info/3,
|
handle_sync_event/4, code_change/4, handle_info/3,
|
||||||
terminate/3, print_state/1, migrate/3,
|
terminate/3, print_state/1, migrate/3,
|
||||||
migrate_shutdown/3]).
|
migrate_shutdown/3]).
|
||||||
|
@ -195,7 +198,28 @@ get_subscription(LFrom, StateData) ->
|
||||||
broadcast(FsmRef, Type, From, Packet) ->
|
broadcast(FsmRef, Type, From, Packet) ->
|
||||||
FsmRef ! {broadcast, Type, From, Packet}.
|
FsmRef ! {broadcast, Type, From, Packet}.
|
||||||
|
|
||||||
stop(FsmRef) -> (?GEN_FSM):send_event(FsmRef, closed).
|
%% Used by mod_ack and mod_ping.
|
||||||
|
%% If the client is not oor capable, we must stop the session,
|
||||||
|
%% and be sure to not return until the c2s process has really stopped. This
|
||||||
|
%% is to avoid race conditions when resending messages in mod_ack (EJABS-1677).
|
||||||
|
%% In the other side, if the client is oor capable, then this just
|
||||||
|
%% switch reception to false, and returns inmediately.
|
||||||
|
stop_or_detach(FsmRef) ->
|
||||||
|
case ?GEN_FSM:sync_send_event(FsmRef, stop_or_detach) of
|
||||||
|
stopped ->
|
||||||
|
MRef = erlang:monitor(process, FsmRef),
|
||||||
|
receive
|
||||||
|
{'DOWN', MRef, process, FsmRef, _Reason}->
|
||||||
|
ok
|
||||||
|
after 5 ->
|
||||||
|
catch exit(FsmRef, kill)
|
||||||
|
end,
|
||||||
|
erlang:demonitor(MRef, [flush]),
|
||||||
|
ok;
|
||||||
|
detached ->
|
||||||
|
ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
migrate(FsmRef, Node, After) ->
|
migrate(FsmRef, Node, After) ->
|
||||||
erlang:send_after(After, FsmRef, {migrate, Node}).
|
erlang:send_after(After, FsmRef, {migrate, Node}).
|
||||||
|
@ -575,6 +599,8 @@ wait_for_stream({xmlstreamerror, _}, StateData) ->
|
||||||
{stop, normal, StateData};
|
{stop, normal, StateData};
|
||||||
wait_for_stream(closed, StateData) ->
|
wait_for_stream(closed, StateData) ->
|
||||||
{stop, normal, StateData}.
|
{stop, normal, StateData}.
|
||||||
|
wait_for_stream(stop_or_detach, _From, StateData) ->
|
||||||
|
{stop, normal, stopped, StateData}.
|
||||||
|
|
||||||
wait_for_auth({xmlstreamelement, El}, StateData) ->
|
wait_for_auth({xmlstreamelement, El}, StateData) ->
|
||||||
case is_auth_packet(El) of
|
case is_auth_packet(El) of
|
||||||
|
@ -762,6 +788,8 @@ wait_for_auth({xmlstreamerror, _}, StateData) ->
|
||||||
{stop, normal, StateData};
|
{stop, normal, StateData};
|
||||||
wait_for_auth(closed, StateData) ->
|
wait_for_auth(closed, StateData) ->
|
||||||
{stop, normal, StateData}.
|
{stop, normal, StateData}.
|
||||||
|
wait_for_auth(stop_or_detach,_From, StateData) ->
|
||||||
|
{stop, normal, stopped, StateData}.
|
||||||
|
|
||||||
wait_for_feature_request({xmlstreamelement, El},
|
wait_for_feature_request({xmlstreamelement, El},
|
||||||
StateData) ->
|
StateData) ->
|
||||||
|
@ -951,6 +979,8 @@ wait_for_feature_request({xmlstreamerror, _},
|
||||||
{stop, normal, StateData};
|
{stop, normal, StateData};
|
||||||
wait_for_feature_request(closed, StateData) ->
|
wait_for_feature_request(closed, StateData) ->
|
||||||
{stop, normal, StateData}.
|
{stop, normal, StateData}.
|
||||||
|
wait_for_feature_request(stop_or_detach, _From, StateData) ->
|
||||||
|
{stop, normal, stopped, StateData}.
|
||||||
|
|
||||||
wait_for_sasl_response({xmlstreamelement, El},
|
wait_for_sasl_response({xmlstreamelement, El},
|
||||||
StateData) ->
|
StateData) ->
|
||||||
|
@ -1063,6 +1093,8 @@ wait_for_sasl_response({xmlstreamerror, _},
|
||||||
{stop, normal, StateData};
|
{stop, normal, StateData};
|
||||||
wait_for_sasl_response(closed, StateData) ->
|
wait_for_sasl_response(closed, StateData) ->
|
||||||
{stop, normal, StateData}.
|
{stop, normal, StateData}.
|
||||||
|
wait_for_sasl_response(stop_or_detach, _From, StateData) ->
|
||||||
|
{stop, normal, stopped, StateData}.
|
||||||
|
|
||||||
resource_conflict_action(U, S, R) ->
|
resource_conflict_action(U, S, R) ->
|
||||||
OptionRaw = case ejabberd_sm:is_existing_resource(U, S,
|
OptionRaw = case ejabberd_sm:is_existing_resource(U, S,
|
||||||
|
@ -1155,6 +1187,8 @@ wait_for_bind({xmlstreamerror, _}, StateData) ->
|
||||||
{stop, normal, StateData};
|
{stop, normal, StateData};
|
||||||
wait_for_bind(closed, StateData) ->
|
wait_for_bind(closed, StateData) ->
|
||||||
{stop, normal, StateData}.
|
{stop, normal, StateData}.
|
||||||
|
wait_for_bind(stop_or_detach, _From, StateData) ->
|
||||||
|
{stop, normal, stopped, StateData}.
|
||||||
|
|
||||||
wait_for_session({xmlstreamelement, El}, StateData) ->
|
wait_for_session({xmlstreamelement, El}, StateData) ->
|
||||||
case jlib:iq_query_info(El) of
|
case jlib:iq_query_info(El) of
|
||||||
|
@ -1224,6 +1258,8 @@ wait_for_session({xmlstreamerror, _}, StateData) ->
|
||||||
{stop, normal, StateData};
|
{stop, normal, StateData};
|
||||||
wait_for_session(closed, StateData) ->
|
wait_for_session(closed, StateData) ->
|
||||||
{stop, normal, StateData}.
|
{stop, normal, StateData}.
|
||||||
|
wait_for_session(stop_or_detach, _From, StateData) ->
|
||||||
|
{stop, normal, stopped, StateData}.
|
||||||
|
|
||||||
session_established({xmlstreamelement, El},
|
session_established({xmlstreamelement, El},
|
||||||
StateData) ->
|
StateData) ->
|
||||||
|
@ -1267,6 +1303,19 @@ session_established(closed, StateData) ->
|
||||||
fsm_next_state(session_established, NewState);
|
fsm_next_state(session_established, NewState);
|
||||||
true -> {stop, normal, StateData}
|
true -> {stop, normal, StateData}
|
||||||
end.
|
end.
|
||||||
|
session_established(stop_or_detach, From, StateData) ->
|
||||||
|
if
|
||||||
|
not StateData#state.reception ->
|
||||||
|
?GEN_FSM:reply(From, detached),
|
||||||
|
fsm_next_state(session_established, StateData);
|
||||||
|
(StateData#state.keepalive_timer /= undefined) ->
|
||||||
|
NewState1 = change_reception(StateData, false),
|
||||||
|
NewState = start_keepalive_timer(NewState1),
|
||||||
|
?GEN_FSM:reply(From, detached),
|
||||||
|
fsm_next_state(session_established, NewState);
|
||||||
|
true ->
|
||||||
|
{stop, normal, stopped, StateData}
|
||||||
|
end.
|
||||||
|
|
||||||
session_established2(El, StateData) ->
|
session_established2(El, StateData) ->
|
||||||
#xmlel{name = Name, attrs = Attrs} = El,
|
#xmlel{name = Name, attrs = Attrs} = El,
|
||||||
|
|
|
@ -241,7 +241,7 @@ handle_cast(_Msg, State) -> {noreply, State}.
|
||||||
handle_info({timeout, _TRef, {ID, Pid}}, State) ->
|
handle_info({timeout, _TRef, {ID, Pid}}, State) ->
|
||||||
case lookup(Pid, ID, State#state.timers) of
|
case lookup(Pid, ID, State#state.timers) of
|
||||||
{ok, _} ->
|
{ok, _} ->
|
||||||
catch ejabberd_c2s:stop(Pid),
|
catch ejabberd_c2s:stop_or_detach(Pid),
|
||||||
handle_cast({del, Pid}, State);
|
handle_cast({del, Pid}, State);
|
||||||
error ->
|
error ->
|
||||||
?WARNING_MSG("ack ID not found :~p", [ID]),
|
?WARNING_MSG("ack ID not found :~p", [ID]),
|
||||||
|
|
|
@ -165,7 +165,7 @@ handle_cast({iq_pong, JID, timeout}, State) ->
|
||||||
JID,
|
JID,
|
||||||
case ejabberd_sm:get_session_pid(User, Server, Resource)
|
case ejabberd_sm:get_session_pid(User, Server, Resource)
|
||||||
of
|
of
|
||||||
Pid when is_pid(Pid) -> ejabberd_c2s:stop(Pid);
|
Pid when is_pid(Pid) -> ejabberd_c2s:stop_or_detach(Pid);
|
||||||
_ -> ok
|
_ -> ok
|
||||||
end;
|
end;
|
||||||
_ -> ok
|
_ -> ok
|
||||||
|
|
Loading…
Reference in New Issue
Block a user