25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-11-22 16:20:52 +01:00

Support pausing sessions (thanks to Stefan Strigler) (thanks to Stefan Strigler)

SVN Revision: 2286
This commit is contained in:
Badlop 2009-06-16 18:25:22 +00:00
parent c151da684d
commit 8aede81188

View File

@ -4,12 +4,12 @@
%%% Purpose : Implements XMPP over BOSH (XEP-0205) (formerly known as %%% Purpose : Implements XMPP over BOSH (XEP-0205) (formerly known as
%%% HTTP Binding) %%% HTTP Binding)
%%% Created : 21 Sep 2005 by Stefan Strigler <steve@zeank.in-berlin.de> %%% Created : 21 Sep 2005 by Stefan Strigler <steve@zeank.in-berlin.de>
%%% Id : $Id: ejabberd_http_bind.erl 278 2007-08-16 10:53:28Z sstrigler $ %%% Id : $Id: ejabberd_http_bind.erl 280 2007-08-16 13:25:41Z sstrigler $
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
-module(ejabberd_http_bind). -module(ejabberd_http_bind).
-author('steve@zeank.in-berlin.de'). -author('steve@zeank.in-berlin.de').
-vsn('$Rev: 278 $'). -vsn('$Rev: 280 $').
-behaviour(gen_fsm). -behaviour(gen_fsm).
@ -53,6 +53,7 @@
last_poll, last_poll,
ctime = 0, ctime = 0,
timer, timer,
pause=0,
req_list = [] % list of requests req_list = [] % list of requests
}). }).
@ -76,6 +77,9 @@
-define(MAX_WAIT, 3600). % max num of secs to keep a request on hold -define(MAX_WAIT, 3600). % max num of secs to keep a request on hold
-define(MAX_INACTIVITY, 30000). % msecs to wait before terminating -define(MAX_INACTIVITY, 30000). % msecs to wait before terminating
% idle sessions % idle sessions
-define(MAX_PAUSE, 120). % may num of sec a client is allowed to pause
% the session
-define(CT, {"Content-Type", "text/xml; charset=utf-8"}). -define(CT, {"Content-Type", "text/xml; charset=utf-8"}).
-define(HEADER, [?CT]). -define(HEADER, [?CT]).
@ -288,14 +292,19 @@ handle_sync_event({http_put, Rid, Attrs, Payload, Hold, StreamTo},
RidAllow = case StateData#state.rid of RidAllow = case StateData#state.rid of
none -> none ->
%% first request - nothing saved so far %% first request - nothing saved so far
true; {true, 0};
OldRid -> OldRid ->
?DEBUG("state.rid/cur rid: ~p/~p", ?DEBUG("state.rid/cur rid: ~p/~p",
[OldRid, Rid]), [OldRid, Rid]),
if if
(OldRid < Rid) and (OldRid < Rid) and
(Rid =< (OldRid + Hold + 1)) -> (Rid =< (OldRid + Hold + 1)) ->
true; case xml:get_attr_s("pause", Attrs) of
Pause1 when Pause1 =< ?MAX_PAUSE ->
{true, Pause1};
_ ->
{true, 0}
end;
(Rid =< OldRid) and (Rid =< OldRid) and
(Rid > OldRid - Hold - 1) -> (Rid > OldRid - Hold - 1) ->
repeat; repeat;
@ -309,7 +318,7 @@ handle_sync_event({http_put, Rid, Attrs, Payload, Hold, StreamTo},
true; true;
false -> false ->
false; false;
true -> {true, _} ->
case StateData#state.key of case StateData#state.key of
"" -> "" ->
true; true;
@ -360,7 +369,7 @@ handle_sync_event({http_put, Rid, Attrs, Payload, Hold, StreamTo},
end, end,
{reply, Reply, StateName, {reply, Reply, StateName,
StateData#state{input = "cancel", last_poll = LastPoll}}; StateData#state{input = "cancel", last_poll = LastPoll}};
true -> {true, Pause} ->
SaveKey = if SaveKey = if
NewKey == "" -> NewKey == "" ->
Key; Key;
@ -380,11 +389,19 @@ handle_sync_event({http_put, Rid, Attrs, Payload, Hold, StreamTo},
El#hbr.rid > (Rid - 1 - Hold)] El#hbr.rid > (Rid - 1 - Hold)]
], ],
%% ?DEBUG("reqlist: ~p", [ReqList]), %% ?DEBUG("reqlist: ~p", [ReqList]),
%% setup next timer
cancel_timer(StateData#state.timer),
if
Pause > 0 ->
Timer = erlang:start_timer(
Pause, self(), []);
true ->
Timer = erlang:start_timer(
?MAX_INACTIVITY, self(), [])
end,
case StateData#state.waiting_input of case StateData#state.waiting_input of
false -> false ->
cancel_timer(StateData#state.timer),
Timer = erlang:start_timer(
?MAX_INACTIVITY, self(), []),
Input = Payload ++ [StateData#state.input], Input = Payload ++ [StateData#state.input],
Reply = ok, Reply = ok,
{reply, Reply, StateName, {reply, Reply, StateName,
@ -393,6 +410,7 @@ handle_sync_event({http_put, Rid, Attrs, Payload, Hold, StreamTo},
key = SaveKey, key = SaveKey,
ctime = TNow, ctime = TNow,
timer = Timer, timer = Timer,
pause = Pause,
last_poll = LastPoll, last_poll = LastPoll,
req_list = ReqList req_list = ReqList
}}; }};
@ -416,9 +434,6 @@ handle_sync_event({http_put, Rid, Attrs, Payload, Hold, StreamTo},
?DEBUG("really sending now: ~s", [SendPacket]), ?DEBUG("really sending now: ~s", [SendPacket]),
Receiver ! {tcp, {http_bind, self()}, Receiver ! {tcp, {http_bind, self()},
list_to_binary(SendPacket)}, list_to_binary(SendPacket)},
cancel_timer(StateData#state.timer),
Timer = erlang:start_timer(
?MAX_INACTIVITY, self(), []),
Reply = ok, Reply = ok,
{reply, Reply, StateName, {reply, Reply, StateName,
StateData#state{waiting_input = false, StateData#state{waiting_input = false,
@ -428,6 +443,7 @@ handle_sync_event({http_put, Rid, Attrs, Payload, Hold, StreamTo},
key = SaveKey, key = SaveKey,
ctime = TNow, ctime = TNow,
timer = Timer, timer = Timer,
pause = Pause,
last_poll = LastPoll, last_poll = LastPoll,
req_list = ReqList req_list = ReqList
}} }}
@ -439,16 +455,26 @@ handle_sync_event({http_put, Rid, Attrs, Payload, Hold, StreamTo},
end; end;
handle_sync_event({http_get, Rid, Wait, Hold}, _From, StateName, StateData) -> handle_sync_event({http_get, Rid, Wait, Hold}, _From, StateName, StateData) ->
%% setup timer
cancel_timer(StateData#state.timer),
if
StateData#state.pause > 0 ->
Timer = erlang:start_timer(
StateData#state.pause, self(), []);
true ->
Timer = erlang:start_timer(
?MAX_INACTIVITY, self(), [])
end,
{_,TSec,TMSec} = now(), {_,TSec,TMSec} = now(),
TNow = TSec*1000*1000 + TMSec, TNow = TSec*1000*1000 + TMSec,
cancel_timer(StateData#state.timer),
Timer = erlang:start_timer(?MAX_INACTIVITY, self(), []),
if if
(Hold > 0) and (Hold > 0) and
(StateData#state.output == "") and (StateData#state.output == "") and
((TNow - StateData#state.ctime) < (Wait*1000*1000)) and ((TNow - StateData#state.ctime) < (Wait*1000*1000)) and
(StateData#state.rid == Rid) and (StateData#state.rid == Rid) and
(StateData#state.input /= "cancel") -> (StateData#state.input /= "cancel") and
(StateData#state.pause == 0) ->
Output = StateData#state.output, Output = StateData#state.output,
ReqList = StateData#state.req_list, ReqList = StateData#state.req_list,
Reply = {ok, keep_on_hold}; Reply = {ok, keep_on_hold};
@ -678,6 +704,8 @@ prepare_response(#http_bind{id=Sid, wait=Wait, hold=Hold}=Sess,
{"inactivity", {"inactivity",
integer_to_list( integer_to_list(
trunc(?MAX_INACTIVITY/1000))}, trunc(?MAX_INACTIVITY/1000))},
{"maxpause",
integer_to_list(?MAX_PAUSE)},
{"polling", {"polling",
integer_to_list( integer_to_list(
trunc(?MIN_POLLING/1000000))}, trunc(?MIN_POLLING/1000000))},