25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-11-28 16:34:13 +01:00

Do not trigger item-not-found errors in mod_http_bind (part of EJABS-1827)

This changes what happens to request received with out of order rid,
previously response to such request was send immediately, and client was
free to submit another request, which triggered item-not-found if it was
delivered before request with missing rid.

This change make us wait for sending response to out of order request until
request with missing rid arrives. It also queues all outgoing data before
that condition is meet.
This commit is contained in:
Paweł Chmielowski 2012-04-27 13:19:49 +02:00
parent 437f68a9f3
commit 8b13226d00

View File

@ -66,6 +66,7 @@
last_receiver, last_receiver,
last_poll, last_poll,
http_receiver, http_receiver,
out_of_order_receiver = false,
wait_timer, wait_timer,
ctime = 0, ctime = 0,
timer, timer,
@ -372,6 +373,11 @@ handle_sync_event({send_xml, Packet}, _From, StateName,
Output = [Packet | StateData#state.output], Output = [Packet | StateData#state.output],
Reply = ok, Reply = ok,
{reply, Reply, StateName, StateData#state{output = Output}}; {reply, Reply, StateName, StateData#state{output = Output}};
handle_sync_event({send_xml, Packet}, _From, StateName,
#state{out_of_order_receiver = true} = StateData) ->
Output = [Packet | StateData#state.output],
Reply = ok,
{reply, Reply, StateName, StateData#state{output = Output}};
handle_sync_event({send_xml, Packet}, _From, StateName, StateData) -> handle_sync_event({send_xml, Packet}, _From, StateName, StateData) ->
Output = [Packet | StateData#state.output], Output = [Packet | StateData#state.output],
cancel_timer(StateData#state.timer), cancel_timer(StateData#state.timer),
@ -440,9 +446,9 @@ handle_sync_event({http_get, Rid, Wait, Hold}, From, StateName, StateData) ->
TNow = tnow(), TNow = tnow(),
if if
(Hold > 0) and (Hold > 0) and
(StateData#state.output == []) and ((StateData#state.output == []) or (StateData#state.rid < Rid)) 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) and (StateData#state.input /= cancel) and
(StateData#state.pause == 0) -> (StateData#state.pause == 0) ->
WaitTimer = erlang:start_timer(Wait * 1000, self(), []), WaitTimer = erlang:start_timer(Wait * 1000, self(), []),
@ -450,6 +456,7 @@ handle_sync_event({http_get, Rid, Wait, Hold}, From, StateName, StateData) ->
cancel_timer(StateData#state.timer), cancel_timer(StateData#state.timer),
{next_state, StateName, StateData#state{ {next_state, StateName, StateData#state{
http_receiver = From, http_receiver = From,
out_of_order_receiver = StateData#state.rid < Rid,
wait_timer = WaitTimer, wait_timer = WaitTimer,
timer = undefined}}; timer = undefined}};
(StateData#state.input == cancel) -> (StateData#state.input == cancel) ->
@ -587,10 +594,11 @@ handle_http_put_event(#http_put{rid = Rid, attrs = Attrs,
UnprocessedReqList = [Request | Requests], UnprocessedReqList = [Request | Requests],
cancel_timer(StateData#state.timer), cancel_timer(StateData#state.timer),
Timer = set_inactivity_timer(0, StateData#state.max_inactivity), Timer = set_inactivity_timer(0, StateData#state.max_inactivity),
{reply, buffered, StateName, {reply, ok, StateName,
StateData#state{unprocessed_req_list = UnprocessedReqList, StateData#state{unprocessed_req_list = UnprocessedReqList,
req_list = ReqList, req_list = ReqList,
timer = Timer}}; timer = Timer}, hibernate};
_ -> _ ->
%% Request is in sequence: %% Request is in sequence:
process_http_put(Request, StateName, StateData, RidAllow) process_http_put(Request, StateName, StateData, RidAllow)
@ -794,8 +802,6 @@ handle_http_put(Sid, Rid, Attrs, Payload, PayloadSize, StreamStart, IP) ->
% {"type", "error"}], []})}; % {"type", "error"}], []})};
handle_http_put(Sid, Rid, Attrs, Payload, PayloadSize, handle_http_put(Sid, Rid, Attrs, Payload, PayloadSize,
StreamStart, IP); StreamStart, IP);
{buffered, _Sess} ->
{200, ?HEADER, "<body xmlns='"++?NS_HTTP_BIND++"'/>"};
{ok, Sess} -> {ok, Sess} ->
prepare_response(Sess, Rid, [], StreamStart) prepare_response(Sess, Rid, [], StreamStart)
end. end.