24
1
mirror of https://github.com/processone/ejabberd.git synced 2024-09-27 14:30:55 +02:00

Removed receive_loop (thanks to Alexey Shchepin)

SVN Revision: 2296
This commit is contained in:
Badlop 2009-06-16 18:26:02 +00:00
parent 68754c4b5d
commit 5f07b4bf9b

View File

@ -4,7 +4,7 @@
%%% 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 440 2007-12-06 22:36:21Z badlop $ %%% Id : $Id: ejabberd_http_bind.erl 449 2007-12-18 15:00:10Z alexey $
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
-module(ejabberd_http_bind). -module(ejabberd_http_bind).
@ -50,6 +50,8 @@
waiting_input = false, waiting_input = false,
last_receiver, last_receiver,
last_poll, last_poll,
http_receiver,
wait_timer,
ctime = 0, ctime = 0,
timer, timer,
pause=0, pause=0,
@ -72,7 +74,7 @@
-define(MAX_REQUESTS, 2). % number of simultaneous requests -define(MAX_REQUESTS, 2). % number of simultaneous requests
-define(MIN_POLLING, 2000000). % don't poll faster than that or we will -define(MIN_POLLING, 2000000). % don't poll faster than that or we will
% shoot you (time in µsec) % 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 -define(MAX_INACTIVITY, 30000). % msecs to wait before terminating
% idle sessions % idle sessions
@ -283,8 +285,30 @@ handle_event(_Event, StateName, StateData) ->
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
handle_sync_event({send, Packet}, _From, StateName, StateData) -> handle_sync_event({send, Packet}, _From, StateName, StateData) ->
Output = [StateData#state.output | Packet], Output = [StateData#state.output | Packet],
if
StateData#state.http_receiver /= undefined ->
HTTPReply = case Output of
[[]| OutPacket] ->
{ok, OutPacket};
_ ->
{ok, Output}
end,
gen_fsm:reply(StateData#state.http_receiver, HTTPReply),
if
StateData#state.wait_timer /= undefined ->
cancel_timer(StateData#state.wait_timer);
true ->
ok
end,
Reply = ok, Reply = ok,
{reply, Reply, StateName, StateData#state{output = Output}}; {reply, Reply, StateName,
StateData#state{output = [],
http_receiver = undefined,
wait_timer = undefined}};
true ->
Reply = ok,
{reply, Reply, StateName, StateData#state{output = Output}}
end;
handle_sync_event(stop, _From, _StateName, StateData) -> handle_sync_event(stop, _From, _StateName, StateData) ->
Reply = ok, Reply = ok,
@ -333,7 +357,7 @@ handle_sync_event({http_put, Rid, Attrs, Payload, Hold, StreamTo},
"" -> "" ->
true; true;
OldKey -> OldKey ->
NextKey = string:to_lower( NextKey = jlib:tolower(
hex(binary_to_list( hex(binary_to_list(
crypto:sha(Key)))), crypto:sha(Key)))),
?DEBUG("Key/OldKey/NextKey: ~s/~s/~s", ?DEBUG("Key/OldKey/NextKey: ~s/~s/~s",
@ -464,18 +488,29 @@ handle_sync_event({http_put, Rid, Attrs, Payload, Hold, StreamTo},
{reply, Reply, StateName, StateData} {reply, Reply, StateName, StateData}
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 %% setup timer
cancel_timer(StateData#state.timer), cancel_timer(StateData#state.timer),
if Timer = if
StateData#state.pause > 0 -> StateData#state.pause > 0 ->
Timer = erlang:start_timer( erlang:start_timer(
StateData#state.pause*1000, self(), []); StateData#state.pause*1000, self(), []);
true -> true ->
Timer = erlang:start_timer( erlang:start_timer(
?MAX_INACTIVITY, self(), []) ?MAX_INACTIVITY, self(), [])
end, end,
if
StateData#state.http_receiver /= undefined ->
gen_fsm:reply(StateData#state.http_receiver, {ok, empty});
true ->
ok
end,
if
StateData#state.wait_timer /= undefined ->
cancel_timer(StateData#state.wait_timer);
true ->
ok
end,
{_,TSec,TMSec} = now(), {_,TSec,TMSec} = now(),
TNow = TSec*1000*1000 + TMSec, TNow = TSec*1000*1000 + TMSec,
if if
@ -487,11 +522,25 @@ handle_sync_event({http_get, Rid, Wait, Hold}, _From, StateName, StateData) ->
(StateData#state.pause == 0) -> (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}; WaitTimer = erlang:start_timer(Wait * 1000, self(), []),
{next_state, StateName, StateData#state{
input = "",
output = Output,
http_receiver = From,
wait_timer = WaitTimer,
timer = Timer,
req_list = ReqList}};
(StateData#state.input == "cancel") -> (StateData#state.input == "cancel") ->
Output = StateData#state.output, Output = StateData#state.output,
ReqList = StateData#state.req_list, ReqList = StateData#state.req_list,
Reply = {ok, cancel}; Reply = {ok, cancel},
{reply, Reply, StateName, StateData#state{
input = "",
output = Output,
http_receiver = undefined,
wait_timer = undefined,
timer = Timer,
req_list = ReqList}};
true -> true ->
case StateData#state.output of case StateData#state.output of
[[]| OutPacket] -> [[]| OutPacket] ->
@ -508,13 +557,15 @@ handle_sync_event({http_get, Rid, Wait, Hold}, _From, StateName, StateData) ->
[El || El <- StateData#state.req_list, [El || El <- StateData#state.req_list,
El#hbr.rid /= Rid ] El#hbr.rid /= Rid ]
], ],
Output = "" Output = "",
end,
{reply, Reply, StateName, StateData#state{ {reply, Reply, StateName, StateData#state{
input = "", input = "",
output = Output, output = Output,
http_receiver = undefined,
wait_timer = undefined,
timer = Timer, timer = Timer,
req_list = ReqList}}; req_list = ReqList}}
end;
handle_sync_event(_Event, _From, StateName, StateData) -> handle_sync_event(_Event, _From, StateName, StateData) ->
Reply = ok, Reply = ok,
@ -534,6 +585,18 @@ handle_info({timeout, Timer, _}, _StateName,
?DEBUG("ding dong", []), ?DEBUG("ding dong", []),
{stop, normal, StateData}; {stop, normal, StateData};
handle_info({timeout, Timer, _}, StateName,
#state{wait_timer = Timer} = StateData) ->
if
StateData#state.http_receiver /= undefined ->
gen_fsm:reply(StateData#state.http_receiver, {ok, empty}),
{next_state, StateName,
StateData#state{http_receiver = undefined,
wait_timer = undefined}};
true ->
{next_state, StateName, StateData}
end;
handle_info(_, StateName, StateData) -> handle_info(_, StateName, StateData) ->
{next_state, StateName, StateData}. {next_state, StateName, StateData}.
@ -574,7 +637,7 @@ handle_http_put(Sid, Rid, Attrs, Payload, StreamStart) ->
[OutPacket]), [OutPacket]),
send_outpacket(Sess, OutPacket); send_outpacket(Sess, OutPacket);
{ok, Sess} -> {ok, Sess} ->
receive_loop(Sess, Rid, Attrs, StreamStart) prepare_response(Sess, Rid, Attrs, StreamStart)
end. end.
http_put(Sid, Rid, Attrs, Payload, StreamStart) -> http_put(Sid, Rid, Attrs, Payload, StreamStart) ->
@ -632,22 +695,17 @@ handle_http_put_error(Reason, #http_bind{pid=FsmRef}) ->
end. end.
receive_loop(Sess, Rid, Attrs, StreamStart) ->
receive
after 100 -> ok
end,
prepare_response(Sess, Rid, Attrs, StreamStart).
prepare_response(#http_bind{id=Sid, wait=Wait, hold=Hold}=Sess, prepare_response(#http_bind{id=Sid, wait=Wait, hold=Hold}=Sess,
Rid, Attrs, StreamStart) -> Rid, Attrs, StreamStart) ->
case http_get(Sess, Rid) of receive after 100 -> ok end,
{ok, keep_on_hold} -> case catch http_get(Sess, Rid) of
receive_loop(Sess, Rid, Attrs, StreamStart);
{ok, cancel} -> {ok, cancel} ->
%% actually it would be better if we could completely %% actually it would be better if we could completely
%% cancel this request, but then we would have to hack %% cancel this request, but then we would have to hack
%% ejabberd_http and I'm too lazy now %% ejabberd_http and I'm too lazy now
{200, ?HEADER, "<body type='error' xmlns='"++?NS_HTTP_BIND++"'/>"}; {200, ?HEADER, "<body type='error' xmlns='"++?NS_HTTP_BIND++"'/>"};
{ok, empty} ->
{200, ?HEADER, "<body xmlns='"++?NS_HTTP_BIND++"'/>"};
{ok, OutPacket} -> {ok, OutPacket} ->
?DEBUG("OutPacket: ~s", [OutPacket]), ?DEBUG("OutPacket: ~s", [OutPacket]),
case StreamStart of case StreamStart of
@ -724,12 +782,14 @@ prepare_response(#http_bind{id=Sid, wait=Wait, hold=Hold}=Sess,
{"secure", "true"} %% we're always being secure {"secure", "true"} %% we're always being secure
] ++ BOSH_attribs,OutEls})} ] ++ BOSH_attribs,OutEls})}
end end
end end;
{'EXIT', _Reason} ->
{200, ?HEADER, "<body type='terminate' xmlns='"++?NS_HTTP_BIND++"'/>"}
end. end.
http_get(#http_bind{pid = FsmRef, wait = Wait, hold = Hold}, Rid) -> http_get(#http_bind{pid = FsmRef, wait = Wait, hold = Hold}, Rid) ->
gen_fsm:sync_send_all_state_event(FsmRef, gen_fsm:sync_send_all_state_event(
{http_get, Rid, Wait, Hold}). FsmRef, {http_get, Rid, Wait, Hold}, 2 * ?MAX_WAIT * 1000).
send_outpacket(#http_bind{pid = FsmRef}, OutPacket) -> send_outpacket(#http_bind{pid = FsmRef}, OutPacket) ->
case OutPacket of case OutPacket of
@ -844,7 +904,7 @@ parse_request(Data) ->
Xmlns /= ?NS_HTTP_BIND -> Xmlns /= ?NS_HTTP_BIND ->
{error, bad_request}; {error, bad_request};
true -> true ->
case list_to_integer(xml:get_attr_s("rid", Attrs)) of case catch list_to_integer(xml:get_attr_s("rid", Attrs)) of
{'EXIT', _} -> {'EXIT', _} ->
{error, bad_request}; {error, bad_request};
Rid -> Rid ->