%%% Purpose : Implements XMPP over BOSH (XEP-0205) (formerly known as
%%% HTTP Binding)
%%% 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).
-author('steve@zeank.in-berlin.de').
--vsn('$Rev: 278 $').
+-vsn('$Rev: 280 $').
-behaviour(gen_fsm).
last_poll,
ctime = 0,
timer,
+ pause=0,
req_list = [] % list of requests
}).
-define(MAX_REQUESTS, 2). % number of simultaneous requests
-define(MIN_POLLING, 2000000). % don't poll faster than that or we will
% shoot you (time in µsec)
--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
% 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(HEADER, [?CT]).
RidAllow = case StateData#state.rid of
none ->
%% first request - nothing saved so far
- true;
+ {true, 0};
OldRid ->
?DEBUG("state.rid/cur rid: ~p/~p",
[OldRid, Rid]),
if
(OldRid < Rid) and
(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 - Hold - 1) ->
repeat;
true;
false ->
false;
- true ->
+ {true, _} ->
case StateData#state.key of
"" ->
true;
end,
{reply, Reply, StateName,
StateData#state{input = "cancel", last_poll = LastPoll}};
- true ->
+ {true, Pause} ->
SaveKey = if
NewKey == "" ->
Key;
El#hbr.rid > (Rid - 1 - Hold)]
],
%% ?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
false ->
- cancel_timer(StateData#state.timer),
- Timer = erlang:start_timer(
- ?MAX_INACTIVITY, self(), []),
Input = Payload ++ [StateData#state.input],
Reply = ok,
{reply, Reply, StateName,
key = SaveKey,
ctime = TNow,
timer = Timer,
+ pause = Pause,
last_poll = LastPoll,
req_list = ReqList
}};
?DEBUG("really sending now: ~s", [SendPacket]),
Receiver ! {tcp, {http_bind, self()},
list_to_binary(SendPacket)},
- cancel_timer(StateData#state.timer),
- Timer = erlang:start_timer(
- ?MAX_INACTIVITY, self(), []),
Reply = ok,
{reply, Reply, StateName,
StateData#state{waiting_input = false,
key = SaveKey,
ctime = TNow,
timer = Timer,
+ pause = Pause,
last_poll = LastPoll,
req_list = ReqList
}}
end;
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(),
TNow = TSec*1000*1000 + TMSec,
- cancel_timer(StateData#state.timer),
- Timer = erlang:start_timer(?MAX_INACTIVITY, self(), []),
if
(Hold > 0) and
(StateData#state.output == "") and
((TNow - StateData#state.ctime) < (Wait*1000*1000)) and
(StateData#state.rid == Rid) and
- (StateData#state.input /= "cancel") ->
+ (StateData#state.input /= "cancel") and
+ (StateData#state.pause == 0) ->
Output = StateData#state.output,
ReqList = StateData#state.req_list,
Reply = {ok, keep_on_hold};
{"inactivity",
integer_to_list(
trunc(?MAX_INACTIVITY/1000))},
+ {"maxpause",
+ integer_to_list(?MAX_PAUSE)},
{"polling",
integer_to_list(
trunc(?MIN_POLLING/1000000))},